diff options
Diffstat (limited to 'sound/soc')
152 files changed, 6202 insertions, 3020 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 5138b8493051..d62ce483a443 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -31,8 +31,10 @@ config SND_SOC_GENERIC_DMAENGINE_PCM | |||
31 | select SND_DMAENGINE_PCM | 31 | select SND_DMAENGINE_PCM |
32 | 32 | ||
33 | # All the supported SoCs | 33 | # All the supported SoCs |
34 | source "sound/soc/adi/Kconfig" | ||
34 | source "sound/soc/atmel/Kconfig" | 35 | source "sound/soc/atmel/Kconfig" |
35 | source "sound/soc/au1x/Kconfig" | 36 | source "sound/soc/au1x/Kconfig" |
37 | source "sound/soc/bcm/Kconfig" | ||
36 | source "sound/soc/blackfin/Kconfig" | 38 | source "sound/soc/blackfin/Kconfig" |
37 | source "sound/soc/cirrus/Kconfig" | 39 | source "sound/soc/cirrus/Kconfig" |
38 | source "sound/soc/davinci/Kconfig" | 40 | source "sound/soc/davinci/Kconfig" |
@@ -42,7 +44,7 @@ source "sound/soc/jz4740/Kconfig" | |||
42 | source "sound/soc/nuc900/Kconfig" | 44 | source "sound/soc/nuc900/Kconfig" |
43 | source "sound/soc/omap/Kconfig" | 45 | source "sound/soc/omap/Kconfig" |
44 | source "sound/soc/kirkwood/Kconfig" | 46 | source "sound/soc/kirkwood/Kconfig" |
45 | source "sound/soc/mid-x86/Kconfig" | 47 | source "sound/soc/intel/Kconfig" |
46 | source "sound/soc/mxs/Kconfig" | 48 | source "sound/soc/mxs/Kconfig" |
47 | source "sound/soc/pxa/Kconfig" | 49 | source "sound/soc/pxa/Kconfig" |
48 | source "sound/soc/samsung/Kconfig" | 50 | source "sound/soc/samsung/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 8b9e70105dd2..62a1822e77bf 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -8,15 +8,17 @@ endif | |||
8 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o | 8 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o |
9 | obj-$(CONFIG_SND_SOC) += codecs/ | 9 | obj-$(CONFIG_SND_SOC) += codecs/ |
10 | obj-$(CONFIG_SND_SOC) += generic/ | 10 | obj-$(CONFIG_SND_SOC) += generic/ |
11 | obj-$(CONFIG_SND_SOC) += adi/ | ||
11 | obj-$(CONFIG_SND_SOC) += atmel/ | 12 | obj-$(CONFIG_SND_SOC) += atmel/ |
12 | obj-$(CONFIG_SND_SOC) += au1x/ | 13 | obj-$(CONFIG_SND_SOC) += au1x/ |
14 | obj-$(CONFIG_SND_SOC) += bcm/ | ||
13 | obj-$(CONFIG_SND_SOC) += blackfin/ | 15 | obj-$(CONFIG_SND_SOC) += blackfin/ |
14 | obj-$(CONFIG_SND_SOC) += cirrus/ | 16 | obj-$(CONFIG_SND_SOC) += cirrus/ |
15 | obj-$(CONFIG_SND_SOC) += davinci/ | 17 | obj-$(CONFIG_SND_SOC) += davinci/ |
16 | obj-$(CONFIG_SND_SOC) += dwc/ | 18 | obj-$(CONFIG_SND_SOC) += dwc/ |
17 | obj-$(CONFIG_SND_SOC) += fsl/ | 19 | obj-$(CONFIG_SND_SOC) += fsl/ |
18 | obj-$(CONFIG_SND_SOC) += jz4740/ | 20 | obj-$(CONFIG_SND_SOC) += jz4740/ |
19 | obj-$(CONFIG_SND_SOC) += mid-x86/ | 21 | obj-$(CONFIG_SND_SOC) += intel/ |
20 | obj-$(CONFIG_SND_SOC) += mxs/ | 22 | obj-$(CONFIG_SND_SOC) += mxs/ |
21 | obj-$(CONFIG_SND_SOC) += nuc900/ | 23 | obj-$(CONFIG_SND_SOC) += nuc900/ |
22 | obj-$(CONFIG_SND_SOC) += omap/ | 24 | obj-$(CONFIG_SND_SOC) += omap/ |
diff --git a/sound/soc/adi/Kconfig b/sound/soc/adi/Kconfig new file mode 100644 index 000000000000..dd763f55edac --- /dev/null +++ b/sound/soc/adi/Kconfig | |||
@@ -0,0 +1,21 @@ | |||
1 | config SND_SOC_ADI | ||
2 | tristate "Audio support for Analog Devices reference designs" | ||
3 | depends on MICROBLAZE || ARCH_ZYNQ || COMPILE_TEST | ||
4 | help | ||
5 | Audio support for various reference designs by Analog Devices. | ||
6 | |||
7 | config SND_SOC_ADI_AXI_I2S | ||
8 | tristate "AXI-I2S support" | ||
9 | depends on SND_SOC_ADI | ||
10 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
11 | select REGMAP_MMIO | ||
12 | help | ||
13 | ASoC driver for the Analog Devices AXI-I2S softcore peripheral. | ||
14 | |||
15 | config SND_SOC_ADI_AXI_SPDIF | ||
16 | tristate "AXI-SPDIF support" | ||
17 | depends on SND_SOC_ADI | ||
18 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
19 | select REGMAP_MMIO | ||
20 | help | ||
21 | ASoC driver for the Analog Devices AXI-SPDIF softcore peripheral. | ||
diff --git a/sound/soc/adi/Makefile b/sound/soc/adi/Makefile new file mode 100644 index 000000000000..64456c1e5347 --- /dev/null +++ b/sound/soc/adi/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | snd-soc-adi-axi-i2s-objs := axi-i2s.o | ||
2 | snd-soc-adi-axi-spdif-objs := axi-spdif.o | ||
3 | |||
4 | obj-$(CONFIG_SND_SOC_ADI_AXI_I2S) += snd-soc-adi-axi-i2s.o | ||
5 | obj-$(CONFIG_SND_SOC_ADI_AXI_SPDIF) += snd-soc-adi-axi-spdif.o | ||
diff --git a/sound/soc/adi/axi-i2s.c b/sound/soc/adi/axi-i2s.c new file mode 100644 index 000000000000..7f91a86dd734 --- /dev/null +++ b/sound/soc/adi/axi-i2s.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012-2013, Analog Devices Inc. | ||
3 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
4 | * | ||
5 | * Licensed under the GPL-2. | ||
6 | */ | ||
7 | |||
8 | #include <linux/clk.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/of.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/regmap.h> | ||
15 | #include <linux/slab.h> | ||
16 | |||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include <sound/dmaengine_pcm.h> | ||
22 | |||
23 | #define AXI_I2S_REG_RESET 0x00 | ||
24 | #define AXI_I2S_REG_CTRL 0x04 | ||
25 | #define AXI_I2S_REG_CLK_CTRL 0x08 | ||
26 | #define AXI_I2S_REG_STATUS 0x10 | ||
27 | |||
28 | #define AXI_I2S_REG_RX_FIFO 0x28 | ||
29 | #define AXI_I2S_REG_TX_FIFO 0x2C | ||
30 | |||
31 | #define AXI_I2S_RESET_GLOBAL BIT(0) | ||
32 | #define AXI_I2S_RESET_TX_FIFO BIT(1) | ||
33 | #define AXI_I2S_RESET_RX_FIFO BIT(2) | ||
34 | |||
35 | #define AXI_I2S_CTRL_TX_EN BIT(0) | ||
36 | #define AXI_I2S_CTRL_RX_EN BIT(1) | ||
37 | |||
38 | /* The frame size is configurable, but for now we always set it 64 bit */ | ||
39 | #define AXI_I2S_BITS_PER_FRAME 64 | ||
40 | |||
41 | struct axi_i2s { | ||
42 | struct regmap *regmap; | ||
43 | struct clk *clk; | ||
44 | struct clk *clk_ref; | ||
45 | |||
46 | struct snd_soc_dai_driver dai_driver; | ||
47 | |||
48 | struct snd_dmaengine_dai_dma_data capture_dma_data; | ||
49 | struct snd_dmaengine_dai_dma_data playback_dma_data; | ||
50 | |||
51 | struct snd_ratnum ratnum; | ||
52 | struct snd_pcm_hw_constraint_ratnums rate_constraints; | ||
53 | }; | ||
54 | |||
55 | static int axi_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | ||
56 | struct snd_soc_dai *dai) | ||
57 | { | ||
58 | struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
59 | unsigned int mask, val; | ||
60 | |||
61 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
62 | mask = AXI_I2S_CTRL_RX_EN; | ||
63 | else | ||
64 | mask = AXI_I2S_CTRL_TX_EN; | ||
65 | |||
66 | switch (cmd) { | ||
67 | case SNDRV_PCM_TRIGGER_START: | ||
68 | case SNDRV_PCM_TRIGGER_RESUME: | ||
69 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
70 | val = mask; | ||
71 | break; | ||
72 | case SNDRV_PCM_TRIGGER_STOP: | ||
73 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
74 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
75 | val = 0; | ||
76 | break; | ||
77 | default: | ||
78 | return -EINVAL; | ||
79 | } | ||
80 | |||
81 | regmap_update_bits(i2s->regmap, AXI_I2S_REG_CTRL, mask, val); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int axi_i2s_hw_params(struct snd_pcm_substream *substream, | ||
87 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
88 | { | ||
89 | struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
90 | unsigned int bclk_div, word_size; | ||
91 | unsigned int bclk_rate; | ||
92 | |||
93 | bclk_rate = params_rate(params) * AXI_I2S_BITS_PER_FRAME; | ||
94 | |||
95 | word_size = AXI_I2S_BITS_PER_FRAME / 2 - 1; | ||
96 | bclk_div = DIV_ROUND_UP(clk_get_rate(i2s->clk_ref), bclk_rate) / 2 - 1; | ||
97 | |||
98 | regmap_write(i2s->regmap, AXI_I2S_REG_CLK_CTRL, (word_size << 16) | | ||
99 | bclk_div); | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int axi_i2s_startup(struct snd_pcm_substream *substream, | ||
105 | struct snd_soc_dai *dai) | ||
106 | { | ||
107 | struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
108 | uint32_t mask; | ||
109 | int ret; | ||
110 | |||
111 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
112 | mask = AXI_I2S_RESET_RX_FIFO; | ||
113 | else | ||
114 | mask = AXI_I2S_RESET_TX_FIFO; | ||
115 | |||
116 | regmap_write(i2s->regmap, AXI_I2S_REG_RESET, mask); | ||
117 | |||
118 | ret = snd_pcm_hw_constraint_ratnums(substream->runtime, 0, | ||
119 | SNDRV_PCM_HW_PARAM_RATE, | ||
120 | &i2s->rate_constraints); | ||
121 | if (ret) | ||
122 | return ret; | ||
123 | |||
124 | return clk_prepare_enable(i2s->clk_ref); | ||
125 | } | ||
126 | |||
127 | static void axi_i2s_shutdown(struct snd_pcm_substream *substream, | ||
128 | struct snd_soc_dai *dai) | ||
129 | { | ||
130 | struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
131 | |||
132 | clk_disable_unprepare(i2s->clk_ref); | ||
133 | } | ||
134 | |||
135 | static int axi_i2s_dai_probe(struct snd_soc_dai *dai) | ||
136 | { | ||
137 | struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
138 | |||
139 | snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, | ||
140 | &i2s->capture_dma_data); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static const struct snd_soc_dai_ops axi_i2s_dai_ops = { | ||
146 | .startup = axi_i2s_startup, | ||
147 | .shutdown = axi_i2s_shutdown, | ||
148 | .trigger = axi_i2s_trigger, | ||
149 | .hw_params = axi_i2s_hw_params, | ||
150 | }; | ||
151 | |||
152 | static struct snd_soc_dai_driver axi_i2s_dai = { | ||
153 | .probe = axi_i2s_dai_probe, | ||
154 | .playback = { | ||
155 | .channels_min = 2, | ||
156 | .channels_max = 2, | ||
157 | .rates = SNDRV_PCM_RATE_KNOT, | ||
158 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE, | ||
159 | }, | ||
160 | .capture = { | ||
161 | .channels_min = 2, | ||
162 | .channels_max = 2, | ||
163 | .rates = SNDRV_PCM_RATE_KNOT, | ||
164 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE, | ||
165 | }, | ||
166 | .ops = &axi_i2s_dai_ops, | ||
167 | .symmetric_rates = 1, | ||
168 | }; | ||
169 | |||
170 | static const struct snd_soc_component_driver axi_i2s_component = { | ||
171 | .name = "axi-i2s", | ||
172 | }; | ||
173 | |||
174 | static const struct regmap_config axi_i2s_regmap_config = { | ||
175 | .reg_bits = 32, | ||
176 | .reg_stride = 4, | ||
177 | .val_bits = 32, | ||
178 | .max_register = AXI_I2S_REG_STATUS, | ||
179 | }; | ||
180 | |||
181 | static int axi_i2s_probe(struct platform_device *pdev) | ||
182 | { | ||
183 | struct resource *res; | ||
184 | struct axi_i2s *i2s; | ||
185 | void __iomem *base; | ||
186 | int ret; | ||
187 | |||
188 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); | ||
189 | if (!i2s) | ||
190 | return -ENOMEM; | ||
191 | |||
192 | platform_set_drvdata(pdev, i2s); | ||
193 | |||
194 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
195 | base = devm_ioremap_resource(&pdev->dev, res); | ||
196 | if (IS_ERR(base)) | ||
197 | return PTR_ERR(base); | ||
198 | |||
199 | i2s->regmap = devm_regmap_init_mmio(&pdev->dev, base, | ||
200 | &axi_i2s_regmap_config); | ||
201 | if (IS_ERR(i2s->regmap)) | ||
202 | return PTR_ERR(i2s->regmap); | ||
203 | |||
204 | i2s->clk = devm_clk_get(&pdev->dev, "axi"); | ||
205 | if (IS_ERR(i2s->clk)) | ||
206 | return PTR_ERR(i2s->clk); | ||
207 | |||
208 | i2s->clk_ref = devm_clk_get(&pdev->dev, "ref"); | ||
209 | if (IS_ERR(i2s->clk_ref)) | ||
210 | return PTR_ERR(i2s->clk_ref); | ||
211 | |||
212 | ret = clk_prepare_enable(i2s->clk); | ||
213 | if (ret) | ||
214 | return ret; | ||
215 | |||
216 | i2s->playback_dma_data.addr = res->start + AXI_I2S_REG_TX_FIFO; | ||
217 | i2s->playback_dma_data.addr_width = 4; | ||
218 | i2s->playback_dma_data.maxburst = 1; | ||
219 | |||
220 | i2s->capture_dma_data.addr = res->start + AXI_I2S_REG_RX_FIFO; | ||
221 | i2s->capture_dma_data.addr_width = 4; | ||
222 | i2s->capture_dma_data.maxburst = 1; | ||
223 | |||
224 | i2s->ratnum.num = clk_get_rate(i2s->clk_ref) / 2 / AXI_I2S_BITS_PER_FRAME; | ||
225 | i2s->ratnum.den_step = 1; | ||
226 | i2s->ratnum.den_min = 1; | ||
227 | i2s->ratnum.den_max = 64; | ||
228 | |||
229 | i2s->rate_constraints.rats = &i2s->ratnum; | ||
230 | i2s->rate_constraints.nrats = 1; | ||
231 | |||
232 | regmap_write(i2s->regmap, AXI_I2S_REG_RESET, AXI_I2S_RESET_GLOBAL); | ||
233 | |||
234 | ret = devm_snd_soc_register_component(&pdev->dev, &axi_i2s_component, | ||
235 | &axi_i2s_dai, 1); | ||
236 | if (ret) | ||
237 | goto err_clk_disable; | ||
238 | |||
239 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, | ||
240 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE); | ||
241 | if (ret) | ||
242 | goto err_clk_disable; | ||
243 | |||
244 | err_clk_disable: | ||
245 | clk_disable_unprepare(i2s->clk); | ||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | static int axi_i2s_dev_remove(struct platform_device *pdev) | ||
250 | { | ||
251 | struct axi_i2s *i2s = platform_get_drvdata(pdev); | ||
252 | |||
253 | clk_disable_unprepare(i2s->clk); | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static const struct of_device_id axi_i2s_of_match[] = { | ||
259 | { .compatible = "adi,axi-i2s-1.00.a", }, | ||
260 | {}, | ||
261 | }; | ||
262 | MODULE_DEVICE_TABLE(of, axi_i2s_of_match); | ||
263 | |||
264 | static struct platform_driver axi_i2s_driver = { | ||
265 | .driver = { | ||
266 | .name = "axi-i2s", | ||
267 | .owner = THIS_MODULE, | ||
268 | .of_match_table = axi_i2s_of_match, | ||
269 | }, | ||
270 | .probe = axi_i2s_probe, | ||
271 | .remove = axi_i2s_dev_remove, | ||
272 | }; | ||
273 | module_platform_driver(axi_i2s_driver); | ||
274 | |||
275 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
276 | MODULE_DESCRIPTION("AXI I2S driver"); | ||
277 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/adi/axi-spdif.c b/sound/soc/adi/axi-spdif.c new file mode 100644 index 000000000000..8db7a9920695 --- /dev/null +++ b/sound/soc/adi/axi-spdif.c | |||
@@ -0,0 +1,272 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012-2013, Analog Devices Inc. | ||
3 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
4 | * | ||
5 | * Licensed under the GPL-2. | ||
6 | */ | ||
7 | |||
8 | #include <linux/init.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/of.h> | ||
14 | #include <linux/clk.h> | ||
15 | #include <linux/regmap.h> | ||
16 | |||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include <sound/initval.h> | ||
22 | #include <sound/dmaengine_pcm.h> | ||
23 | |||
24 | #define AXI_SPDIF_REG_CTRL 0x0 | ||
25 | #define AXI_SPDIF_REG_STAT 0x4 | ||
26 | #define AXI_SPDIF_REG_TX_FIFO 0xc | ||
27 | |||
28 | #define AXI_SPDIF_CTRL_TXDATA BIT(1) | ||
29 | #define AXI_SPDIF_CTRL_TXEN BIT(0) | ||
30 | #define AXI_SPDIF_CTRL_CLKDIV_OFFSET 8 | ||
31 | #define AXI_SPDIF_CTRL_CLKDIV_MASK (0xff << 8) | ||
32 | |||
33 | #define AXI_SPDIF_FREQ_44100 (0x0 << 6) | ||
34 | #define AXI_SPDIF_FREQ_48000 (0x1 << 6) | ||
35 | #define AXI_SPDIF_FREQ_32000 (0x2 << 6) | ||
36 | #define AXI_SPDIF_FREQ_NA (0x3 << 6) | ||
37 | |||
38 | struct axi_spdif { | ||
39 | struct regmap *regmap; | ||
40 | struct clk *clk; | ||
41 | struct clk *clk_ref; | ||
42 | |||
43 | struct snd_dmaengine_dai_dma_data dma_data; | ||
44 | |||
45 | struct snd_ratnum ratnum; | ||
46 | struct snd_pcm_hw_constraint_ratnums rate_constraints; | ||
47 | }; | ||
48 | |||
49 | static int axi_spdif_trigger(struct snd_pcm_substream *substream, int cmd, | ||
50 | struct snd_soc_dai *dai) | ||
51 | { | ||
52 | struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); | ||
53 | unsigned int val; | ||
54 | |||
55 | switch (cmd) { | ||
56 | case SNDRV_PCM_TRIGGER_START: | ||
57 | case SNDRV_PCM_TRIGGER_RESUME: | ||
58 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
59 | val = AXI_SPDIF_CTRL_TXDATA; | ||
60 | break; | ||
61 | case SNDRV_PCM_TRIGGER_STOP: | ||
62 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
63 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
64 | val = 0; | ||
65 | break; | ||
66 | default: | ||
67 | return -EINVAL; | ||
68 | } | ||
69 | |||
70 | regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL, | ||
71 | AXI_SPDIF_CTRL_TXDATA, val); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int axi_spdif_hw_params(struct snd_pcm_substream *substream, | ||
77 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
78 | { | ||
79 | struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); | ||
80 | unsigned int rate = params_rate(params); | ||
81 | unsigned int clkdiv, stat; | ||
82 | |||
83 | switch (params_rate(params)) { | ||
84 | case 32000: | ||
85 | stat = AXI_SPDIF_FREQ_32000; | ||
86 | break; | ||
87 | case 44100: | ||
88 | stat = AXI_SPDIF_FREQ_44100; | ||
89 | break; | ||
90 | case 48000: | ||
91 | stat = AXI_SPDIF_FREQ_48000; | ||
92 | break; | ||
93 | default: | ||
94 | stat = AXI_SPDIF_FREQ_NA; | ||
95 | break; | ||
96 | } | ||
97 | |||
98 | clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(spdif->clk_ref), | ||
99 | rate * 64 * 2) - 1; | ||
100 | clkdiv <<= AXI_SPDIF_CTRL_CLKDIV_OFFSET; | ||
101 | |||
102 | regmap_write(spdif->regmap, AXI_SPDIF_REG_STAT, stat); | ||
103 | regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL, | ||
104 | AXI_SPDIF_CTRL_CLKDIV_MASK, clkdiv); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int axi_spdif_dai_probe(struct snd_soc_dai *dai) | ||
110 | { | ||
111 | struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); | ||
112 | |||
113 | snd_soc_dai_init_dma_data(dai, &spdif->dma_data, NULL); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int axi_spdif_startup(struct snd_pcm_substream *substream, | ||
119 | struct snd_soc_dai *dai) | ||
120 | { | ||
121 | struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); | ||
122 | int ret; | ||
123 | |||
124 | ret = snd_pcm_hw_constraint_ratnums(substream->runtime, 0, | ||
125 | SNDRV_PCM_HW_PARAM_RATE, | ||
126 | &spdif->rate_constraints); | ||
127 | if (ret) | ||
128 | return ret; | ||
129 | |||
130 | ret = clk_prepare_enable(spdif->clk_ref); | ||
131 | if (ret) | ||
132 | return ret; | ||
133 | |||
134 | regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL, | ||
135 | AXI_SPDIF_CTRL_TXEN, AXI_SPDIF_CTRL_TXEN); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static void axi_spdif_shutdown(struct snd_pcm_substream *substream, | ||
141 | struct snd_soc_dai *dai) | ||
142 | { | ||
143 | struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); | ||
144 | |||
145 | regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL, | ||
146 | AXI_SPDIF_CTRL_TXEN, 0); | ||
147 | |||
148 | clk_disable_unprepare(spdif->clk_ref); | ||
149 | } | ||
150 | |||
151 | static const struct snd_soc_dai_ops axi_spdif_dai_ops = { | ||
152 | .startup = axi_spdif_startup, | ||
153 | .shutdown = axi_spdif_shutdown, | ||
154 | .trigger = axi_spdif_trigger, | ||
155 | .hw_params = axi_spdif_hw_params, | ||
156 | }; | ||
157 | |||
158 | static struct snd_soc_dai_driver axi_spdif_dai = { | ||
159 | .probe = axi_spdif_dai_probe, | ||
160 | .playback = { | ||
161 | .channels_min = 2, | ||
162 | .channels_max = 2, | ||
163 | .rates = SNDRV_PCM_RATE_KNOT, | ||
164 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
165 | }, | ||
166 | .ops = &axi_spdif_dai_ops, | ||
167 | }; | ||
168 | |||
169 | static const struct snd_soc_component_driver axi_spdif_component = { | ||
170 | .name = "axi-spdif", | ||
171 | }; | ||
172 | |||
173 | static const struct regmap_config axi_spdif_regmap_config = { | ||
174 | .reg_bits = 32, | ||
175 | .reg_stride = 4, | ||
176 | .val_bits = 32, | ||
177 | .max_register = AXI_SPDIF_REG_STAT, | ||
178 | }; | ||
179 | |||
180 | static int axi_spdif_probe(struct platform_device *pdev) | ||
181 | { | ||
182 | struct axi_spdif *spdif; | ||
183 | struct resource *res; | ||
184 | void __iomem *base; | ||
185 | int ret; | ||
186 | |||
187 | spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL); | ||
188 | if (!spdif) | ||
189 | return -ENOMEM; | ||
190 | |||
191 | platform_set_drvdata(pdev, spdif); | ||
192 | |||
193 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
194 | base = devm_ioremap_resource(&pdev->dev, res); | ||
195 | if (IS_ERR(base)) | ||
196 | return PTR_ERR(base); | ||
197 | |||
198 | spdif->regmap = devm_regmap_init_mmio(&pdev->dev, base, | ||
199 | &axi_spdif_regmap_config); | ||
200 | if (IS_ERR(spdif->regmap)) | ||
201 | return PTR_ERR(spdif->regmap); | ||
202 | |||
203 | spdif->clk = devm_clk_get(&pdev->dev, "axi"); | ||
204 | if (IS_ERR(spdif->clk)) | ||
205 | return PTR_ERR(spdif->clk); | ||
206 | |||
207 | spdif->clk_ref = devm_clk_get(&pdev->dev, "ref"); | ||
208 | if (IS_ERR(spdif->clk_ref)) | ||
209 | return PTR_ERR(spdif->clk_ref); | ||
210 | |||
211 | ret = clk_prepare_enable(spdif->clk); | ||
212 | if (ret) | ||
213 | return ret; | ||
214 | |||
215 | spdif->dma_data.addr = res->start + AXI_SPDIF_REG_TX_FIFO; | ||
216 | spdif->dma_data.addr_width = 4; | ||
217 | spdif->dma_data.maxburst = 1; | ||
218 | |||
219 | spdif->ratnum.num = clk_get_rate(spdif->clk_ref) / 128; | ||
220 | spdif->ratnum.den_step = 1; | ||
221 | spdif->ratnum.den_min = 1; | ||
222 | spdif->ratnum.den_max = 64; | ||
223 | |||
224 | spdif->rate_constraints.rats = &spdif->ratnum; | ||
225 | spdif->rate_constraints.nrats = 1; | ||
226 | |||
227 | ret = devm_snd_soc_register_component(&pdev->dev, &axi_spdif_component, | ||
228 | &axi_spdif_dai, 1); | ||
229 | if (ret) | ||
230 | goto err_clk_disable; | ||
231 | |||
232 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, | ||
233 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE); | ||
234 | if (ret) | ||
235 | goto err_clk_disable; | ||
236 | |||
237 | return 0; | ||
238 | |||
239 | err_clk_disable: | ||
240 | clk_disable_unprepare(spdif->clk); | ||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | static int axi_spdif_dev_remove(struct platform_device *pdev) | ||
245 | { | ||
246 | struct axi_spdif *spdif = platform_get_drvdata(pdev); | ||
247 | |||
248 | clk_disable_unprepare(spdif->clk); | ||
249 | |||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static const struct of_device_id axi_spdif_of_match[] = { | ||
254 | { .compatible = "adi,axi-spdif-tx-1.00.a", }, | ||
255 | {}, | ||
256 | }; | ||
257 | MODULE_DEVICE_TABLE(of, axi_spdif_of_match); | ||
258 | |||
259 | static struct platform_driver axi_spdif_driver = { | ||
260 | .driver = { | ||
261 | .name = "axi-spdif", | ||
262 | .owner = THIS_MODULE, | ||
263 | .of_match_table = axi_spdif_of_match, | ||
264 | }, | ||
265 | .probe = axi_spdif_probe, | ||
266 | .remove = axi_spdif_dev_remove, | ||
267 | }; | ||
268 | module_platform_driver(axi_spdif_driver); | ||
269 | |||
270 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
271 | MODULE_DESCRIPTION("AXI SPDIF driver"); | ||
272 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 8697cedccd21..1ead3c977a51 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -648,7 +648,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream, | |||
648 | 648 | ||
649 | dma_params = ssc_p->dma_params[dir]; | 649 | dma_params = ssc_p->dma_params[dir]; |
650 | 650 | ||
651 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); | 651 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); |
652 | ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error); | 652 | ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error); |
653 | 653 | ||
654 | pr_debug("%s enabled SSC_SR=0x%08x\n", | 654 | pr_debug("%s enabled SSC_SR=0x%08x\n", |
@@ -657,6 +657,33 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream, | |||
657 | return 0; | 657 | return 0; |
658 | } | 658 | } |
659 | 659 | ||
660 | static int atmel_ssc_trigger(struct snd_pcm_substream *substream, | ||
661 | int cmd, struct snd_soc_dai *dai) | ||
662 | { | ||
663 | struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; | ||
664 | struct atmel_pcm_dma_params *dma_params; | ||
665 | int dir; | ||
666 | |||
667 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
668 | dir = 0; | ||
669 | else | ||
670 | dir = 1; | ||
671 | |||
672 | dma_params = ssc_p->dma_params[dir]; | ||
673 | |||
674 | switch (cmd) { | ||
675 | case SNDRV_PCM_TRIGGER_START: | ||
676 | case SNDRV_PCM_TRIGGER_RESUME: | ||
677 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
678 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); | ||
679 | break; | ||
680 | default: | ||
681 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); | ||
682 | break; | ||
683 | } | ||
684 | |||
685 | return 0; | ||
686 | } | ||
660 | 687 | ||
661 | #ifdef CONFIG_PM | 688 | #ifdef CONFIG_PM |
662 | static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai) | 689 | static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai) |
@@ -731,6 +758,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = { | |||
731 | .startup = atmel_ssc_startup, | 758 | .startup = atmel_ssc_startup, |
732 | .shutdown = atmel_ssc_shutdown, | 759 | .shutdown = atmel_ssc_shutdown, |
733 | .prepare = atmel_ssc_prepare, | 760 | .prepare = atmel_ssc_prepare, |
761 | .trigger = atmel_ssc_trigger, | ||
734 | .hw_params = atmel_ssc_hw_params, | 762 | .hw_params = atmel_ssc_hw_params, |
735 | .set_fmt = atmel_ssc_set_dai_fmt, | 763 | .set_fmt = atmel_ssc_set_dai_fmt, |
736 | .set_clkdiv = atmel_ssc_set_dai_clkdiv, | 764 | .set_clkdiv = atmel_ssc_set_dai_clkdiv, |
diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c index 992ae38d5a15..3188036a18f0 100644 --- a/sound/soc/atmel/sam9x5_wm8731.c +++ b/sound/soc/atmel/sam9x5_wm8731.c | |||
@@ -97,6 +97,8 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) | |||
97 | goto out; | 97 | goto out; |
98 | } | 98 | } |
99 | 99 | ||
100 | snd_soc_card_set_drvdata(card, priv); | ||
101 | |||
100 | card->dev = &pdev->dev; | 102 | card->dev = &pdev->dev; |
101 | card->owner = THIS_MODULE; | 103 | card->owner = THIS_MODULE; |
102 | card->dai_link = dai; | 104 | card->dai_link = dai; |
@@ -107,7 +109,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) | |||
107 | dai->stream_name = "WM8731 PCM"; | 109 | dai->stream_name = "WM8731 PCM"; |
108 | dai->codec_dai_name = "wm8731-hifi"; | 110 | dai->codec_dai_name = "wm8731-hifi"; |
109 | dai->init = sam9x5_wm8731_init; | 111 | dai->init = sam9x5_wm8731_init; |
110 | dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 112 | dai->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF |
111 | | SND_SOC_DAIFMT_CBM_CFM; | 113 | | SND_SOC_DAIFMT_CBM_CFM; |
112 | 114 | ||
113 | ret = snd_soc_of_parse_card_name(card, "atmel,model"); | 115 | ret = snd_soc_of_parse_card_name(card, "atmel,model"); |
@@ -153,8 +155,6 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) | |||
153 | of_node_put(codec_np); | 155 | of_node_put(codec_np); |
154 | of_node_put(cpu_np); | 156 | of_node_put(cpu_np); |
155 | 157 | ||
156 | platform_set_drvdata(pdev, card); | ||
157 | |||
158 | ret = snd_soc_register_card(card); | 158 | ret = snd_soc_register_card(card); |
159 | if (ret) { | 159 | if (ret) { |
160 | dev_err(&pdev->dev, | 160 | dev_err(&pdev->dev, |
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 3b4eafaf30d3..17a24d804734 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c | |||
@@ -65,19 +65,10 @@ struct au1xpsc_audio_dmadata { | |||
65 | #define AU1XPSC_PERIOD_MIN_BYTES 1024 | 65 | #define AU1XPSC_PERIOD_MIN_BYTES 1024 |
66 | #define AU1XPSC_BUFFER_MIN_BYTES 65536 | 66 | #define AU1XPSC_BUFFER_MIN_BYTES 65536 |
67 | 67 | ||
68 | #define AU1XPSC_PCM_FMTS \ | ||
69 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \ | ||
70 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | ||
71 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | \ | ||
72 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | \ | ||
73 | SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE | \ | ||
74 | 0) | ||
75 | |||
76 | /* PCM hardware DMA capabilities - platform specific */ | 68 | /* PCM hardware DMA capabilities - platform specific */ |
77 | static const struct snd_pcm_hardware au1xpsc_pcm_hardware = { | 69 | static const struct snd_pcm_hardware au1xpsc_pcm_hardware = { |
78 | .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 70 | .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
79 | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH, | 71 | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH, |
80 | .formats = AU1XPSC_PCM_FMTS, | ||
81 | .period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES, | 72 | .period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES, |
82 | .period_bytes_max = 4096 * 1024 - 1, | 73 | .period_bytes_max = 4096 * 1024 - 1, |
83 | .periods_min = 2, | 74 | .periods_min = 2, |
diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c index befd1074f9bd..e920b60bf6c2 100644 --- a/sound/soc/au1x/dma.c +++ b/sound/soc/au1x/dma.c | |||
@@ -21,14 +21,6 @@ | |||
21 | 21 | ||
22 | #include "psc.h" | 22 | #include "psc.h" |
23 | 23 | ||
24 | #define ALCHEMY_PCM_FMTS \ | ||
25 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \ | ||
26 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | ||
27 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | \ | ||
28 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | \ | ||
29 | SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE | \ | ||
30 | 0) | ||
31 | |||
32 | struct pcm_period { | 24 | struct pcm_period { |
33 | u32 start; | 25 | u32 start; |
34 | u32 relative_end; /* relative to start of buffer */ | 26 | u32 relative_end; /* relative to start of buffer */ |
@@ -171,12 +163,6 @@ static irqreturn_t au1000_dma_interrupt(int irq, void *ptr) | |||
171 | static const struct snd_pcm_hardware alchemy_pcm_hardware = { | 163 | static const struct snd_pcm_hardware alchemy_pcm_hardware = { |
172 | .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 164 | .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
173 | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH, | 165 | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH, |
174 | .formats = ALCHEMY_PCM_FMTS, | ||
175 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
176 | .rate_min = SNDRV_PCM_RATE_8000, | ||
177 | .rate_max = SNDRV_PCM_RATE_192000, | ||
178 | .channels_min = 2, | ||
179 | .channels_max = 2, | ||
180 | .period_bytes_min = 1024, | 166 | .period_bytes_min = 1024, |
181 | .period_bytes_max = 16 * 1024 - 1, | 167 | .period_bytes_max = 16 * 1024 - 1, |
182 | .periods_min = 4, | 168 | .periods_min = 4, |
diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig new file mode 100644 index 000000000000..3d82a29ce3a8 --- /dev/null +++ b/sound/soc/bcm/Kconfig | |||
@@ -0,0 +1,10 @@ | |||
1 | config SND_BCM2835_SOC_I2S | ||
2 | tristate "SoC Audio support for the Broadcom BCM2835 I2S module" | ||
3 | depends on ARCH_BCM2835 || COMPILE_TEST | ||
4 | select SND_SOC_DMAENGINE_PCM | ||
5 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
6 | select REGMAP_MMIO | ||
7 | help | ||
8 | Say Y or M if you want to add support for codecs attached to | ||
9 | the BCM2835 I2S interface. You will also need | ||
10 | to select the audio interfaces to support below. | ||
diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile new file mode 100644 index 000000000000..bc816b71e5a4 --- /dev/null +++ b/sound/soc/bcm/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # BCM2835 Platform Support | ||
2 | snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o | ||
3 | |||
4 | obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o | ||
5 | |||
diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c new file mode 100644 index 000000000000..2685fe4f8427 --- /dev/null +++ b/sound/soc/bcm/bcm2835-i2s.c | |||
@@ -0,0 +1,879 @@ | |||
1 | /* | ||
2 | * ALSA SoC I2S Audio Layer for Broadcom BCM2835 SoC | ||
3 | * | ||
4 | * Author: Florian Meier <florian.meier@koalo.de> | ||
5 | * Copyright 2013 | ||
6 | * | ||
7 | * Based on | ||
8 | * Raspberry Pi PCM I2S ALSA Driver | ||
9 | * Copyright (c) by Phil Poole 2013 | ||
10 | * | ||
11 | * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor | ||
12 | * Vladimir Barinov, <vbarinov@embeddedalley.com> | ||
13 | * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com> | ||
14 | * | ||
15 | * OMAP ALSA SoC DAI driver using McBSP port | ||
16 | * Copyright (C) 2008 Nokia Corporation | ||
17 | * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com> | ||
18 | * Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
19 | * | ||
20 | * Freescale SSI ALSA SoC Digital Audio Interface (DAI) driver | ||
21 | * Author: Timur Tabi <timur@freescale.com> | ||
22 | * Copyright 2007-2010 Freescale Semiconductor, Inc. | ||
23 | * | ||
24 | * This program is free software; you can redistribute it and/or | ||
25 | * modify it under the terms of the GNU General Public License | ||
26 | * version 2 as published by the Free Software Foundation. | ||
27 | * | ||
28 | * This program is distributed in the hope that it will be useful, but | ||
29 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
31 | * General Public License for more details. | ||
32 | */ | ||
33 | |||
34 | #include <linux/init.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/device.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/delay.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/clk.h> | ||
41 | |||
42 | #include <sound/core.h> | ||
43 | #include <sound/pcm.h> | ||
44 | #include <sound/pcm_params.h> | ||
45 | #include <sound/initval.h> | ||
46 | #include <sound/soc.h> | ||
47 | #include <sound/dmaengine_pcm.h> | ||
48 | |||
49 | /* Clock registers */ | ||
50 | #define BCM2835_CLK_PCMCTL_REG 0x00 | ||
51 | #define BCM2835_CLK_PCMDIV_REG 0x04 | ||
52 | |||
53 | /* Clock register settings */ | ||
54 | #define BCM2835_CLK_PASSWD (0x5a000000) | ||
55 | #define BCM2835_CLK_PASSWD_MASK (0xff000000) | ||
56 | #define BCM2835_CLK_MASH(v) ((v) << 9) | ||
57 | #define BCM2835_CLK_FLIP BIT(8) | ||
58 | #define BCM2835_CLK_BUSY BIT(7) | ||
59 | #define BCM2835_CLK_KILL BIT(5) | ||
60 | #define BCM2835_CLK_ENAB BIT(4) | ||
61 | #define BCM2835_CLK_SRC(v) (v) | ||
62 | |||
63 | #define BCM2835_CLK_SHIFT (12) | ||
64 | #define BCM2835_CLK_DIVI(v) ((v) << BCM2835_CLK_SHIFT) | ||
65 | #define BCM2835_CLK_DIVF(v) (v) | ||
66 | #define BCM2835_CLK_DIVF_MASK (0xFFF) | ||
67 | |||
68 | enum { | ||
69 | BCM2835_CLK_MASH_0 = 0, | ||
70 | BCM2835_CLK_MASH_1, | ||
71 | BCM2835_CLK_MASH_2, | ||
72 | BCM2835_CLK_MASH_3, | ||
73 | }; | ||
74 | |||
75 | enum { | ||
76 | BCM2835_CLK_SRC_GND = 0, | ||
77 | BCM2835_CLK_SRC_OSC, | ||
78 | BCM2835_CLK_SRC_DBG0, | ||
79 | BCM2835_CLK_SRC_DBG1, | ||
80 | BCM2835_CLK_SRC_PLLA, | ||
81 | BCM2835_CLK_SRC_PLLC, | ||
82 | BCM2835_CLK_SRC_PLLD, | ||
83 | BCM2835_CLK_SRC_HDMI, | ||
84 | }; | ||
85 | |||
86 | /* Most clocks are not useable (freq = 0) */ | ||
87 | static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = { | ||
88 | [BCM2835_CLK_SRC_GND] = 0, | ||
89 | [BCM2835_CLK_SRC_OSC] = 19200000, | ||
90 | [BCM2835_CLK_SRC_DBG0] = 0, | ||
91 | [BCM2835_CLK_SRC_DBG1] = 0, | ||
92 | [BCM2835_CLK_SRC_PLLA] = 0, | ||
93 | [BCM2835_CLK_SRC_PLLC] = 0, | ||
94 | [BCM2835_CLK_SRC_PLLD] = 500000000, | ||
95 | [BCM2835_CLK_SRC_HDMI] = 0, | ||
96 | }; | ||
97 | |||
98 | /* I2S registers */ | ||
99 | #define BCM2835_I2S_CS_A_REG 0x00 | ||
100 | #define BCM2835_I2S_FIFO_A_REG 0x04 | ||
101 | #define BCM2835_I2S_MODE_A_REG 0x08 | ||
102 | #define BCM2835_I2S_RXC_A_REG 0x0c | ||
103 | #define BCM2835_I2S_TXC_A_REG 0x10 | ||
104 | #define BCM2835_I2S_DREQ_A_REG 0x14 | ||
105 | #define BCM2835_I2S_INTEN_A_REG 0x18 | ||
106 | #define BCM2835_I2S_INTSTC_A_REG 0x1c | ||
107 | #define BCM2835_I2S_GRAY_REG 0x20 | ||
108 | |||
109 | /* I2S register settings */ | ||
110 | #define BCM2835_I2S_STBY BIT(25) | ||
111 | #define BCM2835_I2S_SYNC BIT(24) | ||
112 | #define BCM2835_I2S_RXSEX BIT(23) | ||
113 | #define BCM2835_I2S_RXF BIT(22) | ||
114 | #define BCM2835_I2S_TXE BIT(21) | ||
115 | #define BCM2835_I2S_RXD BIT(20) | ||
116 | #define BCM2835_I2S_TXD BIT(19) | ||
117 | #define BCM2835_I2S_RXR BIT(18) | ||
118 | #define BCM2835_I2S_TXW BIT(17) | ||
119 | #define BCM2835_I2S_CS_RXERR BIT(16) | ||
120 | #define BCM2835_I2S_CS_TXERR BIT(15) | ||
121 | #define BCM2835_I2S_RXSYNC BIT(14) | ||
122 | #define BCM2835_I2S_TXSYNC BIT(13) | ||
123 | #define BCM2835_I2S_DMAEN BIT(9) | ||
124 | #define BCM2835_I2S_RXTHR(v) ((v) << 7) | ||
125 | #define BCM2835_I2S_TXTHR(v) ((v) << 5) | ||
126 | #define BCM2835_I2S_RXCLR BIT(4) | ||
127 | #define BCM2835_I2S_TXCLR BIT(3) | ||
128 | #define BCM2835_I2S_TXON BIT(2) | ||
129 | #define BCM2835_I2S_RXON BIT(1) | ||
130 | #define BCM2835_I2S_EN (1) | ||
131 | |||
132 | #define BCM2835_I2S_CLKDIS BIT(28) | ||
133 | #define BCM2835_I2S_PDMN BIT(27) | ||
134 | #define BCM2835_I2S_PDME BIT(26) | ||
135 | #define BCM2835_I2S_FRXP BIT(25) | ||
136 | #define BCM2835_I2S_FTXP BIT(24) | ||
137 | #define BCM2835_I2S_CLKM BIT(23) | ||
138 | #define BCM2835_I2S_CLKI BIT(22) | ||
139 | #define BCM2835_I2S_FSM BIT(21) | ||
140 | #define BCM2835_I2S_FSI BIT(20) | ||
141 | #define BCM2835_I2S_FLEN(v) ((v) << 10) | ||
142 | #define BCM2835_I2S_FSLEN(v) (v) | ||
143 | |||
144 | #define BCM2835_I2S_CHWEX BIT(15) | ||
145 | #define BCM2835_I2S_CHEN BIT(14) | ||
146 | #define BCM2835_I2S_CHPOS(v) ((v) << 4) | ||
147 | #define BCM2835_I2S_CHWID(v) (v) | ||
148 | #define BCM2835_I2S_CH1(v) ((v) << 16) | ||
149 | #define BCM2835_I2S_CH2(v) (v) | ||
150 | |||
151 | #define BCM2835_I2S_TX_PANIC(v) ((v) << 24) | ||
152 | #define BCM2835_I2S_RX_PANIC(v) ((v) << 16) | ||
153 | #define BCM2835_I2S_TX(v) ((v) << 8) | ||
154 | #define BCM2835_I2S_RX(v) (v) | ||
155 | |||
156 | #define BCM2835_I2S_INT_RXERR BIT(3) | ||
157 | #define BCM2835_I2S_INT_TXERR BIT(2) | ||
158 | #define BCM2835_I2S_INT_RXR BIT(1) | ||
159 | #define BCM2835_I2S_INT_TXW BIT(0) | ||
160 | |||
161 | /* I2S DMA interface */ | ||
162 | /* FIXME: Needs IOMMU support */ | ||
163 | #define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000) | ||
164 | |||
165 | /* General device struct */ | ||
166 | struct bcm2835_i2s_dev { | ||
167 | struct device *dev; | ||
168 | struct snd_dmaengine_dai_dma_data dma_data[2]; | ||
169 | unsigned int fmt; | ||
170 | unsigned int bclk_ratio; | ||
171 | |||
172 | struct regmap *i2s_regmap; | ||
173 | struct regmap *clk_regmap; | ||
174 | }; | ||
175 | |||
176 | static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) | ||
177 | { | ||
178 | /* Start the clock if in master mode */ | ||
179 | unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; | ||
180 | |||
181 | switch (master) { | ||
182 | case SND_SOC_DAIFMT_CBS_CFS: | ||
183 | case SND_SOC_DAIFMT_CBS_CFM: | ||
184 | regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, | ||
185 | BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, | ||
186 | BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); | ||
187 | break; | ||
188 | default: | ||
189 | break; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | static void bcm2835_i2s_stop_clock(struct bcm2835_i2s_dev *dev) | ||
194 | { | ||
195 | uint32_t clkreg; | ||
196 | int timeout = 1000; | ||
197 | |||
198 | /* Stop clock */ | ||
199 | regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, | ||
200 | BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, | ||
201 | BCM2835_CLK_PASSWD); | ||
202 | |||
203 | /* Wait for the BUSY flag going down */ | ||
204 | while (--timeout) { | ||
205 | regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); | ||
206 | if (!(clkreg & BCM2835_CLK_BUSY)) | ||
207 | break; | ||
208 | } | ||
209 | |||
210 | if (!timeout) { | ||
211 | /* KILL the clock */ | ||
212 | dev_err(dev->dev, "I2S clock didn't stop. Kill the clock!\n"); | ||
213 | regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, | ||
214 | BCM2835_CLK_KILL | BCM2835_CLK_PASSWD_MASK, | ||
215 | BCM2835_CLK_KILL | BCM2835_CLK_PASSWD); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, | ||
220 | bool tx, bool rx) | ||
221 | { | ||
222 | int timeout = 1000; | ||
223 | uint32_t syncval; | ||
224 | uint32_t csreg; | ||
225 | uint32_t i2s_active_state; | ||
226 | uint32_t clkreg; | ||
227 | uint32_t clk_active_state; | ||
228 | uint32_t off; | ||
229 | uint32_t clr; | ||
230 | |||
231 | off = tx ? BCM2835_I2S_TXON : 0; | ||
232 | off |= rx ? BCM2835_I2S_RXON : 0; | ||
233 | |||
234 | clr = tx ? BCM2835_I2S_TXCLR : 0; | ||
235 | clr |= rx ? BCM2835_I2S_RXCLR : 0; | ||
236 | |||
237 | /* Backup the current state */ | ||
238 | regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg); | ||
239 | i2s_active_state = csreg & (BCM2835_I2S_RXON | BCM2835_I2S_TXON); | ||
240 | |||
241 | regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); | ||
242 | clk_active_state = clkreg & BCM2835_CLK_ENAB; | ||
243 | |||
244 | /* Start clock if not running */ | ||
245 | if (!clk_active_state) { | ||
246 | regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, | ||
247 | BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, | ||
248 | BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); | ||
249 | } | ||
250 | |||
251 | /* Stop I2S module */ | ||
252 | regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, off, 0); | ||
253 | |||
254 | /* | ||
255 | * Clear the FIFOs | ||
256 | * Requires at least 2 PCM clock cycles to take effect | ||
257 | */ | ||
258 | regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, clr, clr); | ||
259 | |||
260 | /* Wait for 2 PCM clock cycles */ | ||
261 | |||
262 | /* | ||
263 | * Toggle the SYNC flag. After 2 PCM clock cycles it can be read back | ||
264 | * FIXME: This does not seem to work for slave mode! | ||
265 | */ | ||
266 | regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &syncval); | ||
267 | syncval &= BCM2835_I2S_SYNC; | ||
268 | |||
269 | regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, | ||
270 | BCM2835_I2S_SYNC, ~syncval); | ||
271 | |||
272 | /* Wait for the SYNC flag changing it's state */ | ||
273 | while (--timeout) { | ||
274 | regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg); | ||
275 | if ((csreg & BCM2835_I2S_SYNC) != syncval) | ||
276 | break; | ||
277 | } | ||
278 | |||
279 | if (!timeout) | ||
280 | dev_err(dev->dev, "I2S SYNC error!\n"); | ||
281 | |||
282 | /* Stop clock if it was not running before */ | ||
283 | if (!clk_active_state) | ||
284 | bcm2835_i2s_stop_clock(dev); | ||
285 | |||
286 | /* Restore I2S state */ | ||
287 | regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, | ||
288 | BCM2835_I2S_RXON | BCM2835_I2S_TXON, i2s_active_state); | ||
289 | } | ||
290 | |||
291 | static int bcm2835_i2s_set_dai_fmt(struct snd_soc_dai *dai, | ||
292 | unsigned int fmt) | ||
293 | { | ||
294 | struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
295 | dev->fmt = fmt; | ||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static int bcm2835_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, | ||
300 | unsigned int ratio) | ||
301 | { | ||
302 | struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
303 | dev->bclk_ratio = ratio; | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, | ||
308 | struct snd_pcm_hw_params *params, | ||
309 | struct snd_soc_dai *dai) | ||
310 | { | ||
311 | struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
312 | |||
313 | unsigned int sampling_rate = params_rate(params); | ||
314 | unsigned int data_length, data_delay, bclk_ratio; | ||
315 | unsigned int ch1pos, ch2pos, mode, format; | ||
316 | unsigned int mash = BCM2835_CLK_MASH_1; | ||
317 | unsigned int divi, divf, target_frequency; | ||
318 | int clk_src = -1; | ||
319 | unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; | ||
320 | bool bit_master = (master == SND_SOC_DAIFMT_CBS_CFS | ||
321 | || master == SND_SOC_DAIFMT_CBS_CFM); | ||
322 | |||
323 | bool frame_master = (master == SND_SOC_DAIFMT_CBS_CFS | ||
324 | || master == SND_SOC_DAIFMT_CBM_CFS); | ||
325 | uint32_t csreg; | ||
326 | |||
327 | /* | ||
328 | * If a stream is already enabled, | ||
329 | * the registers are already set properly. | ||
330 | */ | ||
331 | regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg); | ||
332 | |||
333 | if (csreg & (BCM2835_I2S_TXON | BCM2835_I2S_RXON)) | ||
334 | return 0; | ||
335 | |||
336 | /* | ||
337 | * Adjust the data length according to the format. | ||
338 | * We prefill the half frame length with an integer | ||
339 | * divider of 2400 as explained at the clock settings. | ||
340 | * Maybe it is overwritten there, if the Integer mode | ||
341 | * does not apply. | ||
342 | */ | ||
343 | switch (params_format(params)) { | ||
344 | case SNDRV_PCM_FORMAT_S16_LE: | ||
345 | data_length = 16; | ||
346 | bclk_ratio = 40; | ||
347 | break; | ||
348 | case SNDRV_PCM_FORMAT_S32_LE: | ||
349 | data_length = 32; | ||
350 | bclk_ratio = 80; | ||
351 | break; | ||
352 | default: | ||
353 | return -EINVAL; | ||
354 | } | ||
355 | |||
356 | /* If bclk_ratio already set, use that one. */ | ||
357 | if (dev->bclk_ratio) | ||
358 | bclk_ratio = dev->bclk_ratio; | ||
359 | |||
360 | /* | ||
361 | * Clock Settings | ||
362 | * | ||
363 | * The target frequency of the bit clock is | ||
364 | * sampling rate * frame length | ||
365 | * | ||
366 | * Integer mode: | ||
367 | * Sampling rates that are multiples of 8000 kHz | ||
368 | * can be driven by the oscillator of 19.2 MHz | ||
369 | * with an integer divider as long as the frame length | ||
370 | * is an integer divider of 19200000/8000=2400 as set up above. | ||
371 | * This is no longer possible if the sampling rate | ||
372 | * is too high (e.g. 192 kHz), because the oscillator is too slow. | ||
373 | * | ||
374 | * MASH mode: | ||
375 | * For all other sampling rates, it is not possible to | ||
376 | * have an integer divider. Approximate the clock | ||
377 | * with the MASH module that induces a slight frequency | ||
378 | * variance. To minimize that it is best to have the fastest | ||
379 | * clock here. That is PLLD with 500 MHz. | ||
380 | */ | ||
381 | target_frequency = sampling_rate * bclk_ratio; | ||
382 | clk_src = BCM2835_CLK_SRC_OSC; | ||
383 | mash = BCM2835_CLK_MASH_0; | ||
384 | |||
385 | if (bcm2835_clk_freq[clk_src] % target_frequency == 0 | ||
386 | && bit_master && frame_master) { | ||
387 | divi = bcm2835_clk_freq[clk_src] / target_frequency; | ||
388 | divf = 0; | ||
389 | } else { | ||
390 | uint64_t dividend; | ||
391 | |||
392 | if (!dev->bclk_ratio) { | ||
393 | /* | ||
394 | * Overwrite bclk_ratio, because the | ||
395 | * above trick is not needed or can | ||
396 | * not be used. | ||
397 | */ | ||
398 | bclk_ratio = 2 * data_length; | ||
399 | } | ||
400 | |||
401 | target_frequency = sampling_rate * bclk_ratio; | ||
402 | |||
403 | clk_src = BCM2835_CLK_SRC_PLLD; | ||
404 | mash = BCM2835_CLK_MASH_1; | ||
405 | |||
406 | dividend = bcm2835_clk_freq[clk_src]; | ||
407 | dividend <<= BCM2835_CLK_SHIFT; | ||
408 | do_div(dividend, target_frequency); | ||
409 | divi = dividend >> BCM2835_CLK_SHIFT; | ||
410 | divf = dividend & BCM2835_CLK_DIVF_MASK; | ||
411 | } | ||
412 | |||
413 | /* Set clock divider */ | ||
414 | regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD | ||
415 | | BCM2835_CLK_DIVI(divi) | ||
416 | | BCM2835_CLK_DIVF(divf)); | ||
417 | |||
418 | /* Setup clock, but don't start it yet */ | ||
419 | regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD | ||
420 | | BCM2835_CLK_MASH(mash) | ||
421 | | BCM2835_CLK_SRC(clk_src)); | ||
422 | |||
423 | /* Setup the frame format */ | ||
424 | format = BCM2835_I2S_CHEN; | ||
425 | |||
426 | if (data_length > 24) | ||
427 | format |= BCM2835_I2S_CHWEX; | ||
428 | |||
429 | format |= BCM2835_I2S_CHWID((data_length-8)&0xf); | ||
430 | |||
431 | switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
432 | case SND_SOC_DAIFMT_I2S: | ||
433 | data_delay = 1; | ||
434 | break; | ||
435 | default: | ||
436 | /* | ||
437 | * TODO | ||
438 | * Others are possible but are not implemented at the moment. | ||
439 | */ | ||
440 | dev_err(dev->dev, "%s:bad format\n", __func__); | ||
441 | return -EINVAL; | ||
442 | } | ||
443 | |||
444 | ch1pos = data_delay; | ||
445 | ch2pos = bclk_ratio / 2 + data_delay; | ||
446 | |||
447 | switch (params_channels(params)) { | ||
448 | case 2: | ||
449 | format = BCM2835_I2S_CH1(format) | BCM2835_I2S_CH2(format); | ||
450 | format |= BCM2835_I2S_CH1(BCM2835_I2S_CHPOS(ch1pos)); | ||
451 | format |= BCM2835_I2S_CH2(BCM2835_I2S_CHPOS(ch2pos)); | ||
452 | break; | ||
453 | default: | ||
454 | return -EINVAL; | ||
455 | } | ||
456 | |||
457 | /* | ||
458 | * Set format for both streams. | ||
459 | * We cannot set another frame length | ||
460 | * (and therefore word length) anyway, | ||
461 | * so the format will be the same. | ||
462 | */ | ||
463 | regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format); | ||
464 | regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format); | ||
465 | |||
466 | /* Setup the I2S mode */ | ||
467 | mode = 0; | ||
468 | |||
469 | if (data_length <= 16) { | ||
470 | /* | ||
471 | * Use frame packed mode (2 channels per 32 bit word) | ||
472 | * We cannot set another frame length in the second stream | ||
473 | * (and therefore word length) anyway, | ||
474 | * so the format will be the same. | ||
475 | */ | ||
476 | mode |= BCM2835_I2S_FTXP | BCM2835_I2S_FRXP; | ||
477 | } | ||
478 | |||
479 | mode |= BCM2835_I2S_FLEN(bclk_ratio - 1); | ||
480 | mode |= BCM2835_I2S_FSLEN(bclk_ratio / 2); | ||
481 | |||
482 | /* Master or slave? */ | ||
483 | switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
484 | case SND_SOC_DAIFMT_CBS_CFS: | ||
485 | /* CPU is master */ | ||
486 | break; | ||
487 | case SND_SOC_DAIFMT_CBM_CFS: | ||
488 | /* | ||
489 | * CODEC is bit clock master | ||
490 | * CPU is frame master | ||
491 | */ | ||
492 | mode |= BCM2835_I2S_CLKM; | ||
493 | break; | ||
494 | case SND_SOC_DAIFMT_CBS_CFM: | ||
495 | /* | ||
496 | * CODEC is frame master | ||
497 | * CPU is bit clock master | ||
498 | */ | ||
499 | mode |= BCM2835_I2S_FSM; | ||
500 | break; | ||
501 | case SND_SOC_DAIFMT_CBM_CFM: | ||
502 | /* CODEC is master */ | ||
503 | mode |= BCM2835_I2S_CLKM; | ||
504 | mode |= BCM2835_I2S_FSM; | ||
505 | break; | ||
506 | default: | ||
507 | dev_err(dev->dev, "%s:bad master\n", __func__); | ||
508 | return -EINVAL; | ||
509 | } | ||
510 | |||
511 | /* | ||
512 | * Invert clocks? | ||
513 | * | ||
514 | * The BCM approach seems to be inverted to the classical I2S approach. | ||
515 | */ | ||
516 | switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
517 | case SND_SOC_DAIFMT_NB_NF: | ||
518 | /* None. Therefore, both for BCM */ | ||
519 | mode |= BCM2835_I2S_CLKI; | ||
520 | mode |= BCM2835_I2S_FSI; | ||
521 | break; | ||
522 | case SND_SOC_DAIFMT_IB_IF: | ||
523 | /* Both. Therefore, none for BCM */ | ||
524 | break; | ||
525 | case SND_SOC_DAIFMT_NB_IF: | ||
526 | /* | ||
527 | * Invert only frame sync. Therefore, | ||
528 | * invert only bit clock for BCM | ||
529 | */ | ||
530 | mode |= BCM2835_I2S_CLKI; | ||
531 | break; | ||
532 | case SND_SOC_DAIFMT_IB_NF: | ||
533 | /* | ||
534 | * Invert only bit clock. Therefore, | ||
535 | * invert only frame sync for BCM | ||
536 | */ | ||
537 | mode |= BCM2835_I2S_FSI; | ||
538 | break; | ||
539 | default: | ||
540 | return -EINVAL; | ||
541 | } | ||
542 | |||
543 | regmap_write(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, mode); | ||
544 | |||
545 | /* Setup the DMA parameters */ | ||
546 | regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, | ||
547 | BCM2835_I2S_RXTHR(1) | ||
548 | | BCM2835_I2S_TXTHR(1) | ||
549 | | BCM2835_I2S_DMAEN, 0xffffffff); | ||
550 | |||
551 | regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_DREQ_A_REG, | ||
552 | BCM2835_I2S_TX_PANIC(0x10) | ||
553 | | BCM2835_I2S_RX_PANIC(0x30) | ||
554 | | BCM2835_I2S_TX(0x30) | ||
555 | | BCM2835_I2S_RX(0x20), 0xffffffff); | ||
556 | |||
557 | /* Clear FIFOs */ | ||
558 | bcm2835_i2s_clear_fifos(dev, true, true); | ||
559 | |||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static int bcm2835_i2s_prepare(struct snd_pcm_substream *substream, | ||
564 | struct snd_soc_dai *dai) | ||
565 | { | ||
566 | struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
567 | uint32_t cs_reg; | ||
568 | |||
569 | bcm2835_i2s_start_clock(dev); | ||
570 | |||
571 | /* | ||
572 | * Clear both FIFOs if the one that should be started | ||
573 | * is not empty at the moment. This should only happen | ||
574 | * after overrun. Otherwise, hw_params would have cleared | ||
575 | * the FIFO. | ||
576 | */ | ||
577 | regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &cs_reg); | ||
578 | |||
579 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
580 | && !(cs_reg & BCM2835_I2S_TXE)) | ||
581 | bcm2835_i2s_clear_fifos(dev, true, false); | ||
582 | else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE | ||
583 | && (cs_reg & BCM2835_I2S_RXD)) | ||
584 | bcm2835_i2s_clear_fifos(dev, false, true); | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static void bcm2835_i2s_stop(struct bcm2835_i2s_dev *dev, | ||
590 | struct snd_pcm_substream *substream, | ||
591 | struct snd_soc_dai *dai) | ||
592 | { | ||
593 | uint32_t mask; | ||
594 | |||
595 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
596 | mask = BCM2835_I2S_RXON; | ||
597 | else | ||
598 | mask = BCM2835_I2S_TXON; | ||
599 | |||
600 | regmap_update_bits(dev->i2s_regmap, | ||
601 | BCM2835_I2S_CS_A_REG, mask, 0); | ||
602 | |||
603 | /* Stop also the clock when not SND_SOC_DAIFMT_CONT */ | ||
604 | if (!dai->active && !(dev->fmt & SND_SOC_DAIFMT_CONT)) | ||
605 | bcm2835_i2s_stop_clock(dev); | ||
606 | } | ||
607 | |||
608 | static int bcm2835_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | ||
609 | struct snd_soc_dai *dai) | ||
610 | { | ||
611 | struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
612 | uint32_t mask; | ||
613 | |||
614 | switch (cmd) { | ||
615 | case SNDRV_PCM_TRIGGER_START: | ||
616 | case SNDRV_PCM_TRIGGER_RESUME: | ||
617 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
618 | bcm2835_i2s_start_clock(dev); | ||
619 | |||
620 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
621 | mask = BCM2835_I2S_RXON; | ||
622 | else | ||
623 | mask = BCM2835_I2S_TXON; | ||
624 | |||
625 | regmap_update_bits(dev->i2s_regmap, | ||
626 | BCM2835_I2S_CS_A_REG, mask, mask); | ||
627 | break; | ||
628 | |||
629 | case SNDRV_PCM_TRIGGER_STOP: | ||
630 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
631 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
632 | bcm2835_i2s_stop(dev, substream, dai); | ||
633 | break; | ||
634 | default: | ||
635 | return -EINVAL; | ||
636 | } | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | static int bcm2835_i2s_startup(struct snd_pcm_substream *substream, | ||
642 | struct snd_soc_dai *dai) | ||
643 | { | ||
644 | struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
645 | |||
646 | if (dai->active) | ||
647 | return 0; | ||
648 | |||
649 | /* Should this still be running stop it */ | ||
650 | bcm2835_i2s_stop_clock(dev); | ||
651 | |||
652 | /* Enable PCM block */ | ||
653 | regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, | ||
654 | BCM2835_I2S_EN, BCM2835_I2S_EN); | ||
655 | |||
656 | /* | ||
657 | * Disable STBY. | ||
658 | * Requires at least 4 PCM clock cycles to take effect. | ||
659 | */ | ||
660 | regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, | ||
661 | BCM2835_I2S_STBY, BCM2835_I2S_STBY); | ||
662 | |||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | static void bcm2835_i2s_shutdown(struct snd_pcm_substream *substream, | ||
667 | struct snd_soc_dai *dai) | ||
668 | { | ||
669 | struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
670 | |||
671 | bcm2835_i2s_stop(dev, substream, dai); | ||
672 | |||
673 | /* If both streams are stopped, disable module and clock */ | ||
674 | if (dai->active) | ||
675 | return; | ||
676 | |||
677 | /* Disable the module */ | ||
678 | regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, | ||
679 | BCM2835_I2S_EN, 0); | ||
680 | |||
681 | /* | ||
682 | * Stopping clock is necessary, because stop does | ||
683 | * not stop the clock when SND_SOC_DAIFMT_CONT | ||
684 | */ | ||
685 | bcm2835_i2s_stop_clock(dev); | ||
686 | } | ||
687 | |||
688 | static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = { | ||
689 | .startup = bcm2835_i2s_startup, | ||
690 | .shutdown = bcm2835_i2s_shutdown, | ||
691 | .prepare = bcm2835_i2s_prepare, | ||
692 | .trigger = bcm2835_i2s_trigger, | ||
693 | .hw_params = bcm2835_i2s_hw_params, | ||
694 | .set_fmt = bcm2835_i2s_set_dai_fmt, | ||
695 | .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio | ||
696 | }; | ||
697 | |||
698 | static int bcm2835_i2s_dai_probe(struct snd_soc_dai *dai) | ||
699 | { | ||
700 | struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
701 | |||
702 | snd_soc_dai_init_dma_data(dai, | ||
703 | &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK], | ||
704 | &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]); | ||
705 | |||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | static struct snd_soc_dai_driver bcm2835_i2s_dai = { | ||
710 | .name = "bcm2835-i2s", | ||
711 | .probe = bcm2835_i2s_dai_probe, | ||
712 | .playback = { | ||
713 | .channels_min = 2, | ||
714 | .channels_max = 2, | ||
715 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
716 | .formats = SNDRV_PCM_FMTBIT_S16_LE | ||
717 | | SNDRV_PCM_FMTBIT_S32_LE | ||
718 | }, | ||
719 | .capture = { | ||
720 | .channels_min = 2, | ||
721 | .channels_max = 2, | ||
722 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
723 | .formats = SNDRV_PCM_FMTBIT_S16_LE | ||
724 | | SNDRV_PCM_FMTBIT_S32_LE | ||
725 | }, | ||
726 | .ops = &bcm2835_i2s_dai_ops, | ||
727 | .symmetric_rates = 1 | ||
728 | }; | ||
729 | |||
730 | static bool bcm2835_i2s_volatile_reg(struct device *dev, unsigned int reg) | ||
731 | { | ||
732 | switch (reg) { | ||
733 | case BCM2835_I2S_CS_A_REG: | ||
734 | case BCM2835_I2S_FIFO_A_REG: | ||
735 | case BCM2835_I2S_INTSTC_A_REG: | ||
736 | case BCM2835_I2S_GRAY_REG: | ||
737 | return true; | ||
738 | default: | ||
739 | return false; | ||
740 | }; | ||
741 | } | ||
742 | |||
743 | static bool bcm2835_i2s_precious_reg(struct device *dev, unsigned int reg) | ||
744 | { | ||
745 | switch (reg) { | ||
746 | case BCM2835_I2S_FIFO_A_REG: | ||
747 | return true; | ||
748 | default: | ||
749 | return false; | ||
750 | }; | ||
751 | } | ||
752 | |||
753 | static bool bcm2835_clk_volatile_reg(struct device *dev, unsigned int reg) | ||
754 | { | ||
755 | switch (reg) { | ||
756 | case BCM2835_CLK_PCMCTL_REG: | ||
757 | return true; | ||
758 | default: | ||
759 | return false; | ||
760 | }; | ||
761 | } | ||
762 | |||
763 | static const struct regmap_config bcm2835_regmap_config[] = { | ||
764 | { | ||
765 | .reg_bits = 32, | ||
766 | .reg_stride = 4, | ||
767 | .val_bits = 32, | ||
768 | .max_register = BCM2835_I2S_GRAY_REG, | ||
769 | .precious_reg = bcm2835_i2s_precious_reg, | ||
770 | .volatile_reg = bcm2835_i2s_volatile_reg, | ||
771 | .cache_type = REGCACHE_RBTREE, | ||
772 | }, | ||
773 | { | ||
774 | .reg_bits = 32, | ||
775 | .reg_stride = 4, | ||
776 | .val_bits = 32, | ||
777 | .max_register = BCM2835_CLK_PCMDIV_REG, | ||
778 | .volatile_reg = bcm2835_clk_volatile_reg, | ||
779 | .cache_type = REGCACHE_RBTREE, | ||
780 | }, | ||
781 | }; | ||
782 | |||
783 | static const struct snd_soc_component_driver bcm2835_i2s_component = { | ||
784 | .name = "bcm2835-i2s-comp", | ||
785 | }; | ||
786 | |||
787 | static int bcm2835_i2s_probe(struct platform_device *pdev) | ||
788 | { | ||
789 | struct bcm2835_i2s_dev *dev; | ||
790 | int i; | ||
791 | int ret; | ||
792 | struct regmap *regmap[2]; | ||
793 | struct resource *mem[2]; | ||
794 | |||
795 | /* Request both ioareas */ | ||
796 | for (i = 0; i <= 1; i++) { | ||
797 | void __iomem *base; | ||
798 | |||
799 | mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
800 | base = devm_ioremap_resource(&pdev->dev, mem[i]); | ||
801 | if (IS_ERR(base)) | ||
802 | return PTR_ERR(base); | ||
803 | |||
804 | regmap[i] = devm_regmap_init_mmio(&pdev->dev, base, | ||
805 | &bcm2835_regmap_config[i]); | ||
806 | if (IS_ERR(regmap[i])) | ||
807 | return PTR_ERR(regmap[i]); | ||
808 | } | ||
809 | |||
810 | dev = devm_kzalloc(&pdev->dev, sizeof(*dev), | ||
811 | GFP_KERNEL); | ||
812 | if (!dev) | ||
813 | return -ENOMEM; | ||
814 | |||
815 | dev->i2s_regmap = regmap[0]; | ||
816 | dev->clk_regmap = regmap[1]; | ||
817 | |||
818 | /* Set the DMA address */ | ||
819 | dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = | ||
820 | (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG | ||
821 | + BCM2835_VCMMU_SHIFT; | ||
822 | |||
823 | dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = | ||
824 | (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG | ||
825 | + BCM2835_VCMMU_SHIFT; | ||
826 | |||
827 | /* Set the bus width */ | ||
828 | dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = | ||
829 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
830 | dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr_width = | ||
831 | DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
832 | |||
833 | /* Set burst */ | ||
834 | dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 2; | ||
835 | dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 2; | ||
836 | |||
837 | /* BCLK ratio - use default */ | ||
838 | dev->bclk_ratio = 0; | ||
839 | |||
840 | /* Store the pdev */ | ||
841 | dev->dev = &pdev->dev; | ||
842 | dev_set_drvdata(&pdev->dev, dev); | ||
843 | |||
844 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
845 | &bcm2835_i2s_component, &bcm2835_i2s_dai, 1); | ||
846 | if (ret) { | ||
847 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); | ||
848 | return ret; | ||
849 | } | ||
850 | |||
851 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | ||
852 | if (ret) { | ||
853 | dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); | ||
854 | return ret; | ||
855 | } | ||
856 | |||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | static const struct of_device_id bcm2835_i2s_of_match[] = { | ||
861 | { .compatible = "brcm,bcm2835-i2s", }, | ||
862 | {}, | ||
863 | }; | ||
864 | |||
865 | static struct platform_driver bcm2835_i2s_driver = { | ||
866 | .probe = bcm2835_i2s_probe, | ||
867 | .driver = { | ||
868 | .name = "bcm2835-i2s", | ||
869 | .owner = THIS_MODULE, | ||
870 | .of_match_table = bcm2835_i2s_of_match, | ||
871 | }, | ||
872 | }; | ||
873 | |||
874 | module_platform_driver(bcm2835_i2s_driver); | ||
875 | |||
876 | MODULE_ALIAS("platform:bcm2835-i2s"); | ||
877 | MODULE_DESCRIPTION("BCM2835 I2S interface"); | ||
878 | MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>"); | ||
879 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 1d4c676eb6cc..cdb8ee75ded9 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c | |||
@@ -107,7 +107,6 @@ static const struct snd_pcm_hardware bf5xx_pcm_hardware = { | |||
107 | #endif | 107 | #endif |
108 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | 108 | SNDRV_PCM_INFO_BLOCK_TRANSFER, |
109 | 109 | ||
110 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
111 | .period_bytes_min = 32, | 110 | .period_bytes_min = 32, |
112 | .period_bytes_max = 0x10000, | 111 | .period_bytes_max = 0x10000, |
113 | .periods_min = 1, | 112 | .periods_min = 1, |
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 2a5b43417fd5..a3881c4381c9 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -52,9 +52,6 @@ static const struct snd_pcm_hardware bf5xx_pcm_hardware = { | |||
52 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 52 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
53 | SNDRV_PCM_INFO_MMAP_VALID | | 53 | SNDRV_PCM_INFO_MMAP_VALID | |
54 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | 54 | SNDRV_PCM_INFO_BLOCK_TRANSFER, |
55 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
56 | SNDRV_PCM_FMTBIT_S24_LE | | ||
57 | SNDRV_PCM_FMTBIT_S32_LE, | ||
58 | .period_bytes_min = 32, | 55 | .period_bytes_min = 32, |
59 | .period_bytes_max = 0x10000, | 56 | .period_bytes_max = 0x10000, |
60 | .periods_min = 1, | 57 | .periods_min = 1, |
diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c index c43fb214558a..4f900efc437c 100644 --- a/sound/soc/cirrus/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c | |||
@@ -63,7 +63,7 @@ static struct snd_soc_ops edb93xx_ops = { | |||
63 | static struct snd_soc_dai_link edb93xx_dai = { | 63 | static struct snd_soc_dai_link edb93xx_dai = { |
64 | .name = "CS4271", | 64 | .name = "CS4271", |
65 | .stream_name = "CS4271 HiFi", | 65 | .stream_name = "CS4271 HiFi", |
66 | .platform_name = "ep93xx-pcm-audio", | 66 | .platform_name = "ep93xx-i2s", |
67 | .cpu_dai_name = "ep93xx-i2s", | 67 | .cpu_dai_name = "ep93xx-i2s", |
68 | .codec_name = "spi0.0", | 68 | .codec_name = "spi0.0", |
69 | .codec_dai_name = "cs4271-hifi", | 69 | .codec_dai_name = "cs4271-hifi", |
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index efa75b5086a4..f30dadf85b99 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
@@ -19,11 +19,14 @@ | |||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | 20 | ||
21 | #include <sound/core.h> | 21 | #include <sound/core.h> |
22 | #include <sound/dmaengine_pcm.h> | ||
22 | #include <sound/ac97_codec.h> | 23 | #include <sound/ac97_codec.h> |
23 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
24 | 25 | ||
25 | #include <linux/platform_data/dma-ep93xx.h> | 26 | #include <linux/platform_data/dma-ep93xx.h> |
26 | 27 | ||
28 | #include "ep93xx-pcm.h" | ||
29 | |||
27 | /* | 30 | /* |
28 | * Per channel (1-4) registers. | 31 | * Per channel (1-4) registers. |
29 | */ | 32 | */ |
@@ -95,6 +98,8 @@ struct ep93xx_ac97_info { | |||
95 | struct device *dev; | 98 | struct device *dev; |
96 | void __iomem *regs; | 99 | void __iomem *regs; |
97 | struct completion done; | 100 | struct completion done; |
101 | struct snd_dmaengine_dai_dma_data dma_params_rx; | ||
102 | struct snd_dmaengine_dai_dma_data dma_params_tx; | ||
98 | }; | 103 | }; |
99 | 104 | ||
100 | /* currently ALSA only supports a single AC97 device */ | 105 | /* currently ALSA only supports a single AC97 device */ |
@@ -315,8 +320,13 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, | |||
315 | 320 | ||
316 | static int ep93xx_ac97_dai_probe(struct snd_soc_dai *dai) | 321 | static int ep93xx_ac97_dai_probe(struct snd_soc_dai *dai) |
317 | { | 322 | { |
318 | dai->playback_dma_data = &ep93xx_ac97_pcm_out; | 323 | struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai); |
319 | dai->capture_dma_data = &ep93xx_ac97_pcm_in; | 324 | |
325 | info->dma_params_tx.filter_data = &ep93xx_ac97_pcm_out; | ||
326 | info->dma_params_rx.filter_data = &ep93xx_ac97_pcm_in; | ||
327 | |||
328 | dai->playback_dma_data = &info->dma_params_tx; | ||
329 | dai->capture_dma_data = &info->dma_params_rx; | ||
320 | 330 | ||
321 | return 0; | 331 | return 0; |
322 | } | 332 | } |
@@ -394,8 +404,14 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) | |||
394 | if (ret) | 404 | if (ret) |
395 | goto fail; | 405 | goto fail; |
396 | 406 | ||
407 | ret = devm_ep93xx_pcm_platform_register(&pdev->dev); | ||
408 | if (ret) | ||
409 | goto fail_unregister; | ||
410 | |||
397 | return 0; | 411 | return 0; |
398 | 412 | ||
413 | fail_unregister: | ||
414 | snd_soc_unregister_component(&pdev->dev); | ||
399 | fail: | 415 | fail: |
400 | ep93xx_ac97_info = NULL; | 416 | ep93xx_ac97_info = NULL; |
401 | snd_soc_set_ac97_ops(NULL); | 417 | snd_soc_set_ac97_ops(NULL); |
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index a57643d6402f..943145f9d1b6 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | 22 | ||
23 | #include <sound/core.h> | 23 | #include <sound/core.h> |
24 | #include <sound/dmaengine_pcm.h> | ||
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
26 | #include <sound/initval.h> | 27 | #include <sound/initval.h> |
@@ -30,6 +31,8 @@ | |||
30 | #include <mach/ep93xx-regs.h> | 31 | #include <mach/ep93xx-regs.h> |
31 | #include <linux/platform_data/dma-ep93xx.h> | 32 | #include <linux/platform_data/dma-ep93xx.h> |
32 | 33 | ||
34 | #include "ep93xx-pcm.h" | ||
35 | |||
33 | #define EP93XX_I2S_TXCLKCFG 0x00 | 36 | #define EP93XX_I2S_TXCLKCFG 0x00 |
34 | #define EP93XX_I2S_RXCLKCFG 0x04 | 37 | #define EP93XX_I2S_RXCLKCFG 0x04 |
35 | #define EP93XX_I2S_GLCTRL 0x0C | 38 | #define EP93XX_I2S_GLCTRL 0x0C |
@@ -61,6 +64,8 @@ struct ep93xx_i2s_info { | |||
61 | struct clk *sclk; | 64 | struct clk *sclk; |
62 | struct clk *lrclk; | 65 | struct clk *lrclk; |
63 | void __iomem *regs; | 66 | void __iomem *regs; |
67 | struct snd_dmaengine_dai_dma_data dma_params_rx; | ||
68 | struct snd_dmaengine_dai_dma_data dma_params_tx; | ||
64 | }; | 69 | }; |
65 | 70 | ||
66 | static struct ep93xx_dma_data ep93xx_i2s_dma_data[] = { | 71 | static struct ep93xx_dma_data ep93xx_i2s_dma_data[] = { |
@@ -140,8 +145,15 @@ static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream) | |||
140 | 145 | ||
141 | static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai) | 146 | static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai) |
142 | { | 147 | { |
143 | dai->playback_dma_data = &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_PLAYBACK]; | 148 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); |
144 | dai->capture_dma_data = &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_CAPTURE]; | 149 | |
150 | info->dma_params_tx.filter_data = | ||
151 | &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_PLAYBACK]; | ||
152 | info->dma_params_rx.filter_data = | ||
153 | &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_CAPTURE]; | ||
154 | |||
155 | dai->playback_dma_data = &info->dma_params_tx; | ||
156 | dai->capture_dma_data = &info->dma_params_rx; | ||
145 | 157 | ||
146 | return 0; | 158 | return 0; |
147 | } | 159 | } |
@@ -405,8 +417,14 @@ static int ep93xx_i2s_probe(struct platform_device *pdev) | |||
405 | if (err) | 417 | if (err) |
406 | goto fail_put_lrclk; | 418 | goto fail_put_lrclk; |
407 | 419 | ||
420 | err = devm_ep93xx_pcm_platform_register(&pdev->dev); | ||
421 | if (err) | ||
422 | goto fail_unregister; | ||
423 | |||
408 | return 0; | 424 | return 0; |
409 | 425 | ||
426 | fail_unregister: | ||
427 | snd_soc_unregister_component(&pdev->dev); | ||
410 | fail_put_lrclk: | 428 | fail_put_lrclk: |
411 | clk_put(info->lrclk); | 429 | clk_put(info->lrclk); |
412 | fail_put_sclk: | 430 | fail_put_sclk: |
diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c index cfe517e68009..5f664471d99e 100644 --- a/sound/soc/cirrus/ep93xx-pcm.c +++ b/sound/soc/cirrus/ep93xx-pcm.c | |||
@@ -23,20 +23,13 @@ | |||
23 | 23 | ||
24 | #include <linux/platform_data/dma-ep93xx.h> | 24 | #include <linux/platform_data/dma-ep93xx.h> |
25 | 25 | ||
26 | #include "ep93xx-pcm.h" | ||
27 | |||
26 | static const struct snd_pcm_hardware ep93xx_pcm_hardware = { | 28 | static const struct snd_pcm_hardware ep93xx_pcm_hardware = { |
27 | .info = (SNDRV_PCM_INFO_MMAP | | 29 | .info = (SNDRV_PCM_INFO_MMAP | |
28 | SNDRV_PCM_INFO_MMAP_VALID | | 30 | SNDRV_PCM_INFO_MMAP_VALID | |
29 | SNDRV_PCM_INFO_INTERLEAVED | | 31 | SNDRV_PCM_INFO_INTERLEAVED | |
30 | SNDRV_PCM_INFO_BLOCK_TRANSFER), | 32 | SNDRV_PCM_INFO_BLOCK_TRANSFER), |
31 | |||
32 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
33 | .rate_min = SNDRV_PCM_RATE_8000, | ||
34 | .rate_max = SNDRV_PCM_RATE_192000, | ||
35 | |||
36 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | | ||
37 | SNDRV_PCM_FMTBIT_S24_LE | | ||
38 | SNDRV_PCM_FMTBIT_S32_LE), | ||
39 | |||
40 | .buffer_bytes_max = 131072, | 33 | .buffer_bytes_max = 131072, |
41 | .period_bytes_min = 32, | 34 | .period_bytes_min = 32, |
42 | .period_bytes_max = 32768, | 35 | .period_bytes_max = 32768, |
@@ -57,53 +50,22 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param) | |||
57 | return false; | 50 | return false; |
58 | } | 51 | } |
59 | 52 | ||
60 | static struct dma_chan *ep93xx_compat_request_channel( | ||
61 | struct snd_soc_pcm_runtime *rtd, | ||
62 | struct snd_pcm_substream *substream) | ||
63 | { | ||
64 | struct snd_dmaengine_dai_dma_data *dma_data; | ||
65 | |||
66 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
67 | |||
68 | return snd_dmaengine_pcm_request_channel(ep93xx_pcm_dma_filter, | ||
69 | dma_data); | ||
70 | } | ||
71 | |||
72 | static const struct snd_dmaengine_pcm_config ep93xx_dmaengine_pcm_config = { | 53 | static const struct snd_dmaengine_pcm_config ep93xx_dmaengine_pcm_config = { |
73 | .pcm_hardware = &ep93xx_pcm_hardware, | 54 | .pcm_hardware = &ep93xx_pcm_hardware, |
74 | .compat_filter_fn = ep93xx_pcm_dma_filter, | 55 | .compat_filter_fn = ep93xx_pcm_dma_filter, |
75 | .compat_request_channel = ep93xx_compat_request_channel, | ||
76 | .prealloc_buffer_size = 131072, | 56 | .prealloc_buffer_size = 131072, |
77 | }; | 57 | }; |
78 | 58 | ||
79 | static int ep93xx_soc_platform_probe(struct platform_device *pdev) | 59 | int devm_ep93xx_pcm_platform_register(struct device *dev) |
80 | { | 60 | { |
81 | return snd_dmaengine_pcm_register(&pdev->dev, | 61 | return devm_snd_dmaengine_pcm_register(dev, |
82 | &ep93xx_dmaengine_pcm_config, | 62 | &ep93xx_dmaengine_pcm_config, |
83 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | 63 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | |
84 | SND_DMAENGINE_PCM_FLAG_NO_DT | | 64 | SND_DMAENGINE_PCM_FLAG_NO_DT | |
85 | SND_DMAENGINE_PCM_FLAG_COMPAT); | 65 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
86 | } | 66 | } |
87 | 67 | EXPORT_SYMBOL_GPL(devm_ep93xx_pcm_platform_register); | |
88 | static int ep93xx_soc_platform_remove(struct platform_device *pdev) | ||
89 | { | ||
90 | snd_dmaengine_pcm_unregister(&pdev->dev); | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static struct platform_driver ep93xx_pcm_driver = { | ||
95 | .driver = { | ||
96 | .name = "ep93xx-pcm-audio", | ||
97 | .owner = THIS_MODULE, | ||
98 | }, | ||
99 | |||
100 | .probe = ep93xx_soc_platform_probe, | ||
101 | .remove = ep93xx_soc_platform_remove, | ||
102 | }; | ||
103 | |||
104 | module_platform_driver(ep93xx_pcm_driver); | ||
105 | 68 | ||
106 | MODULE_AUTHOR("Ryan Mallon"); | 69 | MODULE_AUTHOR("Ryan Mallon"); |
107 | MODULE_DESCRIPTION("EP93xx ALSA PCM interface"); | 70 | MODULE_DESCRIPTION("EP93xx ALSA PCM interface"); |
108 | MODULE_LICENSE("GPL"); | 71 | MODULE_LICENSE("GPL"); |
109 | MODULE_ALIAS("platform:ep93xx-pcm-audio"); | ||
diff --git a/sound/soc/cirrus/ep93xx-pcm.h b/sound/soc/cirrus/ep93xx-pcm.h new file mode 100644 index 000000000000..b7a12a2fae9c --- /dev/null +++ b/sound/soc/cirrus/ep93xx-pcm.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #ifndef __EP93XX_PCM_H__ | ||
18 | #define __EP93XX_PCM_H__ | ||
19 | |||
20 | int devm_ep93xx_pcm_platform_register(struct device *dev); | ||
21 | |||
22 | #endif | ||
diff --git a/sound/soc/cirrus/simone.c b/sound/soc/cirrus/simone.c index 4d094d00c34a..822a19a89e74 100644 --- a/sound/soc/cirrus/simone.c +++ b/sound/soc/cirrus/simone.c | |||
@@ -27,7 +27,7 @@ static struct snd_soc_dai_link simone_dai = { | |||
27 | .cpu_dai_name = "ep93xx-ac97", | 27 | .cpu_dai_name = "ep93xx-ac97", |
28 | .codec_dai_name = "ac97-hifi", | 28 | .codec_dai_name = "ac97-hifi", |
29 | .codec_name = "ac97-codec", | 29 | .codec_name = "ac97-codec", |
30 | .platform_name = "ep93xx-pcm-audio", | 30 | .platform_name = "ep93xx-ac97", |
31 | }; | 31 | }; |
32 | 32 | ||
33 | static struct snd_soc_card snd_soc_simone = { | 33 | static struct snd_soc_card snd_soc_simone = { |
diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c index 69041074f2c1..29238a7476dd 100644 --- a/sound/soc/cirrus/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c | |||
@@ -83,7 +83,7 @@ static struct snd_soc_dai_link snappercl15_dai = { | |||
83 | .cpu_dai_name = "ep93xx-i2s", | 83 | .cpu_dai_name = "ep93xx-i2s", |
84 | .codec_dai_name = "tlv320aic23-hifi", | 84 | .codec_dai_name = "tlv320aic23-hifi", |
85 | .codec_name = "tlv320aic23-codec.0-001a", | 85 | .codec_name = "tlv320aic23-codec.0-001a", |
86 | .platform_name = "ep93xx-pcm-audio", | 86 | .platform_name = "ep93xx-i2s", |
87 | .init = snappercl15_tlv320aic23_init, | 87 | .init = snappercl15_tlv320aic23_init, |
88 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | | 88 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | |
89 | SND_SOC_DAIFMT_CBS_CFS, | 89 | SND_SOC_DAIFMT_CBS_CFS, |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index b33b45dfceec..983d087aa92a 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -163,8 +163,10 @@ config SND_SOC_WM_HUBS | |||
163 | config SND_SOC_WM_ADSP | 163 | config SND_SOC_WM_ADSP |
164 | tristate | 164 | tristate |
165 | default y if SND_SOC_WM5102=y | 165 | default y if SND_SOC_WM5102=y |
166 | default y if SND_SOC_WM5110=y | ||
166 | default y if SND_SOC_WM2200=y | 167 | default y if SND_SOC_WM2200=y |
167 | default m if SND_SOC_WM5102=m | 168 | default m if SND_SOC_WM5102=m |
169 | default m if SND_SOC_WM5110=m | ||
168 | default m if SND_SOC_WM2200=m | 170 | default m if SND_SOC_WM2200=m |
169 | 171 | ||
170 | config SND_SOC_AB8500_CODEC | 172 | config SND_SOC_AB8500_CODEC |
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 9a92b7962f41..d7c983862cf0 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -179,6 +179,8 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
179 | case SNDRV_PCM_FORMAT_S32_LE: | 179 | case SNDRV_PCM_FORMAT_S32_LE: |
180 | word_len = AD1836_WORD_LEN_24; | 180 | word_len = AD1836_WORD_LEN_24; |
181 | break; | 181 | break; |
182 | default: | ||
183 | return -EINVAL; | ||
182 | } | 184 | } |
183 | 185 | ||
184 | regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1, | 186 | regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1, |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index aea7e52cf714..12c27eb363dd 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -413,7 +413,7 @@ static struct spi_driver ad193x_spi_driver = { | |||
413 | }; | 413 | }; |
414 | #endif | 414 | #endif |
415 | 415 | ||
416 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 416 | #if IS_ENABLED(CONFIG_I2C) |
417 | 417 | ||
418 | static const struct regmap_config ad193x_i2c_regmap_config = { | 418 | static const struct regmap_config ad193x_i2c_regmap_config = { |
419 | .val_bits = 8, | 419 | .val_bits = 8, |
@@ -470,7 +470,7 @@ static int __init ad193x_modinit(void) | |||
470 | { | 470 | { |
471 | int ret; | 471 | int ret; |
472 | 472 | ||
473 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 473 | #if IS_ENABLED(CONFIG_I2C) |
474 | ret = i2c_add_driver(&ad193x_i2c_driver); | 474 | ret = i2c_add_driver(&ad193x_i2c_driver); |
475 | if (ret != 0) { | 475 | if (ret != 0) { |
476 | printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n", | 476 | printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n", |
@@ -495,7 +495,7 @@ static void __exit ad193x_modexit(void) | |||
495 | spi_unregister_driver(&ad193x_spi_driver); | 495 | spi_unregister_driver(&ad193x_spi_driver); |
496 | #endif | 496 | #endif |
497 | 497 | ||
498 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 498 | #if IS_ENABLED(CONFIG_I2C) |
499 | i2c_del_driver(&ad193x_i2c_driver); | 499 | i2c_del_driver(&ad193x_i2c_driver); |
500 | #endif | 500 | #endif |
501 | } | 501 | } |
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index 14a7c169d004..f7bf45552749 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
@@ -939,7 +939,7 @@ static struct spi_driver adav80x_spi_driver = { | |||
939 | }; | 939 | }; |
940 | #endif | 940 | #endif |
941 | 941 | ||
942 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 942 | #if IS_ENABLED(CONFIG_I2C) |
943 | static const struct regmap_config adav80x_i2c_regmap_config = { | 943 | static const struct regmap_config adav80x_i2c_regmap_config = { |
944 | .val_bits = 8, | 944 | .val_bits = 8, |
945 | .pad_bits = 1, | 945 | .pad_bits = 1, |
@@ -985,7 +985,7 @@ static int __init adav80x_init(void) | |||
985 | { | 985 | { |
986 | int ret = 0; | 986 | int ret = 0; |
987 | 987 | ||
988 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 988 | #if IS_ENABLED(CONFIG_I2C) |
989 | ret = i2c_add_driver(&adav80x_i2c_driver); | 989 | ret = i2c_add_driver(&adav80x_i2c_driver); |
990 | if (ret) | 990 | if (ret) |
991 | return ret; | 991 | return ret; |
@@ -1001,7 +1001,7 @@ module_init(adav80x_init); | |||
1001 | 1001 | ||
1002 | static void __exit adav80x_exit(void) | 1002 | static void __exit adav80x_exit(void) |
1003 | { | 1003 | { |
1004 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1004 | #if IS_ENABLED(CONFIG_I2C) |
1005 | i2c_del_driver(&adav80x_i2c_driver); | 1005 | i2c_del_driver(&adav80x_i2c_driver); |
1006 | #endif | 1006 | #endif |
1007 | #if defined(CONFIG_SPI_MASTER) | 1007 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 49cc5f6d6dba..94cbe508dd37 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/regmap.h> | ||
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
@@ -30,6 +31,7 @@ | |||
30 | 31 | ||
31 | /* codec private data */ | 32 | /* codec private data */ |
32 | struct ak4641_priv { | 33 | struct ak4641_priv { |
34 | struct regmap *regmap; | ||
33 | unsigned int sysclk; | 35 | unsigned int sysclk; |
34 | int deemph; | 36 | int deemph; |
35 | int playback_fs; | 37 | int playback_fs; |
@@ -38,12 +40,12 @@ struct ak4641_priv { | |||
38 | /* | 40 | /* |
39 | * ak4641 register cache | 41 | * ak4641 register cache |
40 | */ | 42 | */ |
41 | static const u8 ak4641_reg[AK4641_CACHEREGNUM] = { | 43 | static const struct reg_default ak4641_reg_defaults[] = { |
42 | 0x00, 0x80, 0x00, 0x80, | 44 | { 0, 0x00 }, { 1, 0x80 }, { 2, 0x00 }, { 3, 0x80 }, |
43 | 0x02, 0x00, 0x11, 0x05, | 45 | { 4, 0x02 }, { 5, 0x00 }, { 6, 0x11 }, { 7, 0x05 }, |
44 | 0x00, 0x00, 0x36, 0x10, | 46 | { 8, 0x00 }, { 9, 0x00 }, { 10, 0x36 }, { 11, 0x10 }, |
45 | 0x00, 0x00, 0x57, 0x00, | 47 | { 12, 0x00 }, { 13, 0x00 }, { 14, 0x57 }, { 15, 0x00 }, |
46 | 0x88, 0x88, 0x08, 0x08 | 48 | { 16, 0x88 }, { 17, 0x88 }, { 18, 0x08 }, { 19, 0x08 } |
47 | }; | 49 | }; |
48 | 50 | ||
49 | static const int deemph_settings[] = {44100, 0, 48000, 32000}; | 51 | static const int deemph_settings[] = {44100, 0, 48000, 32000}; |
@@ -396,6 +398,7 @@ static int ak4641_mute(struct snd_soc_dai *dai, int mute) | |||
396 | static int ak4641_set_bias_level(struct snd_soc_codec *codec, | 398 | static int ak4641_set_bias_level(struct snd_soc_codec *codec, |
397 | enum snd_soc_bias_level level) | 399 | enum snd_soc_bias_level level) |
398 | { | 400 | { |
401 | struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); | ||
399 | struct ak4641_platform_data *pdata = codec->dev->platform_data; | 402 | struct ak4641_platform_data *pdata = codec->dev->platform_data; |
400 | int ret; | 403 | int ret; |
401 | 404 | ||
@@ -417,7 +420,7 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec, | |||
417 | gpio_set_value(pdata->gpio_npdn, 1); | 420 | gpio_set_value(pdata->gpio_npdn, 1); |
418 | mdelay(1); | 421 | mdelay(1); |
419 | 422 | ||
420 | ret = snd_soc_cache_sync(codec); | 423 | ret = regcache_sync(ak4641->regmap); |
421 | if (ret) { | 424 | if (ret) { |
422 | dev_err(codec->dev, | 425 | dev_err(codec->dev, |
423 | "Failed to sync cache: %d\n", ret); | 426 | "Failed to sync cache: %d\n", ret); |
@@ -433,7 +436,7 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec, | |||
433 | gpio_set_value(pdata->gpio_npdn, 0); | 436 | gpio_set_value(pdata->gpio_npdn, 0); |
434 | if (pdata && gpio_is_valid(pdata->gpio_power)) | 437 | if (pdata && gpio_is_valid(pdata->gpio_power)) |
435 | gpio_set_value(pdata->gpio_power, 0); | 438 | gpio_set_value(pdata->gpio_power, 0); |
436 | codec->cache_sync = 1; | 439 | regcache_mark_dirty(ak4641->regmap); |
437 | break; | 440 | break; |
438 | } | 441 | } |
439 | codec->dapm.bias_level = level; | 442 | codec->dapm.bias_level = level; |
@@ -518,7 +521,7 @@ static int ak4641_probe(struct snd_soc_codec *codec) | |||
518 | { | 521 | { |
519 | int ret; | 522 | int ret; |
520 | 523 | ||
521 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | 524 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); |
522 | if (ret != 0) { | 525 | if (ret != 0) { |
523 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 526 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
524 | return ret; | 527 | return ret; |
@@ -550,12 +553,17 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { | |||
550 | .dapm_routes = ak4641_audio_map, | 553 | .dapm_routes = ak4641_audio_map, |
551 | .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), | 554 | .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), |
552 | .set_bias_level = ak4641_set_bias_level, | 555 | .set_bias_level = ak4641_set_bias_level, |
553 | .reg_cache_size = ARRAY_SIZE(ak4641_reg), | ||
554 | .reg_word_size = sizeof(u8), | ||
555 | .reg_cache_default = ak4641_reg, | ||
556 | .reg_cache_step = 1, | ||
557 | }; | 556 | }; |
558 | 557 | ||
558 | static const struct regmap_config ak4641_regmap = { | ||
559 | .reg_bits = 8, | ||
560 | .val_bits = 8, | ||
561 | |||
562 | .max_register = AK4641_BTIF, | ||
563 | .reg_defaults = ak4641_reg_defaults, | ||
564 | .num_reg_defaults = ARRAY_SIZE(ak4641_reg_defaults), | ||
565 | .cache_type = REGCACHE_RBTREE, | ||
566 | }; | ||
559 | 567 | ||
560 | static int ak4641_i2c_probe(struct i2c_client *i2c, | 568 | static int ak4641_i2c_probe(struct i2c_client *i2c, |
561 | const struct i2c_device_id *id) | 569 | const struct i2c_device_id *id) |
@@ -569,6 +577,10 @@ static int ak4641_i2c_probe(struct i2c_client *i2c, | |||
569 | if (!ak4641) | 577 | if (!ak4641) |
570 | return -ENOMEM; | 578 | return -ENOMEM; |
571 | 579 | ||
580 | ak4641->regmap = devm_regmap_init_i2c(i2c, &ak4641_regmap); | ||
581 | if (IS_ERR(ak4641->regmap)) | ||
582 | return PTR_ERR(ak4641->regmap); | ||
583 | |||
572 | if (pdata) { | 584 | if (pdata) { |
573 | if (gpio_is_valid(pdata->gpio_power)) { | 585 | if (gpio_is_valid(pdata->gpio_power)) { |
574 | ret = gpio_request_one(pdata->gpio_power, | 586 | ret = gpio_request_one(pdata->gpio_power, |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 090d499bb7eb..1f646c6e90c6 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/of_device.h> | 29 | #include <linux/of_device.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/regmap.h> | ||
31 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
32 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
33 | #include <sound/tlv.h> | 34 | #include <sound/tlv.h> |
@@ -198,30 +199,30 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = { | |||
198 | /* | 199 | /* |
199 | * ak4642 register cache | 200 | * ak4642 register cache |
200 | */ | 201 | */ |
201 | static const u8 ak4642_reg[] = { | 202 | static const struct reg_default ak4642_reg[] = { |
202 | 0x00, 0x00, 0x01, 0x00, | 203 | { 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 }, |
203 | 0x02, 0x00, 0x00, 0x00, | 204 | { 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 }, |
204 | 0xe1, 0xe1, 0x18, 0x00, | 205 | { 8, 0xe1 }, { 9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 }, |
205 | 0xe1, 0x18, 0x11, 0x08, | 206 | { 12, 0xe1 }, { 13, 0x18 }, { 14, 0x11 }, { 15, 0x08 }, |
206 | 0x00, 0x00, 0x00, 0x00, | 207 | { 16, 0x00 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x00 }, |
207 | 0x00, 0x00, 0x00, 0x00, | 208 | { 20, 0x00 }, { 21, 0x00 }, { 22, 0x00 }, { 23, 0x00 }, |
208 | 0x00, 0x00, 0x00, 0x00, | 209 | { 24, 0x00 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0x00 }, |
209 | 0x00, 0x00, 0x00, 0x00, | 210 | { 28, 0x00 }, { 29, 0x00 }, { 30, 0x00 }, { 31, 0x00 }, |
210 | 0x00, 0x00, 0x00, 0x00, | 211 | { 32, 0x00 }, { 33, 0x00 }, { 34, 0x00 }, { 35, 0x00 }, |
211 | 0x00, | 212 | { 36, 0x00 }, |
212 | }; | 213 | }; |
213 | 214 | ||
214 | static const u8 ak4648_reg[] = { | 215 | static const struct reg_default ak4648_reg[] = { |
215 | 0x00, 0x00, 0x01, 0x00, | 216 | { 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 }, |
216 | 0x02, 0x00, 0x00, 0x00, | 217 | { 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 }, |
217 | 0xe1, 0xe1, 0x18, 0x00, | 218 | { 8, 0xe1 }, { 9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 }, |
218 | 0xe1, 0x18, 0x11, 0xb8, | 219 | { 12, 0xe1 }, { 13, 0x18 }, { 14, 0x11 }, { 15, 0xb8 }, |
219 | 0x00, 0x00, 0x00, 0x00, | 220 | { 16, 0x00 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x00 }, |
220 | 0x00, 0x00, 0x00, 0x00, | 221 | { 20, 0x00 }, { 21, 0x00 }, { 22, 0x00 }, { 23, 0x00 }, |
221 | 0x00, 0x00, 0x00, 0x00, | 222 | { 24, 0x00 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0x00 }, |
222 | 0x00, 0x00, 0x00, 0x00, | 223 | { 28, 0x00 }, { 29, 0x00 }, { 30, 0x00 }, { 31, 0x00 }, |
223 | 0x00, 0x00, 0x00, 0x00, | 224 | { 32, 0x00 }, { 33, 0x00 }, { 34, 0x00 }, { 35, 0x00 }, |
224 | 0x00, 0x88, 0x88, 0x08, | 225 | { 36, 0x00 }, { 37, 0x88 }, { 38, 0x88 }, { 39, 0x08 }, |
225 | }; | 226 | }; |
226 | 227 | ||
227 | static int ak4642_dai_startup(struct snd_pcm_substream *substream, | 228 | static int ak4642_dai_startup(struct snd_pcm_substream *substream, |
@@ -454,7 +455,10 @@ static struct snd_soc_dai_driver ak4642_dai = { | |||
454 | 455 | ||
455 | static int ak4642_resume(struct snd_soc_codec *codec) | 456 | static int ak4642_resume(struct snd_soc_codec *codec) |
456 | { | 457 | { |
457 | snd_soc_cache_sync(codec); | 458 | struct regmap *regmap = dev_get_regmap(codec->dev, NULL); |
459 | |||
460 | regcache_mark_dirty(regmap); | ||
461 | regcache_sync(regmap); | ||
458 | return 0; | 462 | return 0; |
459 | } | 463 | } |
460 | 464 | ||
@@ -463,15 +467,12 @@ static int ak4642_probe(struct snd_soc_codec *codec) | |||
463 | { | 467 | { |
464 | int ret; | 468 | int ret; |
465 | 469 | ||
466 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | 470 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); |
467 | if (ret < 0) { | 471 | if (ret < 0) { |
468 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 472 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
469 | return ret; | 473 | return ret; |
470 | } | 474 | } |
471 | 475 | ||
472 | snd_soc_add_codec_controls(codec, ak4642_snd_controls, | ||
473 | ARRAY_SIZE(ak4642_snd_controls)); | ||
474 | |||
475 | ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 476 | ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
476 | 477 | ||
477 | return 0; | 478 | return 0; |
@@ -488,55 +489,59 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { | |||
488 | .remove = ak4642_remove, | 489 | .remove = ak4642_remove, |
489 | .resume = ak4642_resume, | 490 | .resume = ak4642_resume, |
490 | .set_bias_level = ak4642_set_bias_level, | 491 | .set_bias_level = ak4642_set_bias_level, |
491 | .reg_cache_default = ak4642_reg, /* ak4642 reg */ | 492 | .controls = ak4642_snd_controls, |
492 | .reg_cache_size = ARRAY_SIZE(ak4642_reg), /* ak4642 reg */ | 493 | .num_controls = ARRAY_SIZE(ak4642_snd_controls), |
493 | .reg_word_size = sizeof(u8), | ||
494 | .dapm_widgets = ak4642_dapm_widgets, | 494 | .dapm_widgets = ak4642_dapm_widgets, |
495 | .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), | 495 | .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), |
496 | .dapm_routes = ak4642_intercon, | 496 | .dapm_routes = ak4642_intercon, |
497 | .num_dapm_routes = ARRAY_SIZE(ak4642_intercon), | 497 | .num_dapm_routes = ARRAY_SIZE(ak4642_intercon), |
498 | }; | 498 | }; |
499 | 499 | ||
500 | static struct snd_soc_codec_driver soc_codec_dev_ak4648 = { | 500 | static const struct regmap_config ak4642_regmap = { |
501 | .probe = ak4642_probe, | 501 | .reg_bits = 8, |
502 | .remove = ak4642_remove, | 502 | .val_bits = 8, |
503 | .resume = ak4642_resume, | 503 | .max_register = ARRAY_SIZE(ak4642_reg) + 1, |
504 | .set_bias_level = ak4642_set_bias_level, | 504 | .reg_defaults = ak4642_reg, |
505 | .reg_cache_default = ak4648_reg, /* ak4648 reg */ | 505 | .num_reg_defaults = ARRAY_SIZE(ak4642_reg), |
506 | .reg_cache_size = ARRAY_SIZE(ak4648_reg), /* ak4648 reg */ | 506 | }; |
507 | .reg_word_size = sizeof(u8), | 507 | |
508 | .dapm_widgets = ak4642_dapm_widgets, | 508 | static const struct regmap_config ak4648_regmap = { |
509 | .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), | 509 | .reg_bits = 8, |
510 | .dapm_routes = ak4642_intercon, | 510 | .val_bits = 8, |
511 | .num_dapm_routes = ARRAY_SIZE(ak4642_intercon), | 511 | .max_register = ARRAY_SIZE(ak4648_reg) + 1, |
512 | .reg_defaults = ak4648_reg, | ||
513 | .num_reg_defaults = ARRAY_SIZE(ak4648_reg), | ||
512 | }; | 514 | }; |
513 | 515 | ||
514 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
515 | static struct of_device_id ak4642_of_match[]; | 516 | static struct of_device_id ak4642_of_match[]; |
516 | static int ak4642_i2c_probe(struct i2c_client *i2c, | 517 | static int ak4642_i2c_probe(struct i2c_client *i2c, |
517 | const struct i2c_device_id *id) | 518 | const struct i2c_device_id *id) |
518 | { | 519 | { |
519 | struct device_node *np = i2c->dev.of_node; | 520 | struct device_node *np = i2c->dev.of_node; |
520 | const struct snd_soc_codec_driver *driver; | 521 | const struct regmap_config *regmap_config = NULL; |
522 | struct regmap *regmap; | ||
521 | 523 | ||
522 | driver = NULL; | ||
523 | if (np) { | 524 | if (np) { |
524 | const struct of_device_id *of_id; | 525 | const struct of_device_id *of_id; |
525 | 526 | ||
526 | of_id = of_match_device(ak4642_of_match, &i2c->dev); | 527 | of_id = of_match_device(ak4642_of_match, &i2c->dev); |
527 | if (of_id) | 528 | if (of_id) |
528 | driver = of_id->data; | 529 | regmap_config = of_id->data; |
529 | } else { | 530 | } else { |
530 | driver = (struct snd_soc_codec_driver *)id->driver_data; | 531 | regmap_config = (const struct regmap_config *)id->driver_data; |
531 | } | 532 | } |
532 | 533 | ||
533 | if (!driver) { | 534 | if (!regmap_config) { |
534 | dev_err(&i2c->dev, "no driver\n"); | 535 | dev_err(&i2c->dev, "Unknown device type\n"); |
535 | return -EINVAL; | 536 | return -EINVAL; |
536 | } | 537 | } |
537 | 538 | ||
539 | regmap = devm_regmap_init_i2c(i2c, regmap_config); | ||
540 | if (IS_ERR(regmap)) | ||
541 | return PTR_ERR(regmap); | ||
542 | |||
538 | return snd_soc_register_codec(&i2c->dev, | 543 | return snd_soc_register_codec(&i2c->dev, |
539 | driver, &ak4642_dai, 1); | 544 | &soc_codec_dev_ak4642, &ak4642_dai, 1); |
540 | } | 545 | } |
541 | 546 | ||
542 | static int ak4642_i2c_remove(struct i2c_client *client) | 547 | static int ak4642_i2c_remove(struct i2c_client *client) |
@@ -546,17 +551,17 @@ static int ak4642_i2c_remove(struct i2c_client *client) | |||
546 | } | 551 | } |
547 | 552 | ||
548 | static struct of_device_id ak4642_of_match[] = { | 553 | static struct of_device_id ak4642_of_match[] = { |
549 | { .compatible = "asahi-kasei,ak4642", .data = &soc_codec_dev_ak4642}, | 554 | { .compatible = "asahi-kasei,ak4642", .data = &ak4642_regmap}, |
550 | { .compatible = "asahi-kasei,ak4643", .data = &soc_codec_dev_ak4642}, | 555 | { .compatible = "asahi-kasei,ak4643", .data = &ak4642_regmap}, |
551 | { .compatible = "asahi-kasei,ak4648", .data = &soc_codec_dev_ak4648}, | 556 | { .compatible = "asahi-kasei,ak4648", .data = &ak4648_regmap}, |
552 | {}, | 557 | {}, |
553 | }; | 558 | }; |
554 | MODULE_DEVICE_TABLE(of, ak4642_of_match); | 559 | MODULE_DEVICE_TABLE(of, ak4642_of_match); |
555 | 560 | ||
556 | static const struct i2c_device_id ak4642_i2c_id[] = { | 561 | static const struct i2c_device_id ak4642_i2c_id[] = { |
557 | { "ak4642", (kernel_ulong_t)&soc_codec_dev_ak4642 }, | 562 | { "ak4642", (kernel_ulong_t)&ak4642_regmap }, |
558 | { "ak4643", (kernel_ulong_t)&soc_codec_dev_ak4642 }, | 563 | { "ak4643", (kernel_ulong_t)&ak4642_regmap }, |
559 | { "ak4648", (kernel_ulong_t)&soc_codec_dev_ak4648 }, | 564 | { "ak4648", (kernel_ulong_t)&ak4648_regmap }, |
560 | { } | 565 | { } |
561 | }; | 566 | }; |
562 | MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); | 567 | MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); |
@@ -571,27 +576,8 @@ static struct i2c_driver ak4642_i2c_driver = { | |||
571 | .remove = ak4642_i2c_remove, | 576 | .remove = ak4642_i2c_remove, |
572 | .id_table = ak4642_i2c_id, | 577 | .id_table = ak4642_i2c_id, |
573 | }; | 578 | }; |
574 | #endif | ||
575 | |||
576 | static int __init ak4642_modinit(void) | ||
577 | { | ||
578 | int ret = 0; | ||
579 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
580 | ret = i2c_add_driver(&ak4642_i2c_driver); | ||
581 | #endif | ||
582 | return ret; | ||
583 | 579 | ||
584 | } | 580 | module_i2c_driver(ak4642_i2c_driver); |
585 | module_init(ak4642_modinit); | ||
586 | |||
587 | static void __exit ak4642_exit(void) | ||
588 | { | ||
589 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
590 | i2c_del_driver(&ak4642_i2c_driver); | ||
591 | #endif | ||
592 | |||
593 | } | ||
594 | module_exit(ak4642_exit); | ||
595 | 581 | ||
596 | MODULE_DESCRIPTION("Soc AK4642 driver"); | 582 | MODULE_DESCRIPTION("Soc AK4642 driver"); |
597 | MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>"); | 583 | MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>"); |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index fea991031be1..e4295fee8f13 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -93,7 +93,7 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w, | |||
93 | switch (event) { | 93 | switch (event) { |
94 | case SND_SOC_DAPM_PRE_PMU: | 94 | case SND_SOC_DAPM_PRE_PMU: |
95 | if (!priv->spk_ena && manual_ena) { | 95 | if (!priv->spk_ena && manual_ena) { |
96 | snd_soc_write(codec, 0x4f5, 0x25a); | 96 | regmap_write_async(arizona->regmap, 0x4f5, 0x25a); |
97 | priv->spk_ena_pending = true; | 97 | priv->spk_ena_pending = true; |
98 | } | 98 | } |
99 | break; | 99 | break; |
@@ -105,12 +105,13 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w, | |||
105 | return -EBUSY; | 105 | return -EBUSY; |
106 | } | 106 | } |
107 | 107 | ||
108 | snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1, | 108 | regmap_update_bits_async(arizona->regmap, |
109 | 1 << w->shift, 1 << w->shift); | 109 | ARIZONA_OUTPUT_ENABLES_1, |
110 | 1 << w->shift, 1 << w->shift); | ||
110 | 111 | ||
111 | if (priv->spk_ena_pending) { | 112 | if (priv->spk_ena_pending) { |
112 | msleep(75); | 113 | msleep(75); |
113 | snd_soc_write(codec, 0x4f5, 0xda); | 114 | regmap_write_async(arizona->regmap, 0x4f5, 0xda); |
114 | priv->spk_ena_pending = false; | 115 | priv->spk_ena_pending = false; |
115 | priv->spk_ena++; | 116 | priv->spk_ena++; |
116 | } | 117 | } |
@@ -119,16 +120,19 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w, | |||
119 | if (manual_ena) { | 120 | if (manual_ena) { |
120 | priv->spk_ena--; | 121 | priv->spk_ena--; |
121 | if (!priv->spk_ena) | 122 | if (!priv->spk_ena) |
122 | snd_soc_write(codec, 0x4f5, 0x25a); | 123 | regmap_write_async(arizona->regmap, |
124 | 0x4f5, 0x25a); | ||
123 | } | 125 | } |
124 | 126 | ||
125 | snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1, | 127 | regmap_update_bits_async(arizona->regmap, |
126 | 1 << w->shift, 0); | 128 | ARIZONA_OUTPUT_ENABLES_1, |
129 | 1 << w->shift, 0); | ||
127 | break; | 130 | break; |
128 | case SND_SOC_DAPM_POST_PMD: | 131 | case SND_SOC_DAPM_POST_PMD: |
129 | if (manual_ena) { | 132 | if (manual_ena) { |
130 | if (!priv->spk_ena) | 133 | if (!priv->spk_ena) |
131 | snd_soc_write(codec, 0x4f5, 0x0da); | 134 | regmap_write_async(arizona->regmap, |
135 | 0x4f5, 0x0da); | ||
132 | } | 136 | } |
133 | break; | 137 | break; |
134 | } | 138 | } |
@@ -292,6 +296,10 @@ const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { | |||
292 | "AIF1RX8", | 296 | "AIF1RX8", |
293 | "AIF2RX1", | 297 | "AIF2RX1", |
294 | "AIF2RX2", | 298 | "AIF2RX2", |
299 | "AIF2RX3", | ||
300 | "AIF2RX4", | ||
301 | "AIF2RX5", | ||
302 | "AIF2RX6", | ||
295 | "AIF3RX1", | 303 | "AIF3RX1", |
296 | "AIF3RX2", | 304 | "AIF3RX2", |
297 | "SLIMRX1", | 305 | "SLIMRX1", |
@@ -395,6 +403,10 @@ int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = { | |||
395 | 0x27, | 403 | 0x27, |
396 | 0x28, /* AIF2RX1 */ | 404 | 0x28, /* AIF2RX1 */ |
397 | 0x29, | 405 | 0x29, |
406 | 0x2a, | ||
407 | 0x2b, | ||
408 | 0x2c, | ||
409 | 0x2d, | ||
398 | 0x30, /* AIF3RX1 */ | 410 | 0x30, /* AIF3RX1 */ |
399 | 0x31, | 411 | 0x31, |
400 | 0x38, /* SLIMRX1 */ | 412 | 0x38, /* SLIMRX1 */ |
@@ -486,6 +498,22 @@ const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = { | |||
486 | EXPORT_SYMBOL_GPL(arizona_rate_val); | 498 | EXPORT_SYMBOL_GPL(arizona_rate_val); |
487 | 499 | ||
488 | 500 | ||
501 | const struct soc_enum arizona_isrc_fsh[] = { | ||
502 | SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_1, | ||
503 | ARIZONA_ISRC1_FSH_SHIFT, 0xf, | ||
504 | ARIZONA_RATE_ENUM_SIZE, | ||
505 | arizona_rate_text, arizona_rate_val), | ||
506 | SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_1, | ||
507 | ARIZONA_ISRC2_FSH_SHIFT, 0xf, | ||
508 | ARIZONA_RATE_ENUM_SIZE, | ||
509 | arizona_rate_text, arizona_rate_val), | ||
510 | SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_1, | ||
511 | ARIZONA_ISRC3_FSH_SHIFT, 0xf, | ||
512 | ARIZONA_RATE_ENUM_SIZE, | ||
513 | arizona_rate_text, arizona_rate_val), | ||
514 | }; | ||
515 | EXPORT_SYMBOL_GPL(arizona_isrc_fsh); | ||
516 | |||
489 | const struct soc_enum arizona_isrc_fsl[] = { | 517 | const struct soc_enum arizona_isrc_fsl[] = { |
490 | SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_2, | 518 | SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_2, |
491 | ARIZONA_ISRC1_FSL_SHIFT, 0xf, | 519 | ARIZONA_ISRC1_FSL_SHIFT, 0xf, |
@@ -502,6 +530,13 @@ const struct soc_enum arizona_isrc_fsl[] = { | |||
502 | }; | 530 | }; |
503 | EXPORT_SYMBOL_GPL(arizona_isrc_fsl); | 531 | EXPORT_SYMBOL_GPL(arizona_isrc_fsl); |
504 | 532 | ||
533 | const struct soc_enum arizona_asrc_rate1 = | ||
534 | SOC_VALUE_ENUM_SINGLE(ARIZONA_ASRC_RATE1, | ||
535 | ARIZONA_ASRC_RATE1_SHIFT, 0xf, | ||
536 | ARIZONA_RATE_ENUM_SIZE - 1, | ||
537 | arizona_rate_text, arizona_rate_val); | ||
538 | EXPORT_SYMBOL_GPL(arizona_asrc_rate1); | ||
539 | |||
505 | static const char *arizona_vol_ramp_text[] = { | 540 | static const char *arizona_vol_ramp_text[] = { |
506 | "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", | 541 | "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", |
507 | "15ms/6dB", "30ms/6dB", | 542 | "15ms/6dB", "30ms/6dB", |
@@ -560,6 +595,16 @@ const struct soc_enum arizona_ng_hold = | |||
560 | 4, arizona_ng_hold_text); | 595 | 4, arizona_ng_hold_text); |
561 | EXPORT_SYMBOL_GPL(arizona_ng_hold); | 596 | EXPORT_SYMBOL_GPL(arizona_ng_hold); |
562 | 597 | ||
598 | static const char * const arizona_in_hpf_cut_text[] = { | ||
599 | "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz" | ||
600 | }; | ||
601 | |||
602 | const struct soc_enum arizona_in_hpf_cut_enum = | ||
603 | SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT, | ||
604 | ARRAY_SIZE(arizona_in_hpf_cut_text), | ||
605 | arizona_in_hpf_cut_text); | ||
606 | EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); | ||
607 | |||
563 | static const char * const arizona_in_dmic_osr_text[] = { | 608 | static const char * const arizona_in_dmic_osr_text[] = { |
564 | "1.536MHz", "3.072MHz", "6.144MHz", | 609 | "1.536MHz", "3.072MHz", "6.144MHz", |
565 | }; | 610 | }; |
@@ -669,6 +714,7 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w, | |||
669 | int event) | 714 | int event) |
670 | { | 715 | { |
671 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec); | 716 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec); |
717 | struct arizona *arizona = priv->arizona; | ||
672 | unsigned int mask = 1 << w->shift; | 718 | unsigned int mask = 1 << w->shift; |
673 | unsigned int val; | 719 | unsigned int val; |
674 | 720 | ||
@@ -691,7 +737,8 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w, | |||
691 | if (priv->arizona->hpdet_magic) | 737 | if (priv->arizona->hpdet_magic) |
692 | val = 0; | 738 | val = 0; |
693 | 739 | ||
694 | snd_soc_update_bits(w->codec, ARIZONA_OUTPUT_ENABLES_1, mask, val); | 740 | regmap_update_bits_async(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, |
741 | mask, val); | ||
695 | 742 | ||
696 | return arizona_out_ev(w, kcontrol, event); | 743 | return arizona_out_ev(w, kcontrol, event); |
697 | } | 744 | } |
@@ -846,6 +893,8 @@ EXPORT_SYMBOL_GPL(arizona_set_sysclk); | |||
846 | static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 893 | static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
847 | { | 894 | { |
848 | struct snd_soc_codec *codec = dai->codec; | 895 | struct snd_soc_codec *codec = dai->codec; |
896 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
897 | struct arizona *arizona = priv->arizona; | ||
849 | int lrclk, bclk, mode, base; | 898 | int lrclk, bclk, mode, base; |
850 | 899 | ||
851 | base = dai->driver->base; | 900 | base = dai->driver->base; |
@@ -902,17 +951,19 @@ static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
902 | return -EINVAL; | 951 | return -EINVAL; |
903 | } | 952 | } |
904 | 953 | ||
905 | snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, | 954 | regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_BCLK_CTRL, |
906 | ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR, | 955 | ARIZONA_AIF1_BCLK_INV | |
907 | bclk); | 956 | ARIZONA_AIF1_BCLK_MSTR, |
908 | snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL, | 957 | bclk); |
909 | ARIZONA_AIF1TX_LRCLK_INV | | 958 | regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_TX_PIN_CTRL, |
910 | ARIZONA_AIF1TX_LRCLK_MSTR, lrclk); | 959 | ARIZONA_AIF1TX_LRCLK_INV | |
911 | snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL, | 960 | ARIZONA_AIF1TX_LRCLK_MSTR, lrclk); |
912 | ARIZONA_AIF1RX_LRCLK_INV | | 961 | regmap_update_bits_async(arizona->regmap, |
913 | ARIZONA_AIF1RX_LRCLK_MSTR, lrclk); | 962 | base + ARIZONA_AIF_RX_PIN_CTRL, |
914 | snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT, | 963 | ARIZONA_AIF1RX_LRCLK_INV | |
915 | ARIZONA_AIF1_FMT_MASK, mode); | 964 | ARIZONA_AIF1RX_LRCLK_MSTR, lrclk); |
965 | regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FORMAT, | ||
966 | ARIZONA_AIF1_FMT_MASK, mode); | ||
916 | 967 | ||
917 | return 0; | 968 | return 0; |
918 | } | 969 | } |
@@ -1164,18 +1215,22 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
1164 | if (ret != 0) | 1215 | if (ret != 0) |
1165 | return ret; | 1216 | return ret; |
1166 | 1217 | ||
1167 | snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, | 1218 | regmap_update_bits_async(arizona->regmap, |
1168 | ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); | 1219 | base + ARIZONA_AIF_BCLK_CTRL, |
1169 | snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE, | 1220 | ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); |
1170 | ARIZONA_AIF1TX_BCPF_MASK, lrclk); | 1221 | regmap_update_bits_async(arizona->regmap, |
1171 | snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE, | 1222 | base + ARIZONA_AIF_TX_BCLK_RATE, |
1172 | ARIZONA_AIF1RX_BCPF_MASK, lrclk); | 1223 | ARIZONA_AIF1TX_BCPF_MASK, lrclk); |
1173 | snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1, | 1224 | regmap_update_bits_async(arizona->regmap, |
1174 | ARIZONA_AIF1TX_WL_MASK | | 1225 | base + ARIZONA_AIF_RX_BCLK_RATE, |
1175 | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); | 1226 | ARIZONA_AIF1RX_BCPF_MASK, lrclk); |
1176 | snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2, | 1227 | regmap_update_bits_async(arizona->regmap, |
1177 | ARIZONA_AIF1RX_WL_MASK | | 1228 | base + ARIZONA_AIF_FRAME_CTRL_1, |
1178 | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); | 1229 | ARIZONA_AIF1TX_WL_MASK | |
1230 | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); | ||
1231 | regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2, | ||
1232 | ARIZONA_AIF1RX_WL_MASK | | ||
1233 | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); | ||
1179 | 1234 | ||
1180 | return 0; | 1235 | return 0; |
1181 | } | 1236 | } |
@@ -1428,31 +1483,31 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, | |||
1428 | struct arizona_fll_cfg *cfg, int source, | 1483 | struct arizona_fll_cfg *cfg, int source, |
1429 | bool sync) | 1484 | bool sync) |
1430 | { | 1485 | { |
1431 | regmap_update_bits(arizona->regmap, base + 3, | 1486 | regmap_update_bits_async(arizona->regmap, base + 3, |
1432 | ARIZONA_FLL1_THETA_MASK, cfg->theta); | 1487 | ARIZONA_FLL1_THETA_MASK, cfg->theta); |
1433 | regmap_update_bits(arizona->regmap, base + 4, | 1488 | regmap_update_bits_async(arizona->regmap, base + 4, |
1434 | ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda); | 1489 | ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda); |
1435 | regmap_update_bits(arizona->regmap, base + 5, | 1490 | regmap_update_bits_async(arizona->regmap, base + 5, |
1436 | ARIZONA_FLL1_FRATIO_MASK, | 1491 | ARIZONA_FLL1_FRATIO_MASK, |
1437 | cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT); | 1492 | cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT); |
1438 | regmap_update_bits(arizona->regmap, base + 6, | 1493 | regmap_update_bits_async(arizona->regmap, base + 6, |
1439 | ARIZONA_FLL1_CLK_REF_DIV_MASK | | 1494 | ARIZONA_FLL1_CLK_REF_DIV_MASK | |
1440 | ARIZONA_FLL1_CLK_REF_SRC_MASK, | 1495 | ARIZONA_FLL1_CLK_REF_SRC_MASK, |
1441 | cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | | 1496 | cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | |
1442 | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); | 1497 | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); |
1443 | 1498 | ||
1444 | if (sync) | 1499 | if (sync) |
1445 | regmap_update_bits(arizona->regmap, base + 0x7, | 1500 | regmap_update_bits_async(arizona->regmap, base + 0x7, |
1446 | ARIZONA_FLL1_GAIN_MASK, | 1501 | ARIZONA_FLL1_GAIN_MASK, |
1447 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); | 1502 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); |
1448 | else | 1503 | else |
1449 | regmap_update_bits(arizona->regmap, base + 0x9, | 1504 | regmap_update_bits_async(arizona->regmap, base + 0x9, |
1450 | ARIZONA_FLL1_GAIN_MASK, | 1505 | ARIZONA_FLL1_GAIN_MASK, |
1451 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); | 1506 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); |
1452 | 1507 | ||
1453 | regmap_update_bits(arizona->regmap, base + 2, | 1508 | regmap_update_bits_async(arizona->regmap, base + 2, |
1454 | ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, | 1509 | ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, |
1455 | ARIZONA_FLL1_CTRL_UPD | cfg->n); | 1510 | ARIZONA_FLL1_CTRL_UPD | cfg->n); |
1456 | } | 1511 | } |
1457 | 1512 | ||
1458 | static bool arizona_is_enabled_fll(struct arizona_fll *fll) | 1513 | static bool arizona_is_enabled_fll(struct arizona_fll *fll) |
@@ -1485,9 +1540,9 @@ static void arizona_enable_fll(struct arizona_fll *fll, | |||
1485 | */ | 1540 | */ |
1486 | if (fll->ref_src >= 0 && fll->ref_freq && | 1541 | if (fll->ref_src >= 0 && fll->ref_freq && |
1487 | fll->ref_src != fll->sync_src) { | 1542 | fll->ref_src != fll->sync_src) { |
1488 | regmap_update_bits(arizona->regmap, fll->base + 5, | 1543 | regmap_update_bits_async(arizona->regmap, fll->base + 5, |
1489 | ARIZONA_FLL1_OUTDIV_MASK, | 1544 | ARIZONA_FLL1_OUTDIV_MASK, |
1490 | ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); | 1545 | ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); |
1491 | 1546 | ||
1492 | arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, | 1547 | arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, |
1493 | false); | 1548 | false); |
@@ -1497,15 +1552,15 @@ static void arizona_enable_fll(struct arizona_fll *fll, | |||
1497 | use_sync = true; | 1552 | use_sync = true; |
1498 | } | 1553 | } |
1499 | } else if (fll->sync_src >= 0) { | 1554 | } else if (fll->sync_src >= 0) { |
1500 | regmap_update_bits(arizona->regmap, fll->base + 5, | 1555 | regmap_update_bits_async(arizona->regmap, fll->base + 5, |
1501 | ARIZONA_FLL1_OUTDIV_MASK, | 1556 | ARIZONA_FLL1_OUTDIV_MASK, |
1502 | sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); | 1557 | sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); |
1503 | 1558 | ||
1504 | arizona_apply_fll(arizona, fll->base, sync, | 1559 | arizona_apply_fll(arizona, fll->base, sync, |
1505 | fll->sync_src, false); | 1560 | fll->sync_src, false); |
1506 | 1561 | ||
1507 | regmap_update_bits(arizona->regmap, fll->base + 0x11, | 1562 | regmap_update_bits_async(arizona->regmap, fll->base + 0x11, |
1508 | ARIZONA_FLL1_SYNC_ENA, 0); | 1563 | ARIZONA_FLL1_SYNC_ENA, 0); |
1509 | } else { | 1564 | } else { |
1510 | arizona_fll_err(fll, "No clocks provided\n"); | 1565 | arizona_fll_err(fll, "No clocks provided\n"); |
1511 | return; | 1566 | return; |
@@ -1516,11 +1571,12 @@ static void arizona_enable_fll(struct arizona_fll *fll, | |||
1516 | * sync source. | 1571 | * sync source. |
1517 | */ | 1572 | */ |
1518 | if (use_sync && fll->sync_freq > 100000) | 1573 | if (use_sync && fll->sync_freq > 100000) |
1519 | regmap_update_bits(arizona->regmap, fll->base + 0x17, | 1574 | regmap_update_bits_async(arizona->regmap, fll->base + 0x17, |
1520 | ARIZONA_FLL1_SYNC_BW, 0); | 1575 | ARIZONA_FLL1_SYNC_BW, 0); |
1521 | else | 1576 | else |
1522 | regmap_update_bits(arizona->regmap, fll->base + 0x17, | 1577 | regmap_update_bits_async(arizona->regmap, fll->base + 0x17, |
1523 | ARIZONA_FLL1_SYNC_BW, ARIZONA_FLL1_SYNC_BW); | 1578 | ARIZONA_FLL1_SYNC_BW, |
1579 | ARIZONA_FLL1_SYNC_BW); | ||
1524 | 1580 | ||
1525 | if (!arizona_is_enabled_fll(fll)) | 1581 | if (!arizona_is_enabled_fll(fll)) |
1526 | pm_runtime_get(arizona->dev); | 1582 | pm_runtime_get(arizona->dev); |
@@ -1528,14 +1584,14 @@ static void arizona_enable_fll(struct arizona_fll *fll, | |||
1528 | /* Clear any pending completions */ | 1584 | /* Clear any pending completions */ |
1529 | try_wait_for_completion(&fll->ok); | 1585 | try_wait_for_completion(&fll->ok); |
1530 | 1586 | ||
1531 | regmap_update_bits(arizona->regmap, fll->base + 1, | 1587 | regmap_update_bits_async(arizona->regmap, fll->base + 1, |
1532 | ARIZONA_FLL1_FREERUN, 0); | 1588 | ARIZONA_FLL1_FREERUN, 0); |
1533 | regmap_update_bits(arizona->regmap, fll->base + 1, | 1589 | regmap_update_bits_async(arizona->regmap, fll->base + 1, |
1534 | ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); | 1590 | ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); |
1535 | if (use_sync) | 1591 | if (use_sync) |
1536 | regmap_update_bits(arizona->regmap, fll->base + 0x11, | 1592 | regmap_update_bits_async(arizona->regmap, fll->base + 0x11, |
1537 | ARIZONA_FLL1_SYNC_ENA, | 1593 | ARIZONA_FLL1_SYNC_ENA, |
1538 | ARIZONA_FLL1_SYNC_ENA); | 1594 | ARIZONA_FLL1_SYNC_ENA); |
1539 | 1595 | ||
1540 | ret = wait_for_completion_timeout(&fll->ok, | 1596 | ret = wait_for_completion_timeout(&fll->ok, |
1541 | msecs_to_jiffies(250)); | 1597 | msecs_to_jiffies(250)); |
@@ -1548,8 +1604,8 @@ static void arizona_disable_fll(struct arizona_fll *fll) | |||
1548 | struct arizona *arizona = fll->arizona; | 1604 | struct arizona *arizona = fll->arizona; |
1549 | bool change; | 1605 | bool change; |
1550 | 1606 | ||
1551 | regmap_update_bits(arizona->regmap, fll->base + 1, | 1607 | regmap_update_bits_async(arizona->regmap, fll->base + 1, |
1552 | ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN); | 1608 | ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN); |
1553 | regmap_update_bits_check(arizona->regmap, fll->base + 1, | 1609 | regmap_update_bits_check(arizona->regmap, fll->base + 1, |
1554 | ARIZONA_FLL1_ENA, 0, &change); | 1610 | ARIZONA_FLL1_ENA, 0, &change); |
1555 | regmap_update_bits(arizona->regmap, fll->base + 0x11, | 1611 | regmap_update_bits(arizona->regmap, fll->base + 0x11, |
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 9e81b6392692..10b398477203 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -81,7 +81,7 @@ struct arizona_priv { | |||
81 | unsigned int spk_ena_pending:1; | 81 | unsigned int spk_ena_pending:1; |
82 | }; | 82 | }; |
83 | 83 | ||
84 | #define ARIZONA_NUM_MIXER_INPUTS 99 | 84 | #define ARIZONA_NUM_MIXER_INPUTS 103 |
85 | 85 | ||
86 | extern const unsigned int arizona_mixer_tlv[]; | 86 | extern const unsigned int arizona_mixer_tlv[]; |
87 | extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; | 87 | extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; |
@@ -186,6 +186,8 @@ extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; | |||
186 | extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE]; | 186 | extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE]; |
187 | 187 | ||
188 | extern const struct soc_enum arizona_isrc_fsl[]; | 188 | extern const struct soc_enum arizona_isrc_fsl[]; |
189 | extern const struct soc_enum arizona_isrc_fsh[]; | ||
190 | extern const struct soc_enum arizona_asrc_rate1; | ||
189 | 191 | ||
190 | extern const struct soc_enum arizona_in_vi_ramp; | 192 | extern const struct soc_enum arizona_in_vi_ramp; |
191 | extern const struct soc_enum arizona_in_vd_ramp; | 193 | extern const struct soc_enum arizona_in_vd_ramp; |
@@ -199,6 +201,7 @@ extern const struct soc_enum arizona_lhpf3_mode; | |||
199 | extern const struct soc_enum arizona_lhpf4_mode; | 201 | extern const struct soc_enum arizona_lhpf4_mode; |
200 | 202 | ||
201 | extern const struct soc_enum arizona_ng_hold; | 203 | extern const struct soc_enum arizona_ng_hold; |
204 | extern const struct soc_enum arizona_in_hpf_cut_enum; | ||
202 | extern const struct soc_enum arizona_in_dmic_osr[]; | 205 | extern const struct soc_enum arizona_in_dmic_osr[]; |
203 | 206 | ||
204 | extern int arizona_in_ev(struct snd_soc_dapm_widget *w, | 207 | extern int arizona_in_ev(struct snd_soc_dapm_widget *w, |
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index f6e953454bc0..ce05fd93dc74 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
@@ -675,7 +675,7 @@ static struct spi_driver cs4271_spi_driver = { | |||
675 | }; | 675 | }; |
676 | #endif /* defined(CONFIG_SPI_MASTER) */ | 676 | #endif /* defined(CONFIG_SPI_MASTER) */ |
677 | 677 | ||
678 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 678 | #if IS_ENABLED(CONFIG_I2C) |
679 | static const struct i2c_device_id cs4271_i2c_id[] = { | 679 | static const struct i2c_device_id cs4271_i2c_id[] = { |
680 | {"cs4271", 0}, | 680 | {"cs4271", 0}, |
681 | {} | 681 | {} |
@@ -728,7 +728,7 @@ static struct i2c_driver cs4271_i2c_driver = { | |||
728 | .probe = cs4271_i2c_probe, | 728 | .probe = cs4271_i2c_probe, |
729 | .remove = cs4271_i2c_remove, | 729 | .remove = cs4271_i2c_remove, |
730 | }; | 730 | }; |
731 | #endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */ | 731 | #endif /* IS_ENABLED(CONFIG_I2C) */ |
732 | 732 | ||
733 | /* | 733 | /* |
734 | * We only register our serial bus driver here without | 734 | * We only register our serial bus driver here without |
@@ -741,7 +741,7 @@ static int __init cs4271_modinit(void) | |||
741 | { | 741 | { |
742 | int ret; | 742 | int ret; |
743 | 743 | ||
744 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 744 | #if IS_ENABLED(CONFIG_I2C) |
745 | ret = i2c_add_driver(&cs4271_i2c_driver); | 745 | ret = i2c_add_driver(&cs4271_i2c_driver); |
746 | if (ret) { | 746 | if (ret) { |
747 | pr_err("Failed to register CS4271 I2C driver: %d\n", ret); | 747 | pr_err("Failed to register CS4271 I2C driver: %d\n", ret); |
@@ -767,7 +767,7 @@ static void __exit cs4271_modexit(void) | |||
767 | spi_unregister_driver(&cs4271_spi_driver); | 767 | spi_unregister_driver(&cs4271_spi_driver); |
768 | #endif | 768 | #endif |
769 | 769 | ||
770 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 770 | #if IS_ENABLED(CONFIG_I2C) |
771 | i2c_del_driver(&cs4271_i2c_driver); | 771 | i2c_del_driver(&cs4271_i2c_driver); |
772 | #endif | 772 | #endif |
773 | } | 773 | } |
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 8b427c977083..0bac6d5a4ac8 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/gpio.h> | 20 | #include <linux/of_gpio.h> |
21 | #include <linux/pm.h> | 21 | #include <linux/pm.h> |
22 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
23 | #include <linux/input.h> | 23 | #include <linux/input.h> |
@@ -50,7 +50,7 @@ struct cs42l52_private { | |||
50 | u8 mclksel; | 50 | u8 mclksel; |
51 | u32 mclk; | 51 | u32 mclk; |
52 | u8 flags; | 52 | u8 flags; |
53 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 53 | #if IS_ENABLED(CONFIG_INPUT) |
54 | struct input_dev *beep; | 54 | struct input_dev *beep; |
55 | struct work_struct beep_work; | 55 | struct work_struct beep_work; |
56 | int beep_rate; | 56 | int beep_rate; |
@@ -233,7 +233,7 @@ static const struct soc_enum mic_bias_level_enum = | |||
233 | SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0, | 233 | SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0, |
234 | ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text); | 234 | ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text); |
235 | 235 | ||
236 | static const char * const cs42l52_mic_text[] = { "Single", "Differential" }; | 236 | static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" }; |
237 | 237 | ||
238 | static const struct soc_enum mica_enum = | 238 | static const struct soc_enum mica_enum = |
239 | SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5, | 239 | SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5, |
@@ -243,12 +243,6 @@ static const struct soc_enum micb_enum = | |||
243 | SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5, | 243 | SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5, |
244 | ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); | 244 | ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); |
245 | 245 | ||
246 | static const struct snd_kcontrol_new mica_mux = | ||
247 | SOC_DAPM_ENUM("Left Mic Input Capture Mux", mica_enum); | ||
248 | |||
249 | static const struct snd_kcontrol_new micb_mux = | ||
250 | SOC_DAPM_ENUM("Right Mic Input Capture Mux", micb_enum); | ||
251 | |||
252 | static const char * const digital_output_mux_text[] = {"ADC", "DSP"}; | 246 | static const char * const digital_output_mux_text[] = {"ADC", "DSP"}; |
253 | 247 | ||
254 | static const struct soc_enum digital_output_mux_enum = | 248 | static const struct soc_enum digital_output_mux_enum = |
@@ -531,6 +525,30 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = { | |||
531 | 525 | ||
532 | }; | 526 | }; |
533 | 527 | ||
528 | static const struct snd_kcontrol_new cs42l52_mica_controls[] = { | ||
529 | SOC_ENUM("MICA Select", mica_enum), | ||
530 | }; | ||
531 | |||
532 | static const struct snd_kcontrol_new cs42l52_micb_controls[] = { | ||
533 | SOC_ENUM("MICB Select", micb_enum), | ||
534 | }; | ||
535 | |||
536 | static int cs42l52_add_mic_controls(struct snd_soc_codec *codec) | ||
537 | { | ||
538 | struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec); | ||
539 | struct cs42l52_platform_data *pdata = &cs42l52->pdata; | ||
540 | |||
541 | if (!pdata->mica_diff_cfg) | ||
542 | snd_soc_add_codec_controls(codec, cs42l52_mica_controls, | ||
543 | ARRAY_SIZE(cs42l52_mica_controls)); | ||
544 | |||
545 | if (!pdata->micb_diff_cfg) | ||
546 | snd_soc_add_codec_controls(codec, cs42l52_micb_controls, | ||
547 | ARRAY_SIZE(cs42l52_micb_controls)); | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
534 | static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = { | 552 | static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = { |
535 | 553 | ||
536 | SND_SOC_DAPM_INPUT("AIN1L"), | 554 | SND_SOC_DAPM_INPUT("AIN1L"), |
@@ -550,9 +568,6 @@ static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = { | |||
550 | SND_SOC_DAPM_AIF_OUT("AIFOUTR", NULL, 0, | 568 | SND_SOC_DAPM_AIF_OUT("AIFOUTR", NULL, 0, |
551 | SND_SOC_NOPM, 0, 0), | 569 | SND_SOC_NOPM, 0, 0), |
552 | 570 | ||
553 | SND_SOC_DAPM_MUX("MICA Mux", SND_SOC_NOPM, 0, 0, &mica_mux), | ||
554 | SND_SOC_DAPM_MUX("MICB Mux", SND_SOC_NOPM, 0, 0, &micb_mux), | ||
555 | |||
556 | SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L52_PWRCTL1, 1, 1), | 571 | SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L52_PWRCTL1, 1, 1), |
557 | SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L52_PWRCTL1, 2, 1), | 572 | SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L52_PWRCTL1, 2, 1), |
558 | SND_SOC_DAPM_PGA("PGA Left", CS42L52_PWRCTL1, 3, 1, NULL, 0), | 573 | SND_SOC_DAPM_PGA("PGA Left", CS42L52_PWRCTL1, 3, 1, NULL, 0), |
@@ -953,7 +968,7 @@ static int cs42l52_resume(struct snd_soc_codec *codec) | |||
953 | return 0; | 968 | return 0; |
954 | } | 969 | } |
955 | 970 | ||
956 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 971 | #if IS_ENABLED(CONFIG_INPUT) |
957 | static int beep_rates[] = { | 972 | static int beep_rates[] = { |
958 | 261, 522, 585, 667, 706, 774, 889, 1000, | 973 | 261, 522, 585, 667, 706, 774, 889, 1000, |
959 | 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182 | 974 | 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182 |
@@ -1110,6 +1125,8 @@ static int cs42l52_probe(struct snd_soc_codec *codec) | |||
1110 | } | 1125 | } |
1111 | regcache_cache_only(cs42l52->regmap, true); | 1126 | regcache_cache_only(cs42l52->regmap, true); |
1112 | 1127 | ||
1128 | cs42l52_add_mic_controls(codec); | ||
1129 | |||
1113 | cs42l52_init_beep(codec); | 1130 | cs42l52_init_beep(codec); |
1114 | 1131 | ||
1115 | cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1132 | cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -1176,6 +1193,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, | |||
1176 | int ret; | 1193 | int ret; |
1177 | unsigned int devid = 0; | 1194 | unsigned int devid = 0; |
1178 | unsigned int reg; | 1195 | unsigned int reg; |
1196 | u32 val32; | ||
1179 | 1197 | ||
1180 | cs42l52 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l52_private), | 1198 | cs42l52 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l52_private), |
1181 | GFP_KERNEL); | 1199 | GFP_KERNEL); |
@@ -1189,9 +1207,39 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, | |||
1189 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); | 1207 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); |
1190 | return ret; | 1208 | return ret; |
1191 | } | 1209 | } |
1192 | 1210 | if (pdata) { | |
1193 | if (pdata) | 1211 | cs42l52->pdata = *pdata; |
1212 | } else { | ||
1213 | pdata = devm_kzalloc(&i2c_client->dev, | ||
1214 | sizeof(struct cs42l52_platform_data), | ||
1215 | GFP_KERNEL); | ||
1216 | if (!pdata) { | ||
1217 | dev_err(&i2c_client->dev, "could not allocate pdata\n"); | ||
1218 | return -ENOMEM; | ||
1219 | } | ||
1220 | if (i2c_client->dev.of_node) { | ||
1221 | if (of_property_read_bool(i2c_client->dev.of_node, | ||
1222 | "cirrus,mica-differential-cfg")) | ||
1223 | pdata->mica_diff_cfg = true; | ||
1224 | |||
1225 | if (of_property_read_bool(i2c_client->dev.of_node, | ||
1226 | "cirrus,micb-differential-cfg")) | ||
1227 | pdata->micb_diff_cfg = true; | ||
1228 | |||
1229 | if (of_property_read_u32(i2c_client->dev.of_node, | ||
1230 | "cirrus,micbias-lvl", &val32) >= 0) | ||
1231 | pdata->micbias_lvl = val32; | ||
1232 | |||
1233 | if (of_property_read_u32(i2c_client->dev.of_node, | ||
1234 | "cirrus,chgfreq-divisor", &val32) >= 0) | ||
1235 | pdata->chgfreq = val32; | ||
1236 | |||
1237 | pdata->reset_gpio = | ||
1238 | of_get_named_gpio(i2c_client->dev.of_node, | ||
1239 | "cirrus,reset-gpio", 0); | ||
1240 | } | ||
1194 | cs42l52->pdata = *pdata; | 1241 | cs42l52->pdata = *pdata; |
1242 | } | ||
1195 | 1243 | ||
1196 | if (cs42l52->pdata.reset_gpio) { | 1244 | if (cs42l52->pdata.reset_gpio) { |
1197 | ret = gpio_request_one(cs42l52->pdata.reset_gpio, | 1245 | ret = gpio_request_one(cs42l52->pdata.reset_gpio, |
@@ -1227,29 +1275,18 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, | |||
1227 | reg & 0xFF); | 1275 | reg & 0xFF); |
1228 | 1276 | ||
1229 | /* Set Platform Data */ | 1277 | /* Set Platform Data */ |
1230 | if (cs42l52->pdata.mica_cfg) | 1278 | if (cs42l52->pdata.mica_diff_cfg) |
1231 | regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL, | 1279 | regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL, |
1232 | CS42L52_MIC_CTL_TYPE_MASK, | 1280 | CS42L52_MIC_CTL_TYPE_MASK, |
1233 | cs42l52->pdata.mica_cfg << | 1281 | cs42l52->pdata.mica_diff_cfg << |
1234 | CS42L52_MIC_CTL_TYPE_SHIFT); | 1282 | CS42L52_MIC_CTL_TYPE_SHIFT); |
1235 | 1283 | ||
1236 | if (cs42l52->pdata.micb_cfg) | 1284 | if (cs42l52->pdata.micb_diff_cfg) |
1237 | regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL, | 1285 | regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL, |
1238 | CS42L52_MIC_CTL_TYPE_MASK, | 1286 | CS42L52_MIC_CTL_TYPE_MASK, |
1239 | cs42l52->pdata.micb_cfg << | 1287 | cs42l52->pdata.micb_diff_cfg << |
1240 | CS42L52_MIC_CTL_TYPE_SHIFT); | 1288 | CS42L52_MIC_CTL_TYPE_SHIFT); |
1241 | 1289 | ||
1242 | if (cs42l52->pdata.mica_sel) | ||
1243 | regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL, | ||
1244 | CS42L52_MIC_CTL_MIC_SEL_MASK, | ||
1245 | cs42l52->pdata.mica_sel << | ||
1246 | CS42L52_MIC_CTL_MIC_SEL_SHIFT); | ||
1247 | if (cs42l52->pdata.micb_sel) | ||
1248 | regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL, | ||
1249 | CS42L52_MIC_CTL_MIC_SEL_MASK, | ||
1250 | cs42l52->pdata.micb_sel << | ||
1251 | CS42L52_MIC_CTL_MIC_SEL_SHIFT); | ||
1252 | |||
1253 | if (cs42l52->pdata.chgfreq) | 1290 | if (cs42l52->pdata.chgfreq) |
1254 | regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP, | 1291 | regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP, |
1255 | CS42L52_CHARGE_PUMP_MASK, | 1292 | CS42L52_CHARGE_PUMP_MASK, |
@@ -1274,6 +1311,13 @@ static int cs42l52_i2c_remove(struct i2c_client *client) | |||
1274 | return 0; | 1311 | return 0; |
1275 | } | 1312 | } |
1276 | 1313 | ||
1314 | static const struct of_device_id cs42l52_of_match[] = { | ||
1315 | { .compatible = "cirrus,cs42l52", }, | ||
1316 | {}, | ||
1317 | }; | ||
1318 | MODULE_DEVICE_TABLE(of, cs42l52_of_match); | ||
1319 | |||
1320 | |||
1277 | static const struct i2c_device_id cs42l52_id[] = { | 1321 | static const struct i2c_device_id cs42l52_id[] = { |
1278 | { "cs42l52", 0 }, | 1322 | { "cs42l52", 0 }, |
1279 | { } | 1323 | { } |
@@ -1284,6 +1328,7 @@ static struct i2c_driver cs42l52_i2c_driver = { | |||
1284 | .driver = { | 1328 | .driver = { |
1285 | .name = "cs42l52", | 1329 | .name = "cs42l52", |
1286 | .owner = THIS_MODULE, | 1330 | .owner = THIS_MODULE, |
1331 | .of_match_table = cs42l52_of_match, | ||
1287 | }, | 1332 | }, |
1288 | .id_table = cs42l52_id, | 1333 | .id_table = cs42l52_id, |
1289 | .probe = cs42l52_i2c_probe, | 1334 | .probe = cs42l52_i2c_probe, |
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 9c1231456502..8166dcb2e4a3 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c | |||
@@ -1188,7 +1188,7 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = { | |||
1188 | .num_dapm_routes = ARRAY_SIZE(da7210_audio_map), | 1188 | .num_dapm_routes = ARRAY_SIZE(da7210_audio_map), |
1189 | }; | 1189 | }; |
1190 | 1190 | ||
1191 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1191 | #if IS_ENABLED(CONFIG_I2C) |
1192 | 1192 | ||
1193 | static struct reg_default da7210_regmap_i2c_patch[] = { | 1193 | static struct reg_default da7210_regmap_i2c_patch[] = { |
1194 | 1194 | ||
@@ -1362,7 +1362,7 @@ static struct spi_driver da7210_spi_driver = { | |||
1362 | static int __init da7210_modinit(void) | 1362 | static int __init da7210_modinit(void) |
1363 | { | 1363 | { |
1364 | int ret = 0; | 1364 | int ret = 0; |
1365 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1365 | #if IS_ENABLED(CONFIG_I2C) |
1366 | ret = i2c_add_driver(&da7210_i2c_driver); | 1366 | ret = i2c_add_driver(&da7210_i2c_driver); |
1367 | #endif | 1367 | #endif |
1368 | #if defined(CONFIG_SPI_MASTER) | 1368 | #if defined(CONFIG_SPI_MASTER) |
@@ -1378,7 +1378,7 @@ module_init(da7210_modinit); | |||
1378 | 1378 | ||
1379 | static void __exit da7210_exit(void) | 1379 | static void __exit da7210_exit(void) |
1380 | { | 1380 | { |
1381 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1381 | #if IS_ENABLED(CONFIG_I2C) |
1382 | i2c_del_driver(&da7210_i2c_driver); | 1382 | i2c_del_driver(&da7210_i2c_driver); |
1383 | #endif | 1383 | #endif |
1384 | #if defined(CONFIG_SPI_MASTER) | 1384 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 1f4093f3f3a1..0fcbe90f3ef2 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -115,6 +115,7 @@ struct sgtl5000_priv { | |||
115 | struct ldo_regulator *ldo; | 115 | struct ldo_regulator *ldo; |
116 | struct regmap *regmap; | 116 | struct regmap *regmap; |
117 | struct clk *mclk; | 117 | struct clk *mclk; |
118 | int revision; | ||
118 | }; | 119 | }; |
119 | 120 | ||
120 | /* | 121 | /* |
@@ -1285,41 +1286,45 @@ static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec) | |||
1285 | 1286 | ||
1286 | sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME; | 1287 | sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME; |
1287 | 1288 | ||
1288 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), | ||
1289 | sgtl5000->supplies); | ||
1290 | |||
1291 | if (ret) { | ||
1292 | ldo_regulator_remove(codec); | ||
1293 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
1294 | return ret; | ||
1295 | } | ||
1296 | |||
1297 | dev_info(codec->dev, "Using internal LDO instead of VDDD\n"); | 1289 | dev_info(codec->dev, "Using internal LDO instead of VDDD\n"); |
1298 | return 0; | 1290 | return 0; |
1299 | } | 1291 | } |
1300 | 1292 | ||
1301 | static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | 1293 | static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) |
1302 | { | 1294 | { |
1303 | int reg; | ||
1304 | int ret; | 1295 | int ret; |
1305 | int rev; | ||
1306 | int i; | 1296 | int i; |
1307 | int external_vddd = 0; | 1297 | int external_vddd = 0; |
1308 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | 1298 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); |
1299 | struct regulator *vddd; | ||
1309 | 1300 | ||
1310 | for (i = 0; i < ARRAY_SIZE(sgtl5000->supplies); i++) | 1301 | for (i = 0; i < ARRAY_SIZE(sgtl5000->supplies); i++) |
1311 | sgtl5000->supplies[i].supply = supply_names[i]; | 1302 | sgtl5000->supplies[i].supply = supply_names[i]; |
1312 | 1303 | ||
1313 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), | 1304 | /* External VDDD only works before revision 0x11 */ |
1314 | sgtl5000->supplies); | 1305 | if (sgtl5000->revision < 0x11) { |
1315 | if (!ret) | 1306 | vddd = regulator_get_optional(codec->dev, "VDDD"); |
1316 | external_vddd = 1; | 1307 | if (IS_ERR(vddd)) { |
1317 | else { | 1308 | /* See if it's just not registered yet */ |
1309 | if (PTR_ERR(vddd) == -EPROBE_DEFER) | ||
1310 | return -EPROBE_DEFER; | ||
1311 | } else { | ||
1312 | external_vddd = 1; | ||
1313 | regulator_put(vddd); | ||
1314 | } | ||
1315 | } | ||
1316 | |||
1317 | if (!external_vddd) { | ||
1318 | ret = sgtl5000_replace_vddd_with_ldo(codec); | 1318 | ret = sgtl5000_replace_vddd_with_ldo(codec); |
1319 | if (ret) | 1319 | if (ret) |
1320 | return ret; | 1320 | return ret; |
1321 | } | 1321 | } |
1322 | 1322 | ||
1323 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), | ||
1324 | sgtl5000->supplies); | ||
1325 | if (ret) | ||
1326 | goto err_ldo_remove; | ||
1327 | |||
1323 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), | 1328 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), |
1324 | sgtl5000->supplies); | 1329 | sgtl5000->supplies); |
1325 | if (ret) | 1330 | if (ret) |
@@ -1328,47 +1333,13 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | |||
1328 | /* wait for all power rails bring up */ | 1333 | /* wait for all power rails bring up */ |
1329 | udelay(10); | 1334 | udelay(10); |
1330 | 1335 | ||
1331 | /* | ||
1332 | * workaround for revision 0x11 and later, | ||
1333 | * roll back to use internal LDO | ||
1334 | */ | ||
1335 | |||
1336 | ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, ®); | ||
1337 | if (ret) | ||
1338 | goto err_regulator_disable; | ||
1339 | |||
1340 | rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; | ||
1341 | |||
1342 | if (external_vddd && rev >= 0x11) { | ||
1343 | /* disable all regulator first */ | ||
1344 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | ||
1345 | sgtl5000->supplies); | ||
1346 | /* free VDDD regulator */ | ||
1347 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | ||
1348 | sgtl5000->supplies); | ||
1349 | |||
1350 | ret = sgtl5000_replace_vddd_with_ldo(codec); | ||
1351 | if (ret) | ||
1352 | return ret; | ||
1353 | |||
1354 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), | ||
1355 | sgtl5000->supplies); | ||
1356 | if (ret) | ||
1357 | goto err_regulator_free; | ||
1358 | |||
1359 | /* wait for all power rails bring up */ | ||
1360 | udelay(10); | ||
1361 | } | ||
1362 | |||
1363 | return 0; | 1336 | return 0; |
1364 | 1337 | ||
1365 | err_regulator_disable: | ||
1366 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | ||
1367 | sgtl5000->supplies); | ||
1368 | err_regulator_free: | 1338 | err_regulator_free: |
1369 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | 1339 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), |
1370 | sgtl5000->supplies); | 1340 | sgtl5000->supplies); |
1371 | if (external_vddd) | 1341 | err_ldo_remove: |
1342 | if (!external_vddd) | ||
1372 | ldo_regulator_remove(codec); | 1343 | ldo_regulator_remove(codec); |
1373 | return ret; | 1344 | return ret; |
1374 | 1345 | ||
@@ -1566,6 +1537,7 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, | |||
1566 | 1537 | ||
1567 | rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; | 1538 | rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; |
1568 | dev_info(&client->dev, "sgtl5000 revision 0x%x\n", rev); | 1539 | dev_info(&client->dev, "sgtl5000 revision 0x%x\n", rev); |
1540 | sgtl5000->revision = rev; | ||
1569 | 1541 | ||
1570 | i2c_set_clientdata(client, sgtl5000); | 1542 | i2c_set_clientdata(client, sgtl5000); |
1571 | 1543 | ||
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index 95aed552139a..cc8debce752f 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c | |||
@@ -549,13 +549,13 @@ static int ssm2518_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
549 | right_slot = 0; | 549 | right_slot = 0; |
550 | } else { | 550 | } else { |
551 | /* We assume the left channel < right channel */ | 551 | /* We assume the left channel < right channel */ |
552 | left_slot = ffs(tx_mask); | 552 | left_slot = __ffs(tx_mask); |
553 | tx_mask &= ~(1 << tx_mask); | 553 | tx_mask &= ~(1 << left_slot); |
554 | if (tx_mask == 0) { | 554 | if (tx_mask == 0) { |
555 | right_slot = left_slot; | 555 | right_slot = left_slot; |
556 | } else { | 556 | } else { |
557 | right_slot = ffs(tx_mask); | 557 | right_slot = __ffs(tx_mask); |
558 | tx_mask &= ~(1 << tx_mask); | 558 | tx_mask &= ~(1 << right_slot); |
559 | } | 559 | } |
560 | } | 560 | } |
561 | 561 | ||
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 492644e67ace..c6dd48561884 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -53,8 +53,6 @@ enum ssm2602_type { | |||
53 | struct ssm2602_priv { | 53 | struct ssm2602_priv { |
54 | unsigned int sysclk; | 54 | unsigned int sysclk; |
55 | struct snd_pcm_hw_constraint_list *sysclk_constraints; | 55 | struct snd_pcm_hw_constraint_list *sysclk_constraints; |
56 | struct snd_pcm_substream *master_substream; | ||
57 | struct snd_pcm_substream *slave_substream; | ||
58 | 56 | ||
59 | struct regmap *regmap; | 57 | struct regmap *regmap; |
60 | 58 | ||
@@ -277,11 +275,6 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
277 | int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params)); | 275 | int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params)); |
278 | unsigned int iface; | 276 | unsigned int iface; |
279 | 277 | ||
280 | if (substream == ssm2602->slave_substream) { | ||
281 | dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n"); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | if (srate < 0) | 278 | if (srate < 0) |
286 | return srate; | 279 | return srate; |
287 | 280 | ||
@@ -314,33 +307,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
314 | { | 307 | { |
315 | struct snd_soc_codec *codec = dai->codec; | 308 | struct snd_soc_codec *codec = dai->codec; |
316 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 309 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
317 | struct snd_pcm_runtime *master_runtime; | ||
318 | |||
319 | /* The DAI has shared clocks so if we already have a playback or | ||
320 | * capture going then constrain this substream to match it. | ||
321 | * TODO: the ssm2602 allows pairs of non-matching PB/REC rates | ||
322 | */ | ||
323 | if (ssm2602->master_substream) { | ||
324 | master_runtime = ssm2602->master_substream->runtime; | ||
325 | dev_dbg(codec->dev, "Constraining to %d bits at %dHz\n", | ||
326 | master_runtime->sample_bits, | ||
327 | master_runtime->rate); | ||
328 | |||
329 | if (master_runtime->rate != 0) | ||
330 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
331 | SNDRV_PCM_HW_PARAM_RATE, | ||
332 | master_runtime->rate, | ||
333 | master_runtime->rate); | ||
334 | |||
335 | if (master_runtime->sample_bits != 0) | ||
336 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
337 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | ||
338 | master_runtime->sample_bits, | ||
339 | master_runtime->sample_bits); | ||
340 | |||
341 | ssm2602->slave_substream = substream; | ||
342 | } else | ||
343 | ssm2602->master_substream = substream; | ||
344 | 310 | ||
345 | if (ssm2602->sysclk_constraints) { | 311 | if (ssm2602->sysclk_constraints) { |
346 | snd_pcm_hw_constraint_list(substream->runtime, 0, | 312 | snd_pcm_hw_constraint_list(substream->runtime, 0, |
@@ -351,19 +317,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
351 | return 0; | 317 | return 0; |
352 | } | 318 | } |
353 | 319 | ||
354 | static void ssm2602_shutdown(struct snd_pcm_substream *substream, | ||
355 | struct snd_soc_dai *dai) | ||
356 | { | ||
357 | struct snd_soc_codec *codec = dai->codec; | ||
358 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | ||
359 | |||
360 | if (ssm2602->master_substream == substream) | ||
361 | ssm2602->master_substream = ssm2602->slave_substream; | ||
362 | |||
363 | ssm2602->slave_substream = NULL; | ||
364 | } | ||
365 | |||
366 | |||
367 | static int ssm2602_mute(struct snd_soc_dai *dai, int mute) | 320 | static int ssm2602_mute(struct snd_soc_dai *dai, int mute) |
368 | { | 321 | { |
369 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(dai->codec); | 322 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(dai->codec); |
@@ -530,7 +483,6 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | |||
530 | static const struct snd_soc_dai_ops ssm2602_dai_ops = { | 483 | static const struct snd_soc_dai_ops ssm2602_dai_ops = { |
531 | .startup = ssm2602_startup, | 484 | .startup = ssm2602_startup, |
532 | .hw_params = ssm2602_hw_params, | 485 | .hw_params = ssm2602_hw_params, |
533 | .shutdown = ssm2602_shutdown, | ||
534 | .digital_mute = ssm2602_mute, | 486 | .digital_mute = ssm2602_mute, |
535 | .set_sysclk = ssm2602_set_dai_sysclk, | 487 | .set_sysclk = ssm2602_set_dai_sysclk, |
536 | .set_fmt = ssm2602_set_dai_fmt, | 488 | .set_fmt = ssm2602_set_dai_fmt, |
@@ -551,6 +503,8 @@ static struct snd_soc_dai_driver ssm2602_dai = { | |||
551 | .rates = SSM2602_RATES, | 503 | .rates = SSM2602_RATES, |
552 | .formats = SSM2602_FORMATS,}, | 504 | .formats = SSM2602_FORMATS,}, |
553 | .ops = &ssm2602_dai_ops, | 505 | .ops = &ssm2602_dai_ops, |
506 | .symmetric_rates = 1, | ||
507 | .symmetric_samplebits = 1, | ||
554 | }; | 508 | }; |
555 | 509 | ||
556 | static int ssm2602_suspend(struct snd_soc_codec *codec) | 510 | static int ssm2602_suspend(struct snd_soc_codec *codec) |
@@ -730,7 +684,7 @@ static struct spi_driver ssm2602_spi_driver = { | |||
730 | }; | 684 | }; |
731 | #endif | 685 | #endif |
732 | 686 | ||
733 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 687 | #if IS_ENABLED(CONFIG_I2C) |
734 | /* | 688 | /* |
735 | * ssm2602 2 wire address is determined by GPIO5 | 689 | * ssm2602 2 wire address is determined by GPIO5 |
736 | * state during powerup. | 690 | * state during powerup. |
@@ -797,7 +751,7 @@ static int __init ssm2602_modinit(void) | |||
797 | return ret; | 751 | return ret; |
798 | #endif | 752 | #endif |
799 | 753 | ||
800 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 754 | #if IS_ENABLED(CONFIG_I2C) |
801 | ret = i2c_add_driver(&ssm2602_i2c_driver); | 755 | ret = i2c_add_driver(&ssm2602_i2c_driver); |
802 | if (ret) | 756 | if (ret) |
803 | return ret; | 757 | return ret; |
@@ -813,7 +767,7 @@ static void __exit ssm2602_exit(void) | |||
813 | spi_unregister_driver(&ssm2602_spi_driver); | 767 | spi_unregister_driver(&ssm2602_spi_driver); |
814 | #endif | 768 | #endif |
815 | 769 | ||
816 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 770 | #if IS_ENABLED(CONFIG_I2C) |
817 | i2c_del_driver(&ssm2602_i2c_driver); | 771 | i2c_del_driver(&ssm2602_i2c_driver); |
818 | #endif | 772 | #endif |
819 | } | 773 | } |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 546d16b7d38f..470fbfb4b386 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -350,16 +350,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
350 | DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL, | 350 | DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL, |
351 | 0, 118, 1, output_stage_tlv), | 351 | 0, 118, 1, output_stage_tlv), |
352 | 352 | ||
353 | SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume", | ||
354 | LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL, | ||
355 | 0, 118, 1, output_stage_tlv), | ||
356 | SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume", | ||
357 | PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL, | ||
358 | 0, 118, 1, output_stage_tlv), | ||
359 | SOC_DOUBLE_R_TLV("Mono DAC Playback Volume", | ||
360 | DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL, | ||
361 | 0, 118, 1, output_stage_tlv), | ||
362 | |||
363 | SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume", | 353 | SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume", |
364 | LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL, | 354 | LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL, |
365 | 0, 118, 1, output_stage_tlv), | 355 | 0, 118, 1, output_stage_tlv), |
@@ -383,7 +373,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
383 | /* Output pin mute controls */ | 373 | /* Output pin mute controls */ |
384 | SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3, | 374 | SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3, |
385 | 0x01, 0), | 375 | 0x01, 0), |
386 | SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), | ||
387 | SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, | 376 | SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, |
388 | 0x01, 0), | 377 | 0x01, 0), |
389 | SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, | 378 | SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, |
@@ -412,6 +401,20 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
412 | SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), | 401 | SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), |
413 | }; | 402 | }; |
414 | 403 | ||
404 | static const struct snd_kcontrol_new aic3x_mono_controls[] = { | ||
405 | SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume", | ||
406 | LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL, | ||
407 | 0, 118, 1, output_stage_tlv), | ||
408 | SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume", | ||
409 | PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL, | ||
410 | 0, 118, 1, output_stage_tlv), | ||
411 | SOC_DOUBLE_R_TLV("Mono DAC Playback Volume", | ||
412 | DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL, | ||
413 | 0, 118, 1, output_stage_tlv), | ||
414 | |||
415 | SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), | ||
416 | }; | ||
417 | |||
415 | /* | 418 | /* |
416 | * Class-D amplifier gain. From 0 to 18 dB in 6 dB steps | 419 | * Class-D amplifier gain. From 0 to 18 dB in 6 dB steps |
417 | */ | 420 | */ |
@@ -565,9 +568,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
565 | SND_SOC_DAPM_PGA("Right HP Out", HPROUT_CTRL, 0, 0, NULL, 0), | 568 | SND_SOC_DAPM_PGA("Right HP Out", HPROUT_CTRL, 0, 0, NULL, 0), |
566 | SND_SOC_DAPM_PGA("Right HP Com", HPRCOM_CTRL, 0, 0, NULL, 0), | 569 | SND_SOC_DAPM_PGA("Right HP Com", HPRCOM_CTRL, 0, 0, NULL, 0), |
567 | 570 | ||
568 | /* Mono Output */ | ||
569 | SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0), | ||
570 | |||
571 | /* Inputs to Left ADC */ | 571 | /* Inputs to Left ADC */ |
572 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0), | 572 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0), |
573 | SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0, | 573 | SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0, |
@@ -626,9 +626,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
626 | SND_SOC_DAPM_MIXER("Right Line Mixer", SND_SOC_NOPM, 0, 0, | 626 | SND_SOC_DAPM_MIXER("Right Line Mixer", SND_SOC_NOPM, 0, 0, |
627 | &aic3x_right_line_mixer_controls[0], | 627 | &aic3x_right_line_mixer_controls[0], |
628 | ARRAY_SIZE(aic3x_right_line_mixer_controls)), | 628 | ARRAY_SIZE(aic3x_right_line_mixer_controls)), |
629 | SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, | ||
630 | &aic3x_mono_mixer_controls[0], | ||
631 | ARRAY_SIZE(aic3x_mono_mixer_controls)), | ||
632 | SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0, | 629 | SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0, |
633 | &aic3x_left_hp_mixer_controls[0], | 630 | &aic3x_left_hp_mixer_controls[0], |
634 | ARRAY_SIZE(aic3x_left_hp_mixer_controls)), | 631 | ARRAY_SIZE(aic3x_left_hp_mixer_controls)), |
@@ -644,7 +641,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
644 | 641 | ||
645 | SND_SOC_DAPM_OUTPUT("LLOUT"), | 642 | SND_SOC_DAPM_OUTPUT("LLOUT"), |
646 | SND_SOC_DAPM_OUTPUT("RLOUT"), | 643 | SND_SOC_DAPM_OUTPUT("RLOUT"), |
647 | SND_SOC_DAPM_OUTPUT("MONO_LOUT"), | ||
648 | SND_SOC_DAPM_OUTPUT("HPLOUT"), | 644 | SND_SOC_DAPM_OUTPUT("HPLOUT"), |
649 | SND_SOC_DAPM_OUTPUT("HPROUT"), | 645 | SND_SOC_DAPM_OUTPUT("HPROUT"), |
650 | SND_SOC_DAPM_OUTPUT("HPLCOM"), | 646 | SND_SOC_DAPM_OUTPUT("HPLCOM"), |
@@ -666,6 +662,17 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
666 | SND_SOC_DAPM_OUTPUT("Detection"), | 662 | SND_SOC_DAPM_OUTPUT("Detection"), |
667 | }; | 663 | }; |
668 | 664 | ||
665 | static const struct snd_soc_dapm_widget aic3x_dapm_mono_widgets[] = { | ||
666 | /* Mono Output */ | ||
667 | SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0), | ||
668 | |||
669 | SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, | ||
670 | &aic3x_mono_mixer_controls[0], | ||
671 | ARRAY_SIZE(aic3x_mono_mixer_controls)), | ||
672 | |||
673 | SND_SOC_DAPM_OUTPUT("MONO_LOUT"), | ||
674 | }; | ||
675 | |||
669 | static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = { | 676 | static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = { |
670 | /* Class-D outputs */ | 677 | /* Class-D outputs */ |
671 | SND_SOC_DAPM_PGA("Left Class-D Out", CLASSD_CTRL, 3, 0, NULL, 0), | 678 | SND_SOC_DAPM_PGA("Left Class-D Out", CLASSD_CTRL, 3, 0, NULL, 0), |
@@ -754,17 +761,6 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
754 | {"Right Line Out", NULL, "Right DAC Mux"}, | 761 | {"Right Line Out", NULL, "Right DAC Mux"}, |
755 | {"RLOUT", NULL, "Right Line Out"}, | 762 | {"RLOUT", NULL, "Right Line Out"}, |
756 | 763 | ||
757 | /* Mono Output */ | ||
758 | {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
759 | {"Mono Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, | ||
760 | {"Mono Mixer", "DACL1 Switch", "Left DAC Mux"}, | ||
761 | {"Mono Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
762 | {"Mono Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, | ||
763 | {"Mono Mixer", "DACR1 Switch", "Right DAC Mux"}, | ||
764 | |||
765 | {"Mono Out", NULL, "Mono Mixer"}, | ||
766 | {"MONO_LOUT", NULL, "Mono Out"}, | ||
767 | |||
768 | /* Left HP Output */ | 764 | /* Left HP Output */ |
769 | {"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | 765 | {"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, |
770 | {"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, | 766 | {"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, |
@@ -820,6 +816,18 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
820 | {"HPRCOM", NULL, "Right HP Com"}, | 816 | {"HPRCOM", NULL, "Right HP Com"}, |
821 | }; | 817 | }; |
822 | 818 | ||
819 | static const struct snd_soc_dapm_route intercon_mono[] = { | ||
820 | /* Mono Output */ | ||
821 | {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
822 | {"Mono Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, | ||
823 | {"Mono Mixer", "DACL1 Switch", "Left DAC Mux"}, | ||
824 | {"Mono Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
825 | {"Mono Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, | ||
826 | {"Mono Mixer", "DACR1 Switch", "Right DAC Mux"}, | ||
827 | {"Mono Out", NULL, "Mono Mixer"}, | ||
828 | {"MONO_LOUT", NULL, "Mono Out"}, | ||
829 | }; | ||
830 | |||
823 | static const struct snd_soc_dapm_route intercon_3007[] = { | 831 | static const struct snd_soc_dapm_route intercon_3007[] = { |
824 | /* Class-D outputs */ | 832 | /* Class-D outputs */ |
825 | {"Left Class-D Out", NULL, "Left Line Out"}, | 833 | {"Left Class-D Out", NULL, "Left Line Out"}, |
@@ -833,11 +841,20 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec) | |||
833 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 841 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
834 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 842 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
835 | 843 | ||
836 | if (aic3x->model == AIC3X_MODEL_3007) { | 844 | switch (aic3x->model) { |
845 | case AIC3X_MODEL_3X: | ||
846 | case AIC3X_MODEL_33: | ||
847 | snd_soc_dapm_new_controls(dapm, aic3x_dapm_mono_widgets, | ||
848 | ARRAY_SIZE(aic3x_dapm_mono_widgets)); | ||
849 | snd_soc_dapm_add_routes(dapm, intercon_mono, | ||
850 | ARRAY_SIZE(intercon_mono)); | ||
851 | break; | ||
852 | case AIC3X_MODEL_3007: | ||
837 | snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets, | 853 | snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets, |
838 | ARRAY_SIZE(aic3007_dapm_widgets)); | 854 | ARRAY_SIZE(aic3007_dapm_widgets)); |
839 | snd_soc_dapm_add_routes(dapm, intercon_3007, | 855 | snd_soc_dapm_add_routes(dapm, intercon_3007, |
840 | ARRAY_SIZE(intercon_3007)); | 856 | ARRAY_SIZE(intercon_3007)); |
857 | break; | ||
841 | } | 858 | } |
842 | 859 | ||
843 | return 0; | 860 | return 0; |
@@ -1218,6 +1235,24 @@ static int aic3x_resume(struct snd_soc_codec *codec) | |||
1218 | return 0; | 1235 | return 0; |
1219 | } | 1236 | } |
1220 | 1237 | ||
1238 | static void aic3x_mono_init(struct snd_soc_codec *codec) | ||
1239 | { | ||
1240 | /* DAC to Mono Line Out default volume and route to Output mixer */ | ||
1241 | snd_soc_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON); | ||
1242 | snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON); | ||
1243 | |||
1244 | /* unmute all outputs */ | ||
1245 | snd_soc_update_bits(codec, MONOLOPM_CTRL, UNMUTE, UNMUTE); | ||
1246 | |||
1247 | /* PGA to Mono Line Out default volume, disconnect from Output Mixer */ | ||
1248 | snd_soc_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL); | ||
1249 | snd_soc_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL); | ||
1250 | |||
1251 | /* Line2 to Mono Out default volume, disconnect from Output Mixer */ | ||
1252 | snd_soc_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL); | ||
1253 | snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); | ||
1254 | } | ||
1255 | |||
1221 | /* | 1256 | /* |
1222 | * initialise the AIC3X driver | 1257 | * initialise the AIC3X driver |
1223 | * register the mixer and dsp interfaces with the kernel | 1258 | * register the mixer and dsp interfaces with the kernel |
@@ -1241,14 +1276,10 @@ static int aic3x_init(struct snd_soc_codec *codec) | |||
1241 | /* DAC to Line Out default volume and route to Output mixer */ | 1276 | /* DAC to Line Out default volume and route to Output mixer */ |
1242 | snd_soc_write(codec, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON); | 1277 | snd_soc_write(codec, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON); |
1243 | snd_soc_write(codec, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON); | 1278 | snd_soc_write(codec, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON); |
1244 | /* DAC to Mono Line Out default volume and route to Output mixer */ | ||
1245 | snd_soc_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON); | ||
1246 | snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON); | ||
1247 | 1279 | ||
1248 | /* unmute all outputs */ | 1280 | /* unmute all outputs */ |
1249 | snd_soc_update_bits(codec, LLOPM_CTRL, UNMUTE, UNMUTE); | 1281 | snd_soc_update_bits(codec, LLOPM_CTRL, UNMUTE, UNMUTE); |
1250 | snd_soc_update_bits(codec, RLOPM_CTRL, UNMUTE, UNMUTE); | 1282 | snd_soc_update_bits(codec, RLOPM_CTRL, UNMUTE, UNMUTE); |
1251 | snd_soc_update_bits(codec, MONOLOPM_CTRL, UNMUTE, UNMUTE); | ||
1252 | snd_soc_update_bits(codec, HPLOUT_CTRL, UNMUTE, UNMUTE); | 1283 | snd_soc_update_bits(codec, HPLOUT_CTRL, UNMUTE, UNMUTE); |
1253 | snd_soc_update_bits(codec, HPROUT_CTRL, UNMUTE, UNMUTE); | 1284 | snd_soc_update_bits(codec, HPROUT_CTRL, UNMUTE, UNMUTE); |
1254 | snd_soc_update_bits(codec, HPLCOM_CTRL, UNMUTE, UNMUTE); | 1285 | snd_soc_update_bits(codec, HPLCOM_CTRL, UNMUTE, UNMUTE); |
@@ -1269,9 +1300,6 @@ static int aic3x_init(struct snd_soc_codec *codec) | |||
1269 | /* PGA to Line Out default volume, disconnect from Output Mixer */ | 1300 | /* PGA to Line Out default volume, disconnect from Output Mixer */ |
1270 | snd_soc_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL); | 1301 | snd_soc_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL); |
1271 | snd_soc_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL); | 1302 | snd_soc_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL); |
1272 | /* PGA to Mono Line Out default volume, disconnect from Output Mixer */ | ||
1273 | snd_soc_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL); | ||
1274 | snd_soc_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL); | ||
1275 | 1303 | ||
1276 | /* Line2 to HP Bypass default volume, disconnect from Output Mixer */ | 1304 | /* Line2 to HP Bypass default volume, disconnect from Output Mixer */ |
1277 | snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL); | 1305 | snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL); |
@@ -1281,12 +1309,15 @@ static int aic3x_init(struct snd_soc_codec *codec) | |||
1281 | /* Line2 Line Out default volume, disconnect from Output Mixer */ | 1309 | /* Line2 Line Out default volume, disconnect from Output Mixer */ |
1282 | snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL); | 1310 | snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL); |
1283 | snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL); | 1311 | snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL); |
1284 | /* Line2 to Mono Out default volume, disconnect from Output Mixer */ | ||
1285 | snd_soc_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL); | ||
1286 | snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); | ||
1287 | 1312 | ||
1288 | if (aic3x->model == AIC3X_MODEL_3007) { | 1313 | switch (aic3x->model) { |
1314 | case AIC3X_MODEL_3X: | ||
1315 | case AIC3X_MODEL_33: | ||
1316 | aic3x_mono_init(codec); | ||
1317 | break; | ||
1318 | case AIC3X_MODEL_3007: | ||
1289 | snd_soc_write(codec, CLASSD_CTRL, 0); | 1319 | snd_soc_write(codec, CLASSD_CTRL, 0); |
1320 | break; | ||
1290 | } | 1321 | } |
1291 | 1322 | ||
1292 | return 0; | 1323 | return 0; |
@@ -1343,8 +1374,17 @@ static int aic3x_probe(struct snd_soc_codec *codec) | |||
1343 | (aic3x->setup->gpio_func[1] & 0xf) << 4); | 1374 | (aic3x->setup->gpio_func[1] & 0xf) << 4); |
1344 | } | 1375 | } |
1345 | 1376 | ||
1346 | if (aic3x->model == AIC3X_MODEL_3007) | 1377 | switch (aic3x->model) { |
1347 | snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); | 1378 | case AIC3X_MODEL_3X: |
1379 | case AIC3X_MODEL_33: | ||
1380 | snd_soc_add_codec_controls(codec, aic3x_mono_controls, | ||
1381 | ARRAY_SIZE(aic3x_mono_controls)); | ||
1382 | break; | ||
1383 | case AIC3X_MODEL_3007: | ||
1384 | snd_soc_add_codec_controls(codec, | ||
1385 | &aic3x_classd_amp_gain_ctrl, 1); | ||
1386 | break; | ||
1387 | } | ||
1348 | 1388 | ||
1349 | /* set mic bias voltage */ | 1389 | /* set mic bias voltage */ |
1350 | switch (aic3x->micbias_vg) { | 1390 | switch (aic3x->micbias_vg) { |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index f2f4bcb2ff71..0afe8bef6765 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -72,6 +72,7 @@ struct twl6040_data { | |||
72 | int hs_power_mode_locked; | 72 | int hs_power_mode_locked; |
73 | bool dl1_unmuted; | 73 | bool dl1_unmuted; |
74 | bool dl2_unmuted; | 74 | bool dl2_unmuted; |
75 | u8 dl12_cache[TWL6040_REG_HFRCTL - TWL6040_REG_HSLCTL + 1]; | ||
75 | unsigned int clk_in; | 76 | unsigned int clk_in; |
76 | unsigned int sysclk; | 77 | unsigned int sysclk; |
77 | struct twl6040_jack_data hs_jack; | 78 | struct twl6040_jack_data hs_jack; |
@@ -79,75 +80,6 @@ struct twl6040_data { | |||
79 | struct mutex mutex; | 80 | struct mutex mutex; |
80 | }; | 81 | }; |
81 | 82 | ||
82 | /* | ||
83 | * twl6040 register cache & default register settings | ||
84 | */ | ||
85 | static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = { | ||
86 | 0x00, /* not used 0x00 */ | ||
87 | 0x4B, /* REG_ASICID 0x01 (ro) */ | ||
88 | 0x00, /* REG_ASICREV 0x02 (ro) */ | ||
89 | 0x00, /* REG_INTID 0x03 */ | ||
90 | 0x00, /* REG_INTMR 0x04 */ | ||
91 | 0x00, /* REG_NCPCTRL 0x05 */ | ||
92 | 0x00, /* REG_LDOCTL 0x06 */ | ||
93 | 0x60, /* REG_HPPLLCTL 0x07 */ | ||
94 | 0x00, /* REG_LPPLLCTL 0x08 */ | ||
95 | 0x4A, /* REG_LPPLLDIV 0x09 */ | ||
96 | 0x00, /* REG_AMICBCTL 0x0A */ | ||
97 | 0x00, /* REG_DMICBCTL 0x0B */ | ||
98 | 0x00, /* REG_MICLCTL 0x0C */ | ||
99 | 0x00, /* REG_MICRCTL 0x0D */ | ||
100 | 0x00, /* REG_MICGAIN 0x0E */ | ||
101 | 0x1B, /* REG_LINEGAIN 0x0F */ | ||
102 | 0x00, /* REG_HSLCTL 0x10 */ | ||
103 | 0x00, /* REG_HSRCTL 0x11 */ | ||
104 | 0x00, /* REG_HSGAIN 0x12 */ | ||
105 | 0x00, /* REG_EARCTL 0x13 */ | ||
106 | 0x00, /* REG_HFLCTL 0x14 */ | ||
107 | 0x00, /* REG_HFLGAIN 0x15 */ | ||
108 | 0x00, /* REG_HFRCTL 0x16 */ | ||
109 | 0x00, /* REG_HFRGAIN 0x17 */ | ||
110 | 0x00, /* REG_VIBCTLL 0x18 */ | ||
111 | 0x00, /* REG_VIBDATL 0x19 */ | ||
112 | 0x00, /* REG_VIBCTLR 0x1A */ | ||
113 | 0x00, /* REG_VIBDATR 0x1B */ | ||
114 | 0x00, /* REG_HKCTL1 0x1C */ | ||
115 | 0x00, /* REG_HKCTL2 0x1D */ | ||
116 | 0x00, /* REG_GPOCTL 0x1E */ | ||
117 | 0x00, /* REG_ALB 0x1F */ | ||
118 | 0x00, /* REG_DLB 0x20 */ | ||
119 | 0x00, /* not used 0x21 */ | ||
120 | 0x00, /* not used 0x22 */ | ||
121 | 0x00, /* not used 0x23 */ | ||
122 | 0x00, /* not used 0x24 */ | ||
123 | 0x00, /* not used 0x25 */ | ||
124 | 0x00, /* not used 0x26 */ | ||
125 | 0x00, /* not used 0x27 */ | ||
126 | 0x00, /* REG_TRIM1 0x28 */ | ||
127 | 0x00, /* REG_TRIM2 0x29 */ | ||
128 | 0x00, /* REG_TRIM3 0x2A */ | ||
129 | 0x00, /* REG_HSOTRIM 0x2B */ | ||
130 | 0x00, /* REG_HFOTRIM 0x2C */ | ||
131 | 0x09, /* REG_ACCCTL 0x2D */ | ||
132 | 0x00, /* REG_STATUS 0x2E (ro) */ | ||
133 | }; | ||
134 | |||
135 | /* List of registers to be restored after power up */ | ||
136 | static const int twl6040_restore_list[] = { | ||
137 | TWL6040_REG_MICLCTL, | ||
138 | TWL6040_REG_MICRCTL, | ||
139 | TWL6040_REG_MICGAIN, | ||
140 | TWL6040_REG_LINEGAIN, | ||
141 | TWL6040_REG_HSLCTL, | ||
142 | TWL6040_REG_HSRCTL, | ||
143 | TWL6040_REG_HSGAIN, | ||
144 | TWL6040_REG_EARCTL, | ||
145 | TWL6040_REG_HFLCTL, | ||
146 | TWL6040_REG_HFLGAIN, | ||
147 | TWL6040_REG_HFRCTL, | ||
148 | TWL6040_REG_HFRGAIN, | ||
149 | }; | ||
150 | |||
151 | /* set of rates for each pll: low-power and high-performance */ | 83 | /* set of rates for each pll: low-power and high-performance */ |
152 | static unsigned int lp_rates[] = { | 84 | static unsigned int lp_rates[] = { |
153 | 8000, | 85 | 8000, |
@@ -174,53 +106,33 @@ static struct snd_pcm_hw_constraint_list sysclk_constraints[] = { | |||
174 | { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, }, | 106 | { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, }, |
175 | }; | 107 | }; |
176 | 108 | ||
177 | /* | 109 | static unsigned int twl6040_read(struct snd_soc_codec *codec, unsigned int reg) |
178 | * read twl6040 register cache | ||
179 | */ | ||
180 | static inline unsigned int twl6040_read_reg_cache(struct snd_soc_codec *codec, | ||
181 | unsigned int reg) | ||
182 | { | ||
183 | u8 *cache = codec->reg_cache; | ||
184 | |||
185 | if (reg >= TWL6040_CACHEREGNUM) | ||
186 | return -EIO; | ||
187 | |||
188 | return cache[reg]; | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * write twl6040 register cache | ||
193 | */ | ||
194 | static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec, | ||
195 | u8 reg, u8 value) | ||
196 | { | ||
197 | u8 *cache = codec->reg_cache; | ||
198 | |||
199 | if (reg >= TWL6040_CACHEREGNUM) | ||
200 | return; | ||
201 | cache[reg] = value; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * read from twl6040 hardware register | ||
206 | */ | ||
207 | static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, | ||
208 | unsigned int reg) | ||
209 | { | 110 | { |
111 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | ||
210 | struct twl6040 *twl6040 = codec->control_data; | 112 | struct twl6040 *twl6040 = codec->control_data; |
211 | u8 value; | 113 | u8 value; |
212 | 114 | ||
213 | if (reg >= TWL6040_CACHEREGNUM) | 115 | if (reg >= TWL6040_CACHEREGNUM) |
214 | return -EIO; | 116 | return -EIO; |
215 | 117 | ||
216 | value = twl6040_reg_read(twl6040, reg); | 118 | switch (reg) { |
217 | twl6040_write_reg_cache(codec, reg, value); | 119 | case TWL6040_REG_HSLCTL: |
120 | case TWL6040_REG_HSRCTL: | ||
121 | case TWL6040_REG_EARCTL: | ||
122 | case TWL6040_REG_HFLCTL: | ||
123 | case TWL6040_REG_HFRCTL: | ||
124 | value = priv->dl12_cache[reg - TWL6040_REG_HSLCTL]; | ||
125 | break; | ||
126 | default: | ||
127 | value = twl6040_reg_read(twl6040, reg); | ||
128 | break; | ||
129 | } | ||
218 | 130 | ||
219 | return value; | 131 | return value; |
220 | } | 132 | } |
221 | 133 | ||
222 | static bool twl6040_is_path_unmuted(struct snd_soc_codec *codec, | 134 | static bool twl6040_can_write_to_chip(struct snd_soc_codec *codec, |
223 | unsigned int reg) | 135 | unsigned int reg) |
224 | { | 136 | { |
225 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | 137 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
226 | 138 | ||
@@ -238,9 +150,24 @@ static bool twl6040_is_path_unmuted(struct snd_soc_codec *codec, | |||
238 | } | 150 | } |
239 | } | 151 | } |
240 | 152 | ||
241 | /* | 153 | static inline void twl6040_update_dl12_cache(struct snd_soc_codec *codec, |
242 | * write to the twl6040 register space | 154 | u8 reg, u8 value) |
243 | */ | 155 | { |
156 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | ||
157 | |||
158 | switch (reg) { | ||
159 | case TWL6040_REG_HSLCTL: | ||
160 | case TWL6040_REG_HSRCTL: | ||
161 | case TWL6040_REG_EARCTL: | ||
162 | case TWL6040_REG_HFLCTL: | ||
163 | case TWL6040_REG_HFRCTL: | ||
164 | priv->dl12_cache[reg - TWL6040_REG_HSLCTL] = value; | ||
165 | break; | ||
166 | default: | ||
167 | break; | ||
168 | } | ||
169 | } | ||
170 | |||
244 | static int twl6040_write(struct snd_soc_codec *codec, | 171 | static int twl6040_write(struct snd_soc_codec *codec, |
245 | unsigned int reg, unsigned int value) | 172 | unsigned int reg, unsigned int value) |
246 | { | 173 | { |
@@ -249,8 +176,8 @@ static int twl6040_write(struct snd_soc_codec *codec, | |||
249 | if (reg >= TWL6040_CACHEREGNUM) | 176 | if (reg >= TWL6040_CACHEREGNUM) |
250 | return -EIO; | 177 | return -EIO; |
251 | 178 | ||
252 | twl6040_write_reg_cache(codec, reg, value); | 179 | twl6040_update_dl12_cache(codec, reg, value); |
253 | if (twl6040_is_path_unmuted(codec, reg)) | 180 | if (twl6040_can_write_to_chip(codec, reg)) |
254 | return twl6040_reg_write(twl6040, reg, value); | 181 | return twl6040_reg_write(twl6040, reg, value); |
255 | else | 182 | else |
256 | return 0; | 183 | return 0; |
@@ -258,45 +185,27 @@ static int twl6040_write(struct snd_soc_codec *codec, | |||
258 | 185 | ||
259 | static void twl6040_init_chip(struct snd_soc_codec *codec) | 186 | static void twl6040_init_chip(struct snd_soc_codec *codec) |
260 | { | 187 | { |
261 | struct twl6040 *twl6040 = codec->control_data; | 188 | twl6040_read(codec, TWL6040_REG_TRIM1); |
262 | u8 val; | 189 | twl6040_read(codec, TWL6040_REG_TRIM2); |
263 | 190 | twl6040_read(codec, TWL6040_REG_TRIM3); | |
264 | /* Update reg_cache: ASICREV, and TRIM values */ | 191 | twl6040_read(codec, TWL6040_REG_HSOTRIM); |
265 | val = twl6040_get_revid(twl6040); | 192 | twl6040_read(codec, TWL6040_REG_HFOTRIM); |
266 | twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val); | ||
267 | |||
268 | twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM1); | ||
269 | twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM2); | ||
270 | twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM3); | ||
271 | twl6040_read_reg_volatile(codec, TWL6040_REG_HSOTRIM); | ||
272 | twl6040_read_reg_volatile(codec, TWL6040_REG_HFOTRIM); | ||
273 | 193 | ||
274 | /* Change chip defaults */ | 194 | /* Change chip defaults */ |
275 | /* No imput selected for microphone amplifiers */ | 195 | /* No imput selected for microphone amplifiers */ |
276 | twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18); | 196 | twl6040_write(codec, TWL6040_REG_MICLCTL, 0x18); |
277 | twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18); | 197 | twl6040_write(codec, TWL6040_REG_MICRCTL, 0x18); |
278 | 198 | ||
279 | /* | 199 | /* |
280 | * We need to lower the default gain values, so the ramp code | 200 | * We need to lower the default gain values, so the ramp code |
281 | * can work correctly for the first playback. | 201 | * can work correctly for the first playback. |
282 | * This reduces the pop noise heard at the first playback. | 202 | * This reduces the pop noise heard at the first playback. |
283 | */ | 203 | */ |
284 | twl6040_write_reg_cache(codec, TWL6040_REG_HSGAIN, 0xff); | 204 | twl6040_write(codec, TWL6040_REG_HSGAIN, 0xff); |
285 | twl6040_write_reg_cache(codec, TWL6040_REG_EARCTL, 0x1e); | 205 | twl6040_write(codec, TWL6040_REG_EARCTL, 0x1e); |
286 | twl6040_write_reg_cache(codec, TWL6040_REG_HFLGAIN, 0x1d); | 206 | twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1d); |
287 | twl6040_write_reg_cache(codec, TWL6040_REG_HFRGAIN, 0x1d); | 207 | twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1d); |
288 | twl6040_write_reg_cache(codec, TWL6040_REG_LINEGAIN, 0); | 208 | twl6040_write(codec, TWL6040_REG_LINEGAIN, 0); |
289 | } | ||
290 | |||
291 | static void twl6040_restore_regs(struct snd_soc_codec *codec) | ||
292 | { | ||
293 | u8 *cache = codec->reg_cache; | ||
294 | int reg, i; | ||
295 | |||
296 | for (i = 0; i < ARRAY_SIZE(twl6040_restore_list); i++) { | ||
297 | reg = twl6040_restore_list[i]; | ||
298 | twl6040_write(codec, reg, cache[reg]); | ||
299 | } | ||
300 | } | 209 | } |
301 | 210 | ||
302 | /* set headset dac and driver power mode */ | 211 | /* set headset dac and driver power mode */ |
@@ -305,8 +214,8 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf) | |||
305 | int hslctl, hsrctl; | 214 | int hslctl, hsrctl; |
306 | int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE; | 215 | int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE; |
307 | 216 | ||
308 | hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); | 217 | hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL); |
309 | hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); | 218 | hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL); |
310 | 219 | ||
311 | if (high_perf) { | 220 | if (high_perf) { |
312 | hslctl &= ~mask; | 221 | hslctl &= ~mask; |
@@ -333,8 +242,8 @@ static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w, | |||
333 | * Both HS DAC need to be turned on (before the HS driver) and off at | 242 | * Both HS DAC need to be turned on (before the HS driver) and off at |
334 | * the same time. | 243 | * the same time. |
335 | */ | 244 | */ |
336 | hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); | 245 | hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL); |
337 | hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); | 246 | hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL); |
338 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 247 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
339 | hslctl |= TWL6040_HSDACENA; | 248 | hslctl |= TWL6040_HSDACENA; |
340 | hsrctl |= TWL6040_HSDACENA; | 249 | hsrctl |= TWL6040_HSDACENA; |
@@ -379,7 +288,7 @@ static void twl6040_hs_jack_report(struct snd_soc_codec *codec, | |||
379 | mutex_lock(&priv->mutex); | 288 | mutex_lock(&priv->mutex); |
380 | 289 | ||
381 | /* Sync status */ | 290 | /* Sync status */ |
382 | status = twl6040_read_reg_volatile(codec, TWL6040_REG_STATUS); | 291 | status = twl6040_read(codec, TWL6040_REG_STATUS); |
383 | if (status & TWL6040_PLUGCOMP) | 292 | if (status & TWL6040_PLUGCOMP) |
384 | snd_soc_jack_report(jack, report, report); | 293 | snd_soc_jack_report(jack, report, report); |
385 | else | 294 | else |
@@ -431,7 +340,7 @@ static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol, | |||
431 | unsigned int val; | 340 | unsigned int val; |
432 | 341 | ||
433 | /* Do not allow changes while Input/FF efect is running */ | 342 | /* Do not allow changes while Input/FF efect is running */ |
434 | val = twl6040_read_reg_volatile(codec, e->reg); | 343 | val = twl6040_read(codec, e->reg); |
435 | if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL)) | 344 | if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL)) |
436 | return -EBUSY; | 345 | return -EBUSY; |
437 | 346 | ||
@@ -656,7 +565,7 @@ int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim) | |||
656 | if (unlikely(trim >= TWL6040_TRIM_INVAL)) | 565 | if (unlikely(trim >= TWL6040_TRIM_INVAL)) |
657 | return -EINVAL; | 566 | return -EINVAL; |
658 | 567 | ||
659 | return twl6040_read_reg_cache(codec, TWL6040_REG_TRIM1 + trim); | 568 | return twl6040_read(codec, TWL6040_REG_TRIM1 + trim); |
660 | } | 569 | } |
661 | EXPORT_SYMBOL_GPL(twl6040_get_trim_value); | 570 | EXPORT_SYMBOL_GPL(twl6040_get_trim_value); |
662 | 571 | ||
@@ -931,8 +840,6 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec, | |||
931 | 840 | ||
932 | priv->codec_powered = 1; | 841 | priv->codec_powered = 1; |
933 | 842 | ||
934 | twl6040_restore_regs(codec); | ||
935 | |||
936 | /* Set external boost GPO */ | 843 | /* Set external boost GPO */ |
937 | twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); | 844 | twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); |
938 | break; | 845 | break; |
@@ -1053,9 +960,9 @@ static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id i | |||
1053 | 960 | ||
1054 | switch (id) { | 961 | switch (id) { |
1055 | case TWL6040_DAI_DL1: | 962 | case TWL6040_DAI_DL1: |
1056 | hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); | 963 | hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL); |
1057 | hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); | 964 | hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL); |
1058 | earctl = twl6040_read_reg_cache(codec, TWL6040_REG_EARCTL); | 965 | earctl = twl6040_read(codec, TWL6040_REG_EARCTL); |
1059 | 966 | ||
1060 | if (mute) { | 967 | if (mute) { |
1061 | /* Power down drivers and DACs */ | 968 | /* Power down drivers and DACs */ |
@@ -1071,8 +978,8 @@ static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id i | |||
1071 | priv->dl1_unmuted = !mute; | 978 | priv->dl1_unmuted = !mute; |
1072 | break; | 979 | break; |
1073 | case TWL6040_DAI_DL2: | 980 | case TWL6040_DAI_DL2: |
1074 | hflctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFLCTL); | 981 | hflctl = twl6040_read(codec, TWL6040_REG_HFLCTL); |
1075 | hfrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFRCTL); | 982 | hfrctl = twl6040_read(codec, TWL6040_REG_HFRCTL); |
1076 | 983 | ||
1077 | if (mute) { | 984 | if (mute) { |
1078 | /* Power down drivers and DACs */ | 985 | /* Power down drivers and DACs */ |
@@ -1209,6 +1116,7 @@ static int twl6040_resume(struct snd_soc_codec *codec) | |||
1209 | static int twl6040_probe(struct snd_soc_codec *codec) | 1116 | static int twl6040_probe(struct snd_soc_codec *codec) |
1210 | { | 1117 | { |
1211 | struct twl6040_data *priv; | 1118 | struct twl6040_data *priv; |
1119 | struct twl6040 *twl6040 = dev_get_drvdata(codec->dev->parent); | ||
1212 | struct platform_device *pdev = container_of(codec->dev, | 1120 | struct platform_device *pdev = container_of(codec->dev, |
1213 | struct platform_device, dev); | 1121 | struct platform_device, dev); |
1214 | int ret = 0; | 1122 | int ret = 0; |
@@ -1220,7 +1128,7 @@ static int twl6040_probe(struct snd_soc_codec *codec) | |||
1220 | snd_soc_codec_set_drvdata(codec, priv); | 1128 | snd_soc_codec_set_drvdata(codec, priv); |
1221 | 1129 | ||
1222 | priv->codec = codec; | 1130 | priv->codec = codec; |
1223 | codec->control_data = dev_get_drvdata(codec->dev->parent); | 1131 | codec->control_data = twl6040; |
1224 | 1132 | ||
1225 | priv->plug_irq = platform_get_irq(pdev, 0); | 1133 | priv->plug_irq = platform_get_irq(pdev, 0); |
1226 | if (priv->plug_irq < 0) { | 1134 | if (priv->plug_irq < 0) { |
@@ -1240,10 +1148,10 @@ static int twl6040_probe(struct snd_soc_codec *codec) | |||
1240 | return ret; | 1148 | return ret; |
1241 | } | 1149 | } |
1242 | 1150 | ||
1151 | twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1243 | twl6040_init_chip(codec); | 1152 | twl6040_init_chip(codec); |
1244 | 1153 | ||
1245 | /* power on device */ | 1154 | return 0; |
1246 | return twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1247 | } | 1155 | } |
1248 | 1156 | ||
1249 | static int twl6040_remove(struct snd_soc_codec *codec) | 1157 | static int twl6040_remove(struct snd_soc_codec *codec) |
@@ -1261,12 +1169,9 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { | |||
1261 | .remove = twl6040_remove, | 1169 | .remove = twl6040_remove, |
1262 | .suspend = twl6040_suspend, | 1170 | .suspend = twl6040_suspend, |
1263 | .resume = twl6040_resume, | 1171 | .resume = twl6040_resume, |
1264 | .read = twl6040_read_reg_cache, | 1172 | .read = twl6040_read, |
1265 | .write = twl6040_write, | 1173 | .write = twl6040_write, |
1266 | .set_bias_level = twl6040_set_bias_level, | 1174 | .set_bias_level = twl6040_set_bias_level, |
1267 | .reg_cache_size = ARRAY_SIZE(twl6040_reg), | ||
1268 | .reg_word_size = sizeof(u8), | ||
1269 | .reg_cache_default = twl6040_reg, | ||
1270 | .ignore_pmdown_time = true, | 1175 | .ignore_pmdown_time = true, |
1271 | 1176 | ||
1272 | .controls = twl6040_snd_controls, | 1177 | .controls = twl6040_snd_controls, |
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index fd0a314bc209..726df6d43c2b 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c | |||
@@ -794,7 +794,7 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { | |||
794 | .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes), | 794 | .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes), |
795 | }; | 795 | }; |
796 | 796 | ||
797 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 797 | #if IS_ENABLED(CONFIG_I2C) |
798 | static int uda1380_i2c_probe(struct i2c_client *i2c, | 798 | static int uda1380_i2c_probe(struct i2c_client *i2c, |
799 | const struct i2c_device_id *id) | 799 | const struct i2c_device_id *id) |
800 | { | 800 | { |
@@ -840,7 +840,7 @@ static struct i2c_driver uda1380_i2c_driver = { | |||
840 | static int __init uda1380_modinit(void) | 840 | static int __init uda1380_modinit(void) |
841 | { | 841 | { |
842 | int ret = 0; | 842 | int ret = 0; |
843 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 843 | #if IS_ENABLED(CONFIG_I2C) |
844 | ret = i2c_add_driver(&uda1380_i2c_driver); | 844 | ret = i2c_add_driver(&uda1380_i2c_driver); |
845 | if (ret != 0) | 845 | if (ret != 0) |
846 | pr_err("Failed to register UDA1380 I2C driver: %d\n", ret); | 846 | pr_err("Failed to register UDA1380 I2C driver: %d\n", ret); |
@@ -851,7 +851,7 @@ module_init(uda1380_modinit); | |||
851 | 851 | ||
852 | static void __exit uda1380_exit(void) | 852 | static void __exit uda1380_exit(void) |
853 | { | 853 | { |
854 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 854 | #if IS_ENABLED(CONFIG_I2C) |
855 | i2c_del_driver(&uda1380_i2c_driver); | 855 | i2c_del_driver(&uda1380_i2c_driver); |
856 | #endif | 856 | #endif |
857 | } | 857 | } |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index a08e8bf6d07c..ce9c8e14d4bd 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -601,8 +601,8 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
601 | case SND_SOC_DAPM_POST_PMU: | 601 | case SND_SOC_DAPM_POST_PMU: |
602 | if (patch) | 602 | if (patch) |
603 | for (i = 0; i < patch_size; i++) | 603 | for (i = 0; i < patch_size; i++) |
604 | regmap_write(regmap, patch[i].reg, | 604 | regmap_write_async(regmap, patch[i].reg, |
605 | patch[i].def); | 605 | patch[i].def); |
606 | break; | 606 | break; |
607 | 607 | ||
608 | default: | 608 | default: |
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index c3c7396a6181..22bd7dd80bba 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -30,13 +30,51 @@ | |||
30 | #include <linux/mfd/arizona/registers.h> | 30 | #include <linux/mfd/arizona/registers.h> |
31 | 31 | ||
32 | #include "arizona.h" | 32 | #include "arizona.h" |
33 | #include "wm_adsp.h" | ||
33 | #include "wm5110.h" | 34 | #include "wm5110.h" |
34 | 35 | ||
36 | #define WM5110_NUM_ADSP 4 | ||
37 | |||
35 | struct wm5110_priv { | 38 | struct wm5110_priv { |
36 | struct arizona_priv core; | 39 | struct arizona_priv core; |
37 | struct arizona_fll fll[2]; | 40 | struct arizona_fll fll[2]; |
38 | }; | 41 | }; |
39 | 42 | ||
43 | static const struct wm_adsp_region wm5110_dsp1_regions[] = { | ||
44 | { .type = WMFW_ADSP2_PM, .base = 0x100000 }, | ||
45 | { .type = WMFW_ADSP2_ZM, .base = 0x180000 }, | ||
46 | { .type = WMFW_ADSP2_XM, .base = 0x190000 }, | ||
47 | { .type = WMFW_ADSP2_YM, .base = 0x1a8000 }, | ||
48 | }; | ||
49 | |||
50 | static const struct wm_adsp_region wm5110_dsp2_regions[] = { | ||
51 | { .type = WMFW_ADSP2_PM, .base = 0x200000 }, | ||
52 | { .type = WMFW_ADSP2_ZM, .base = 0x280000 }, | ||
53 | { .type = WMFW_ADSP2_XM, .base = 0x290000 }, | ||
54 | { .type = WMFW_ADSP2_YM, .base = 0x2a8000 }, | ||
55 | }; | ||
56 | |||
57 | static const struct wm_adsp_region wm5110_dsp3_regions[] = { | ||
58 | { .type = WMFW_ADSP2_PM, .base = 0x300000 }, | ||
59 | { .type = WMFW_ADSP2_ZM, .base = 0x380000 }, | ||
60 | { .type = WMFW_ADSP2_XM, .base = 0x390000 }, | ||
61 | { .type = WMFW_ADSP2_YM, .base = 0x3a8000 }, | ||
62 | }; | ||
63 | |||
64 | static const struct wm_adsp_region wm5110_dsp4_regions[] = { | ||
65 | { .type = WMFW_ADSP2_PM, .base = 0x400000 }, | ||
66 | { .type = WMFW_ADSP2_ZM, .base = 0x480000 }, | ||
67 | { .type = WMFW_ADSP2_XM, .base = 0x490000 }, | ||
68 | { .type = WMFW_ADSP2_YM, .base = 0x4a8000 }, | ||
69 | }; | ||
70 | |||
71 | static const struct wm_adsp_region *wm5110_dsp_regions[] = { | ||
72 | wm5110_dsp1_regions, | ||
73 | wm5110_dsp2_regions, | ||
74 | wm5110_dsp3_regions, | ||
75 | wm5110_dsp4_regions, | ||
76 | }; | ||
77 | |||
40 | static const struct reg_default wm5110_sysclk_revd_patch[] = { | 78 | static const struct reg_default wm5110_sysclk_revd_patch[] = { |
41 | { 0x3093, 0x1001 }, | 79 | { 0x3093, 0x1001 }, |
42 | { 0x30E3, 0x1301 }, | 80 | { 0x30E3, 0x1301 }, |
@@ -67,8 +105,8 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
67 | case SND_SOC_DAPM_POST_PMU: | 105 | case SND_SOC_DAPM_POST_PMU: |
68 | if (patch) | 106 | if (patch) |
69 | for (i = 0; i < patch_size; i++) | 107 | for (i = 0; i < patch_size; i++) |
70 | regmap_write(regmap, patch[i].reg, | 108 | regmap_write_async(regmap, patch[i].reg, |
71 | patch[i].def); | 109 | patch[i].def); |
72 | break; | 110 | break; |
73 | 111 | ||
74 | default: | 112 | default: |
@@ -117,6 +155,25 @@ SOC_SINGLE_RANGE_TLV("IN3L Volume", ARIZONA_IN3L_CONTROL, | |||
117 | SOC_SINGLE_RANGE_TLV("IN3R Volume", ARIZONA_IN3R_CONTROL, | 155 | SOC_SINGLE_RANGE_TLV("IN3R Volume", ARIZONA_IN3R_CONTROL, |
118 | ARIZONA_IN3R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | 156 | ARIZONA_IN3R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), |
119 | 157 | ||
158 | SOC_ENUM("IN HPF Cutoff Frequency", arizona_in_hpf_cut_enum), | ||
159 | |||
160 | SOC_SINGLE("IN1L HPF Switch", ARIZONA_IN1L_CONTROL, | ||
161 | ARIZONA_IN1L_HPF_SHIFT, 1, 0), | ||
162 | SOC_SINGLE("IN1R HPF Switch", ARIZONA_IN1R_CONTROL, | ||
163 | ARIZONA_IN1R_HPF_SHIFT, 1, 0), | ||
164 | SOC_SINGLE("IN2L HPF Switch", ARIZONA_IN2L_CONTROL, | ||
165 | ARIZONA_IN2L_HPF_SHIFT, 1, 0), | ||
166 | SOC_SINGLE("IN2R HPF Switch", ARIZONA_IN2R_CONTROL, | ||
167 | ARIZONA_IN2R_HPF_SHIFT, 1, 0), | ||
168 | SOC_SINGLE("IN3L HPF Switch", ARIZONA_IN3L_CONTROL, | ||
169 | ARIZONA_IN3L_HPF_SHIFT, 1, 0), | ||
170 | SOC_SINGLE("IN3R HPF Switch", ARIZONA_IN3R_CONTROL, | ||
171 | ARIZONA_IN3R_HPF_SHIFT, 1, 0), | ||
172 | SOC_SINGLE("IN4L HPF Switch", ARIZONA_IN4L_CONTROL, | ||
173 | ARIZONA_IN4L_HPF_SHIFT, 1, 0), | ||
174 | SOC_SINGLE("IN4R HPF Switch", ARIZONA_IN4R_CONTROL, | ||
175 | ARIZONA_IN4R_HPF_SHIFT, 1, 0), | ||
176 | |||
120 | SOC_SINGLE_TLV("IN1L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L, | 177 | SOC_SINGLE_TLV("IN1L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L, |
121 | ARIZONA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), | 178 | ARIZONA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), |
122 | SOC_SINGLE_TLV("IN1R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1R, | 179 | SOC_SINGLE_TLV("IN1R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1R, |
@@ -220,6 +277,14 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | |||
220 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | 277 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), |
221 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), | 278 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), |
222 | 279 | ||
280 | SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]), | ||
281 | SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]), | ||
282 | SOC_VALUE_ENUM("ISRC3 FSL", arizona_isrc_fsl[2]), | ||
283 | SOC_VALUE_ENUM("ISRC1 FSH", arizona_isrc_fsh[0]), | ||
284 | SOC_VALUE_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]), | ||
285 | SOC_VALUE_ENUM("ISRC3 FSH", arizona_isrc_fsh[2]), | ||
286 | SOC_VALUE_ENUM("ASRC RATE 1", arizona_asrc_rate1), | ||
287 | |||
223 | ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE), | 288 | ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE), |
224 | ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE), | 289 | ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE), |
225 | ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE), | 290 | ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE), |
@@ -248,19 +313,6 @@ ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), | |||
248 | ARIZONA_MIXER_CONTROLS("SPKDAT2L", ARIZONA_OUT6LMIX_INPUT_1_SOURCE), | 313 | ARIZONA_MIXER_CONTROLS("SPKDAT2L", ARIZONA_OUT6LMIX_INPUT_1_SOURCE), |
249 | ARIZONA_MIXER_CONTROLS("SPKDAT2R", ARIZONA_OUT6RMIX_INPUT_1_SOURCE), | 314 | ARIZONA_MIXER_CONTROLS("SPKDAT2R", ARIZONA_OUT6RMIX_INPUT_1_SOURCE), |
250 | 315 | ||
251 | SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L, | ||
252 | ARIZONA_OUT1_OSR_SHIFT, 1, 0), | ||
253 | SOC_SINGLE("HPOUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L, | ||
254 | ARIZONA_OUT2_OSR_SHIFT, 1, 0), | ||
255 | SOC_SINGLE("HPOUT3 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L, | ||
256 | ARIZONA_OUT3_OSR_SHIFT, 1, 0), | ||
257 | SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, | ||
258 | ARIZONA_OUT4_OSR_SHIFT, 1, 0), | ||
259 | SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, | ||
260 | ARIZONA_OUT5_OSR_SHIFT, 1, 0), | ||
261 | SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L, | ||
262 | ARIZONA_OUT6_OSR_SHIFT, 1, 0), | ||
263 | |||
264 | SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, | 316 | SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, |
265 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), | 317 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), |
266 | SOC_DOUBLE_R("HPOUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, | 318 | SOC_DOUBLE_R("HPOUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, |
@@ -293,23 +345,18 @@ SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_6L, | |||
293 | ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_VOL_SHIFT, | 345 | ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_VOL_SHIFT, |
294 | 0xbf, 0, digital_tlv), | 346 | 0xbf, 0, digital_tlv), |
295 | 347 | ||
296 | SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L, | ||
297 | ARIZONA_OUTPUT_PATH_CONFIG_1R, | ||
298 | ARIZONA_OUT1L_PGA_VOL_SHIFT, | ||
299 | 0x34, 0x40, 0, ana_tlv), | ||
300 | SOC_DOUBLE_R_RANGE_TLV("HPOUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L, | ||
301 | ARIZONA_OUTPUT_PATH_CONFIG_2R, | ||
302 | ARIZONA_OUT2L_PGA_VOL_SHIFT, | ||
303 | 0x34, 0x40, 0, ana_tlv), | ||
304 | SOC_DOUBLE_R_RANGE_TLV("HPOUT3 Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L, | ||
305 | ARIZONA_OUTPUT_PATH_CONFIG_3R, | ||
306 | ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv), | ||
307 | |||
308 | SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | 348 | SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, |
309 | ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), | 349 | ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), |
310 | SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT, | 350 | SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT, |
311 | ARIZONA_SPK2R_MUTE_SHIFT, 1, 1), | 351 | ARIZONA_SPK2R_MUTE_SHIFT, 1, 1), |
312 | 352 | ||
353 | SOC_DOUBLE("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE, | ||
354 | ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0), | ||
355 | SOC_DOUBLE("HPOUT2 DRE Switch", ARIZONA_DRE_ENABLE, | ||
356 | ARIZONA_DRE2L_ENA_SHIFT, ARIZONA_DRE2R_ENA_SHIFT, 1, 0), | ||
357 | SOC_DOUBLE("HPOUT3 DRE Switch", ARIZONA_DRE_ENABLE, | ||
358 | ARIZONA_DRE3L_ENA_SHIFT, ARIZONA_DRE3R_ENA_SHIFT, 1, 0), | ||
359 | |||
313 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), | 360 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), |
314 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), | 361 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), |
315 | 362 | ||
@@ -343,6 +390,10 @@ ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE), | |||
343 | 390 | ||
344 | ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE), | 391 | ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE), |
345 | ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), | 392 | ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), |
393 | ARIZONA_MIXER_CONTROLS("AIF2TX3", ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE), | ||
394 | ARIZONA_MIXER_CONTROLS("AIF2TX4", ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE), | ||
395 | ARIZONA_MIXER_CONTROLS("AIF2TX5", ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE), | ||
396 | ARIZONA_MIXER_CONTROLS("AIF2TX6", ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE), | ||
346 | 397 | ||
347 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), | 398 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), |
348 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), | 399 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), |
@@ -372,6 +423,22 @@ ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); | |||
372 | ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE); | 423 | ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE); |
373 | ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE); | 424 | ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE); |
374 | 425 | ||
426 | ARIZONA_MIXER_ENUMS(DSP1L, ARIZONA_DSP1LMIX_INPUT_1_SOURCE); | ||
427 | ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE); | ||
428 | ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE); | ||
429 | |||
430 | ARIZONA_MIXER_ENUMS(DSP2L, ARIZONA_DSP2LMIX_INPUT_1_SOURCE); | ||
431 | ARIZONA_MIXER_ENUMS(DSP2R, ARIZONA_DSP2RMIX_INPUT_1_SOURCE); | ||
432 | ARIZONA_DSP_AUX_ENUMS(DSP2, ARIZONA_DSP2AUX1MIX_INPUT_1_SOURCE); | ||
433 | |||
434 | ARIZONA_MIXER_ENUMS(DSP3L, ARIZONA_DSP3LMIX_INPUT_1_SOURCE); | ||
435 | ARIZONA_MIXER_ENUMS(DSP3R, ARIZONA_DSP3RMIX_INPUT_1_SOURCE); | ||
436 | ARIZONA_DSP_AUX_ENUMS(DSP3, ARIZONA_DSP3AUX1MIX_INPUT_1_SOURCE); | ||
437 | |||
438 | ARIZONA_MIXER_ENUMS(DSP4L, ARIZONA_DSP4LMIX_INPUT_1_SOURCE); | ||
439 | ARIZONA_MIXER_ENUMS(DSP4R, ARIZONA_DSP4RMIX_INPUT_1_SOURCE); | ||
440 | ARIZONA_DSP_AUX_ENUMS(DSP4, ARIZONA_DSP4AUX1MIX_INPUT_1_SOURCE); | ||
441 | |||
375 | ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE); | 442 | ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE); |
376 | ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE); | 443 | ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE); |
377 | 444 | ||
@@ -402,6 +469,10 @@ ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE); | |||
402 | 469 | ||
403 | ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE); | 470 | ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE); |
404 | ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | 471 | ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); |
472 | ARIZONA_MIXER_ENUMS(AIF2TX3, ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE); | ||
473 | ARIZONA_MIXER_ENUMS(AIF2TX4, ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE); | ||
474 | ARIZONA_MIXER_ENUMS(AIF2TX5, ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE); | ||
475 | ARIZONA_MIXER_ENUMS(AIF2TX6, ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE); | ||
405 | 476 | ||
406 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | 477 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); |
407 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | 478 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); |
@@ -420,6 +491,36 @@ ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | |||
420 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 491 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
421 | ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | 492 | ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); |
422 | 493 | ||
494 | ARIZONA_MUX_ENUMS(ISRC1INT1, ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE); | ||
495 | ARIZONA_MUX_ENUMS(ISRC1INT2, ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE); | ||
496 | ARIZONA_MUX_ENUMS(ISRC1INT3, ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE); | ||
497 | ARIZONA_MUX_ENUMS(ISRC1INT4, ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE); | ||
498 | |||
499 | ARIZONA_MUX_ENUMS(ISRC1DEC1, ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE); | ||
500 | ARIZONA_MUX_ENUMS(ISRC1DEC2, ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE); | ||
501 | ARIZONA_MUX_ENUMS(ISRC1DEC3, ARIZONA_ISRC1DEC3MIX_INPUT_1_SOURCE); | ||
502 | ARIZONA_MUX_ENUMS(ISRC1DEC4, ARIZONA_ISRC1DEC4MIX_INPUT_1_SOURCE); | ||
503 | |||
504 | ARIZONA_MUX_ENUMS(ISRC2INT1, ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE); | ||
505 | ARIZONA_MUX_ENUMS(ISRC2INT2, ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE); | ||
506 | ARIZONA_MUX_ENUMS(ISRC2INT3, ARIZONA_ISRC2INT3MIX_INPUT_1_SOURCE); | ||
507 | ARIZONA_MUX_ENUMS(ISRC2INT4, ARIZONA_ISRC2INT4MIX_INPUT_1_SOURCE); | ||
508 | |||
509 | ARIZONA_MUX_ENUMS(ISRC2DEC1, ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE); | ||
510 | ARIZONA_MUX_ENUMS(ISRC2DEC2, ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE); | ||
511 | ARIZONA_MUX_ENUMS(ISRC2DEC3, ARIZONA_ISRC2DEC3MIX_INPUT_1_SOURCE); | ||
512 | ARIZONA_MUX_ENUMS(ISRC2DEC4, ARIZONA_ISRC2DEC4MIX_INPUT_1_SOURCE); | ||
513 | |||
514 | ARIZONA_MUX_ENUMS(ISRC3INT1, ARIZONA_ISRC3INT1MIX_INPUT_1_SOURCE); | ||
515 | ARIZONA_MUX_ENUMS(ISRC3INT2, ARIZONA_ISRC3INT2MIX_INPUT_1_SOURCE); | ||
516 | ARIZONA_MUX_ENUMS(ISRC3INT3, ARIZONA_ISRC3INT3MIX_INPUT_1_SOURCE); | ||
517 | ARIZONA_MUX_ENUMS(ISRC3INT4, ARIZONA_ISRC3INT4MIX_INPUT_1_SOURCE); | ||
518 | |||
519 | ARIZONA_MUX_ENUMS(ISRC3DEC1, ARIZONA_ISRC3DEC1MIX_INPUT_1_SOURCE); | ||
520 | ARIZONA_MUX_ENUMS(ISRC3DEC2, ARIZONA_ISRC3DEC2MIX_INPUT_1_SOURCE); | ||
521 | ARIZONA_MUX_ENUMS(ISRC3DEC3, ARIZONA_ISRC3DEC3MIX_INPUT_1_SOURCE); | ||
522 | ARIZONA_MUX_ENUMS(ISRC3DEC4, ARIZONA_ISRC3DEC4MIX_INPUT_1_SOURCE); | ||
523 | |||
423 | static const char *wm5110_aec_loopback_texts[] = { | 524 | static const char *wm5110_aec_loopback_texts[] = { |
424 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", | 525 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", |
425 | "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", "SPKDAT2L", "SPKDAT2R", | 526 | "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", "SPKDAT2L", "SPKDAT2R", |
@@ -560,6 +661,65 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, | |||
560 | SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, | 661 | SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, |
561 | NULL, 0), | 662 | NULL, 0), |
562 | 663 | ||
664 | WM_ADSP2("DSP1", 0), | ||
665 | WM_ADSP2("DSP2", 1), | ||
666 | WM_ADSP2("DSP3", 2), | ||
667 | WM_ADSP2("DSP4", 3), | ||
668 | |||
669 | SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3, | ||
670 | ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0), | ||
671 | SND_SOC_DAPM_PGA("ISRC1INT2", ARIZONA_ISRC_1_CTRL_3, | ||
672 | ARIZONA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0), | ||
673 | SND_SOC_DAPM_PGA("ISRC1INT3", ARIZONA_ISRC_1_CTRL_3, | ||
674 | ARIZONA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0), | ||
675 | SND_SOC_DAPM_PGA("ISRC1INT4", ARIZONA_ISRC_1_CTRL_3, | ||
676 | ARIZONA_ISRC1_INT3_ENA_SHIFT, 0, NULL, 0), | ||
677 | |||
678 | SND_SOC_DAPM_PGA("ISRC1DEC1", ARIZONA_ISRC_1_CTRL_3, | ||
679 | ARIZONA_ISRC1_DEC0_ENA_SHIFT, 0, NULL, 0), | ||
680 | SND_SOC_DAPM_PGA("ISRC1DEC2", ARIZONA_ISRC_1_CTRL_3, | ||
681 | ARIZONA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
682 | SND_SOC_DAPM_PGA("ISRC1DEC3", ARIZONA_ISRC_1_CTRL_3, | ||
683 | ARIZONA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0), | ||
684 | SND_SOC_DAPM_PGA("ISRC1DEC4", ARIZONA_ISRC_1_CTRL_3, | ||
685 | ARIZONA_ISRC1_DEC3_ENA_SHIFT, 0, NULL, 0), | ||
686 | |||
687 | SND_SOC_DAPM_PGA("ISRC2INT1", ARIZONA_ISRC_2_CTRL_3, | ||
688 | ARIZONA_ISRC2_INT0_ENA_SHIFT, 0, NULL, 0), | ||
689 | SND_SOC_DAPM_PGA("ISRC2INT2", ARIZONA_ISRC_2_CTRL_3, | ||
690 | ARIZONA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0), | ||
691 | SND_SOC_DAPM_PGA("ISRC2INT3", ARIZONA_ISRC_2_CTRL_3, | ||
692 | ARIZONA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0), | ||
693 | SND_SOC_DAPM_PGA("ISRC2INT4", ARIZONA_ISRC_2_CTRL_3, | ||
694 | ARIZONA_ISRC2_INT3_ENA_SHIFT, 0, NULL, 0), | ||
695 | |||
696 | SND_SOC_DAPM_PGA("ISRC2DEC1", ARIZONA_ISRC_2_CTRL_3, | ||
697 | ARIZONA_ISRC2_DEC0_ENA_SHIFT, 0, NULL, 0), | ||
698 | SND_SOC_DAPM_PGA("ISRC2DEC2", ARIZONA_ISRC_2_CTRL_3, | ||
699 | ARIZONA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
700 | SND_SOC_DAPM_PGA("ISRC2DEC3", ARIZONA_ISRC_2_CTRL_3, | ||
701 | ARIZONA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0), | ||
702 | SND_SOC_DAPM_PGA("ISRC2DEC4", ARIZONA_ISRC_2_CTRL_3, | ||
703 | ARIZONA_ISRC2_DEC3_ENA_SHIFT, 0, NULL, 0), | ||
704 | |||
705 | SND_SOC_DAPM_PGA("ISRC3INT1", ARIZONA_ISRC_3_CTRL_3, | ||
706 | ARIZONA_ISRC3_INT0_ENA_SHIFT, 0, NULL, 0), | ||
707 | SND_SOC_DAPM_PGA("ISRC3INT2", ARIZONA_ISRC_3_CTRL_3, | ||
708 | ARIZONA_ISRC3_INT1_ENA_SHIFT, 0, NULL, 0), | ||
709 | SND_SOC_DAPM_PGA("ISRC3INT3", ARIZONA_ISRC_3_CTRL_3, | ||
710 | ARIZONA_ISRC3_INT2_ENA_SHIFT, 0, NULL, 0), | ||
711 | SND_SOC_DAPM_PGA("ISRC3INT4", ARIZONA_ISRC_3_CTRL_3, | ||
712 | ARIZONA_ISRC3_INT3_ENA_SHIFT, 0, NULL, 0), | ||
713 | |||
714 | SND_SOC_DAPM_PGA("ISRC3DEC1", ARIZONA_ISRC_3_CTRL_3, | ||
715 | ARIZONA_ISRC3_DEC0_ENA_SHIFT, 0, NULL, 0), | ||
716 | SND_SOC_DAPM_PGA("ISRC3DEC2", ARIZONA_ISRC_3_CTRL_3, | ||
717 | ARIZONA_ISRC3_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
718 | SND_SOC_DAPM_PGA("ISRC3DEC3", ARIZONA_ISRC_3_CTRL_3, | ||
719 | ARIZONA_ISRC3_DEC2_ENA_SHIFT, 0, NULL, 0), | ||
720 | SND_SOC_DAPM_PGA("ISRC3DEC4", ARIZONA_ISRC_3_CTRL_3, | ||
721 | ARIZONA_ISRC3_DEC3_ENA_SHIFT, 0, NULL, 0), | ||
722 | |||
563 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | 723 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, |
564 | ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0, | 724 | ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0, |
565 | &wm5110_aec_loopback_mux), | 725 | &wm5110_aec_loopback_mux), |
@@ -602,11 +762,27 @@ SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, | |||
602 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), | 762 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), |
603 | SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, | 763 | SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, |
604 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), | 764 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), |
765 | SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, | ||
766 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX3_ENA_SHIFT, 0), | ||
767 | SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, | ||
768 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX4_ENA_SHIFT, 0), | ||
769 | SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, | ||
770 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX5_ENA_SHIFT, 0), | ||
771 | SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, | ||
772 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX6_ENA_SHIFT, 0), | ||
605 | 773 | ||
606 | SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, | 774 | SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, |
607 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), | 775 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), |
608 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, | 776 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, |
609 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), | 777 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), |
778 | SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, | ||
779 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX3_ENA_SHIFT, 0), | ||
780 | SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, | ||
781 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX4_ENA_SHIFT, 0), | ||
782 | SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, | ||
783 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX5_ENA_SHIFT, 0), | ||
784 | SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, | ||
785 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX6_ENA_SHIFT, 0), | ||
610 | 786 | ||
611 | SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, | 787 | SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, |
612 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | 788 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, |
@@ -744,6 +920,10 @@ ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), | |||
744 | 920 | ||
745 | ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), | 921 | ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), |
746 | ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | 922 | ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), |
923 | ARIZONA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"), | ||
924 | ARIZONA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"), | ||
925 | ARIZONA_MIXER_WIDGETS(AIF2TX5, "AIF2TX5"), | ||
926 | ARIZONA_MIXER_WIDGETS(AIF2TX6, "AIF2TX6"), | ||
747 | 927 | ||
748 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | 928 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), |
749 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | 929 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), |
@@ -762,6 +942,41 @@ ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), | |||
762 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), | 942 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), |
763 | ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"), | 943 | ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"), |
764 | 944 | ||
945 | ARIZONA_DSP_WIDGETS(DSP1, "DSP1"), | ||
946 | ARIZONA_DSP_WIDGETS(DSP2, "DSP2"), | ||
947 | ARIZONA_DSP_WIDGETS(DSP3, "DSP3"), | ||
948 | ARIZONA_DSP_WIDGETS(DSP4, "DSP4"), | ||
949 | |||
950 | ARIZONA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), | ||
951 | ARIZONA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), | ||
952 | ARIZONA_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"), | ||
953 | ARIZONA_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"), | ||
954 | |||
955 | ARIZONA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), | ||
956 | ARIZONA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), | ||
957 | ARIZONA_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"), | ||
958 | ARIZONA_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"), | ||
959 | |||
960 | ARIZONA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), | ||
961 | ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), | ||
962 | ARIZONA_MUX_WIDGETS(ISRC2DEC3, "ISRC2DEC3"), | ||
963 | ARIZONA_MUX_WIDGETS(ISRC2DEC4, "ISRC2DEC4"), | ||
964 | |||
965 | ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), | ||
966 | ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), | ||
967 | ARIZONA_MUX_WIDGETS(ISRC2INT3, "ISRC2INT3"), | ||
968 | ARIZONA_MUX_WIDGETS(ISRC2INT4, "ISRC2INT4"), | ||
969 | |||
970 | ARIZONA_MUX_WIDGETS(ISRC3DEC1, "ISRC3DEC1"), | ||
971 | ARIZONA_MUX_WIDGETS(ISRC3DEC2, "ISRC3DEC2"), | ||
972 | ARIZONA_MUX_WIDGETS(ISRC3DEC3, "ISRC3DEC3"), | ||
973 | ARIZONA_MUX_WIDGETS(ISRC3DEC4, "ISRC3DEC4"), | ||
974 | |||
975 | ARIZONA_MUX_WIDGETS(ISRC3INT1, "ISRC3INT1"), | ||
976 | ARIZONA_MUX_WIDGETS(ISRC3INT2, "ISRC3INT2"), | ||
977 | ARIZONA_MUX_WIDGETS(ISRC3INT3, "ISRC3INT3"), | ||
978 | ARIZONA_MUX_WIDGETS(ISRC3INT4, "ISRC3INT4"), | ||
979 | |||
765 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), | 980 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), |
766 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | 981 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), |
767 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), | 982 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), |
@@ -805,6 +1020,10 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"), | |||
805 | { name, "AIF1RX8", "AIF1RX8" }, \ | 1020 | { name, "AIF1RX8", "AIF1RX8" }, \ |
806 | { name, "AIF2RX1", "AIF2RX1" }, \ | 1021 | { name, "AIF2RX1", "AIF2RX1" }, \ |
807 | { name, "AIF2RX2", "AIF2RX2" }, \ | 1022 | { name, "AIF2RX2", "AIF2RX2" }, \ |
1023 | { name, "AIF2RX3", "AIF2RX3" }, \ | ||
1024 | { name, "AIF2RX4", "AIF2RX4" }, \ | ||
1025 | { name, "AIF2RX5", "AIF2RX5" }, \ | ||
1026 | { name, "AIF2RX6", "AIF2RX6" }, \ | ||
808 | { name, "AIF3RX1", "AIF3RX1" }, \ | 1027 | { name, "AIF3RX1", "AIF3RX1" }, \ |
809 | { name, "AIF3RX2", "AIF3RX2" }, \ | 1028 | { name, "AIF3RX2", "AIF3RX2" }, \ |
810 | { name, "SLIMRX1", "SLIMRX1" }, \ | 1029 | { name, "SLIMRX1", "SLIMRX1" }, \ |
@@ -830,7 +1049,55 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"), | |||
830 | { name, "ASRC1L", "ASRC1L" }, \ | 1049 | { name, "ASRC1L", "ASRC1L" }, \ |
831 | { name, "ASRC1R", "ASRC1R" }, \ | 1050 | { name, "ASRC1R", "ASRC1R" }, \ |
832 | { name, "ASRC2L", "ASRC2L" }, \ | 1051 | { name, "ASRC2L", "ASRC2L" }, \ |
833 | { name, "ASRC2R", "ASRC2R" } | 1052 | { name, "ASRC2R", "ASRC2R" }, \ |
1053 | { name, "ISRC1DEC1", "ISRC1DEC1" }, \ | ||
1054 | { name, "ISRC1DEC2", "ISRC1DEC2" }, \ | ||
1055 | { name, "ISRC1DEC3", "ISRC1DEC3" }, \ | ||
1056 | { name, "ISRC1DEC4", "ISRC1DEC4" }, \ | ||
1057 | { name, "ISRC1INT1", "ISRC1INT1" }, \ | ||
1058 | { name, "ISRC1INT2", "ISRC1INT2" }, \ | ||
1059 | { name, "ISRC1INT3", "ISRC1INT3" }, \ | ||
1060 | { name, "ISRC1INT4", "ISRC1INT4" }, \ | ||
1061 | { name, "ISRC2DEC1", "ISRC2DEC1" }, \ | ||
1062 | { name, "ISRC2DEC2", "ISRC2DEC2" }, \ | ||
1063 | { name, "ISRC2DEC3", "ISRC2DEC3" }, \ | ||
1064 | { name, "ISRC2DEC4", "ISRC2DEC4" }, \ | ||
1065 | { name, "ISRC2INT1", "ISRC2INT1" }, \ | ||
1066 | { name, "ISRC2INT2", "ISRC2INT2" }, \ | ||
1067 | { name, "ISRC2INT3", "ISRC2INT3" }, \ | ||
1068 | { name, "ISRC2INT4", "ISRC2INT4" }, \ | ||
1069 | { name, "ISRC3DEC1", "ISRC3DEC1" }, \ | ||
1070 | { name, "ISRC3DEC2", "ISRC3DEC2" }, \ | ||
1071 | { name, "ISRC3DEC3", "ISRC3DEC3" }, \ | ||
1072 | { name, "ISRC3DEC4", "ISRC3DEC4" }, \ | ||
1073 | { name, "ISRC3INT1", "ISRC3INT1" }, \ | ||
1074 | { name, "ISRC3INT2", "ISRC3INT2" }, \ | ||
1075 | { name, "ISRC3INT3", "ISRC3INT3" }, \ | ||
1076 | { name, "ISRC3INT4", "ISRC3INT4" }, \ | ||
1077 | { name, "DSP1.1", "DSP1" }, \ | ||
1078 | { name, "DSP1.2", "DSP1" }, \ | ||
1079 | { name, "DSP1.3", "DSP1" }, \ | ||
1080 | { name, "DSP1.4", "DSP1" }, \ | ||
1081 | { name, "DSP1.5", "DSP1" }, \ | ||
1082 | { name, "DSP1.6", "DSP1" }, \ | ||
1083 | { name, "DSP2.1", "DSP2" }, \ | ||
1084 | { name, "DSP2.2", "DSP2" }, \ | ||
1085 | { name, "DSP2.3", "DSP2" }, \ | ||
1086 | { name, "DSP2.4", "DSP2" }, \ | ||
1087 | { name, "DSP2.5", "DSP2" }, \ | ||
1088 | { name, "DSP2.6", "DSP2" }, \ | ||
1089 | { name, "DSP3.1", "DSP3" }, \ | ||
1090 | { name, "DSP3.2", "DSP3" }, \ | ||
1091 | { name, "DSP3.3", "DSP3" }, \ | ||
1092 | { name, "DSP3.4", "DSP3" }, \ | ||
1093 | { name, "DSP3.5", "DSP3" }, \ | ||
1094 | { name, "DSP3.6", "DSP3" }, \ | ||
1095 | { name, "DSP4.1", "DSP4" }, \ | ||
1096 | { name, "DSP4.2", "DSP4" }, \ | ||
1097 | { name, "DSP4.3", "DSP4" }, \ | ||
1098 | { name, "DSP4.4", "DSP4" }, \ | ||
1099 | { name, "DSP4.5", "DSP4" }, \ | ||
1100 | { name, "DSP4.6", "DSP4" } | ||
834 | 1101 | ||
835 | static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | 1102 | static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { |
836 | { "AIF2 Capture", NULL, "DBVDD2" }, | 1103 | { "AIF2 Capture", NULL, "DBVDD2" }, |
@@ -902,9 +1169,17 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
902 | 1169 | ||
903 | { "AIF2 Capture", NULL, "AIF2TX1" }, | 1170 | { "AIF2 Capture", NULL, "AIF2TX1" }, |
904 | { "AIF2 Capture", NULL, "AIF2TX2" }, | 1171 | { "AIF2 Capture", NULL, "AIF2TX2" }, |
1172 | { "AIF2 Capture", NULL, "AIF2TX3" }, | ||
1173 | { "AIF2 Capture", NULL, "AIF2TX4" }, | ||
1174 | { "AIF2 Capture", NULL, "AIF2TX5" }, | ||
1175 | { "AIF2 Capture", NULL, "AIF2TX6" }, | ||
905 | 1176 | ||
906 | { "AIF2RX1", NULL, "AIF2 Playback" }, | 1177 | { "AIF2RX1", NULL, "AIF2 Playback" }, |
907 | { "AIF2RX2", NULL, "AIF2 Playback" }, | 1178 | { "AIF2RX2", NULL, "AIF2 Playback" }, |
1179 | { "AIF2RX3", NULL, "AIF2 Playback" }, | ||
1180 | { "AIF2RX4", NULL, "AIF2 Playback" }, | ||
1181 | { "AIF2RX5", NULL, "AIF2 Playback" }, | ||
1182 | { "AIF2RX6", NULL, "AIF2 Playback" }, | ||
908 | 1183 | ||
909 | { "AIF3 Capture", NULL, "AIF3TX1" }, | 1184 | { "AIF3 Capture", NULL, "AIF3TX1" }, |
910 | { "AIF3 Capture", NULL, "AIF3TX2" }, | 1185 | { "AIF3 Capture", NULL, "AIF3TX2" }, |
@@ -988,6 +1263,10 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
988 | 1263 | ||
989 | ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), | 1264 | ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), |
990 | ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), | 1265 | ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), |
1266 | ARIZONA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"), | ||
1267 | ARIZONA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"), | ||
1268 | ARIZONA_MIXER_ROUTES("AIF2TX5", "AIF2TX5"), | ||
1269 | ARIZONA_MIXER_ROUTES("AIF2TX6", "AIF2TX6"), | ||
991 | 1270 | ||
992 | ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), | 1271 | ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), |
993 | ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), | 1272 | ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), |
@@ -1024,6 +1303,41 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
1024 | ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"), | 1303 | ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"), |
1025 | ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"), | 1304 | ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"), |
1026 | 1305 | ||
1306 | ARIZONA_DSP_ROUTES("DSP1"), | ||
1307 | ARIZONA_DSP_ROUTES("DSP2"), | ||
1308 | ARIZONA_DSP_ROUTES("DSP3"), | ||
1309 | ARIZONA_DSP_ROUTES("DSP4"), | ||
1310 | |||
1311 | ARIZONA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), | ||
1312 | ARIZONA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), | ||
1313 | ARIZONA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"), | ||
1314 | ARIZONA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"), | ||
1315 | |||
1316 | ARIZONA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), | ||
1317 | ARIZONA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), | ||
1318 | ARIZONA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"), | ||
1319 | ARIZONA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"), | ||
1320 | |||
1321 | ARIZONA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), | ||
1322 | ARIZONA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), | ||
1323 | ARIZONA_MUX_ROUTES("ISRC2INT3", "ISRC2INT3"), | ||
1324 | ARIZONA_MUX_ROUTES("ISRC2INT4", "ISRC2INT4"), | ||
1325 | |||
1326 | ARIZONA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), | ||
1327 | ARIZONA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), | ||
1328 | ARIZONA_MUX_ROUTES("ISRC2DEC3", "ISRC2DEC3"), | ||
1329 | ARIZONA_MUX_ROUTES("ISRC2DEC4", "ISRC2DEC4"), | ||
1330 | |||
1331 | ARIZONA_MUX_ROUTES("ISRC3INT1", "ISRC3INT1"), | ||
1332 | ARIZONA_MUX_ROUTES("ISRC3INT2", "ISRC3INT2"), | ||
1333 | ARIZONA_MUX_ROUTES("ISRC3INT3", "ISRC3INT3"), | ||
1334 | ARIZONA_MUX_ROUTES("ISRC3INT4", "ISRC3INT4"), | ||
1335 | |||
1336 | ARIZONA_MUX_ROUTES("ISRC3DEC1", "ISRC3DEC1"), | ||
1337 | ARIZONA_MUX_ROUTES("ISRC3DEC2", "ISRC3DEC2"), | ||
1338 | ARIZONA_MUX_ROUTES("ISRC3DEC3", "ISRC3DEC3"), | ||
1339 | ARIZONA_MUX_ROUTES("ISRC3DEC4", "ISRC3DEC4"), | ||
1340 | |||
1027 | { "AEC Loopback", "HPOUT1L", "OUT1L" }, | 1341 | { "AEC Loopback", "HPOUT1L", "OUT1L" }, |
1028 | { "AEC Loopback", "HPOUT1R", "OUT1R" }, | 1342 | { "AEC Loopback", "HPOUT1R", "OUT1R" }, |
1029 | { "HPOUT1L", NULL, "OUT1L" }, | 1343 | { "HPOUT1L", NULL, "OUT1L" }, |
@@ -1037,7 +1351,7 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
1037 | { "AEC Loopback", "HPOUT3L", "OUT3L" }, | 1351 | { "AEC Loopback", "HPOUT3L", "OUT3L" }, |
1038 | { "AEC Loopback", "HPOUT3R", "OUT3R" }, | 1352 | { "AEC Loopback", "HPOUT3R", "OUT3R" }, |
1039 | { "HPOUT3L", NULL, "OUT3L" }, | 1353 | { "HPOUT3L", NULL, "OUT3L" }, |
1040 | { "HPOUT3R", NULL, "OUT3L" }, | 1354 | { "HPOUT3R", NULL, "OUT3R" }, |
1041 | 1355 | ||
1042 | { "AEC Loopback", "SPKOUTL", "OUT4L" }, | 1356 | { "AEC Loopback", "SPKOUTL", "OUT4L" }, |
1043 | { "SPKOUTLN", NULL, "OUT4L" }, | 1357 | { "SPKOUTLN", NULL, "OUT4L" }, |
@@ -1120,14 +1434,14 @@ static struct snd_soc_dai_driver wm5110_dai[] = { | |||
1120 | .playback = { | 1434 | .playback = { |
1121 | .stream_name = "AIF2 Playback", | 1435 | .stream_name = "AIF2 Playback", |
1122 | .channels_min = 1, | 1436 | .channels_min = 1, |
1123 | .channels_max = 2, | 1437 | .channels_max = 6, |
1124 | .rates = WM5110_RATES, | 1438 | .rates = WM5110_RATES, |
1125 | .formats = WM5110_FORMATS, | 1439 | .formats = WM5110_FORMATS, |
1126 | }, | 1440 | }, |
1127 | .capture = { | 1441 | .capture = { |
1128 | .stream_name = "AIF2 Capture", | 1442 | .stream_name = "AIF2 Capture", |
1129 | .channels_min = 1, | 1443 | .channels_min = 1, |
1130 | .channels_max = 2, | 1444 | .channels_max = 6, |
1131 | .rates = WM5110_RATES, | 1445 | .rates = WM5110_RATES, |
1132 | .formats = WM5110_FORMATS, | 1446 | .formats = WM5110_FORMATS, |
1133 | }, | 1447 | }, |
@@ -1229,6 +1543,10 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) | |||
1229 | arizona_init_spk(codec); | 1543 | arizona_init_spk(codec); |
1230 | arizona_init_gpio(codec); | 1544 | arizona_init_gpio(codec); |
1231 | 1545 | ||
1546 | ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8); | ||
1547 | if (ret != 0) | ||
1548 | return ret; | ||
1549 | |||
1232 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); | 1550 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); |
1233 | 1551 | ||
1234 | priv->core.arizona->dapm = &codec->dapm; | 1552 | priv->core.arizona->dapm = &codec->dapm; |
@@ -1283,7 +1601,7 @@ static int wm5110_probe(struct platform_device *pdev) | |||
1283 | { | 1601 | { |
1284 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | 1602 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); |
1285 | struct wm5110_priv *wm5110; | 1603 | struct wm5110_priv *wm5110; |
1286 | int i; | 1604 | int i, ret; |
1287 | 1605 | ||
1288 | wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv), | 1606 | wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv), |
1289 | GFP_KERNEL); | 1607 | GFP_KERNEL); |
@@ -1294,6 +1612,24 @@ static int wm5110_probe(struct platform_device *pdev) | |||
1294 | wm5110->core.arizona = arizona; | 1612 | wm5110->core.arizona = arizona; |
1295 | wm5110->core.num_inputs = 8; | 1613 | wm5110->core.num_inputs = 8; |
1296 | 1614 | ||
1615 | for (i = 0; i < WM5110_NUM_ADSP; i++) { | ||
1616 | wm5110->core.adsp[i].part = "wm5110"; | ||
1617 | wm5110->core.adsp[i].num = i + 1; | ||
1618 | wm5110->core.adsp[i].type = WMFW_ADSP2; | ||
1619 | wm5110->core.adsp[i].dev = arizona->dev; | ||
1620 | wm5110->core.adsp[i].regmap = arizona->regmap; | ||
1621 | |||
1622 | wm5110->core.adsp[i].base = ARIZONA_DSP1_CONTROL_1 | ||
1623 | + (0x100 * i); | ||
1624 | wm5110->core.adsp[i].mem = wm5110_dsp_regions[i]; | ||
1625 | wm5110->core.adsp[i].num_mems | ||
1626 | = ARRAY_SIZE(wm5110_dsp1_regions); | ||
1627 | |||
1628 | ret = wm_adsp2_init(&wm5110->core.adsp[i], false); | ||
1629 | if (ret != 0) | ||
1630 | return ret; | ||
1631 | } | ||
1632 | |||
1297 | for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) | 1633 | for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) |
1298 | wm5110->fll[i].vco_mult = 3; | 1634 | wm5110->fll[i].vco_mult = 3; |
1299 | 1635 | ||
@@ -1304,6 +1640,12 @@ static int wm5110_probe(struct platform_device *pdev) | |||
1304 | ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, | 1640 | ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, |
1305 | &wm5110->fll[1]); | 1641 | &wm5110->fll[1]); |
1306 | 1642 | ||
1643 | /* SR2 fixed at 8kHz, SR3 fixed at 16kHz */ | ||
1644 | regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_2, | ||
1645 | ARIZONA_SAMPLE_RATE_2_MASK, 0x11); | ||
1646 | regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_3, | ||
1647 | ARIZONA_SAMPLE_RATE_3_MASK, 0x12); | ||
1648 | |||
1307 | for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++) | 1649 | for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++) |
1308 | arizona_init_dai(&wm5110->core, i); | 1650 | arizona_init_dai(&wm5110->core, i); |
1309 | 1651 | ||
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 6ed5433943ea..7df7d4572755 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -684,7 +684,7 @@ static struct spi_driver wm8510_spi_driver = { | |||
684 | }; | 684 | }; |
685 | #endif /* CONFIG_SPI_MASTER */ | 685 | #endif /* CONFIG_SPI_MASTER */ |
686 | 686 | ||
687 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 687 | #if IS_ENABLED(CONFIG_I2C) |
688 | static int wm8510_i2c_probe(struct i2c_client *i2c, | 688 | static int wm8510_i2c_probe(struct i2c_client *i2c, |
689 | const struct i2c_device_id *id) | 689 | const struct i2c_device_id *id) |
690 | { | 690 | { |
@@ -735,7 +735,7 @@ static struct i2c_driver wm8510_i2c_driver = { | |||
735 | static int __init wm8510_modinit(void) | 735 | static int __init wm8510_modinit(void) |
736 | { | 736 | { |
737 | int ret = 0; | 737 | int ret = 0; |
738 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 738 | #if IS_ENABLED(CONFIG_I2C) |
739 | ret = i2c_add_driver(&wm8510_i2c_driver); | 739 | ret = i2c_add_driver(&wm8510_i2c_driver); |
740 | if (ret != 0) { | 740 | if (ret != 0) { |
741 | printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n", | 741 | printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n", |
@@ -755,7 +755,7 @@ module_init(wm8510_modinit); | |||
755 | 755 | ||
756 | static void __exit wm8510_exit(void) | 756 | static void __exit wm8510_exit(void) |
757 | { | 757 | { |
758 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 758 | #if IS_ENABLED(CONFIG_I2C) |
759 | i2c_del_driver(&wm8510_i2c_driver); | 759 | i2c_del_driver(&wm8510_i2c_driver); |
760 | #endif | 760 | #endif |
761 | #if defined(CONFIG_SPI_MASTER) | 761 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 139bf9ac9407..74d106dc7667 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -452,7 +452,7 @@ static const struct regmap_config wm8523_regmap = { | |||
452 | .volatile_reg = wm8523_volatile_register, | 452 | .volatile_reg = wm8523_volatile_register, |
453 | }; | 453 | }; |
454 | 454 | ||
455 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 455 | #if IS_ENABLED(CONFIG_I2C) |
456 | static int wm8523_i2c_probe(struct i2c_client *i2c, | 456 | static int wm8523_i2c_probe(struct i2c_client *i2c, |
457 | const struct i2c_device_id *id) | 457 | const struct i2c_device_id *id) |
458 | { | 458 | { |
@@ -555,7 +555,7 @@ static struct i2c_driver wm8523_i2c_driver = { | |||
555 | static int __init wm8523_modinit(void) | 555 | static int __init wm8523_modinit(void) |
556 | { | 556 | { |
557 | int ret; | 557 | int ret; |
558 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 558 | #if IS_ENABLED(CONFIG_I2C) |
559 | ret = i2c_add_driver(&wm8523_i2c_driver); | 559 | ret = i2c_add_driver(&wm8523_i2c_driver); |
560 | if (ret != 0) { | 560 | if (ret != 0) { |
561 | printk(KERN_ERR "Failed to register WM8523 I2C driver: %d\n", | 561 | printk(KERN_ERR "Failed to register WM8523 I2C driver: %d\n", |
@@ -568,7 +568,7 @@ module_init(wm8523_modinit); | |||
568 | 568 | ||
569 | static void __exit wm8523_exit(void) | 569 | static void __exit wm8523_exit(void) |
570 | { | 570 | { |
571 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 571 | #if IS_ENABLED(CONFIG_I2C) |
572 | i2c_del_driver(&wm8523_i2c_driver); | 572 | i2c_del_driver(&wm8523_i2c_driver); |
573 | #endif | 573 | #endif |
574 | } | 574 | } |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 08a414b57b1e..318989acbbe5 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -941,7 +941,7 @@ static const struct regmap_config wm8580_regmap = { | |||
941 | .volatile_reg = wm8580_volatile, | 941 | .volatile_reg = wm8580_volatile, |
942 | }; | 942 | }; |
943 | 943 | ||
944 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 944 | #if IS_ENABLED(CONFIG_I2C) |
945 | static int wm8580_i2c_probe(struct i2c_client *i2c, | 945 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
946 | const struct i2c_device_id *id) | 946 | const struct i2c_device_id *id) |
947 | { | 947 | { |
@@ -1003,7 +1003,7 @@ static int __init wm8580_modinit(void) | |||
1003 | { | 1003 | { |
1004 | int ret = 0; | 1004 | int ret = 0; |
1005 | 1005 | ||
1006 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1006 | #if IS_ENABLED(CONFIG_I2C) |
1007 | ret = i2c_add_driver(&wm8580_i2c_driver); | 1007 | ret = i2c_add_driver(&wm8580_i2c_driver); |
1008 | if (ret != 0) { | 1008 | if (ret != 0) { |
1009 | pr_err("Failed to register WM8580 I2C driver: %d\n", ret); | 1009 | pr_err("Failed to register WM8580 I2C driver: %d\n", ret); |
@@ -1016,7 +1016,7 @@ module_init(wm8580_modinit); | |||
1016 | 1016 | ||
1017 | static void __exit wm8580_exit(void) | 1017 | static void __exit wm8580_exit(void) |
1018 | { | 1018 | { |
1019 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1019 | #if IS_ENABLED(CONFIG_I2C) |
1020 | i2c_del_driver(&wm8580_i2c_driver); | 1020 | i2c_del_driver(&wm8580_i2c_driver); |
1021 | #endif | 1021 | #endif |
1022 | } | 1022 | } |
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 5b428b060d41..d99f948c513c 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -469,7 +469,7 @@ static struct spi_driver wm8711_spi_driver = { | |||
469 | }; | 469 | }; |
470 | #endif /* CONFIG_SPI_MASTER */ | 470 | #endif /* CONFIG_SPI_MASTER */ |
471 | 471 | ||
472 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 472 | #if IS_ENABLED(CONFIG_I2C) |
473 | static int wm8711_i2c_probe(struct i2c_client *client, | 473 | static int wm8711_i2c_probe(struct i2c_client *client, |
474 | const struct i2c_device_id *id) | 474 | const struct i2c_device_id *id) |
475 | { | 475 | { |
@@ -520,7 +520,7 @@ static struct i2c_driver wm8711_i2c_driver = { | |||
520 | static int __init wm8711_modinit(void) | 520 | static int __init wm8711_modinit(void) |
521 | { | 521 | { |
522 | int ret; | 522 | int ret; |
523 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 523 | #if IS_ENABLED(CONFIG_I2C) |
524 | ret = i2c_add_driver(&wm8711_i2c_driver); | 524 | ret = i2c_add_driver(&wm8711_i2c_driver); |
525 | if (ret != 0) { | 525 | if (ret != 0) { |
526 | printk(KERN_ERR "Failed to register WM8711 I2C driver: %d\n", | 526 | printk(KERN_ERR "Failed to register WM8711 I2C driver: %d\n", |
@@ -540,7 +540,7 @@ module_init(wm8711_modinit); | |||
540 | 540 | ||
541 | static void __exit wm8711_exit(void) | 541 | static void __exit wm8711_exit(void) |
542 | { | 542 | { |
543 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 543 | #if IS_ENABLED(CONFIG_I2C) |
544 | i2c_del_driver(&wm8711_i2c_driver); | 544 | i2c_del_driver(&wm8711_i2c_driver); |
545 | #endif | 545 | #endif |
546 | #if defined(CONFIG_SPI_MASTER) | 546 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index c6a292dcded0..cd89033e84c0 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -320,7 +320,7 @@ static struct spi_driver wm8728_spi_driver = { | |||
320 | }; | 320 | }; |
321 | #endif /* CONFIG_SPI_MASTER */ | 321 | #endif /* CONFIG_SPI_MASTER */ |
322 | 322 | ||
323 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 323 | #if IS_ENABLED(CONFIG_I2C) |
324 | static int wm8728_i2c_probe(struct i2c_client *i2c, | 324 | static int wm8728_i2c_probe(struct i2c_client *i2c, |
325 | const struct i2c_device_id *id) | 325 | const struct i2c_device_id *id) |
326 | { | 326 | { |
@@ -371,7 +371,7 @@ static struct i2c_driver wm8728_i2c_driver = { | |||
371 | static int __init wm8728_modinit(void) | 371 | static int __init wm8728_modinit(void) |
372 | { | 372 | { |
373 | int ret = 0; | 373 | int ret = 0; |
374 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 374 | #if IS_ENABLED(CONFIG_I2C) |
375 | ret = i2c_add_driver(&wm8728_i2c_driver); | 375 | ret = i2c_add_driver(&wm8728_i2c_driver); |
376 | if (ret != 0) { | 376 | if (ret != 0) { |
377 | printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n", | 377 | printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n", |
@@ -391,7 +391,7 @@ module_init(wm8728_modinit); | |||
391 | 391 | ||
392 | static void __exit wm8728_exit(void) | 392 | static void __exit wm8728_exit(void) |
393 | { | 393 | { |
394 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 394 | #if IS_ENABLED(CONFIG_I2C) |
395 | i2c_del_driver(&wm8728_i2c_driver); | 395 | i2c_del_driver(&wm8728_i2c_driver); |
396 | #endif | 396 | #endif |
397 | #if defined(CONFIG_SPI_MASTER) | 397 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 456bb8c6d759..029720366ff8 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -447,10 +447,10 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
447 | iface |= 0x0001; | 447 | iface |= 0x0001; |
448 | break; | 448 | break; |
449 | case SND_SOC_DAIFMT_DSP_A: | 449 | case SND_SOC_DAIFMT_DSP_A: |
450 | iface |= 0x0003; | 450 | iface |= 0x0013; |
451 | break; | 451 | break; |
452 | case SND_SOC_DAIFMT_DSP_B: | 452 | case SND_SOC_DAIFMT_DSP_B: |
453 | iface |= 0x0013; | 453 | iface |= 0x0003; |
454 | break; | 454 | break; |
455 | default: | 455 | default: |
456 | return -EINVAL; | 456 | return -EINVAL; |
@@ -732,7 +732,7 @@ static struct spi_driver wm8731_spi_driver = { | |||
732 | }; | 732 | }; |
733 | #endif /* CONFIG_SPI_MASTER */ | 733 | #endif /* CONFIG_SPI_MASTER */ |
734 | 734 | ||
735 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 735 | #if IS_ENABLED(CONFIG_I2C) |
736 | static int wm8731_i2c_probe(struct i2c_client *i2c, | 736 | static int wm8731_i2c_probe(struct i2c_client *i2c, |
737 | const struct i2c_device_id *id) | 737 | const struct i2c_device_id *id) |
738 | { | 738 | { |
@@ -791,7 +791,7 @@ static struct i2c_driver wm8731_i2c_driver = { | |||
791 | static int __init wm8731_modinit(void) | 791 | static int __init wm8731_modinit(void) |
792 | { | 792 | { |
793 | int ret = 0; | 793 | int ret = 0; |
794 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 794 | #if IS_ENABLED(CONFIG_I2C) |
795 | ret = i2c_add_driver(&wm8731_i2c_driver); | 795 | ret = i2c_add_driver(&wm8731_i2c_driver); |
796 | if (ret != 0) { | 796 | if (ret != 0) { |
797 | printk(KERN_ERR "Failed to register WM8731 I2C driver: %d\n", | 797 | printk(KERN_ERR "Failed to register WM8731 I2C driver: %d\n", |
@@ -811,7 +811,7 @@ module_init(wm8731_modinit); | |||
811 | 811 | ||
812 | static void __exit wm8731_exit(void) | 812 | static void __exit wm8731_exit(void) |
813 | { | 813 | { |
814 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 814 | #if IS_ENABLED(CONFIG_I2C) |
815 | i2c_del_driver(&wm8731_i2c_driver); | 815 | i2c_del_driver(&wm8731_i2c_driver); |
816 | #endif | 816 | #endif |
817 | #if defined(CONFIG_SPI_MASTER) | 817 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index b18813cc7ba9..2895c8d3b5e4 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -500,7 +500,7 @@ static const struct regmap_config wm8741_regmap = { | |||
500 | .readable_reg = wm8741_readable, | 500 | .readable_reg = wm8741_readable, |
501 | }; | 501 | }; |
502 | 502 | ||
503 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 503 | #if IS_ENABLED(CONFIG_I2C) |
504 | static int wm8741_i2c_probe(struct i2c_client *i2c, | 504 | static int wm8741_i2c_probe(struct i2c_client *i2c, |
505 | const struct i2c_device_id *id) | 505 | const struct i2c_device_id *id) |
506 | { | 506 | { |
@@ -617,7 +617,7 @@ static int __init wm8741_modinit(void) | |||
617 | { | 617 | { |
618 | int ret = 0; | 618 | int ret = 0; |
619 | 619 | ||
620 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 620 | #if IS_ENABLED(CONFIG_I2C) |
621 | ret = i2c_add_driver(&wm8741_i2c_driver); | 621 | ret = i2c_add_driver(&wm8741_i2c_driver); |
622 | if (ret != 0) | 622 | if (ret != 0) |
623 | pr_err("Failed to register WM8741 I2C driver: %d\n", ret); | 623 | pr_err("Failed to register WM8741 I2C driver: %d\n", ret); |
@@ -639,7 +639,7 @@ static void __exit wm8741_exit(void) | |||
639 | #if defined(CONFIG_SPI_MASTER) | 639 | #if defined(CONFIG_SPI_MASTER) |
640 | spi_unregister_driver(&wm8741_spi_driver); | 640 | spi_unregister_driver(&wm8741_spi_driver); |
641 | #endif | 641 | #endif |
642 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 642 | #if IS_ENABLED(CONFIG_I2C) |
643 | i2c_del_driver(&wm8741_i2c_driver); | 643 | i2c_del_driver(&wm8741_i2c_driver); |
644 | #endif | 644 | #endif |
645 | } | 645 | } |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 50d5ff616232..78616a638a55 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -816,7 +816,7 @@ static struct spi_driver wm8750_spi_driver = { | |||
816 | }; | 816 | }; |
817 | #endif /* CONFIG_SPI_MASTER */ | 817 | #endif /* CONFIG_SPI_MASTER */ |
818 | 818 | ||
819 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 819 | #if IS_ENABLED(CONFIG_I2C) |
820 | static int wm8750_i2c_probe(struct i2c_client *i2c, | 820 | static int wm8750_i2c_probe(struct i2c_client *i2c, |
821 | const struct i2c_device_id *id) | 821 | const struct i2c_device_id *id) |
822 | { | 822 | { |
@@ -868,7 +868,7 @@ static struct i2c_driver wm8750_i2c_driver = { | |||
868 | static int __init wm8750_modinit(void) | 868 | static int __init wm8750_modinit(void) |
869 | { | 869 | { |
870 | int ret = 0; | 870 | int ret = 0; |
871 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 871 | #if IS_ENABLED(CONFIG_I2C) |
872 | ret = i2c_add_driver(&wm8750_i2c_driver); | 872 | ret = i2c_add_driver(&wm8750_i2c_driver); |
873 | if (ret != 0) { | 873 | if (ret != 0) { |
874 | printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n", | 874 | printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n", |
@@ -888,7 +888,7 @@ module_init(wm8750_modinit); | |||
888 | 888 | ||
889 | static void __exit wm8750_exit(void) | 889 | static void __exit wm8750_exit(void) |
890 | { | 890 | { |
891 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 891 | #if IS_ENABLED(CONFIG_I2C) |
892 | i2c_del_driver(&wm8750_i2c_driver); | 892 | i2c_del_driver(&wm8750_i2c_driver); |
893 | #endif | 893 | #endif |
894 | #if defined(CONFIG_SPI_MASTER) | 894 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index d96ebf52d953..be85da93a268 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -1596,7 +1596,7 @@ static struct spi_driver wm8753_spi_driver = { | |||
1596 | }; | 1596 | }; |
1597 | #endif /* CONFIG_SPI_MASTER */ | 1597 | #endif /* CONFIG_SPI_MASTER */ |
1598 | 1598 | ||
1599 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1599 | #if IS_ENABLED(CONFIG_I2C) |
1600 | static int wm8753_i2c_probe(struct i2c_client *i2c, | 1600 | static int wm8753_i2c_probe(struct i2c_client *i2c, |
1601 | const struct i2c_device_id *id) | 1601 | const struct i2c_device_id *id) |
1602 | { | 1602 | { |
@@ -1653,7 +1653,7 @@ static struct i2c_driver wm8753_i2c_driver = { | |||
1653 | static int __init wm8753_modinit(void) | 1653 | static int __init wm8753_modinit(void) |
1654 | { | 1654 | { |
1655 | int ret = 0; | 1655 | int ret = 0; |
1656 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1656 | #if IS_ENABLED(CONFIG_I2C) |
1657 | ret = i2c_add_driver(&wm8753_i2c_driver); | 1657 | ret = i2c_add_driver(&wm8753_i2c_driver); |
1658 | if (ret != 0) { | 1658 | if (ret != 0) { |
1659 | printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n", | 1659 | printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n", |
@@ -1673,7 +1673,7 @@ module_init(wm8753_modinit); | |||
1673 | 1673 | ||
1674 | static void __exit wm8753_exit(void) | 1674 | static void __exit wm8753_exit(void) |
1675 | { | 1675 | { |
1676 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1676 | #if IS_ENABLED(CONFIG_I2C) |
1677 | i2c_del_driver(&wm8753_i2c_driver); | 1677 | i2c_del_driver(&wm8753_i2c_driver); |
1678 | #endif | 1678 | #endif |
1679 | #if defined(CONFIG_SPI_MASTER) | 1679 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 942d58e455f3..ef8246725232 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -532,7 +532,7 @@ static struct spi_driver wm8776_spi_driver = { | |||
532 | }; | 532 | }; |
533 | #endif /* CONFIG_SPI_MASTER */ | 533 | #endif /* CONFIG_SPI_MASTER */ |
534 | 534 | ||
535 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 535 | #if IS_ENABLED(CONFIG_I2C) |
536 | static int wm8776_i2c_probe(struct i2c_client *i2c, | 536 | static int wm8776_i2c_probe(struct i2c_client *i2c, |
537 | const struct i2c_device_id *id) | 537 | const struct i2c_device_id *id) |
538 | { | 538 | { |
@@ -584,7 +584,7 @@ static struct i2c_driver wm8776_i2c_driver = { | |||
584 | static int __init wm8776_modinit(void) | 584 | static int __init wm8776_modinit(void) |
585 | { | 585 | { |
586 | int ret = 0; | 586 | int ret = 0; |
587 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 587 | #if IS_ENABLED(CONFIG_I2C) |
588 | ret = i2c_add_driver(&wm8776_i2c_driver); | 588 | ret = i2c_add_driver(&wm8776_i2c_driver); |
589 | if (ret != 0) { | 589 | if (ret != 0) { |
590 | printk(KERN_ERR "Failed to register wm8776 I2C driver: %d\n", | 590 | printk(KERN_ERR "Failed to register wm8776 I2C driver: %d\n", |
@@ -604,7 +604,7 @@ module_init(wm8776_modinit); | |||
604 | 604 | ||
605 | static void __exit wm8776_exit(void) | 605 | static void __exit wm8776_exit(void) |
606 | { | 606 | { |
607 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 607 | #if IS_ENABLED(CONFIG_I2C) |
608 | i2c_del_driver(&wm8776_i2c_driver); | 608 | i2c_del_driver(&wm8776_i2c_driver); |
609 | #endif | 609 | #endif |
610 | #if defined(CONFIG_SPI_MASTER) | 610 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 1704b1e119cb..9bc8206a6807 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -739,7 +739,7 @@ static struct spi_driver wm8804_spi_driver = { | |||
739 | }; | 739 | }; |
740 | #endif | 740 | #endif |
741 | 741 | ||
742 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 742 | #if IS_ENABLED(CONFIG_I2C) |
743 | static int wm8804_i2c_probe(struct i2c_client *i2c, | 743 | static int wm8804_i2c_probe(struct i2c_client *i2c, |
744 | const struct i2c_device_id *id) | 744 | const struct i2c_device_id *id) |
745 | { | 745 | { |
@@ -791,7 +791,7 @@ static int __init wm8804_modinit(void) | |||
791 | { | 791 | { |
792 | int ret = 0; | 792 | int ret = 0; |
793 | 793 | ||
794 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 794 | #if IS_ENABLED(CONFIG_I2C) |
795 | ret = i2c_add_driver(&wm8804_i2c_driver); | 795 | ret = i2c_add_driver(&wm8804_i2c_driver); |
796 | if (ret) { | 796 | if (ret) { |
797 | printk(KERN_ERR "Failed to register wm8804 I2C driver: %d\n", | 797 | printk(KERN_ERR "Failed to register wm8804 I2C driver: %d\n", |
@@ -811,7 +811,7 @@ module_init(wm8804_modinit); | |||
811 | 811 | ||
812 | static void __exit wm8804_exit(void) | 812 | static void __exit wm8804_exit(void) |
813 | { | 813 | { |
814 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 814 | #if IS_ENABLED(CONFIG_I2C) |
815 | i2c_del_driver(&wm8804_i2c_driver); | 815 | i2c_del_driver(&wm8804_i2c_driver); |
816 | #endif | 816 | #endif |
817 | #if defined(CONFIG_SPI_MASTER) | 817 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 734209e252c3..e98bc7038a08 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -1288,7 +1288,7 @@ static struct spi_driver wm8900_spi_driver = { | |||
1288 | }; | 1288 | }; |
1289 | #endif /* CONFIG_SPI_MASTER */ | 1289 | #endif /* CONFIG_SPI_MASTER */ |
1290 | 1290 | ||
1291 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1291 | #if IS_ENABLED(CONFIG_I2C) |
1292 | static int wm8900_i2c_probe(struct i2c_client *i2c, | 1292 | static int wm8900_i2c_probe(struct i2c_client *i2c, |
1293 | const struct i2c_device_id *id) | 1293 | const struct i2c_device_id *id) |
1294 | { | 1294 | { |
@@ -1338,7 +1338,7 @@ static struct i2c_driver wm8900_i2c_driver = { | |||
1338 | static int __init wm8900_modinit(void) | 1338 | static int __init wm8900_modinit(void) |
1339 | { | 1339 | { |
1340 | int ret = 0; | 1340 | int ret = 0; |
1341 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1341 | #if IS_ENABLED(CONFIG_I2C) |
1342 | ret = i2c_add_driver(&wm8900_i2c_driver); | 1342 | ret = i2c_add_driver(&wm8900_i2c_driver); |
1343 | if (ret != 0) { | 1343 | if (ret != 0) { |
1344 | printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n", | 1344 | printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n", |
@@ -1358,7 +1358,7 @@ module_init(wm8900_modinit); | |||
1358 | 1358 | ||
1359 | static void __exit wm8900_exit(void) | 1359 | static void __exit wm8900_exit(void) |
1360 | { | 1360 | { |
1361 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1361 | #if IS_ENABLED(CONFIG_I2C) |
1362 | i2c_del_driver(&wm8900_i2c_driver); | 1362 | i2c_del_driver(&wm8900_i2c_driver); |
1363 | #endif | 1363 | #endif |
1364 | #if defined(CONFIG_SPI_MASTER) | 1364 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 3938fb1c203e..53bbfac6a83a 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -1444,7 +1444,7 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
1444 | 1444 | ||
1445 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 1445 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
1446 | case SND_SOC_DAIFMT_DSP_B: | 1446 | case SND_SOC_DAIFMT_DSP_B: |
1447 | aif1 |= WM8904_AIF_LRCLK_INV; | 1447 | aif1 |= 0x3 | WM8904_AIF_LRCLK_INV; |
1448 | case SND_SOC_DAIFMT_DSP_A: | 1448 | case SND_SOC_DAIFMT_DSP_A: |
1449 | aif1 |= 0x3; | 1449 | aif1 |= 0x3; |
1450 | break; | 1450 | break; |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index b1591c61c254..b404c26c1753 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/pm.h> | 29 | #include <linux/pm.h> |
30 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
31 | #include <linux/spi/spi.h> | 31 | #include <linux/regmap.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <sound/core.h> | 33 | #include <sound/core.h> |
34 | #include <sound/pcm.h> | 34 | #include <sound/pcm.h> |
@@ -41,78 +41,116 @@ | |||
41 | 41 | ||
42 | struct wm8940_priv { | 42 | struct wm8940_priv { |
43 | unsigned int sysclk; | 43 | unsigned int sysclk; |
44 | enum snd_soc_control_type control_type; | 44 | struct regmap *regmap; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | static int wm8940_volatile_register(struct snd_soc_codec *codec, | 47 | static bool wm8940_volatile_register(struct device *dev, unsigned int reg) |
48 | unsigned int reg) | ||
49 | { | 48 | { |
50 | switch (reg) { | 49 | switch (reg) { |
51 | case WM8940_SOFTRESET: | 50 | case WM8940_SOFTRESET: |
52 | return 1; | 51 | return true; |
53 | default: | 52 | default: |
54 | return 0; | 53 | return false; |
54 | } | ||
55 | } | ||
56 | |||
57 | static bool wm8940_readable_register(struct device *dev, unsigned int reg) | ||
58 | { | ||
59 | switch (reg) { | ||
60 | case WM8940_SOFTRESET: | ||
61 | case WM8940_POWER1: | ||
62 | case WM8940_POWER2: | ||
63 | case WM8940_POWER3: | ||
64 | case WM8940_IFACE: | ||
65 | case WM8940_COMPANDINGCTL: | ||
66 | case WM8940_CLOCK: | ||
67 | case WM8940_ADDCNTRL: | ||
68 | case WM8940_GPIO: | ||
69 | case WM8940_CTLINT: | ||
70 | case WM8940_DAC: | ||
71 | case WM8940_DACVOL: | ||
72 | case WM8940_ADC: | ||
73 | case WM8940_ADCVOL: | ||
74 | case WM8940_NOTCH1: | ||
75 | case WM8940_NOTCH2: | ||
76 | case WM8940_NOTCH3: | ||
77 | case WM8940_NOTCH4: | ||
78 | case WM8940_NOTCH5: | ||
79 | case WM8940_NOTCH6: | ||
80 | case WM8940_NOTCH7: | ||
81 | case WM8940_NOTCH8: | ||
82 | case WM8940_DACLIM1: | ||
83 | case WM8940_DACLIM2: | ||
84 | case WM8940_ALC1: | ||
85 | case WM8940_ALC2: | ||
86 | case WM8940_ALC3: | ||
87 | case WM8940_NOISEGATE: | ||
88 | case WM8940_PLLN: | ||
89 | case WM8940_PLLK1: | ||
90 | case WM8940_PLLK2: | ||
91 | case WM8940_PLLK3: | ||
92 | case WM8940_ALC4: | ||
93 | case WM8940_INPUTCTL: | ||
94 | case WM8940_PGAGAIN: | ||
95 | case WM8940_ADCBOOST: | ||
96 | case WM8940_OUTPUTCTL: | ||
97 | case WM8940_SPKMIX: | ||
98 | case WM8940_SPKVOL: | ||
99 | case WM8940_MONOMIX: | ||
100 | return true; | ||
101 | default: | ||
102 | return false; | ||
55 | } | 103 | } |
56 | } | 104 | } |
57 | 105 | ||
58 | static u16 wm8940_reg_defaults[] = { | 106 | static const struct reg_default wm8940_reg_defaults[] = { |
59 | 0x8940, /* Soft Reset */ | 107 | { 0x1, 0x0000 }, /* Power 1 */ |
60 | 0x0000, /* Power 1 */ | 108 | { 0x2, 0x0000 }, /* Power 2 */ |
61 | 0x0000, /* Power 2 */ | 109 | { 0x3, 0x0000 }, /* Power 3 */ |
62 | 0x0000, /* Power 3 */ | 110 | { 0x4, 0x0010 }, /* Interface Control */ |
63 | 0x0010, /* Interface Control */ | 111 | { 0x5, 0x0000 }, /* Companding Control */ |
64 | 0x0000, /* Companding Control */ | 112 | { 0x6, 0x0140 }, /* Clock Control */ |
65 | 0x0140, /* Clock Control */ | 113 | { 0x7, 0x0000 }, /* Additional Controls */ |
66 | 0x0000, /* Additional Controls */ | 114 | { 0x8, 0x0000 }, /* GPIO Control */ |
67 | 0x0000, /* GPIO Control */ | 115 | { 0x9, 0x0002 }, /* Auto Increment Control */ |
68 | 0x0002, /* Auto Increment Control */ | 116 | { 0xa, 0x0000 }, /* DAC Control */ |
69 | 0x0000, /* DAC Control */ | 117 | { 0xb, 0x00FF }, /* DAC Volume */ |
70 | 0x00FF, /* DAC Volume */ | 118 | |
71 | 0, | 119 | { 0xe, 0x0100 }, /* ADC Control */ |
72 | 0, | 120 | { 0xf, 0x00FF }, /* ADC Volume */ |
73 | 0x0100, /* ADC Control */ | 121 | { 0x10, 0x0000 }, /* Notch Filter 1 Control 1 */ |
74 | 0x00FF, /* ADC Volume */ | 122 | { 0x11, 0x0000 }, /* Notch Filter 1 Control 2 */ |
75 | 0x0000, /* Notch Filter 1 Control 1 */ | 123 | { 0x12, 0x0000 }, /* Notch Filter 2 Control 1 */ |
76 | 0x0000, /* Notch Filter 1 Control 2 */ | 124 | { 0x13, 0x0000 }, /* Notch Filter 2 Control 2 */ |
77 | 0x0000, /* Notch Filter 2 Control 1 */ | 125 | { 0x14, 0x0000 }, /* Notch Filter 3 Control 1 */ |
78 | 0x0000, /* Notch Filter 2 Control 2 */ | 126 | { 0x15, 0x0000 }, /* Notch Filter 3 Control 2 */ |
79 | 0x0000, /* Notch Filter 3 Control 1 */ | 127 | { 0x16, 0x0000 }, /* Notch Filter 4 Control 1 */ |
80 | 0x0000, /* Notch Filter 3 Control 2 */ | 128 | { 0x17, 0x0000 }, /* Notch Filter 4 Control 2 */ |
81 | 0x0000, /* Notch Filter 4 Control 1 */ | 129 | { 0x18, 0x0032 }, /* DAC Limit Control 1 */ |
82 | 0x0000, /* Notch Filter 4 Control 2 */ | 130 | { 0x19, 0x0000 }, /* DAC Limit Control 2 */ |
83 | 0x0032, /* DAC Limit Control 1 */ | 131 | |
84 | 0x0000, /* DAC Limit Control 2 */ | 132 | { 0x20, 0x0038 }, /* ALC Control 1 */ |
85 | 0, | 133 | { 0x21, 0x000B }, /* ALC Control 2 */ |
86 | 0, | 134 | { 0x22, 0x0032 }, /* ALC Control 3 */ |
87 | 0, | 135 | { 0x23, 0x0000 }, /* Noise Gate */ |
88 | 0, | 136 | { 0x24, 0x0041 }, /* PLLN */ |
89 | 0, | 137 | { 0x25, 0x000C }, /* PLLK1 */ |
90 | 0, | 138 | { 0x26, 0x0093 }, /* PLLK2 */ |
91 | 0x0038, /* ALC Control 1 */ | 139 | { 0x27, 0x00E9 }, /* PLLK3 */ |
92 | 0x000B, /* ALC Control 2 */ | 140 | |
93 | 0x0032, /* ALC Control 3 */ | 141 | { 0x2a, 0x0030 }, /* ALC Control 4 */ |
94 | 0x0000, /* Noise Gate */ | 142 | |
95 | 0x0041, /* PLLN */ | 143 | { 0x2c, 0x0002 }, /* Input Control */ |
96 | 0x000C, /* PLLK1 */ | 144 | { 0x2d, 0x0050 }, /* PGA Gain */ |
97 | 0x0093, /* PLLK2 */ | 145 | |
98 | 0x00E9, /* PLLK3 */ | 146 | { 0x2f, 0x0002 }, /* ADC Boost Control */ |
99 | 0, | 147 | |
100 | 0, | 148 | { 0x31, 0x0002 }, /* Output Control */ |
101 | 0x0030, /* ALC Control 4 */ | 149 | { 0x32, 0x0000 }, /* Speaker Mixer Control */ |
102 | 0, | 150 | |
103 | 0x0002, /* Input Control */ | 151 | { 0x36, 0x0079 }, /* Speaker Volume */ |
104 | 0x0050, /* PGA Gain */ | 152 | |
105 | 0, | 153 | { 0x38, 0x0000 }, /* Mono Mixer Control */ |
106 | 0x0002, /* ADC Boost Control */ | ||
107 | 0, | ||
108 | 0x0002, /* Output Control */ | ||
109 | 0x0000, /* Speaker Mixer Control */ | ||
110 | 0, | ||
111 | 0, | ||
112 | 0, | ||
113 | 0x0079, /* Speaker Volume */ | ||
114 | 0, | ||
115 | 0x0000, /* Mono Mixer Control */ | ||
116 | }; | 154 | }; |
117 | 155 | ||
118 | static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" }; | 156 | static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" }; |
@@ -264,7 +302,7 @@ static const struct snd_soc_dapm_widget wm8940_dapm_widgets[] = { | |||
264 | SND_SOC_DAPM_INPUT("AUX"), | 302 | SND_SOC_DAPM_INPUT("AUX"), |
265 | }; | 303 | }; |
266 | 304 | ||
267 | static const struct snd_soc_dapm_route audio_map[] = { | 305 | static const struct snd_soc_dapm_route wm8940_dapm_routes[] = { |
268 | /* Mono output mixer */ | 306 | /* Mono output mixer */ |
269 | {"Mono Mixer", "PCM Playback Switch", "DAC"}, | 307 | {"Mono Mixer", "PCM Playback Switch", "DAC"}, |
270 | {"Mono Mixer", "Aux Playback Switch", "Aux Input"}, | 308 | {"Mono Mixer", "Aux Playback Switch", "Aux Input"}, |
@@ -296,21 +334,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
296 | {"ADC", NULL, "Boost Mixer"}, | 334 | {"ADC", NULL, "Boost Mixer"}, |
297 | }; | 335 | }; |
298 | 336 | ||
299 | static int wm8940_add_widgets(struct snd_soc_codec *codec) | ||
300 | { | ||
301 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
302 | int ret; | ||
303 | |||
304 | ret = snd_soc_dapm_new_controls(dapm, wm8940_dapm_widgets, | ||
305 | ARRAY_SIZE(wm8940_dapm_widgets)); | ||
306 | if (ret) | ||
307 | goto error_ret; | ||
308 | ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
309 | |||
310 | error_ret: | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | #define wm8940_reset(c) snd_soc_write(c, WM8940_SOFTRESET, 0); | 337 | #define wm8940_reset(c) snd_soc_write(c, WM8940_SOFTRESET, 0); |
315 | 338 | ||
316 | static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai, | 339 | static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai, |
@@ -446,6 +469,7 @@ static int wm8940_mute(struct snd_soc_dai *dai, int mute) | |||
446 | static int wm8940_set_bias_level(struct snd_soc_codec *codec, | 469 | static int wm8940_set_bias_level(struct snd_soc_codec *codec, |
447 | enum snd_soc_bias_level level) | 470 | enum snd_soc_bias_level level) |
448 | { | 471 | { |
472 | struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec); | ||
449 | u16 val; | 473 | u16 val; |
450 | u16 pwr_reg = snd_soc_read(codec, WM8940_POWER1) & 0x1F0; | 474 | u16 pwr_reg = snd_soc_read(codec, WM8940_POWER1) & 0x1F0; |
451 | int ret = 0; | 475 | int ret = 0; |
@@ -469,7 +493,7 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec, | |||
469 | break; | 493 | break; |
470 | case SND_SOC_BIAS_STANDBY: | 494 | case SND_SOC_BIAS_STANDBY: |
471 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 495 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
472 | ret = snd_soc_cache_sync(codec); | 496 | ret = regcache_sync(wm8940->regmap); |
473 | if (ret < 0) { | 497 | if (ret < 0) { |
474 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); | 498 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); |
475 | return ret; | 499 | return ret; |
@@ -684,12 +708,11 @@ static int wm8940_resume(struct snd_soc_codec *codec) | |||
684 | 708 | ||
685 | static int wm8940_probe(struct snd_soc_codec *codec) | 709 | static int wm8940_probe(struct snd_soc_codec *codec) |
686 | { | 710 | { |
687 | struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec); | ||
688 | struct wm8940_setup_data *pdata = codec->dev->platform_data; | 711 | struct wm8940_setup_data *pdata = codec->dev->platform_data; |
689 | int ret; | 712 | int ret; |
690 | u16 reg; | 713 | u16 reg; |
691 | 714 | ||
692 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type); | 715 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); |
693 | if (ret < 0) { | 716 | if (ret < 0) { |
694 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 717 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
695 | return ret; | 718 | return ret; |
@@ -716,11 +739,6 @@ static int wm8940_probe(struct snd_soc_codec *codec) | |||
716 | return ret; | 739 | return ret; |
717 | } | 740 | } |
718 | 741 | ||
719 | ret = snd_soc_add_codec_controls(codec, wm8940_snd_controls, | ||
720 | ARRAY_SIZE(wm8940_snd_controls)); | ||
721 | if (ret) | ||
722 | return ret; | ||
723 | ret = wm8940_add_widgets(codec); | ||
724 | return ret; | 742 | return ret; |
725 | } | 743 | } |
726 | 744 | ||
@@ -736,10 +754,24 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { | |||
736 | .suspend = wm8940_suspend, | 754 | .suspend = wm8940_suspend, |
737 | .resume = wm8940_resume, | 755 | .resume = wm8940_resume, |
738 | .set_bias_level = wm8940_set_bias_level, | 756 | .set_bias_level = wm8940_set_bias_level, |
739 | .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults), | 757 | .controls = wm8940_snd_controls, |
740 | .reg_word_size = sizeof(u16), | 758 | .num_controls = ARRAY_SIZE(wm8940_snd_controls), |
741 | .reg_cache_default = wm8940_reg_defaults, | 759 | .dapm_widgets = wm8940_dapm_widgets, |
742 | .volatile_register = wm8940_volatile_register, | 760 | .num_dapm_widgets = ARRAY_SIZE(wm8940_dapm_widgets), |
761 | .dapm_routes = wm8940_dapm_routes, | ||
762 | .num_dapm_routes = ARRAY_SIZE(wm8940_dapm_routes), | ||
763 | }; | ||
764 | |||
765 | static const struct regmap_config wm8940_regmap = { | ||
766 | .reg_bits = 8, | ||
767 | .val_bits = 16, | ||
768 | |||
769 | .max_register = WM8940_MONOMIX, | ||
770 | .reg_defaults = wm8940_reg_defaults, | ||
771 | .num_reg_defaults = ARRAY_SIZE(wm8940_reg_defaults), | ||
772 | |||
773 | .readable_reg = wm8940_readable_register, | ||
774 | .volatile_reg = wm8940_volatile_register, | ||
743 | }; | 775 | }; |
744 | 776 | ||
745 | static int wm8940_i2c_probe(struct i2c_client *i2c, | 777 | static int wm8940_i2c_probe(struct i2c_client *i2c, |
@@ -753,8 +785,11 @@ static int wm8940_i2c_probe(struct i2c_client *i2c, | |||
753 | if (wm8940 == NULL) | 785 | if (wm8940 == NULL) |
754 | return -ENOMEM; | 786 | return -ENOMEM; |
755 | 787 | ||
788 | wm8940->regmap = devm_regmap_init_i2c(i2c, &wm8940_regmap); | ||
789 | if (IS_ERR(wm8940->regmap)) | ||
790 | return PTR_ERR(wm8940->regmap); | ||
791 | |||
756 | i2c_set_clientdata(i2c, wm8940); | 792 | i2c_set_clientdata(i2c, wm8940); |
757 | wm8940->control_type = SND_SOC_I2C; | ||
758 | 793 | ||
759 | ret = snd_soc_register_codec(&i2c->dev, | 794 | ret = snd_soc_register_codec(&i2c->dev, |
760 | &soc_codec_dev_wm8940, &wm8940_dai, 1); | 795 | &soc_codec_dev_wm8940, &wm8940_dai, 1); |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 543c5c2631b6..97db3b45b411 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -74,7 +74,7 @@ struct wm8962_priv { | |||
74 | struct regulator_bulk_data supplies[WM8962_NUM_SUPPLIES]; | 74 | struct regulator_bulk_data supplies[WM8962_NUM_SUPPLIES]; |
75 | struct notifier_block disable_nb[WM8962_NUM_SUPPLIES]; | 75 | struct notifier_block disable_nb[WM8962_NUM_SUPPLIES]; |
76 | 76 | ||
77 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 77 | #if IS_ENABLED(CONFIG_INPUT) |
78 | struct input_dev *beep; | 78 | struct input_dev *beep; |
79 | struct work_struct beep_work; | 79 | struct work_struct beep_work; |
80 | int beep_rate; | 80 | int beep_rate; |
@@ -2439,7 +2439,20 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec) | |||
2439 | snd_soc_update_bits(codec, WM8962_CLOCKING_4, | 2439 | snd_soc_update_bits(codec, WM8962_CLOCKING_4, |
2440 | WM8962_SYSCLK_RATE_MASK, clocking4); | 2440 | WM8962_SYSCLK_RATE_MASK, clocking4); |
2441 | 2441 | ||
2442 | /* DSPCLK_DIV can be only generated correctly after enabling SYSCLK. | ||
2443 | * So we here provisionally enable it and then disable it afterward | ||
2444 | * if current bias_level hasn't reached SND_SOC_BIAS_ON. | ||
2445 | */ | ||
2446 | if (codec->dapm.bias_level != SND_SOC_BIAS_ON) | ||
2447 | snd_soc_update_bits(codec, WM8962_CLOCKING2, | ||
2448 | WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA); | ||
2449 | |||
2442 | dspclk = snd_soc_read(codec, WM8962_CLOCKING1); | 2450 | dspclk = snd_soc_read(codec, WM8962_CLOCKING1); |
2451 | |||
2452 | if (codec->dapm.bias_level != SND_SOC_BIAS_ON) | ||
2453 | snd_soc_update_bits(codec, WM8962_CLOCKING2, | ||
2454 | WM8962_SYSCLK_ENA_MASK, 0); | ||
2455 | |||
2443 | if (dspclk < 0) { | 2456 | if (dspclk < 0) { |
2444 | dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); | 2457 | dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); |
2445 | return; | 2458 | return; |
@@ -3108,7 +3121,7 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
3108 | } | 3121 | } |
3109 | EXPORT_SYMBOL_GPL(wm8962_mic_detect); | 3122 | EXPORT_SYMBOL_GPL(wm8962_mic_detect); |
3110 | 3123 | ||
3111 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 3124 | #if IS_ENABLED(CONFIG_INPUT) |
3112 | static int beep_rates[] = { | 3125 | static int beep_rates[] = { |
3113 | 500, 1000, 2000, 4000, | 3126 | 500, 1000, 2000, 4000, |
3114 | }; | 3127 | }; |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index a2d01d10a5dd..15f45c7bd833 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/regmap.h> | ||
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
@@ -27,22 +28,22 @@ | |||
27 | 28 | ||
28 | #include "wm8974.h" | 29 | #include "wm8974.h" |
29 | 30 | ||
30 | static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { | 31 | static const struct reg_default wm8974_reg_defaults[] = { |
31 | 0x0000, 0x0000, 0x0000, 0x0000, | 32 | { 0, 0x0000 }, { 1, 0x0000 }, { 2, 0x0000 }, { 3, 0x0000 }, |
32 | 0x0050, 0x0000, 0x0140, 0x0000, | 33 | { 4, 0x0050 }, { 5, 0x0000 }, { 6, 0x0140 }, { 7, 0x0000 }, |
33 | 0x0000, 0x0000, 0x0000, 0x00ff, | 34 | { 8, 0x0000 }, { 9, 0x0000 }, { 10, 0x0000 }, { 11, 0x00ff }, |
34 | 0x0000, 0x0000, 0x0100, 0x00ff, | 35 | { 12, 0x0000 }, { 13, 0x0000 }, { 14, 0x0100 }, { 15, 0x00ff }, |
35 | 0x0000, 0x0000, 0x012c, 0x002c, | 36 | { 16, 0x0000 }, { 17, 0x0000 }, { 18, 0x012c }, { 19, 0x002c }, |
36 | 0x002c, 0x002c, 0x002c, 0x0000, | 37 | { 20, 0x002c }, { 21, 0x002c }, { 22, 0x002c }, { 23, 0x0000 }, |
37 | 0x0032, 0x0000, 0x0000, 0x0000, | 38 | { 24, 0x0032 }, { 25, 0x0000 }, { 26, 0x0000 }, { 27, 0x0000 }, |
38 | 0x0000, 0x0000, 0x0000, 0x0000, | 39 | { 28, 0x0000 }, { 29, 0x0000 }, { 30, 0x0000 }, { 31, 0x0000 }, |
39 | 0x0038, 0x000b, 0x0032, 0x0000, | 40 | { 32, 0x0038 }, { 33, 0x000b }, { 34, 0x0032 }, { 35, 0x0000 }, |
40 | 0x0008, 0x000c, 0x0093, 0x00e9, | 41 | { 36, 0x0008 }, { 37, 0x000c }, { 38, 0x0093 }, { 39, 0x00e9 }, |
41 | 0x0000, 0x0000, 0x0000, 0x0000, | 42 | { 40, 0x0000 }, { 41, 0x0000 }, { 42, 0x0000 }, { 43, 0x0000 }, |
42 | 0x0003, 0x0010, 0x0000, 0x0000, | 43 | { 44, 0x0003 }, { 45, 0x0010 }, { 46, 0x0000 }, { 47, 0x0000 }, |
43 | 0x0000, 0x0002, 0x0000, 0x0000, | 44 | { 48, 0x0000 }, { 49, 0x0002 }, { 50, 0x0000 }, { 51, 0x0000 }, |
44 | 0x0000, 0x0000, 0x0039, 0x0000, | 45 | { 52, 0x0000 }, { 53, 0x0000 }, { 54, 0x0039 }, { 55, 0x0000 }, |
45 | 0x0000, | 46 | { 56, 0x0000 }, |
46 | }; | 47 | }; |
47 | 48 | ||
48 | #define WM8974_POWER1_BIASEN 0x08 | 49 | #define WM8974_POWER1_BIASEN 0x08 |
@@ -514,7 +515,7 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec, | |||
514 | power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN; | 515 | power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN; |
515 | 516 | ||
516 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 517 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
517 | snd_soc_cache_sync(codec); | 518 | regcache_sync(dev_get_regmap(codec->dev, NULL)); |
518 | 519 | ||
519 | /* Initial cap charge at VMID 5k */ | 520 | /* Initial cap charge at VMID 5k */ |
520 | snd_soc_write(codec, WM8974_POWER1, power1 | 0x3); | 521 | snd_soc_write(codec, WM8974_POWER1, power1 | 0x3); |
@@ -579,11 +580,20 @@ static int wm8974_resume(struct snd_soc_codec *codec) | |||
579 | return 0; | 580 | return 0; |
580 | } | 581 | } |
581 | 582 | ||
583 | static const struct regmap_config wm8974_regmap = { | ||
584 | .reg_bits = 7, | ||
585 | .val_bits = 9, | ||
586 | |||
587 | .max_register = WM8974_MONOMIX, | ||
588 | .reg_defaults = wm8974_reg_defaults, | ||
589 | .num_reg_defaults = ARRAY_SIZE(wm8974_reg_defaults), | ||
590 | }; | ||
591 | |||
582 | static int wm8974_probe(struct snd_soc_codec *codec) | 592 | static int wm8974_probe(struct snd_soc_codec *codec) |
583 | { | 593 | { |
584 | int ret = 0; | 594 | int ret = 0; |
585 | 595 | ||
586 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); | 596 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
587 | if (ret < 0) { | 597 | if (ret < 0) { |
588 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 598 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
589 | return ret; | 599 | return ret; |
@@ -613,9 +623,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { | |||
613 | .suspend = wm8974_suspend, | 623 | .suspend = wm8974_suspend, |
614 | .resume = wm8974_resume, | 624 | .resume = wm8974_resume, |
615 | .set_bias_level = wm8974_set_bias_level, | 625 | .set_bias_level = wm8974_set_bias_level, |
616 | .reg_cache_size = ARRAY_SIZE(wm8974_reg), | ||
617 | .reg_word_size = sizeof(u16), | ||
618 | .reg_cache_default = wm8974_reg, | ||
619 | 626 | ||
620 | .controls = wm8974_snd_controls, | 627 | .controls = wm8974_snd_controls, |
621 | .num_controls = ARRAY_SIZE(wm8974_snd_controls), | 628 | .num_controls = ARRAY_SIZE(wm8974_snd_controls), |
@@ -628,8 +635,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { | |||
628 | static int wm8974_i2c_probe(struct i2c_client *i2c, | 635 | static int wm8974_i2c_probe(struct i2c_client *i2c, |
629 | const struct i2c_device_id *id) | 636 | const struct i2c_device_id *id) |
630 | { | 637 | { |
638 | struct regmap *regmap; | ||
631 | int ret; | 639 | int ret; |
632 | 640 | ||
641 | regmap = devm_regmap_init_i2c(i2c, &wm8974_regmap); | ||
642 | if (IS_ERR(regmap)) | ||
643 | return PTR_ERR(regmap); | ||
644 | |||
633 | ret = snd_soc_register_codec(&i2c->dev, | 645 | ret = snd_soc_register_codec(&i2c->dev, |
634 | &soc_codec_dev_wm8974, &wm8974_dai, 1); | 646 | &soc_codec_dev_wm8974, &wm8974_dai, 1); |
635 | 647 | ||
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 18f2babe1090..271b517911a4 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c | |||
@@ -1148,7 +1148,7 @@ static struct spi_driver wm8985_spi_driver = { | |||
1148 | }; | 1148 | }; |
1149 | #endif | 1149 | #endif |
1150 | 1150 | ||
1151 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1151 | #if IS_ENABLED(CONFIG_I2C) |
1152 | static int wm8985_i2c_probe(struct i2c_client *i2c, | 1152 | static int wm8985_i2c_probe(struct i2c_client *i2c, |
1153 | const struct i2c_device_id *id) | 1153 | const struct i2c_device_id *id) |
1154 | { | 1154 | { |
@@ -1201,7 +1201,7 @@ static int __init wm8985_modinit(void) | |||
1201 | { | 1201 | { |
1202 | int ret = 0; | 1202 | int ret = 0; |
1203 | 1203 | ||
1204 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1204 | #if IS_ENABLED(CONFIG_I2C) |
1205 | ret = i2c_add_driver(&wm8985_i2c_driver); | 1205 | ret = i2c_add_driver(&wm8985_i2c_driver); |
1206 | if (ret) { | 1206 | if (ret) { |
1207 | printk(KERN_ERR "Failed to register wm8985 I2C driver: %d\n", | 1207 | printk(KERN_ERR "Failed to register wm8985 I2C driver: %d\n", |
@@ -1221,7 +1221,7 @@ module_init(wm8985_modinit); | |||
1221 | 1221 | ||
1222 | static void __exit wm8985_exit(void) | 1222 | static void __exit wm8985_exit(void) |
1223 | { | 1223 | { |
1224 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1224 | #if IS_ENABLED(CONFIG_I2C) |
1225 | i2c_del_driver(&wm8985_i2c_driver); | 1225 | i2c_del_driver(&wm8985_i2c_driver); |
1226 | #endif | 1226 | #endif |
1227 | #if defined(CONFIG_SPI_MASTER) | 1227 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 39b9acceb595..a55e1c2c382e 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -912,7 +912,7 @@ static struct spi_driver wm8988_spi_driver = { | |||
912 | }; | 912 | }; |
913 | #endif /* CONFIG_SPI_MASTER */ | 913 | #endif /* CONFIG_SPI_MASTER */ |
914 | 914 | ||
915 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 915 | #if IS_ENABLED(CONFIG_I2C) |
916 | static int wm8988_i2c_probe(struct i2c_client *i2c, | 916 | static int wm8988_i2c_probe(struct i2c_client *i2c, |
917 | const struct i2c_device_id *id) | 917 | const struct i2c_device_id *id) |
918 | { | 918 | { |
@@ -964,7 +964,7 @@ static struct i2c_driver wm8988_i2c_driver = { | |||
964 | static int __init wm8988_modinit(void) | 964 | static int __init wm8988_modinit(void) |
965 | { | 965 | { |
966 | int ret = 0; | 966 | int ret = 0; |
967 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 967 | #if IS_ENABLED(CONFIG_I2C) |
968 | ret = i2c_add_driver(&wm8988_i2c_driver); | 968 | ret = i2c_add_driver(&wm8988_i2c_driver); |
969 | if (ret != 0) { | 969 | if (ret != 0) { |
970 | printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n", | 970 | printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n", |
@@ -984,7 +984,7 @@ module_init(wm8988_modinit); | |||
984 | 984 | ||
985 | static void __exit wm8988_exit(void) | 985 | static void __exit wm8988_exit(void) |
986 | { | 986 | { |
987 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 987 | #if IS_ENABLED(CONFIG_I2C) |
988 | i2c_del_driver(&wm8988_i2c_driver); | 988 | i2c_del_driver(&wm8988_i2c_driver); |
989 | #endif | 989 | #endif |
990 | #if defined(CONFIG_SPI_MASTER) | 990 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 253c88bb7a4c..0ccd4d8d043b 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/regmap.h> | ||
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
@@ -30,13 +31,12 @@ | |||
30 | 31 | ||
31 | /* codec private data */ | 32 | /* codec private data */ |
32 | struct wm8990_priv { | 33 | struct wm8990_priv { |
33 | enum snd_soc_control_type control_type; | 34 | struct regmap *regmap; |
34 | unsigned int sysclk; | 35 | unsigned int sysclk; |
35 | unsigned int pcmclk; | 36 | unsigned int pcmclk; |
36 | }; | 37 | }; |
37 | 38 | ||
38 | static int wm8990_volatile_register(struct snd_soc_codec *codec, | 39 | static bool wm8990_volatile_register(struct device *dev, unsigned int reg) |
39 | unsigned int reg) | ||
40 | { | 40 | { |
41 | switch (reg) { | 41 | switch (reg) { |
42 | case WM8990_RESET: | 42 | case WM8990_RESET: |
@@ -46,71 +46,69 @@ static int wm8990_volatile_register(struct snd_soc_codec *codec, | |||
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
49 | static const u16 wm8990_reg[] = { | 49 | static const struct reg_default wm8990_reg_defaults[] = { |
50 | 0x8990, /* R0 - Reset */ | 50 | { 1, 0x0000 }, /* R1 - Power Management (1) */ |
51 | 0x0000, /* R1 - Power Management (1) */ | 51 | { 2, 0x6000 }, /* R2 - Power Management (2) */ |
52 | 0x6000, /* R2 - Power Management (2) */ | 52 | { 3, 0x0000 }, /* R3 - Power Management (3) */ |
53 | 0x0000, /* R3 - Power Management (3) */ | 53 | { 4, 0x4050 }, /* R4 - Audio Interface (1) */ |
54 | 0x4050, /* R4 - Audio Interface (1) */ | 54 | { 5, 0x4000 }, /* R5 - Audio Interface (2) */ |
55 | 0x4000, /* R5 - Audio Interface (2) */ | 55 | { 6, 0x01C8 }, /* R6 - Clocking (1) */ |
56 | 0x01C8, /* R6 - Clocking (1) */ | 56 | { 7, 0x0000 }, /* R7 - Clocking (2) */ |
57 | 0x0000, /* R7 - Clocking (2) */ | 57 | { 8, 0x0040 }, /* R8 - Audio Interface (3) */ |
58 | 0x0040, /* R8 - Audio Interface (3) */ | 58 | { 9, 0x0040 }, /* R9 - Audio Interface (4) */ |
59 | 0x0040, /* R9 - Audio Interface (4) */ | 59 | { 10, 0x0004 }, /* R10 - DAC CTRL */ |
60 | 0x0004, /* R10 - DAC CTRL */ | 60 | { 11, 0x00C0 }, /* R11 - Left DAC Digital Volume */ |
61 | 0x00C0, /* R11 - Left DAC Digital Volume */ | 61 | { 12, 0x00C0 }, /* R12 - Right DAC Digital Volume */ |
62 | 0x00C0, /* R12 - Right DAC Digital Volume */ | 62 | { 13, 0x0000 }, /* R13 - Digital Side Tone */ |
63 | 0x0000, /* R13 - Digital Side Tone */ | 63 | { 14, 0x0100 }, /* R14 - ADC CTRL */ |
64 | 0x0100, /* R14 - ADC CTRL */ | 64 | { 15, 0x00C0 }, /* R15 - Left ADC Digital Volume */ |
65 | 0x00C0, /* R15 - Left ADC Digital Volume */ | 65 | { 16, 0x00C0 }, /* R16 - Right ADC Digital Volume */ |
66 | 0x00C0, /* R16 - Right ADC Digital Volume */ | 66 | |
67 | 0x0000, /* R17 */ | 67 | { 18, 0x0000 }, /* R18 - GPIO CTRL 1 */ |
68 | 0x0000, /* R18 - GPIO CTRL 1 */ | 68 | { 19, 0x1000 }, /* R19 - GPIO1 & GPIO2 */ |
69 | 0x1000, /* R19 - GPIO1 & GPIO2 */ | 69 | { 20, 0x1010 }, /* R20 - GPIO3 & GPIO4 */ |
70 | 0x1010, /* R20 - GPIO3 & GPIO4 */ | 70 | { 21, 0x1010 }, /* R21 - GPIO5 & GPIO6 */ |
71 | 0x1010, /* R21 - GPIO5 & GPIO6 */ | 71 | { 22, 0x8000 }, /* R22 - GPIOCTRL 2 */ |
72 | 0x8000, /* R22 - GPIOCTRL 2 */ | 72 | { 23, 0x0800 }, /* R23 - GPIO_POL */ |
73 | 0x0800, /* R23 - GPIO_POL */ | 73 | { 24, 0x008B }, /* R24 - Left Line Input 1&2 Volume */ |
74 | 0x008B, /* R24 - Left Line Input 1&2 Volume */ | 74 | { 25, 0x008B }, /* R25 - Left Line Input 3&4 Volume */ |
75 | 0x008B, /* R25 - Left Line Input 3&4 Volume */ | 75 | { 26, 0x008B }, /* R26 - Right Line Input 1&2 Volume */ |
76 | 0x008B, /* R26 - Right Line Input 1&2 Volume */ | 76 | { 27, 0x008B }, /* R27 - Right Line Input 3&4 Volume */ |
77 | 0x008B, /* R27 - Right Line Input 3&4 Volume */ | 77 | { 28, 0x0000 }, /* R28 - Left Output Volume */ |
78 | 0x0000, /* R28 - Left Output Volume */ | 78 | { 29, 0x0000 }, /* R29 - Right Output Volume */ |
79 | 0x0000, /* R29 - Right Output Volume */ | 79 | { 30, 0x0066 }, /* R30 - Line Outputs Volume */ |
80 | 0x0066, /* R30 - Line Outputs Volume */ | 80 | { 31, 0x0022 }, /* R31 - Out3/4 Volume */ |
81 | 0x0022, /* R31 - Out3/4 Volume */ | 81 | { 32, 0x0079 }, /* R32 - Left OPGA Volume */ |
82 | 0x0079, /* R32 - Left OPGA Volume */ | 82 | { 33, 0x0079 }, /* R33 - Right OPGA Volume */ |
83 | 0x0079, /* R33 - Right OPGA Volume */ | 83 | { 34, 0x0003 }, /* R34 - Speaker Volume */ |
84 | 0x0003, /* R34 - Speaker Volume */ | 84 | { 35, 0x0003 }, /* R35 - ClassD1 */ |
85 | 0x0003, /* R35 - ClassD1 */ | 85 | |
86 | 0x0000, /* R36 */ | 86 | { 37, 0x0100 }, /* R37 - ClassD3 */ |
87 | 0x0100, /* R37 - ClassD3 */ | 87 | { 38, 0x0079 }, /* R38 - ClassD4 */ |
88 | 0x0079, /* R38 - ClassD4 */ | 88 | { 39, 0x0000 }, /* R39 - Input Mixer1 */ |
89 | 0x0000, /* R39 - Input Mixer1 */ | 89 | { 40, 0x0000 }, /* R40 - Input Mixer2 */ |
90 | 0x0000, /* R40 - Input Mixer2 */ | 90 | { 41, 0x0000 }, /* R41 - Input Mixer3 */ |
91 | 0x0000, /* R41 - Input Mixer3 */ | 91 | { 42, 0x0000 }, /* R42 - Input Mixer4 */ |
92 | 0x0000, /* R42 - Input Mixer4 */ | 92 | { 43, 0x0000 }, /* R43 - Input Mixer5 */ |
93 | 0x0000, /* R43 - Input Mixer5 */ | 93 | { 44, 0x0000 }, /* R44 - Input Mixer6 */ |
94 | 0x0000, /* R44 - Input Mixer6 */ | 94 | { 45, 0x0000 }, /* R45 - Output Mixer1 */ |
95 | 0x0000, /* R45 - Output Mixer1 */ | 95 | { 46, 0x0000 }, /* R46 - Output Mixer2 */ |
96 | 0x0000, /* R46 - Output Mixer2 */ | 96 | { 47, 0x0000 }, /* R47 - Output Mixer3 */ |
97 | 0x0000, /* R47 - Output Mixer3 */ | 97 | { 48, 0x0000 }, /* R48 - Output Mixer4 */ |
98 | 0x0000, /* R48 - Output Mixer4 */ | 98 | { 49, 0x0000 }, /* R49 - Output Mixer5 */ |
99 | 0x0000, /* R49 - Output Mixer5 */ | 99 | { 50, 0x0000 }, /* R50 - Output Mixer6 */ |
100 | 0x0000, /* R50 - Output Mixer6 */ | 100 | { 51, 0x0180 }, /* R51 - Out3/4 Mixer */ |
101 | 0x0180, /* R51 - Out3/4 Mixer */ | 101 | { 52, 0x0000 }, /* R52 - Line Mixer1 */ |
102 | 0x0000, /* R52 - Line Mixer1 */ | 102 | { 53, 0x0000 }, /* R53 - Line Mixer2 */ |
103 | 0x0000, /* R53 - Line Mixer2 */ | 103 | { 54, 0x0000 }, /* R54 - Speaker Mixer */ |
104 | 0x0000, /* R54 - Speaker Mixer */ | 104 | { 55, 0x0000 }, /* R55 - Additional Control */ |
105 | 0x0000, /* R55 - Additional Control */ | 105 | { 56, 0x0000 }, /* R56 - AntiPOP1 */ |
106 | 0x0000, /* R56 - AntiPOP1 */ | 106 | { 57, 0x0000 }, /* R57 - AntiPOP2 */ |
107 | 0x0000, /* R57 - AntiPOP2 */ | 107 | { 58, 0x0000 }, /* R58 - MICBIAS */ |
108 | 0x0000, /* R58 - MICBIAS */ | 108 | |
109 | 0x0000, /* R59 */ | 109 | { 60, 0x0008 }, /* R60 - PLL1 */ |
110 | 0x0008, /* R60 - PLL1 */ | 110 | { 61, 0x0031 }, /* R61 - PLL2 */ |
111 | 0x0031, /* R61 - PLL2 */ | 111 | { 62, 0x0026 }, /* R62 - PLL3 */ |
112 | 0x0026, /* R62 - PLL3 */ | ||
113 | 0x0000, /* R63 - Driver internal */ | ||
114 | }; | 112 | }; |
115 | 113 | ||
116 | #define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0) | 114 | #define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0) |
@@ -376,32 +374,6 @@ SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME, | |||
376 | * _DAPM_ Controls | 374 | * _DAPM_ Controls |
377 | */ | 375 | */ |
378 | 376 | ||
379 | static int inmixer_event(struct snd_soc_dapm_widget *w, | ||
380 | struct snd_kcontrol *kcontrol, int event) | ||
381 | { | ||
382 | u16 reg, fakepower; | ||
383 | |||
384 | reg = snd_soc_read(w->codec, WM8990_POWER_MANAGEMENT_2); | ||
385 | fakepower = snd_soc_read(w->codec, WM8990_INTDRIVBITS); | ||
386 | |||
387 | if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) | | ||
388 | (1 << WM8990_AINLMUX_PWR_BIT))) { | ||
389 | reg |= WM8990_AINL_ENA; | ||
390 | } else { | ||
391 | reg &= ~WM8990_AINL_ENA; | ||
392 | } | ||
393 | |||
394 | if (fakepower & ((1 << WM8990_INMIXR_PWR_BIT) | | ||
395 | (1 << WM8990_AINRMUX_PWR_BIT))) { | ||
396 | reg |= WM8990_AINR_ENA; | ||
397 | } else { | ||
398 | reg &= ~WM8990_AINR_ENA; | ||
399 | } | ||
400 | snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static int outmixer_event(struct snd_soc_dapm_widget *w, | 377 | static int outmixer_event(struct snd_soc_dapm_widget *w, |
406 | struct snd_kcontrol *kcontrol, int event) | 378 | struct snd_kcontrol *kcontrol, int event) |
407 | { | 379 | { |
@@ -656,6 +628,11 @@ SND_SOC_DAPM_INPUT("RIN1"), | |||
656 | SND_SOC_DAPM_INPUT("RIN2"), | 628 | SND_SOC_DAPM_INPUT("RIN2"), |
657 | SND_SOC_DAPM_INPUT("Internal ADC Source"), | 629 | SND_SOC_DAPM_INPUT("Internal ADC Source"), |
658 | 630 | ||
631 | SND_SOC_DAPM_SUPPLY("INL", WM8990_POWER_MANAGEMENT_2, WM8990_AINL_ENA_BIT, 0, | ||
632 | NULL, 0), | ||
633 | SND_SOC_DAPM_SUPPLY("INR", WM8990_POWER_MANAGEMENT_2, WM8990_AINR_ENA_BIT, 0, | ||
634 | NULL, 0), | ||
635 | |||
659 | /* DACs */ | 636 | /* DACs */ |
660 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8990_POWER_MANAGEMENT_2, | 637 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8990_POWER_MANAGEMENT_2, |
661 | WM8990_ADCL_ENA_BIT, 0), | 638 | WM8990_ADCL_ENA_BIT, 0), |
@@ -677,26 +654,20 @@ SND_SOC_DAPM_MIXER("RIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN34_ENA_BIT, | |||
677 | ARRAY_SIZE(wm8990_dapm_rin34_pga_controls)), | 654 | ARRAY_SIZE(wm8990_dapm_rin34_pga_controls)), |
678 | 655 | ||
679 | /* INMIXL */ | 656 | /* INMIXL */ |
680 | SND_SOC_DAPM_MIXER_E("INMIXL", WM8990_INTDRIVBITS, WM8990_INMIXL_PWR_BIT, 0, | 657 | SND_SOC_DAPM_MIXER("INMIXL", SND_SOC_NOPM, 0, 0, |
681 | &wm8990_dapm_inmixl_controls[0], | 658 | &wm8990_dapm_inmixl_controls[0], |
682 | ARRAY_SIZE(wm8990_dapm_inmixl_controls), | 659 | ARRAY_SIZE(wm8990_dapm_inmixl_controls)), |
683 | inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
684 | 660 | ||
685 | /* AINLMUX */ | 661 | /* AINLMUX */ |
686 | SND_SOC_DAPM_MUX_E("AINLMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0, | 662 | SND_SOC_DAPM_MUX("AINLMUX", SND_SOC_NOPM, 0, 0, &wm8990_dapm_ainlmux_controls), |
687 | &wm8990_dapm_ainlmux_controls, inmixer_event, | ||
688 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
689 | 663 | ||
690 | /* INMIXR */ | 664 | /* INMIXR */ |
691 | SND_SOC_DAPM_MIXER_E("INMIXR", WM8990_INTDRIVBITS, WM8990_INMIXR_PWR_BIT, 0, | 665 | SND_SOC_DAPM_MIXER("INMIXR", SND_SOC_NOPM, 0, 0, |
692 | &wm8990_dapm_inmixr_controls[0], | 666 | &wm8990_dapm_inmixr_controls[0], |
693 | ARRAY_SIZE(wm8990_dapm_inmixr_controls), | 667 | ARRAY_SIZE(wm8990_dapm_inmixr_controls)), |
694 | inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
695 | 668 | ||
696 | /* AINRMUX */ | 669 | /* AINRMUX */ |
697 | SND_SOC_DAPM_MUX_E("AINRMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0, | 670 | SND_SOC_DAPM_MUX("AINRMUX", SND_SOC_NOPM, 0, 0, &wm8990_dapm_ainrmux_controls), |
698 | &wm8990_dapm_ainrmux_controls, inmixer_event, | ||
699 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
700 | 671 | ||
701 | /* Output Side */ | 672 | /* Output Side */ |
702 | /* DACs */ | 673 | /* DACs */ |
@@ -787,7 +758,7 @@ SND_SOC_DAPM_OUTPUT("RON"), | |||
787 | SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), | 758 | SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), |
788 | }; | 759 | }; |
789 | 760 | ||
790 | static const struct snd_soc_dapm_route audio_map[] = { | 761 | static const struct snd_soc_dapm_route wm8990_dapm_routes[] = { |
791 | /* Make DACs turn on when playing even if not mixed into any outputs */ | 762 | /* Make DACs turn on when playing even if not mixed into any outputs */ |
792 | {"Internal DAC Sink", NULL, "Left DAC"}, | 763 | {"Internal DAC Sink", NULL, "Left DAC"}, |
793 | {"Internal DAC Sink", NULL, "Right DAC"}, | 764 | {"Internal DAC Sink", NULL, "Right DAC"}, |
@@ -796,6 +767,11 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
796 | {"Left ADC", NULL, "Internal ADC Source"}, | 767 | {"Left ADC", NULL, "Internal ADC Source"}, |
797 | {"Right ADC", NULL, "Internal ADC Source"}, | 768 | {"Right ADC", NULL, "Internal ADC Source"}, |
798 | 769 | ||
770 | {"AINLMUX", NULL, "INL"}, | ||
771 | {"INMIXL", NULL, "INL"}, | ||
772 | {"AINRMUX", NULL, "INR"}, | ||
773 | {"INMIXR", NULL, "INR"}, | ||
774 | |||
799 | /* Input Side */ | 775 | /* Input Side */ |
800 | /* LIN12 PGA */ | 776 | /* LIN12 PGA */ |
801 | {"LIN12 PGA", "LIN1 Switch", "LIN1"}, | 777 | {"LIN12 PGA", "LIN1 Switch", "LIN1"}, |
@@ -912,18 +888,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
912 | {"RON", NULL, "RONMIX"}, | 888 | {"RON", NULL, "RONMIX"}, |
913 | }; | 889 | }; |
914 | 890 | ||
915 | static int wm8990_add_widgets(struct snd_soc_codec *codec) | ||
916 | { | ||
917 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
918 | |||
919 | snd_soc_dapm_new_controls(dapm, wm8990_dapm_widgets, | ||
920 | ARRAY_SIZE(wm8990_dapm_widgets)); | ||
921 | /* set up the WM8990 audio map */ | ||
922 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
923 | |||
924 | return 0; | ||
925 | } | ||
926 | |||
927 | /* PLL divisors */ | 891 | /* PLL divisors */ |
928 | struct _pll_div { | 892 | struct _pll_div { |
929 | u32 div2; | 893 | u32 div2; |
@@ -1148,6 +1112,7 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute) | |||
1148 | static int wm8990_set_bias_level(struct snd_soc_codec *codec, | 1112 | static int wm8990_set_bias_level(struct snd_soc_codec *codec, |
1149 | enum snd_soc_bias_level level) | 1113 | enum snd_soc_bias_level level) |
1150 | { | 1114 | { |
1115 | struct wm8990_priv *wm8990 = snd_soc_codec_get_drvdata(codec); | ||
1151 | int ret; | 1116 | int ret; |
1152 | 1117 | ||
1153 | switch (level) { | 1118 | switch (level) { |
@@ -1162,7 +1127,7 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, | |||
1162 | 1127 | ||
1163 | case SND_SOC_BIAS_STANDBY: | 1128 | case SND_SOC_BIAS_STANDBY: |
1164 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1129 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
1165 | ret = snd_soc_cache_sync(codec); | 1130 | ret = regcache_sync(wm8990->regmap); |
1166 | if (ret < 0) { | 1131 | if (ret < 0) { |
1167 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); | 1132 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); |
1168 | return ret; | 1133 | return ret; |
@@ -1259,6 +1224,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, | |||
1259 | 1224 | ||
1260 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ | 1225 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ |
1261 | snd_soc_write(codec, WM8990_ANTIPOP2, 0x0); | 1226 | snd_soc_write(codec, WM8990_ANTIPOP2, 0x0); |
1227 | |||
1228 | regcache_mark_dirty(wm8990->regmap); | ||
1262 | break; | 1229 | break; |
1263 | } | 1230 | } |
1264 | 1231 | ||
@@ -1327,7 +1294,7 @@ static int wm8990_probe(struct snd_soc_codec *codec) | |||
1327 | { | 1294 | { |
1328 | int ret; | 1295 | int ret; |
1329 | 1296 | ||
1330 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1297 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); |
1331 | if (ret < 0) { | 1298 | if (ret < 0) { |
1332 | printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); | 1299 | printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); |
1333 | return ret; | 1300 | return ret; |
@@ -1350,10 +1317,6 @@ static int wm8990_probe(struct snd_soc_codec *codec) | |||
1350 | snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1317 | snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1351 | snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1318 | snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1352 | 1319 | ||
1353 | snd_soc_add_codec_controls(codec, wm8990_snd_controls, | ||
1354 | ARRAY_SIZE(wm8990_snd_controls)); | ||
1355 | wm8990_add_widgets(codec); | ||
1356 | |||
1357 | return 0; | 1320 | return 0; |
1358 | } | 1321 | } |
1359 | 1322 | ||
@@ -1370,13 +1333,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { | |||
1370 | .suspend = wm8990_suspend, | 1333 | .suspend = wm8990_suspend, |
1371 | .resume = wm8990_resume, | 1334 | .resume = wm8990_resume, |
1372 | .set_bias_level = wm8990_set_bias_level, | 1335 | .set_bias_level = wm8990_set_bias_level, |
1373 | .reg_cache_size = ARRAY_SIZE(wm8990_reg), | 1336 | .controls = wm8990_snd_controls, |
1374 | .reg_word_size = sizeof(u16), | 1337 | .num_controls = ARRAY_SIZE(wm8990_snd_controls), |
1375 | .reg_cache_default = wm8990_reg, | 1338 | .dapm_widgets = wm8990_dapm_widgets, |
1376 | .volatile_register = wm8990_volatile_register, | 1339 | .num_dapm_widgets = ARRAY_SIZE(wm8990_dapm_widgets), |
1340 | .dapm_routes = wm8990_dapm_routes, | ||
1341 | .num_dapm_routes = ARRAY_SIZE(wm8990_dapm_routes), | ||
1342 | }; | ||
1343 | |||
1344 | static const struct regmap_config wm8990_regmap = { | ||
1345 | .reg_bits = 8, | ||
1346 | .val_bits = 16, | ||
1347 | |||
1348 | .max_register = WM8990_PLL3, | ||
1349 | .volatile_reg = wm8990_volatile_register, | ||
1350 | .reg_defaults = wm8990_reg_defaults, | ||
1351 | .num_reg_defaults = ARRAY_SIZE(wm8990_reg_defaults), | ||
1352 | .cache_type = REGCACHE_RBTREE, | ||
1377 | }; | 1353 | }; |
1378 | 1354 | ||
1379 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1380 | static int wm8990_i2c_probe(struct i2c_client *i2c, | 1355 | static int wm8990_i2c_probe(struct i2c_client *i2c, |
1381 | const struct i2c_device_id *id) | 1356 | const struct i2c_device_id *id) |
1382 | { | 1357 | { |
@@ -1418,29 +1393,8 @@ static struct i2c_driver wm8990_i2c_driver = { | |||
1418 | .remove = wm8990_i2c_remove, | 1393 | .remove = wm8990_i2c_remove, |
1419 | .id_table = wm8990_i2c_id, | 1394 | .id_table = wm8990_i2c_id, |
1420 | }; | 1395 | }; |
1421 | #endif | ||
1422 | 1396 | ||
1423 | static int __init wm8990_modinit(void) | 1397 | module_i2c_driver(wm8990_i2c_driver); |
1424 | { | ||
1425 | int ret = 0; | ||
1426 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1427 | ret = i2c_add_driver(&wm8990_i2c_driver); | ||
1428 | if (ret != 0) { | ||
1429 | printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n", | ||
1430 | ret); | ||
1431 | } | ||
1432 | #endif | ||
1433 | return ret; | ||
1434 | } | ||
1435 | module_init(wm8990_modinit); | ||
1436 | |||
1437 | static void __exit wm8990_exit(void) | ||
1438 | { | ||
1439 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1440 | i2c_del_driver(&wm8990_i2c_driver); | ||
1441 | #endif | ||
1442 | } | ||
1443 | module_exit(wm8990_exit); | ||
1444 | 1398 | ||
1445 | MODULE_DESCRIPTION("ASoC WM8990 driver"); | 1399 | MODULE_DESCRIPTION("ASoC WM8990 driver"); |
1446 | MODULE_AUTHOR("Liam Girdwood"); | 1400 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h index 77c98a4bfe9c..0e9c78040c4c 100644 --- a/sound/soc/codecs/wm8990.h +++ b/sound/soc/codecs/wm8990.h | |||
@@ -78,7 +78,6 @@ | |||
78 | #define WM8990_PLL1 0x3C | 78 | #define WM8990_PLL1 0x3C |
79 | #define WM8990_PLL2 0x3D | 79 | #define WM8990_PLL2 0x3D |
80 | #define WM8990_PLL3 0x3E | 80 | #define WM8990_PLL3 0x3E |
81 | #define WM8990_INTDRIVBITS 0x3F | ||
82 | 81 | ||
83 | #define WM8990_EXT_ACCESS_ENA 0x75 | 82 | #define WM8990_EXT_ACCESS_ENA 0x75 |
84 | #define WM8990_EXT_CTL1 0x7a | 83 | #define WM8990_EXT_CTL1 0x7a |
@@ -818,14 +817,6 @@ | |||
818 | */ | 817 | */ |
819 | #define WM8990_PLLK2_MASK 0x00FF /* PLLK2 - [7:0] */ | 818 | #define WM8990_PLLK2_MASK 0x00FF /* PLLK2 - [7:0] */ |
820 | 819 | ||
821 | /* | ||
822 | * R63 (0x3F) - Internal Driver Bits | ||
823 | */ | ||
824 | #define WM8990_INMIXL_PWR_BIT 0 | ||
825 | #define WM8990_AINLMUX_PWR_BIT 1 | ||
826 | #define WM8990_INMIXR_PWR_BIT 2 | ||
827 | #define WM8990_AINRMUX_PWR_BIT 3 | ||
828 | |||
829 | #define WM8990_MCLK_DIV 0 | 820 | #define WM8990_MCLK_DIV 0 |
830 | #define WM8990_DACCLK_DIV 1 | 821 | #define WM8990_DACCLK_DIV 1 |
831 | #define WM8990_ADCCLK_DIV 2 | 822 | #define WM8990_ADCCLK_DIV 2 |
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 3a39df7a3829..dba0306c42a5 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/regmap.h> | ||
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
@@ -31,77 +32,84 @@ | |||
31 | #include "wm8991.h" | 32 | #include "wm8991.h" |
32 | 33 | ||
33 | struct wm8991_priv { | 34 | struct wm8991_priv { |
34 | enum snd_soc_control_type control_type; | 35 | struct regmap *regmap; |
35 | unsigned int pcmclk; | 36 | unsigned int pcmclk; |
36 | }; | 37 | }; |
37 | 38 | ||
38 | static const u16 wm8991_reg_defs[] = { | 39 | static const struct reg_default wm8991_reg_defaults[] = { |
39 | 0x8991, /* R0 - Reset */ | 40 | { 1, 0x0000 }, /* R1 - Power Management (1) */ |
40 | 0x0000, /* R1 - Power Management (1) */ | 41 | { 2, 0x6000 }, /* R2 - Power Management (2) */ |
41 | 0x6000, /* R2 - Power Management (2) */ | 42 | { 3, 0x0000 }, /* R3 - Power Management (3) */ |
42 | 0x0000, /* R3 - Power Management (3) */ | 43 | { 4, 0x4050 }, /* R4 - Audio Interface (1) */ |
43 | 0x4050, /* R4 - Audio Interface (1) */ | 44 | { 5, 0x4000 }, /* R5 - Audio Interface (2) */ |
44 | 0x4000, /* R5 - Audio Interface (2) */ | 45 | { 6, 0x01C8 }, /* R6 - Clocking (1) */ |
45 | 0x01C8, /* R6 - Clocking (1) */ | 46 | { 7, 0x0000 }, /* R7 - Clocking (2) */ |
46 | 0x0000, /* R7 - Clocking (2) */ | 47 | { 8, 0x0040 }, /* R8 - Audio Interface (3) */ |
47 | 0x0040, /* R8 - Audio Interface (3) */ | 48 | { 9, 0x0040 }, /* R9 - Audio Interface (4) */ |
48 | 0x0040, /* R9 - Audio Interface (4) */ | 49 | { 10, 0x0004 }, /* R10 - DAC CTRL */ |
49 | 0x0004, /* R10 - DAC CTRL */ | 50 | { 11, 0x00C0 }, /* R11 - Left DAC Digital Volume */ |
50 | 0x00C0, /* R11 - Left DAC Digital Volume */ | 51 | { 12, 0x00C0 }, /* R12 - Right DAC Digital Volume */ |
51 | 0x00C0, /* R12 - Right DAC Digital Volume */ | 52 | { 13, 0x0000 }, /* R13 - Digital Side Tone */ |
52 | 0x0000, /* R13 - Digital Side Tone */ | 53 | { 14, 0x0100 }, /* R14 - ADC CTRL */ |
53 | 0x0100, /* R14 - ADC CTRL */ | 54 | { 15, 0x00C0 }, /* R15 - Left ADC Digital Volume */ |
54 | 0x00C0, /* R15 - Left ADC Digital Volume */ | 55 | { 16, 0x00C0 }, /* R16 - Right ADC Digital Volume */ |
55 | 0x00C0, /* R16 - Right ADC Digital Volume */ | 56 | |
56 | 0x0000, /* R17 */ | 57 | { 18, 0x0000 }, /* R18 - GPIO CTRL 1 */ |
57 | 0x0000, /* R18 - GPIO CTRL 1 */ | 58 | { 19, 0x1000 }, /* R19 - GPIO1 & GPIO2 */ |
58 | 0x1000, /* R19 - GPIO1 & GPIO2 */ | 59 | { 20, 0x1010 }, /* R20 - GPIO3 & GPIO4 */ |
59 | 0x1010, /* R20 - GPIO3 & GPIO4 */ | 60 | { 21, 0x1010 }, /* R21 - GPIO5 & GPIO6 */ |
60 | 0x1010, /* R21 - GPIO5 & GPIO6 */ | 61 | { 22, 0x8000 }, /* R22 - GPIOCTRL 2 */ |
61 | 0x8000, /* R22 - GPIOCTRL 2 */ | 62 | { 23, 0x0800 }, /* R23 - GPIO_POL */ |
62 | 0x0800, /* R23 - GPIO_POL */ | 63 | { 24, 0x008B }, /* R24 - Left Line Input 1&2 Volume */ |
63 | 0x008B, /* R24 - Left Line Input 1&2 Volume */ | 64 | { 25, 0x008B }, /* R25 - Left Line Input 3&4 Volume */ |
64 | 0x008B, /* R25 - Left Line Input 3&4 Volume */ | 65 | { 26, 0x008B }, /* R26 - Right Line Input 1&2 Volume */ |
65 | 0x008B, /* R26 - Right Line Input 1&2 Volume */ | 66 | { 27, 0x008B }, /* R27 - Right Line Input 3&4 Volume */ |
66 | 0x008B, /* R27 - Right Line Input 3&4 Volume */ | 67 | { 28, 0x0000 }, /* R28 - Left Output Volume */ |
67 | 0x0000, /* R28 - Left Output Volume */ | 68 | { 29, 0x0000 }, /* R29 - Right Output Volume */ |
68 | 0x0000, /* R29 - Right Output Volume */ | 69 | { 30, 0x0066 }, /* R30 - Line Outputs Volume */ |
69 | 0x0066, /* R30 - Line Outputs Volume */ | 70 | { 31, 0x0022 }, /* R31 - Out3/4 Volume */ |
70 | 0x0022, /* R31 - Out3/4 Volume */ | 71 | { 32, 0x0079 }, /* R32 - Left OPGA Volume */ |
71 | 0x0079, /* R32 - Left OPGA Volume */ | 72 | { 33, 0x0079 }, /* R33 - Right OPGA Volume */ |
72 | 0x0079, /* R33 - Right OPGA Volume */ | 73 | { 34, 0x0003 }, /* R34 - Speaker Volume */ |
73 | 0x0003, /* R34 - Speaker Volume */ | 74 | { 35, 0x0003 }, /* R35 - ClassD1 */ |
74 | 0x0003, /* R35 - ClassD1 */ | 75 | |
75 | 0x0000, /* R36 */ | 76 | { 37, 0x0100 }, /* R37 - ClassD3 */ |
76 | 0x0100, /* R37 - ClassD3 */ | 77 | |
77 | 0x0000, /* R38 */ | 78 | { 39, 0x0000 }, /* R39 - Input Mixer1 */ |
78 | 0x0000, /* R39 - Input Mixer1 */ | 79 | { 40, 0x0000 }, /* R40 - Input Mixer2 */ |
79 | 0x0000, /* R40 - Input Mixer2 */ | 80 | { 41, 0x0000 }, /* R41 - Input Mixer3 */ |
80 | 0x0000, /* R41 - Input Mixer3 */ | 81 | { 42, 0x0000 }, /* R42 - Input Mixer4 */ |
81 | 0x0000, /* R42 - Input Mixer4 */ | 82 | { 43, 0x0000 }, /* R43 - Input Mixer5 */ |
82 | 0x0000, /* R43 - Input Mixer5 */ | 83 | { 44, 0x0000 }, /* R44 - Input Mixer6 */ |
83 | 0x0000, /* R44 - Input Mixer6 */ | 84 | { 45, 0x0000 }, /* R45 - Output Mixer1 */ |
84 | 0x0000, /* R45 - Output Mixer1 */ | 85 | { 46, 0x0000 }, /* R46 - Output Mixer2 */ |
85 | 0x0000, /* R46 - Output Mixer2 */ | 86 | { 47, 0x0000 }, /* R47 - Output Mixer3 */ |
86 | 0x0000, /* R47 - Output Mixer3 */ | 87 | { 48, 0x0000 }, /* R48 - Output Mixer4 */ |
87 | 0x0000, /* R48 - Output Mixer4 */ | 88 | { 49, 0x0000 }, /* R49 - Output Mixer5 */ |
88 | 0x0000, /* R49 - Output Mixer5 */ | 89 | { 50, 0x0000 }, /* R50 - Output Mixer6 */ |
89 | 0x0000, /* R50 - Output Mixer6 */ | 90 | { 51, 0x0180 }, /* R51 - Out3/4 Mixer */ |
90 | 0x0180, /* R51 - Out3/4 Mixer */ | 91 | { 52, 0x0000 }, /* R52 - Line Mixer1 */ |
91 | 0x0000, /* R52 - Line Mixer1 */ | 92 | { 53, 0x0000 }, /* R53 - Line Mixer2 */ |
92 | 0x0000, /* R53 - Line Mixer2 */ | 93 | { 54, 0x0000 }, /* R54 - Speaker Mixer */ |
93 | 0x0000, /* R54 - Speaker Mixer */ | 94 | { 55, 0x0000 }, /* R55 - Additional Control */ |
94 | 0x0000, /* R55 - Additional Control */ | 95 | { 56, 0x0000 }, /* R56 - AntiPOP1 */ |
95 | 0x0000, /* R56 - AntiPOP1 */ | 96 | { 57, 0x0000 }, /* R57 - AntiPOP2 */ |
96 | 0x0000, /* R57 - AntiPOP2 */ | 97 | { 58, 0x0000 }, /* R58 - MICBIAS */ |
97 | 0x0000, /* R58 - MICBIAS */ | 98 | |
98 | 0x0000, /* R59 */ | 99 | { 60, 0x0008 }, /* R60 - PLL1 */ |
99 | 0x0008, /* R60 - PLL1 */ | 100 | { 61, 0x0031 }, /* R61 - PLL2 */ |
100 | 0x0031, /* R61 - PLL2 */ | 101 | { 62, 0x0026 }, /* R62 - PLL3 */ |
101 | 0x0026, /* R62 - PLL3 */ | ||
102 | }; | 102 | }; |
103 | 103 | ||
104 | #define wm8991_reset(c) snd_soc_write(c, WM8991_RESET, 0) | 104 | static bool wm8991_volatile(struct device *dev, unsigned int reg) |
105 | { | ||
106 | switch (reg) { | ||
107 | case WM8991_RESET: | ||
108 | return true; | ||
109 | default: | ||
110 | return false; | ||
111 | } | ||
112 | } | ||
105 | 113 | ||
106 | static const unsigned int rec_mix_tlv[] = { | 114 | static const unsigned int rec_mix_tlv[] = { |
107 | TLV_DB_RANGE_HEAD(1), | 115 | TLV_DB_RANGE_HEAD(1), |
@@ -374,30 +382,6 @@ static const struct snd_kcontrol_new wm8991_snd_controls[] = { | |||
374 | /* | 382 | /* |
375 | * _DAPM_ Controls | 383 | * _DAPM_ Controls |
376 | */ | 384 | */ |
377 | static int inmixer_event(struct snd_soc_dapm_widget *w, | ||
378 | struct snd_kcontrol *kcontrol, int event) | ||
379 | { | ||
380 | u16 reg, fakepower; | ||
381 | |||
382 | reg = snd_soc_read(w->codec, WM8991_POWER_MANAGEMENT_2); | ||
383 | fakepower = snd_soc_read(w->codec, WM8991_INTDRIVBITS); | ||
384 | |||
385 | if (fakepower & ((1 << WM8991_INMIXL_PWR_BIT) | | ||
386 | (1 << WM8991_AINLMUX_PWR_BIT))) | ||
387 | reg |= WM8991_AINL_ENA; | ||
388 | else | ||
389 | reg &= ~WM8991_AINL_ENA; | ||
390 | |||
391 | if (fakepower & ((1 << WM8991_INMIXR_PWR_BIT) | | ||
392 | (1 << WM8991_AINRMUX_PWR_BIT))) | ||
393 | reg |= WM8991_AINR_ENA; | ||
394 | else | ||
395 | reg &= ~WM8991_AINR_ENA; | ||
396 | |||
397 | snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg); | ||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static int outmixer_event(struct snd_soc_dapm_widget *w, | 385 | static int outmixer_event(struct snd_soc_dapm_widget *w, |
402 | struct snd_kcontrol *kcontrol, int event) | 386 | struct snd_kcontrol *kcontrol, int event) |
403 | { | 387 | { |
@@ -655,6 +639,11 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = { | |||
655 | SND_SOC_DAPM_INPUT("RIN2"), | 639 | SND_SOC_DAPM_INPUT("RIN2"), |
656 | SND_SOC_DAPM_INPUT("Internal ADC Source"), | 640 | SND_SOC_DAPM_INPUT("Internal ADC Source"), |
657 | 641 | ||
642 | SND_SOC_DAPM_SUPPLY("INL", WM8991_POWER_MANAGEMENT_2, | ||
643 | WM8991_AINL_ENA_BIT, 0, NULL, 0), | ||
644 | SND_SOC_DAPM_SUPPLY("INR", WM8991_POWER_MANAGEMENT_2, | ||
645 | WM8991_AINR_ENA_BIT, 0, NULL, 0), | ||
646 | |||
658 | /* DACs */ | 647 | /* DACs */ |
659 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8991_POWER_MANAGEMENT_2, | 648 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8991_POWER_MANAGEMENT_2, |
660 | WM8991_ADCL_ENA_BIT, 0), | 649 | WM8991_ADCL_ENA_BIT, 0), |
@@ -676,26 +665,22 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = { | |||
676 | ARRAY_SIZE(wm8991_dapm_rin34_pga_controls)), | 665 | ARRAY_SIZE(wm8991_dapm_rin34_pga_controls)), |
677 | 666 | ||
678 | /* INMIXL */ | 667 | /* INMIXL */ |
679 | SND_SOC_DAPM_MIXER_E("INMIXL", WM8991_INTDRIVBITS, WM8991_INMIXL_PWR_BIT, 0, | 668 | SND_SOC_DAPM_MIXER("INMIXL", SND_SOC_NOPM, 0, 0, |
680 | &wm8991_dapm_inmixl_controls[0], | 669 | &wm8991_dapm_inmixl_controls[0], |
681 | ARRAY_SIZE(wm8991_dapm_inmixl_controls), | 670 | ARRAY_SIZE(wm8991_dapm_inmixl_controls)), |
682 | inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
683 | 671 | ||
684 | /* AINLMUX */ | 672 | /* AINLMUX */ |
685 | SND_SOC_DAPM_MUX_E("AINLMUX", WM8991_INTDRIVBITS, WM8991_AINLMUX_PWR_BIT, 0, | 673 | SND_SOC_DAPM_MUX("AINLMUX", SND_SOC_NOPM, 0, 0, |
686 | &wm8991_dapm_ainlmux_controls, inmixer_event, | 674 | &wm8991_dapm_ainlmux_controls), |
687 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
688 | 675 | ||
689 | /* INMIXR */ | 676 | /* INMIXR */ |
690 | SND_SOC_DAPM_MIXER_E("INMIXR", WM8991_INTDRIVBITS, WM8991_INMIXR_PWR_BIT, 0, | 677 | SND_SOC_DAPM_MIXER("INMIXR", SND_SOC_NOPM, 0, 0, |
691 | &wm8991_dapm_inmixr_controls[0], | 678 | &wm8991_dapm_inmixr_controls[0], |
692 | ARRAY_SIZE(wm8991_dapm_inmixr_controls), | 679 | ARRAY_SIZE(wm8991_dapm_inmixr_controls)), |
693 | inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
694 | 680 | ||
695 | /* AINRMUX */ | 681 | /* AINRMUX */ |
696 | SND_SOC_DAPM_MUX_E("AINRMUX", WM8991_INTDRIVBITS, WM8991_AINRMUX_PWR_BIT, 0, | 682 | SND_SOC_DAPM_MUX("AINRMUX", SND_SOC_NOPM, 0, 0, |
697 | &wm8991_dapm_ainrmux_controls, inmixer_event, | 683 | &wm8991_dapm_ainrmux_controls), |
698 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
699 | 684 | ||
700 | /* Output Side */ | 685 | /* Output Side */ |
701 | /* DACs */ | 686 | /* DACs */ |
@@ -787,7 +772,7 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = { | |||
787 | SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), | 772 | SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), |
788 | }; | 773 | }; |
789 | 774 | ||
790 | static const struct snd_soc_dapm_route audio_map[] = { | 775 | static const struct snd_soc_dapm_route wm8991_dapm_routes[] = { |
791 | /* Make DACs turn on when playing even if not mixed into any outputs */ | 776 | /* Make DACs turn on when playing even if not mixed into any outputs */ |
792 | {"Internal DAC Sink", NULL, "Left DAC"}, | 777 | {"Internal DAC Sink", NULL, "Left DAC"}, |
793 | {"Internal DAC Sink", NULL, "Right DAC"}, | 778 | {"Internal DAC Sink", NULL, "Right DAC"}, |
@@ -797,6 +782,10 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
797 | {"Right ADC", NULL, "Internal ADC Source"}, | 782 | {"Right ADC", NULL, "Internal ADC Source"}, |
798 | 783 | ||
799 | /* Input Side */ | 784 | /* Input Side */ |
785 | {"INMIXL", NULL, "INL"}, | ||
786 | {"AINLMUX", NULL, "INL"}, | ||
787 | {"INMIXR", NULL, "INR"}, | ||
788 | {"AINRMUX", NULL, "INR"}, | ||
800 | /* LIN12 PGA */ | 789 | /* LIN12 PGA */ |
801 | {"LIN12 PGA", "LIN1 Switch", "LIN1"}, | 790 | {"LIN12 PGA", "LIN1 Switch", "LIN1"}, |
802 | {"LIN12 PGA", "LIN2 Switch", "LIN2"}, | 791 | {"LIN12 PGA", "LIN2 Switch", "LIN2"}, |
@@ -1129,6 +1118,7 @@ static int wm8991_mute(struct snd_soc_dai *dai, int mute) | |||
1129 | static int wm8991_set_bias_level(struct snd_soc_codec *codec, | 1118 | static int wm8991_set_bias_level(struct snd_soc_codec *codec, |
1130 | enum snd_soc_bias_level level) | 1119 | enum snd_soc_bias_level level) |
1131 | { | 1120 | { |
1121 | struct wm8991_priv *wm8991 = snd_soc_codec_get_drvdata(codec); | ||
1132 | u16 val; | 1122 | u16 val; |
1133 | 1123 | ||
1134 | switch (level) { | 1124 | switch (level) { |
@@ -1144,7 +1134,7 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec, | |||
1144 | 1134 | ||
1145 | case SND_SOC_BIAS_STANDBY: | 1135 | case SND_SOC_BIAS_STANDBY: |
1146 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1136 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
1147 | snd_soc_cache_sync(codec); | 1137 | regcache_sync(wm8991->regmap); |
1148 | /* Enable all output discharge bits */ | 1138 | /* Enable all output discharge bits */ |
1149 | snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE | | 1139 | snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE | |
1150 | WM8991_DIS_RLINE | WM8991_DIS_OUT3 | | 1140 | WM8991_DIS_RLINE | WM8991_DIS_OUT3 | |
@@ -1232,7 +1222,7 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec, | |||
1232 | 1222 | ||
1233 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ | 1223 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ |
1234 | snd_soc_write(codec, WM8991_ANTIPOP2, 0x0); | 1224 | snd_soc_write(codec, WM8991_ANTIPOP2, 0x0); |
1235 | codec->cache_sync = 1; | 1225 | regcache_mark_dirty(wm8991->regmap); |
1236 | break; | 1226 | break; |
1237 | } | 1227 | } |
1238 | 1228 | ||
@@ -1266,44 +1256,14 @@ static int wm8991_probe(struct snd_soc_codec *codec) | |||
1266 | 1256 | ||
1267 | wm8991 = snd_soc_codec_get_drvdata(codec); | 1257 | wm8991 = snd_soc_codec_get_drvdata(codec); |
1268 | 1258 | ||
1269 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8991->control_type); | 1259 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); |
1270 | if (ret < 0) { | 1260 | if (ret < 0) { |
1271 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | 1261 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); |
1272 | return ret; | 1262 | return ret; |
1273 | } | 1263 | } |
1274 | 1264 | ||
1275 | ret = wm8991_reset(codec); | ||
1276 | if (ret < 0) { | ||
1277 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
1278 | return ret; | ||
1279 | } | ||
1280 | |||
1281 | wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1265 | wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1282 | 1266 | ||
1283 | snd_soc_update_bits(codec, WM8991_AUDIO_INTERFACE_4, | ||
1284 | WM8991_ALRCGPIO1, WM8991_ALRCGPIO1); | ||
1285 | |||
1286 | snd_soc_update_bits(codec, WM8991_GPIO1_GPIO2, | ||
1287 | WM8991_GPIO1_SEL_MASK, 1); | ||
1288 | |||
1289 | snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_1, | ||
1290 | WM8991_VREF_ENA | WM8991_VMID_MODE_MASK, | ||
1291 | WM8991_VREF_ENA | WM8991_VMID_MODE_MASK); | ||
1292 | |||
1293 | snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_2, | ||
1294 | WM8991_OPCLK_ENA, WM8991_OPCLK_ENA); | ||
1295 | |||
1296 | snd_soc_write(codec, WM8991_DAC_CTRL, 0); | ||
1297 | snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); | ||
1298 | snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); | ||
1299 | |||
1300 | snd_soc_add_codec_controls(codec, wm8991_snd_controls, | ||
1301 | ARRAY_SIZE(wm8991_snd_controls)); | ||
1302 | |||
1303 | snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets, | ||
1304 | ARRAY_SIZE(wm8991_dapm_widgets)); | ||
1305 | snd_soc_dapm_add_routes(&codec->dapm, audio_map, | ||
1306 | ARRAY_SIZE(audio_map)); | ||
1307 | return 0; | 1267 | return 0; |
1308 | } | 1268 | } |
1309 | 1269 | ||
@@ -1352,24 +1312,77 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8991 = { | |||
1352 | .suspend = wm8991_suspend, | 1312 | .suspend = wm8991_suspend, |
1353 | .resume = wm8991_resume, | 1313 | .resume = wm8991_resume, |
1354 | .set_bias_level = wm8991_set_bias_level, | 1314 | .set_bias_level = wm8991_set_bias_level, |
1355 | .reg_cache_size = WM8991_MAX_REGISTER + 1, | 1315 | .controls = wm8991_snd_controls, |
1356 | .reg_word_size = sizeof(u16), | 1316 | .num_controls = ARRAY_SIZE(wm8991_snd_controls), |
1357 | .reg_cache_default = wm8991_reg_defs | 1317 | .dapm_widgets = wm8991_dapm_widgets, |
1318 | .num_dapm_widgets = ARRAY_SIZE(wm8991_dapm_widgets), | ||
1319 | .dapm_routes = wm8991_dapm_routes, | ||
1320 | .num_dapm_routes = ARRAY_SIZE(wm8991_dapm_routes), | ||
1321 | }; | ||
1322 | |||
1323 | static const struct regmap_config wm8991_regmap = { | ||
1324 | .reg_bits = 8, | ||
1325 | .val_bits = 16, | ||
1326 | |||
1327 | .max_register = WM8991_PLL3, | ||
1328 | .volatile_reg = wm8991_volatile, | ||
1329 | .reg_defaults = wm8991_reg_defaults, | ||
1330 | .num_reg_defaults = ARRAY_SIZE(wm8991_reg_defaults), | ||
1331 | .cache_type = REGCACHE_RBTREE, | ||
1358 | }; | 1332 | }; |
1359 | 1333 | ||
1360 | static int wm8991_i2c_probe(struct i2c_client *i2c, | 1334 | static int wm8991_i2c_probe(struct i2c_client *i2c, |
1361 | const struct i2c_device_id *id) | 1335 | const struct i2c_device_id *id) |
1362 | { | 1336 | { |
1363 | struct wm8991_priv *wm8991; | 1337 | struct wm8991_priv *wm8991; |
1338 | unsigned int val; | ||
1364 | int ret; | 1339 | int ret; |
1365 | 1340 | ||
1366 | wm8991 = devm_kzalloc(&i2c->dev, sizeof(*wm8991), GFP_KERNEL); | 1341 | wm8991 = devm_kzalloc(&i2c->dev, sizeof(*wm8991), GFP_KERNEL); |
1367 | if (!wm8991) | 1342 | if (!wm8991) |
1368 | return -ENOMEM; | 1343 | return -ENOMEM; |
1369 | 1344 | ||
1370 | wm8991->control_type = SND_SOC_I2C; | 1345 | wm8991->regmap = devm_regmap_init_i2c(i2c, &wm8991_regmap); |
1346 | if (IS_ERR(wm8991->regmap)) | ||
1347 | return PTR_ERR(wm8991->regmap); | ||
1348 | |||
1371 | i2c_set_clientdata(i2c, wm8991); | 1349 | i2c_set_clientdata(i2c, wm8991); |
1372 | 1350 | ||
1351 | ret = regmap_read(wm8991->regmap, WM8991_RESET, &val); | ||
1352 | if (ret != 0) { | ||
1353 | dev_err(&i2c->dev, "Failed to read device ID: %d\n", ret); | ||
1354 | return ret; | ||
1355 | } | ||
1356 | if (val != 0x8991) { | ||
1357 | dev_err(&i2c->dev, "Device with ID %x is not a WM8991\n", val); | ||
1358 | return -EINVAL; | ||
1359 | } | ||
1360 | |||
1361 | ret = regmap_write(wm8991->regmap, WM8991_RESET, 0); | ||
1362 | if (ret < 0) { | ||
1363 | dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); | ||
1364 | return ret; | ||
1365 | } | ||
1366 | |||
1367 | regmap_update_bits(wm8991->regmap, WM8991_AUDIO_INTERFACE_4, | ||
1368 | WM8991_ALRCGPIO1, WM8991_ALRCGPIO1); | ||
1369 | |||
1370 | regmap_update_bits(wm8991->regmap, WM8991_GPIO1_GPIO2, | ||
1371 | WM8991_GPIO1_SEL_MASK, 1); | ||
1372 | |||
1373 | regmap_update_bits(wm8991->regmap, WM8991_POWER_MANAGEMENT_1, | ||
1374 | WM8991_VREF_ENA | WM8991_VMID_MODE_MASK, | ||
1375 | WM8991_VREF_ENA | WM8991_VMID_MODE_MASK); | ||
1376 | |||
1377 | regmap_update_bits(wm8991->regmap, WM8991_POWER_MANAGEMENT_2, | ||
1378 | WM8991_OPCLK_ENA, WM8991_OPCLK_ENA); | ||
1379 | |||
1380 | regmap_write(wm8991->regmap, WM8991_DAC_CTRL, 0); | ||
1381 | regmap_write(wm8991->regmap, WM8991_LEFT_OUTPUT_VOLUME, | ||
1382 | 0x50 | (1<<8)); | ||
1383 | regmap_write(wm8991->regmap, WM8991_RIGHT_OUTPUT_VOLUME, | ||
1384 | 0x50 | (1<<8)); | ||
1385 | |||
1373 | ret = snd_soc_register_codec(&i2c->dev, | 1386 | ret = snd_soc_register_codec(&i2c->dev, |
1374 | &soc_codec_dev_wm8991, &wm8991_dai, 1); | 1387 | &soc_codec_dev_wm8991, &wm8991_dai, 1); |
1375 | 1388 | ||
diff --git a/sound/soc/codecs/wm8991.h b/sound/soc/codecs/wm8991.h index 07707d8d7e20..08ed383303c0 100644 --- a/sound/soc/codecs/wm8991.h +++ b/sound/soc/codecs/wm8991.h | |||
@@ -76,7 +76,6 @@ | |||
76 | #define WM8991_PLL1 0x3C | 76 | #define WM8991_PLL1 0x3C |
77 | #define WM8991_PLL2 0x3D | 77 | #define WM8991_PLL2 0x3D |
78 | #define WM8991_PLL3 0x3E | 78 | #define WM8991_PLL3 0x3E |
79 | #define WM8991_INTDRIVBITS 0x3F | ||
80 | 79 | ||
81 | #define WM8991_REGISTER_COUNT 60 | 80 | #define WM8991_REGISTER_COUNT 60 |
82 | #define WM8991_MAX_REGISTER 0x3F | 81 | #define WM8991_MAX_REGISTER 0x3F |
@@ -807,14 +806,6 @@ | |||
807 | */ | 806 | */ |
808 | #define WM8991_PLLK2_MASK 0x00FF /* PLLK2 - [7:0] */ | 807 | #define WM8991_PLLK2_MASK 0x00FF /* PLLK2 - [7:0] */ |
809 | 808 | ||
810 | /* | ||
811 | * R63 (0x3F) - Internal Driver Bits | ||
812 | */ | ||
813 | #define WM8991_INMIXL_PWR_BIT 0 | ||
814 | #define WM8991_AINLMUX_PWR_BIT 1 | ||
815 | #define WM8991_INMIXR_PWR_BIT 2 | ||
816 | #define WM8991_AINRMUX_PWR_BIT 3 | ||
817 | |||
818 | #define WM8991_MCLK_DIV 0 | 809 | #define WM8991_MCLK_DIV 0 |
819 | #define WM8991_DACCLK_DIV 1 | 810 | #define WM8991_DACCLK_DIV 1 |
820 | #define WM8991_ADCCLK_DIV 2 | 811 | #define WM8991_ADCCLK_DIV 2 |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 86426a117b07..b9be9cbc4603 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -4077,12 +4077,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4077 | wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, | 4077 | wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, |
4078 | wm8994_temp_shut, "Thermal shutdown", codec); | 4078 | wm8994_temp_shut, "Thermal shutdown", codec); |
4079 | 4079 | ||
4080 | ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE, | ||
4081 | wm_hubs_dcs_done, "DC servo done", | ||
4082 | &wm8994->hubs); | ||
4083 | if (ret == 0) | ||
4084 | wm8994->hubs.dcs_done_irq = true; | ||
4085 | |||
4086 | switch (control->type) { | 4080 | switch (control->type) { |
4087 | case WM8994: | 4081 | case WM8994: |
4088 | if (wm8994->micdet_irq) { | 4082 | if (wm8994->micdet_irq) { |
@@ -4313,6 +4307,11 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4313 | } | 4307 | } |
4314 | 4308 | ||
4315 | wm_hubs_add_analogue_routes(codec, 0, 0); | 4309 | wm_hubs_add_analogue_routes(codec, 0, 0); |
4310 | ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE, | ||
4311 | wm_hubs_dcs_done, "DC servo done", | ||
4312 | &wm8994->hubs); | ||
4313 | if (ret == 0) | ||
4314 | wm8994->hubs.dcs_done_irq = true; | ||
4316 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | 4315 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); |
4317 | 4316 | ||
4318 | switch (control->type) { | 4317 | switch (control->type) { |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index da2899e6c401..4300caff1783 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -2293,7 +2293,7 @@ static struct spi_driver wm8995_spi_driver = { | |||
2293 | }; | 2293 | }; |
2294 | #endif | 2294 | #endif |
2295 | 2295 | ||
2296 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 2296 | #if IS_ENABLED(CONFIG_I2C) |
2297 | static int wm8995_i2c_probe(struct i2c_client *i2c, | 2297 | static int wm8995_i2c_probe(struct i2c_client *i2c, |
2298 | const struct i2c_device_id *id) | 2298 | const struct i2c_device_id *id) |
2299 | { | 2299 | { |
@@ -2350,7 +2350,7 @@ static int __init wm8995_modinit(void) | |||
2350 | { | 2350 | { |
2351 | int ret = 0; | 2351 | int ret = 0; |
2352 | 2352 | ||
2353 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 2353 | #if IS_ENABLED(CONFIG_I2C) |
2354 | ret = i2c_add_driver(&wm8995_i2c_driver); | 2354 | ret = i2c_add_driver(&wm8995_i2c_driver); |
2355 | if (ret) { | 2355 | if (ret) { |
2356 | printk(KERN_ERR "Failed to register wm8995 I2C driver: %d\n", | 2356 | printk(KERN_ERR "Failed to register wm8995 I2C driver: %d\n", |
@@ -2371,7 +2371,7 @@ module_init(wm8995_modinit); | |||
2371 | 2371 | ||
2372 | static void __exit wm8995_exit(void) | 2372 | static void __exit wm8995_exit(void) |
2373 | { | 2373 | { |
2374 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 2374 | #if IS_ENABLED(CONFIG_I2C) |
2375 | i2c_del_driver(&wm8995_i2c_driver); | 2375 | i2c_del_driver(&wm8995_i2c_driver); |
2376 | #endif | 2376 | #endif |
2377 | #if defined(CONFIG_SPI_MASTER) | 2377 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 1392bb3c9254..555115ee2159 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c | |||
@@ -103,8 +103,8 @@ static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
103 | case SND_SOC_DAPM_POST_PMU: | 103 | case SND_SOC_DAPM_POST_PMU: |
104 | if (patch) | 104 | if (patch) |
105 | for (i = 0; i < patch_size; i++) | 105 | for (i = 0; i < patch_size; i++) |
106 | regmap_write(regmap, patch[i].reg, | 106 | regmap_write_async(regmap, patch[i].reg, |
107 | patch[i].def); | 107 | patch[i].def); |
108 | break; | 108 | break; |
109 | default: | 109 | default: |
110 | break; | 110 | break; |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 630b3d776ec2..0982c1d38ec4 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -1326,7 +1326,7 @@ static const struct regmap_config wm9081_regmap = { | |||
1326 | .cache_type = REGCACHE_RBTREE, | 1326 | .cache_type = REGCACHE_RBTREE, |
1327 | }; | 1327 | }; |
1328 | 1328 | ||
1329 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1329 | #if IS_ENABLED(CONFIG_I2C) |
1330 | static int wm9081_i2c_probe(struct i2c_client *i2c, | 1330 | static int wm9081_i2c_probe(struct i2c_client *i2c, |
1331 | const struct i2c_device_id *id) | 1331 | const struct i2c_device_id *id) |
1332 | { | 1332 | { |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 46ec0e9744d4..fb0c678939bf 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -1286,6 +1286,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) | |||
1286 | reg = wm_adsp_region_to_reg(mem, | 1286 | reg = wm_adsp_region_to_reg(mem, |
1287 | reg); | 1287 | reg); |
1288 | reg += offset; | 1288 | reg += offset; |
1289 | break; | ||
1289 | } | 1290 | } |
1290 | } | 1291 | } |
1291 | 1292 | ||
@@ -1468,19 +1469,23 @@ static int wm_adsp2_ena(struct wm_adsp *dsp) | |||
1468 | unsigned int val; | 1469 | unsigned int val; |
1469 | int ret, count; | 1470 | int ret, count; |
1470 | 1471 | ||
1471 | ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, | 1472 | ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL, |
1472 | ADSP2_SYS_ENA, ADSP2_SYS_ENA); | 1473 | ADSP2_SYS_ENA, ADSP2_SYS_ENA); |
1473 | if (ret != 0) | 1474 | if (ret != 0) |
1474 | return ret; | 1475 | return ret; |
1475 | 1476 | ||
1476 | /* Wait for the RAM to start, should be near instantaneous */ | 1477 | /* Wait for the RAM to start, should be near instantaneous */ |
1477 | count = 0; | 1478 | for (count = 0; count < 10; ++count) { |
1478 | do { | ||
1479 | ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, | 1479 | ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, |
1480 | &val); | 1480 | &val); |
1481 | if (ret != 0) | 1481 | if (ret != 0) |
1482 | return ret; | 1482 | return ret; |
1483 | } while (!(val & ADSP2_RAM_RDY) && ++count < 10); | 1483 | |
1484 | if (val & ADSP2_RAM_RDY) | ||
1485 | break; | ||
1486 | |||
1487 | msleep(1); | ||
1488 | } | ||
1484 | 1489 | ||
1485 | if (!(val & ADSP2_RAM_RDY)) { | 1490 | if (!(val & ADSP2_RAM_RDY)) { |
1486 | adsp_err(dsp, "Failed to start DSP RAM\n"); | 1491 | adsp_err(dsp, "Failed to start DSP RAM\n"); |
@@ -1488,7 +1493,6 @@ static int wm_adsp2_ena(struct wm_adsp *dsp) | |||
1488 | } | 1493 | } |
1489 | 1494 | ||
1490 | adsp_dbg(dsp, "RAM ready after %d polls\n", count); | 1495 | adsp_dbg(dsp, "RAM ready after %d polls\n", count); |
1491 | adsp_info(dsp, "RAM ready after %d polls\n", count); | ||
1492 | 1496 | ||
1493 | return 0; | 1497 | return 0; |
1494 | } | 1498 | } |
@@ -1521,9 +1525,9 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
1521 | val = (val & ARIZONA_SYSCLK_FREQ_MASK) | 1525 | val = (val & ARIZONA_SYSCLK_FREQ_MASK) |
1522 | >> ARIZONA_SYSCLK_FREQ_SHIFT; | 1526 | >> ARIZONA_SYSCLK_FREQ_SHIFT; |
1523 | 1527 | ||
1524 | ret = regmap_update_bits(dsp->regmap, | 1528 | ret = regmap_update_bits_async(dsp->regmap, |
1525 | dsp->base + ADSP2_CLOCKING, | 1529 | dsp->base + ADSP2_CLOCKING, |
1526 | ADSP2_CLK_SEL_MASK, val); | 1530 | ADSP2_CLK_SEL_MASK, val); |
1527 | if (ret != 0) { | 1531 | if (ret != 0) { |
1528 | adsp_err(dsp, "Failed to set clock rate: %d\n", | 1532 | adsp_err(dsp, "Failed to set clock rate: %d\n", |
1529 | ret); | 1533 | ret); |
@@ -1586,10 +1590,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
1586 | if (ret != 0) | 1590 | if (ret != 0) |
1587 | goto err; | 1591 | goto err; |
1588 | 1592 | ||
1589 | ret = regmap_update_bits(dsp->regmap, | 1593 | ret = regmap_update_bits_async(dsp->regmap, |
1590 | dsp->base + ADSP2_CONTROL, | 1594 | dsp->base + ADSP2_CONTROL, |
1591 | ADSP2_CORE_ENA | ADSP2_START, | 1595 | ADSP2_CORE_ENA | ADSP2_START, |
1592 | ADSP2_CORE_ENA | ADSP2_START); | 1596 | ADSP2_CORE_ENA | ADSP2_START); |
1593 | if (ret != 0) | 1597 | if (ret != 0) |
1594 | goto err; | 1598 | goto err; |
1595 | 1599 | ||
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index 95970f5db3ec..a8ec1fc3e4d0 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig | |||
@@ -1,11 +1,6 @@ | |||
1 | config SND_DAVINCI_SOC | 1 | config SND_DAVINCI_SOC |
2 | tristate "SoC Audio for the TI DAVINCI or AM33XX chip" | 2 | tristate "SoC Audio for TI DAVINCI or AM33XX/AM43XX chips" |
3 | depends on ARCH_DAVINCI || SOC_AM33XX | 3 | depends on ARCH_DAVINCI || SOC_AM33XX || SOC_AM43XX |
4 | help | ||
5 | Platform driver for daVinci or AM33xx | ||
6 | Say Y or M if you want to add support for codecs attached to | ||
7 | the DAVINCI AC97, I2S, or McASP interface. You will also need | ||
8 | to select the audio interfaces to support below. | ||
9 | 4 | ||
10 | config SND_DAVINCI_SOC_I2S | 5 | config SND_DAVINCI_SOC_I2S |
11 | tristate | 6 | tristate |
@@ -16,11 +11,15 @@ config SND_DAVINCI_SOC_MCASP | |||
16 | config SND_DAVINCI_SOC_VCIF | 11 | config SND_DAVINCI_SOC_VCIF |
17 | tristate | 12 | tristate |
18 | 13 | ||
14 | config SND_DAVINCI_SOC_GENERIC_EVM | ||
15 | tristate | ||
16 | select SND_SOC_TLV320AIC3X | ||
17 | select SND_DAVINCI_SOC_MCASP | ||
18 | |||
19 | config SND_AM33XX_SOC_EVM | 19 | config SND_AM33XX_SOC_EVM |
20 | tristate "SoC Audio for the AM33XX chip based boards" | 20 | tristate "SoC Audio for the AM33XX chip based boards" |
21 | depends on SND_DAVINCI_SOC && SOC_AM33XX | 21 | depends on SND_DAVINCI_SOC && SOC_AM33XX |
22 | select SND_SOC_TLV320AIC3X | 22 | select SND_DAVINCI_SOC_GENERIC_EVM |
23 | select SND_DAVINCI_SOC_MCASP | ||
24 | help | 23 | help |
25 | Say Y or M if you want to add support for SoC audio on AM33XX | 24 | Say Y or M if you want to add support for SoC audio on AM33XX |
26 | boards using McASP and TLV320AIC3X codec. For example AM335X-EVM, | 25 | boards using McASP and TLV320AIC3X codec. For example AM335X-EVM, |
@@ -31,8 +30,7 @@ config SND_DAVINCI_SOC_EVM | |||
31 | tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" | 30 | tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" |
32 | depends on SND_DAVINCI_SOC | 31 | depends on SND_DAVINCI_SOC |
33 | depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM | 32 | depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM |
34 | select SND_DAVINCI_SOC_I2S | 33 | select SND_DAVINCI_SOC_GENERIC_EVM |
35 | select SND_SOC_TLV320AIC3X | ||
36 | help | 34 | help |
37 | Say Y if you want to add support for SoC audio on TI | 35 | Say Y if you want to add support for SoC audio on TI |
38 | DaVinci DM6446, DM355 or DM365 EVM platforms. | 36 | DaVinci DM6446, DM355 or DM365 EVM platforms. |
@@ -59,8 +57,7 @@ endchoice | |||
59 | config SND_DM6467_SOC_EVM | 57 | config SND_DM6467_SOC_EVM |
60 | tristate "SoC Audio support for DaVinci DM6467 EVM" | 58 | tristate "SoC Audio support for DaVinci DM6467 EVM" |
61 | depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM | 59 | depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM |
62 | select SND_DAVINCI_SOC_MCASP | 60 | select SND_DAVINCI_SOC_GENERIC_EVM |
63 | select SND_SOC_TLV320AIC3X | ||
64 | select SND_SOC_SPDIF | 61 | select SND_SOC_SPDIF |
65 | 62 | ||
66 | help | 63 | help |
@@ -69,8 +66,7 @@ config SND_DM6467_SOC_EVM | |||
69 | config SND_DA830_SOC_EVM | 66 | config SND_DA830_SOC_EVM |
70 | tristate "SoC Audio support for DA830/OMAP-L137 EVM" | 67 | tristate "SoC Audio support for DA830/OMAP-L137 EVM" |
71 | depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM | 68 | depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM |
72 | select SND_DAVINCI_SOC_MCASP | 69 | select SND_DAVINCI_SOC_GENERIC_EVM |
73 | select SND_SOC_TLV320AIC3X | ||
74 | 70 | ||
75 | help | 71 | help |
76 | Say Y if you want to add support for SoC audio on TI | 72 | Say Y if you want to add support for SoC audio on TI |
@@ -79,8 +75,7 @@ config SND_DA830_SOC_EVM | |||
79 | config SND_DA850_SOC_EVM | 75 | config SND_DA850_SOC_EVM |
80 | tristate "SoC Audio support for DA850/OMAP-L138 EVM" | 76 | tristate "SoC Audio support for DA850/OMAP-L138 EVM" |
81 | depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM | 77 | depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM |
82 | select SND_DAVINCI_SOC_MCASP | 78 | select SND_DAVINCI_SOC_GENERIC_EVM |
83 | select SND_SOC_TLV320AIC3X | ||
84 | help | 79 | help |
85 | Say Y if you want to add support for SoC audio on TI | 80 | Say Y if you want to add support for SoC audio on TI |
86 | DA850/OMAP-L138 EVM | 81 | DA850/OMAP-L138 EVM |
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile index bc81e79fc301..744d4d9a0184 100644 --- a/sound/soc/davinci/Makefile +++ b/sound/soc/davinci/Makefile | |||
@@ -9,11 +9,7 @@ obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o | |||
9 | obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o | 9 | obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o |
10 | obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o | 10 | obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o |
11 | 11 | ||
12 | # DAVINCI Machine Support | 12 | # Generic DAVINCI/AM33xx Machine Support |
13 | snd-soc-evm-objs := davinci-evm.o | 13 | snd-soc-evm-objs := davinci-evm.o |
14 | 14 | ||
15 | obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o | 15 | obj-$(CONFIG_SND_DAVINCI_SOC_GENERIC_EVM) += snd-soc-evm.o |
16 | obj-$(CONFIG_SND_AM33XX_SOC_EVM) += snd-soc-evm.o | ||
17 | obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o | ||
18 | obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o | ||
19 | obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o | ||
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 623eb5e7c089..70ff3772079f 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -28,14 +28,11 @@ | |||
28 | 28 | ||
29 | #include "davinci-pcm.h" | 29 | #include "davinci-pcm.h" |
30 | #include "davinci-i2s.h" | 30 | #include "davinci-i2s.h" |
31 | #include "davinci-mcasp.h" | ||
32 | 31 | ||
33 | struct snd_soc_card_drvdata_davinci { | 32 | struct snd_soc_card_drvdata_davinci { |
34 | unsigned sysclk; | 33 | unsigned sysclk; |
35 | }; | 34 | }; |
36 | 35 | ||
37 | #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ | ||
38 | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) | ||
39 | static int evm_hw_params(struct snd_pcm_substream *substream, | 36 | static int evm_hw_params(struct snd_pcm_substream *substream, |
40 | struct snd_pcm_hw_params *params) | 37 | struct snd_pcm_hw_params *params) |
41 | { | 38 | { |
@@ -48,16 +45,6 @@ static int evm_hw_params(struct snd_pcm_substream *substream, | |||
48 | unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *) | 45 | unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *) |
49 | snd_soc_card_get_drvdata(soc_card))->sysclk; | 46 | snd_soc_card_get_drvdata(soc_card))->sysclk; |
50 | 47 | ||
51 | /* set codec DAI configuration */ | ||
52 | ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT); | ||
53 | if (ret < 0) | ||
54 | return ret; | ||
55 | |||
56 | /* set cpu DAI configuration */ | ||
57 | ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); | ||
58 | if (ret < 0) | ||
59 | return ret; | ||
60 | |||
61 | /* set the codec system clock */ | 48 | /* set the codec system clock */ |
62 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT); | 49 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT); |
63 | if (ret < 0) | 50 | if (ret < 0) |
@@ -71,24 +58,10 @@ static int evm_hw_params(struct snd_pcm_substream *substream, | |||
71 | return 0; | 58 | return 0; |
72 | } | 59 | } |
73 | 60 | ||
74 | static int evm_spdif_hw_params(struct snd_pcm_substream *substream, | ||
75 | struct snd_pcm_hw_params *params) | ||
76 | { | ||
77 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
78 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
79 | |||
80 | /* set cpu DAI configuration */ | ||
81 | return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); | ||
82 | } | ||
83 | |||
84 | static struct snd_soc_ops evm_ops = { | 61 | static struct snd_soc_ops evm_ops = { |
85 | .hw_params = evm_hw_params, | 62 | .hw_params = evm_hw_params, |
86 | }; | 63 | }; |
87 | 64 | ||
88 | static struct snd_soc_ops evm_spdif_ops = { | ||
89 | .hw_params = evm_spdif_hw_params, | ||
90 | }; | ||
91 | |||
92 | /* davinci-evm machine dapm widgets */ | 65 | /* davinci-evm machine dapm widgets */ |
93 | static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | 66 | static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { |
94 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | 67 | SND_SOC_DAPM_HP("Headphone Jack", NULL), |
@@ -165,6 +138,8 @@ static struct snd_soc_dai_link dm6446_evm_dai = { | |||
165 | .platform_name = "davinci-mcbsp", | 138 | .platform_name = "davinci-mcbsp", |
166 | .init = evm_aic3x_init, | 139 | .init = evm_aic3x_init, |
167 | .ops = &evm_ops, | 140 | .ops = &evm_ops, |
141 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | | ||
142 | SND_SOC_DAIFMT_IB_NF, | ||
168 | }; | 143 | }; |
169 | 144 | ||
170 | static struct snd_soc_dai_link dm355_evm_dai = { | 145 | static struct snd_soc_dai_link dm355_evm_dai = { |
@@ -176,6 +151,8 @@ static struct snd_soc_dai_link dm355_evm_dai = { | |||
176 | .platform_name = "davinci-mcbsp.1", | 151 | .platform_name = "davinci-mcbsp.1", |
177 | .init = evm_aic3x_init, | 152 | .init = evm_aic3x_init, |
178 | .ops = &evm_ops, | 153 | .ops = &evm_ops, |
154 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | | ||
155 | SND_SOC_DAIFMT_IB_NF, | ||
179 | }; | 156 | }; |
180 | 157 | ||
181 | static struct snd_soc_dai_link dm365_evm_dai = { | 158 | static struct snd_soc_dai_link dm365_evm_dai = { |
@@ -184,10 +161,12 @@ static struct snd_soc_dai_link dm365_evm_dai = { | |||
184 | .stream_name = "AIC3X", | 161 | .stream_name = "AIC3X", |
185 | .cpu_dai_name = "davinci-mcbsp", | 162 | .cpu_dai_name = "davinci-mcbsp", |
186 | .codec_dai_name = "tlv320aic3x-hifi", | 163 | .codec_dai_name = "tlv320aic3x-hifi", |
187 | .init = evm_aic3x_init, | ||
188 | .codec_name = "tlv320aic3x-codec.1-0018", | 164 | .codec_name = "tlv320aic3x-codec.1-0018", |
189 | .ops = &evm_ops, | ||
190 | .platform_name = "davinci-mcbsp", | 165 | .platform_name = "davinci-mcbsp", |
166 | .init = evm_aic3x_init, | ||
167 | .ops = &evm_ops, | ||
168 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | | ||
169 | SND_SOC_DAIFMT_IB_NF, | ||
191 | #elif defined(CONFIG_SND_DM365_VOICE_CODEC) | 170 | #elif defined(CONFIG_SND_DM365_VOICE_CODEC) |
192 | .name = "Voice Codec - CQ93VC", | 171 | .name = "Voice Codec - CQ93VC", |
193 | .stream_name = "CQ93", | 172 | .stream_name = "CQ93", |
@@ -208,6 +187,8 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { | |||
208 | .codec_name = "tlv320aic3x-codec.0-001a", | 187 | .codec_name = "tlv320aic3x-codec.0-001a", |
209 | .init = evm_aic3x_init, | 188 | .init = evm_aic3x_init, |
210 | .ops = &evm_ops, | 189 | .ops = &evm_ops, |
190 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | | ||
191 | SND_SOC_DAIFMT_IB_NF, | ||
211 | }, | 192 | }, |
212 | { | 193 | { |
213 | .name = "McASP", | 194 | .name = "McASP", |
@@ -216,7 +197,8 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { | |||
216 | .codec_dai_name = "dit-hifi", | 197 | .codec_dai_name = "dit-hifi", |
217 | .codec_name = "spdif_dit", | 198 | .codec_name = "spdif_dit", |
218 | .platform_name = "davinci-mcasp.1", | 199 | .platform_name = "davinci-mcasp.1", |
219 | .ops = &evm_spdif_ops, | 200 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | |
201 | SND_SOC_DAIFMT_IB_NF, | ||
220 | }, | 202 | }, |
221 | }; | 203 | }; |
222 | 204 | ||
@@ -229,6 +211,8 @@ static struct snd_soc_dai_link da830_evm_dai = { | |||
229 | .platform_name = "davinci-mcasp.1", | 211 | .platform_name = "davinci-mcasp.1", |
230 | .init = evm_aic3x_init, | 212 | .init = evm_aic3x_init, |
231 | .ops = &evm_ops, | 213 | .ops = &evm_ops, |
214 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | | ||
215 | SND_SOC_DAIFMT_IB_NF, | ||
232 | }; | 216 | }; |
233 | 217 | ||
234 | static struct snd_soc_dai_link da850_evm_dai = { | 218 | static struct snd_soc_dai_link da850_evm_dai = { |
@@ -240,6 +224,8 @@ static struct snd_soc_dai_link da850_evm_dai = { | |||
240 | .platform_name = "davinci-mcasp.0", | 224 | .platform_name = "davinci-mcasp.0", |
241 | .init = evm_aic3x_init, | 225 | .init = evm_aic3x_init, |
242 | .ops = &evm_ops, | 226 | .ops = &evm_ops, |
227 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | | ||
228 | SND_SOC_DAIFMT_IB_NF, | ||
243 | }; | 229 | }; |
244 | 230 | ||
245 | /* davinci dm6446 evm audio machine driver */ | 231 | /* davinci dm6446 evm audio machine driver */ |
@@ -336,6 +322,8 @@ static struct snd_soc_dai_link evm_dai_tlv320aic3x = { | |||
336 | .codec_dai_name = "tlv320aic3x-hifi", | 322 | .codec_dai_name = "tlv320aic3x-hifi", |
337 | .ops = &evm_ops, | 323 | .ops = &evm_ops, |
338 | .init = evm_aic3x_init, | 324 | .init = evm_aic3x_init, |
325 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | | ||
326 | SND_SOC_DAIFMT_IB_NF, | ||
339 | }; | 327 | }; |
340 | 328 | ||
341 | static const struct of_device_id davinci_evm_dt_ids[] = { | 329 | static const struct of_device_id davinci_evm_dt_ids[] = { |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 71e14bb3a8cd..b7858bfa0295 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/clk.h> | ||
24 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
25 | #include <linux/of.h> | 26 | #include <linux/of.h> |
26 | #include <linux/of_platform.h> | 27 | #include <linux/of_platform.h> |
@@ -31,351 +32,147 @@ | |||
31 | #include <sound/pcm_params.h> | 32 | #include <sound/pcm_params.h> |
32 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
33 | #include <sound/soc.h> | 34 | #include <sound/soc.h> |
35 | #include <sound/dmaengine_pcm.h> | ||
34 | 36 | ||
35 | #include "davinci-pcm.h" | 37 | #include "davinci-pcm.h" |
36 | #include "davinci-mcasp.h" | 38 | #include "davinci-mcasp.h" |
37 | 39 | ||
38 | /* | 40 | struct davinci_mcasp { |
39 | * McASP register definitions | 41 | struct davinci_pcm_dma_params dma_params[2]; |
40 | */ | 42 | struct snd_dmaengine_dai_dma_data dma_data[2]; |
41 | #define DAVINCI_MCASP_PID_REG 0x00 | 43 | void __iomem *base; |
42 | #define DAVINCI_MCASP_PWREMUMGT_REG 0x04 | 44 | u32 fifo_base; |
43 | 45 | struct device *dev; | |
44 | #define DAVINCI_MCASP_PFUNC_REG 0x10 | ||
45 | #define DAVINCI_MCASP_PDIR_REG 0x14 | ||
46 | #define DAVINCI_MCASP_PDOUT_REG 0x18 | ||
47 | #define DAVINCI_MCASP_PDSET_REG 0x1c | ||
48 | |||
49 | #define DAVINCI_MCASP_PDCLR_REG 0x20 | ||
50 | |||
51 | #define DAVINCI_MCASP_TLGC_REG 0x30 | ||
52 | #define DAVINCI_MCASP_TLMR_REG 0x34 | ||
53 | |||
54 | #define DAVINCI_MCASP_GBLCTL_REG 0x44 | ||
55 | #define DAVINCI_MCASP_AMUTE_REG 0x48 | ||
56 | #define DAVINCI_MCASP_LBCTL_REG 0x4c | ||
57 | |||
58 | #define DAVINCI_MCASP_TXDITCTL_REG 0x50 | ||
59 | |||
60 | #define DAVINCI_MCASP_GBLCTLR_REG 0x60 | ||
61 | #define DAVINCI_MCASP_RXMASK_REG 0x64 | ||
62 | #define DAVINCI_MCASP_RXFMT_REG 0x68 | ||
63 | #define DAVINCI_MCASP_RXFMCTL_REG 0x6c | ||
64 | |||
65 | #define DAVINCI_MCASP_ACLKRCTL_REG 0x70 | ||
66 | #define DAVINCI_MCASP_AHCLKRCTL_REG 0x74 | ||
67 | #define DAVINCI_MCASP_RXTDM_REG 0x78 | ||
68 | #define DAVINCI_MCASP_EVTCTLR_REG 0x7c | ||
69 | |||
70 | #define DAVINCI_MCASP_RXSTAT_REG 0x80 | ||
71 | #define DAVINCI_MCASP_RXTDMSLOT_REG 0x84 | ||
72 | #define DAVINCI_MCASP_RXCLKCHK_REG 0x88 | ||
73 | #define DAVINCI_MCASP_REVTCTL_REG 0x8c | ||
74 | |||
75 | #define DAVINCI_MCASP_GBLCTLX_REG 0xa0 | ||
76 | #define DAVINCI_MCASP_TXMASK_REG 0xa4 | ||
77 | #define DAVINCI_MCASP_TXFMT_REG 0xa8 | ||
78 | #define DAVINCI_MCASP_TXFMCTL_REG 0xac | ||
79 | |||
80 | #define DAVINCI_MCASP_ACLKXCTL_REG 0xb0 | ||
81 | #define DAVINCI_MCASP_AHCLKXCTL_REG 0xb4 | ||
82 | #define DAVINCI_MCASP_TXTDM_REG 0xb8 | ||
83 | #define DAVINCI_MCASP_EVTCTLX_REG 0xbc | ||
84 | |||
85 | #define DAVINCI_MCASP_TXSTAT_REG 0xc0 | ||
86 | #define DAVINCI_MCASP_TXTDMSLOT_REG 0xc4 | ||
87 | #define DAVINCI_MCASP_TXCLKCHK_REG 0xc8 | ||
88 | #define DAVINCI_MCASP_XEVTCTL_REG 0xcc | ||
89 | |||
90 | /* Left(even TDM Slot) Channel Status Register File */ | ||
91 | #define DAVINCI_MCASP_DITCSRA_REG 0x100 | ||
92 | /* Right(odd TDM slot) Channel Status Register File */ | ||
93 | #define DAVINCI_MCASP_DITCSRB_REG 0x118 | ||
94 | /* Left(even TDM slot) User Data Register File */ | ||
95 | #define DAVINCI_MCASP_DITUDRA_REG 0x130 | ||
96 | /* Right(odd TDM Slot) User Data Register File */ | ||
97 | #define DAVINCI_MCASP_DITUDRB_REG 0x148 | ||
98 | |||
99 | /* Serializer n Control Register */ | ||
100 | #define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180 | ||
101 | #define DAVINCI_MCASP_XRSRCTL_REG(n) (DAVINCI_MCASP_XRSRCTL_BASE_REG + \ | ||
102 | (n << 2)) | ||
103 | |||
104 | /* Transmit Buffer for Serializer n */ | ||
105 | #define DAVINCI_MCASP_TXBUF_REG 0x200 | ||
106 | /* Receive Buffer for Serializer n */ | ||
107 | #define DAVINCI_MCASP_RXBUF_REG 0x280 | ||
108 | |||
109 | /* McASP FIFO Registers */ | ||
110 | #define DAVINCI_MCASP_WFIFOCTL (0x1010) | ||
111 | #define DAVINCI_MCASP_WFIFOSTS (0x1014) | ||
112 | #define DAVINCI_MCASP_RFIFOCTL (0x1018) | ||
113 | #define DAVINCI_MCASP_RFIFOSTS (0x101C) | ||
114 | #define MCASP_VER3_WFIFOCTL (0x1000) | ||
115 | #define MCASP_VER3_WFIFOSTS (0x1004) | ||
116 | #define MCASP_VER3_RFIFOCTL (0x1008) | ||
117 | #define MCASP_VER3_RFIFOSTS (0x100C) | ||
118 | |||
119 | /* | ||
120 | * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management | ||
121 | * Register Bits | ||
122 | */ | ||
123 | #define MCASP_FREE BIT(0) | ||
124 | #define MCASP_SOFT BIT(1) | ||
125 | |||
126 | /* | ||
127 | * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits | ||
128 | */ | ||
129 | #define AXR(n) (1<<n) | ||
130 | #define PFUNC_AMUTE BIT(25) | ||
131 | #define ACLKX BIT(26) | ||
132 | #define AHCLKX BIT(27) | ||
133 | #define AFSX BIT(28) | ||
134 | #define ACLKR BIT(29) | ||
135 | #define AHCLKR BIT(30) | ||
136 | #define AFSR BIT(31) | ||
137 | |||
138 | /* | ||
139 | * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits | ||
140 | */ | ||
141 | #define AXR(n) (1<<n) | ||
142 | #define PDIR_AMUTE BIT(25) | ||
143 | #define ACLKX BIT(26) | ||
144 | #define AHCLKX BIT(27) | ||
145 | #define AFSX BIT(28) | ||
146 | #define ACLKR BIT(29) | ||
147 | #define AHCLKR BIT(30) | ||
148 | #define AFSR BIT(31) | ||
149 | |||
150 | /* | ||
151 | * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits | ||
152 | */ | ||
153 | #define DITEN BIT(0) /* Transmit DIT mode enable/disable */ | ||
154 | #define VA BIT(2) | ||
155 | #define VB BIT(3) | ||
156 | |||
157 | /* | ||
158 | * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits | ||
159 | */ | ||
160 | #define TXROT(val) (val) | ||
161 | #define TXSEL BIT(3) | ||
162 | #define TXSSZ(val) (val<<4) | ||
163 | #define TXPBIT(val) (val<<8) | ||
164 | #define TXPAD(val) (val<<13) | ||
165 | #define TXORD BIT(15) | ||
166 | #define FSXDLY(val) (val<<16) | ||
167 | |||
168 | /* | ||
169 | * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits | ||
170 | */ | ||
171 | #define RXROT(val) (val) | ||
172 | #define RXSEL BIT(3) | ||
173 | #define RXSSZ(val) (val<<4) | ||
174 | #define RXPBIT(val) (val<<8) | ||
175 | #define RXPAD(val) (val<<13) | ||
176 | #define RXORD BIT(15) | ||
177 | #define FSRDLY(val) (val<<16) | ||
178 | |||
179 | /* | ||
180 | * DAVINCI_MCASP_TXFMCTL_REG - Transmit Frame Control Register Bits | ||
181 | */ | ||
182 | #define FSXPOL BIT(0) | ||
183 | #define AFSXE BIT(1) | ||
184 | #define FSXDUR BIT(4) | ||
185 | #define FSXMOD(val) (val<<7) | ||
186 | |||
187 | /* | ||
188 | * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits | ||
189 | */ | ||
190 | #define FSRPOL BIT(0) | ||
191 | #define AFSRE BIT(1) | ||
192 | #define FSRDUR BIT(4) | ||
193 | #define FSRMOD(val) (val<<7) | ||
194 | |||
195 | /* | ||
196 | * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits | ||
197 | */ | ||
198 | #define ACLKXDIV(val) (val) | ||
199 | #define ACLKXE BIT(5) | ||
200 | #define TX_ASYNC BIT(6) | ||
201 | #define ACLKXPOL BIT(7) | ||
202 | #define ACLKXDIV_MASK 0x1f | ||
203 | |||
204 | /* | ||
205 | * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits | ||
206 | */ | ||
207 | #define ACLKRDIV(val) (val) | ||
208 | #define ACLKRE BIT(5) | ||
209 | #define RX_ASYNC BIT(6) | ||
210 | #define ACLKRPOL BIT(7) | ||
211 | #define ACLKRDIV_MASK 0x1f | ||
212 | |||
213 | /* | ||
214 | * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control | ||
215 | * Register Bits | ||
216 | */ | ||
217 | #define AHCLKXDIV(val) (val) | ||
218 | #define AHCLKXPOL BIT(14) | ||
219 | #define AHCLKXE BIT(15) | ||
220 | #define AHCLKXDIV_MASK 0xfff | ||
221 | 46 | ||
222 | /* | 47 | /* McASP specific data */ |
223 | * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control | 48 | int tdm_slots; |
224 | * Register Bits | 49 | u8 op_mode; |
225 | */ | 50 | u8 num_serializer; |
226 | #define AHCLKRDIV(val) (val) | 51 | u8 *serial_dir; |
227 | #define AHCLKRPOL BIT(14) | 52 | u8 version; |
228 | #define AHCLKRE BIT(15) | 53 | u16 bclk_lrclk_ratio; |
229 | #define AHCLKRDIV_MASK 0xfff | 54 | int streams; |
230 | 55 | ||
231 | /* | 56 | /* McASP FIFO related */ |
232 | * DAVINCI_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits | 57 | u8 txnumevt; |
233 | */ | 58 | u8 rxnumevt; |
234 | #define MODE(val) (val) | ||
235 | #define DISMOD (val)(val<<2) | ||
236 | #define TXSTATE BIT(4) | ||
237 | #define RXSTATE BIT(5) | ||
238 | #define SRMOD_MASK 3 | ||
239 | #define SRMOD_INACTIVE 0 | ||
240 | |||
241 | /* | ||
242 | * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits | ||
243 | */ | ||
244 | #define LBEN BIT(0) | ||
245 | #define LBORD BIT(1) | ||
246 | #define LBGENMODE(val) (val<<2) | ||
247 | 59 | ||
248 | /* | 60 | bool dat_port; |
249 | * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration | ||
250 | */ | ||
251 | #define TXTDMS(n) (1<<n) | ||
252 | |||
253 | /* | ||
254 | * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration | ||
255 | */ | ||
256 | #define RXTDMS(n) (1<<n) | ||
257 | |||
258 | /* | ||
259 | * DAVINCI_MCASP_GBLCTL_REG - Global Control Register Bits | ||
260 | */ | ||
261 | #define RXCLKRST BIT(0) /* Receiver Clock Divider Reset */ | ||
262 | #define RXHCLKRST BIT(1) /* Receiver High Frequency Clock Divider */ | ||
263 | #define RXSERCLR BIT(2) /* Receiver Serializer Clear */ | ||
264 | #define RXSMRST BIT(3) /* Receiver State Machine Reset */ | ||
265 | #define RXFSRST BIT(4) /* Frame Sync Generator Reset */ | ||
266 | #define TXCLKRST BIT(8) /* Transmitter Clock Divider Reset */ | ||
267 | #define TXHCLKRST BIT(9) /* Transmitter High Frequency Clock Divider*/ | ||
268 | #define TXSERCLR BIT(10) /* Transmit Serializer Clear */ | ||
269 | #define TXSMRST BIT(11) /* Transmitter State Machine Reset */ | ||
270 | #define TXFSRST BIT(12) /* Frame Sync Generator Reset */ | ||
271 | 61 | ||
272 | /* | 62 | #ifdef CONFIG_PM_SLEEP |
273 | * DAVINCI_MCASP_AMUTE_REG - Mute Control Register Bits | 63 | struct { |
274 | */ | 64 | u32 txfmtctl; |
275 | #define MUTENA(val) (val) | 65 | u32 rxfmtctl; |
276 | #define MUTEINPOL BIT(2) | 66 | u32 txfmt; |
277 | #define MUTEINENA BIT(3) | 67 | u32 rxfmt; |
278 | #define MUTEIN BIT(4) | 68 | u32 aclkxctl; |
279 | #define MUTER BIT(5) | 69 | u32 aclkrctl; |
280 | #define MUTEX BIT(6) | 70 | u32 pdir; |
281 | #define MUTEFSR BIT(7) | 71 | } context; |
282 | #define MUTEFSX BIT(8) | 72 | #endif |
283 | #define MUTEBADCLKR BIT(9) | 73 | }; |
284 | #define MUTEBADCLKX BIT(10) | ||
285 | #define MUTERXDMAERR BIT(11) | ||
286 | #define MUTETXDMAERR BIT(12) | ||
287 | |||
288 | /* | ||
289 | * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits | ||
290 | */ | ||
291 | #define RXDATADMADIS BIT(0) | ||
292 | |||
293 | /* | ||
294 | * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits | ||
295 | */ | ||
296 | #define TXDATADMADIS BIT(0) | ||
297 | |||
298 | /* | ||
299 | * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits | ||
300 | */ | ||
301 | #define FIFO_ENABLE BIT(16) | ||
302 | #define NUMEVT_MASK (0xFF << 8) | ||
303 | #define NUMDMA_MASK (0xFF) | ||
304 | |||
305 | #define DAVINCI_MCASP_NUM_SERIALIZER 16 | ||
306 | 74 | ||
307 | static inline void mcasp_set_bits(void __iomem *reg, u32 val) | 75 | static inline void mcasp_set_bits(struct davinci_mcasp *mcasp, u32 offset, |
76 | u32 val) | ||
308 | { | 77 | { |
78 | void __iomem *reg = mcasp->base + offset; | ||
309 | __raw_writel(__raw_readl(reg) | val, reg); | 79 | __raw_writel(__raw_readl(reg) | val, reg); |
310 | } | 80 | } |
311 | 81 | ||
312 | static inline void mcasp_clr_bits(void __iomem *reg, u32 val) | 82 | static inline void mcasp_clr_bits(struct davinci_mcasp *mcasp, u32 offset, |
83 | u32 val) | ||
313 | { | 84 | { |
85 | void __iomem *reg = mcasp->base + offset; | ||
314 | __raw_writel((__raw_readl(reg) & ~(val)), reg); | 86 | __raw_writel((__raw_readl(reg) & ~(val)), reg); |
315 | } | 87 | } |
316 | 88 | ||
317 | static inline void mcasp_mod_bits(void __iomem *reg, u32 val, u32 mask) | 89 | static inline void mcasp_mod_bits(struct davinci_mcasp *mcasp, u32 offset, |
90 | u32 val, u32 mask) | ||
318 | { | 91 | { |
92 | void __iomem *reg = mcasp->base + offset; | ||
319 | __raw_writel((__raw_readl(reg) & ~mask) | val, reg); | 93 | __raw_writel((__raw_readl(reg) & ~mask) | val, reg); |
320 | } | 94 | } |
321 | 95 | ||
322 | static inline void mcasp_set_reg(void __iomem *reg, u32 val) | 96 | static inline void mcasp_set_reg(struct davinci_mcasp *mcasp, u32 offset, |
97 | u32 val) | ||
323 | { | 98 | { |
324 | __raw_writel(val, reg); | 99 | __raw_writel(val, mcasp->base + offset); |
325 | } | 100 | } |
326 | 101 | ||
327 | static inline u32 mcasp_get_reg(void __iomem *reg) | 102 | static inline u32 mcasp_get_reg(struct davinci_mcasp *mcasp, u32 offset) |
328 | { | 103 | { |
329 | return (unsigned int)__raw_readl(reg); | 104 | return (u32)__raw_readl(mcasp->base + offset); |
330 | } | 105 | } |
331 | 106 | ||
332 | static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val) | 107 | static void mcasp_set_ctl_reg(struct davinci_mcasp *mcasp, u32 ctl_reg, u32 val) |
333 | { | 108 | { |
334 | int i = 0; | 109 | int i = 0; |
335 | 110 | ||
336 | mcasp_set_bits(regs, val); | 111 | mcasp_set_bits(mcasp, ctl_reg, val); |
337 | 112 | ||
338 | /* programming GBLCTL needs to read back from GBLCTL and verfiy */ | 113 | /* programming GBLCTL needs to read back from GBLCTL and verfiy */ |
339 | /* loop count is to avoid the lock-up */ | 114 | /* loop count is to avoid the lock-up */ |
340 | for (i = 0; i < 1000; i++) { | 115 | for (i = 0; i < 1000; i++) { |
341 | if ((mcasp_get_reg(regs) & val) == val) | 116 | if ((mcasp_get_reg(mcasp, ctl_reg) & val) == val) |
342 | break; | 117 | break; |
343 | } | 118 | } |
344 | 119 | ||
345 | if (i == 1000 && ((mcasp_get_reg(regs) & val) != val)) | 120 | if (i == 1000 && ((mcasp_get_reg(mcasp, ctl_reg) & val) != val)) |
346 | printk(KERN_ERR "GBLCTL write error\n"); | 121 | printk(KERN_ERR "GBLCTL write error\n"); |
347 | } | 122 | } |
348 | 123 | ||
349 | static void mcasp_start_rx(struct davinci_audio_dev *dev) | 124 | static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp) |
350 | { | 125 | { |
351 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); | 126 | u32 rxfmctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); |
352 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); | 127 | u32 aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); |
353 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); | ||
354 | mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); | ||
355 | 128 | ||
356 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); | 129 | return !(aclkxctl & TX_ASYNC) && rxfmctl & AFSRE; |
357 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); | 130 | } |
358 | mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); | ||
359 | 131 | ||
360 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); | 132 | static void mcasp_start_rx(struct davinci_mcasp *mcasp) |
361 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); | 133 | { |
134 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); | ||
135 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); | ||
136 | |||
137 | /* | ||
138 | * When ASYNC == 0 the transmit and receive sections operate | ||
139 | * synchronously from the transmit clock and frame sync. We need to make | ||
140 | * sure that the TX signlas are enabled when starting reception. | ||
141 | */ | ||
142 | if (mcasp_is_synchronous(mcasp)) { | ||
143 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); | ||
144 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); | ||
145 | } | ||
146 | |||
147 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); | ||
148 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0); | ||
149 | |||
150 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); | ||
151 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); | ||
152 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0); | ||
153 | |||
154 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); | ||
155 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); | ||
156 | |||
157 | if (mcasp_is_synchronous(mcasp)) | ||
158 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); | ||
362 | } | 159 | } |
363 | 160 | ||
364 | static void mcasp_start_tx(struct davinci_audio_dev *dev) | 161 | static void mcasp_start_tx(struct davinci_mcasp *mcasp) |
365 | { | 162 | { |
366 | u8 offset = 0, i; | 163 | u8 offset = 0, i; |
367 | u32 cnt; | 164 | u32 cnt; |
368 | 165 | ||
369 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); | 166 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); |
370 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); | 167 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); |
371 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); | 168 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); |
372 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); | 169 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0); |
373 | 170 | ||
374 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); | 171 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); |
375 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); | 172 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); |
376 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); | 173 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0); |
377 | for (i = 0; i < dev->num_serializer; i++) { | 174 | for (i = 0; i < mcasp->num_serializer; i++) { |
378 | if (dev->serial_dir[i] == TX_MODE) { | 175 | if (mcasp->serial_dir[i] == TX_MODE) { |
379 | offset = i; | 176 | offset = i; |
380 | break; | 177 | break; |
381 | } | 178 | } |
@@ -383,156 +180,140 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev) | |||
383 | 180 | ||
384 | /* wait for TX ready */ | 181 | /* wait for TX ready */ |
385 | cnt = 0; | 182 | cnt = 0; |
386 | while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) & | 183 | while (!(mcasp_get_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(offset)) & |
387 | TXSTATE) && (cnt < 100000)) | 184 | TXSTATE) && (cnt < 100000)) |
388 | cnt++; | 185 | cnt++; |
389 | 186 | ||
390 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); | 187 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0); |
391 | } | 188 | } |
392 | 189 | ||
393 | static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) | 190 | static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream) |
394 | { | 191 | { |
192 | u32 reg; | ||
193 | |||
194 | mcasp->streams++; | ||
195 | |||
395 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 196 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
396 | if (dev->txnumevt) { /* enable FIFO */ | 197 | if (mcasp->txnumevt) { /* enable FIFO */ |
397 | switch (dev->version) { | 198 | reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; |
398 | case MCASP_VERSION_3: | 199 | mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); |
399 | mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, | 200 | mcasp_set_bits(mcasp, reg, FIFO_ENABLE); |
400 | FIFO_ENABLE); | ||
401 | mcasp_set_bits(dev->base + MCASP_VER3_WFIFOCTL, | ||
402 | FIFO_ENABLE); | ||
403 | break; | ||
404 | default: | ||
405 | mcasp_clr_bits(dev->base + | ||
406 | DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
407 | mcasp_set_bits(dev->base + | ||
408 | DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
409 | } | ||
410 | } | 201 | } |
411 | mcasp_start_tx(dev); | 202 | mcasp_start_tx(mcasp); |
412 | } else { | 203 | } else { |
413 | if (dev->rxnumevt) { /* enable FIFO */ | 204 | if (mcasp->rxnumevt) { /* enable FIFO */ |
414 | switch (dev->version) { | 205 | reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; |
415 | case MCASP_VERSION_3: | 206 | mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); |
416 | mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, | 207 | mcasp_set_bits(mcasp, reg, FIFO_ENABLE); |
417 | FIFO_ENABLE); | ||
418 | mcasp_set_bits(dev->base + MCASP_VER3_RFIFOCTL, | ||
419 | FIFO_ENABLE); | ||
420 | break; | ||
421 | default: | ||
422 | mcasp_clr_bits(dev->base + | ||
423 | DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
424 | mcasp_set_bits(dev->base + | ||
425 | DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
426 | } | ||
427 | } | 208 | } |
428 | mcasp_start_rx(dev); | 209 | mcasp_start_rx(mcasp); |
429 | } | 210 | } |
430 | } | 211 | } |
431 | 212 | ||
432 | static void mcasp_stop_rx(struct davinci_audio_dev *dev) | 213 | static void mcasp_stop_rx(struct davinci_mcasp *mcasp) |
433 | { | 214 | { |
434 | mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0); | 215 | /* |
435 | mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); | 216 | * In synchronous mode stop the TX clocks if no other stream is |
217 | * running | ||
218 | */ | ||
219 | if (mcasp_is_synchronous(mcasp) && !mcasp->streams) | ||
220 | mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0); | ||
221 | |||
222 | mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0); | ||
223 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); | ||
436 | } | 224 | } |
437 | 225 | ||
438 | static void mcasp_stop_tx(struct davinci_audio_dev *dev) | 226 | static void mcasp_stop_tx(struct davinci_mcasp *mcasp) |
439 | { | 227 | { |
440 | mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0); | 228 | u32 val = 0; |
441 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); | 229 | |
230 | /* | ||
231 | * In synchronous mode keep TX clocks running if the capture stream is | ||
232 | * still running. | ||
233 | */ | ||
234 | if (mcasp_is_synchronous(mcasp) && mcasp->streams) | ||
235 | val = TXHCLKRST | TXCLKRST | TXFSRST; | ||
236 | |||
237 | mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val); | ||
238 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); | ||
442 | } | 239 | } |
443 | 240 | ||
444 | static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) | 241 | static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream) |
445 | { | 242 | { |
243 | u32 reg; | ||
244 | |||
245 | mcasp->streams--; | ||
246 | |||
446 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 247 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
447 | if (dev->txnumevt) { /* disable FIFO */ | 248 | if (mcasp->txnumevt) { /* disable FIFO */ |
448 | switch (dev->version) { | 249 | reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; |
449 | case MCASP_VERSION_3: | 250 | mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); |
450 | mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, | ||
451 | FIFO_ENABLE); | ||
452 | break; | ||
453 | default: | ||
454 | mcasp_clr_bits(dev->base + | ||
455 | DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
456 | } | ||
457 | } | 251 | } |
458 | mcasp_stop_tx(dev); | 252 | mcasp_stop_tx(mcasp); |
459 | } else { | 253 | } else { |
460 | if (dev->rxnumevt) { /* disable FIFO */ | 254 | if (mcasp->rxnumevt) { /* disable FIFO */ |
461 | switch (dev->version) { | 255 | reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; |
462 | case MCASP_VERSION_3: | 256 | mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); |
463 | mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, | ||
464 | FIFO_ENABLE); | ||
465 | break; | ||
466 | |||
467 | default: | ||
468 | mcasp_clr_bits(dev->base + | ||
469 | DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
470 | } | ||
471 | } | 257 | } |
472 | mcasp_stop_rx(dev); | 258 | mcasp_stop_rx(mcasp); |
473 | } | 259 | } |
474 | } | 260 | } |
475 | 261 | ||
476 | static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 262 | static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
477 | unsigned int fmt) | 263 | unsigned int fmt) |
478 | { | 264 | { |
479 | struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); | 265 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); |
480 | void __iomem *base = dev->base; | ||
481 | 266 | ||
482 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 267 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
483 | case SND_SOC_DAIFMT_DSP_B: | 268 | case SND_SOC_DAIFMT_DSP_B: |
484 | case SND_SOC_DAIFMT_AC97: | 269 | case SND_SOC_DAIFMT_AC97: |
485 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); | 270 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); |
486 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); | 271 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); |
487 | break; | 272 | break; |
488 | default: | 273 | default: |
489 | /* configure a full-word SYNC pulse (LRCLK) */ | 274 | /* configure a full-word SYNC pulse (LRCLK) */ |
490 | mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); | 275 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); |
491 | mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); | 276 | mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); |
492 | 277 | ||
493 | /* make 1st data bit occur one ACLK cycle after the frame sync */ | 278 | /* make 1st data bit occur one ACLK cycle after the frame sync */ |
494 | mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, FSXDLY(1)); | 279 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(1)); |
495 | mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, FSRDLY(1)); | 280 | mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(1)); |
496 | break; | 281 | break; |
497 | } | 282 | } |
498 | 283 | ||
499 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 284 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
500 | case SND_SOC_DAIFMT_CBS_CFS: | 285 | case SND_SOC_DAIFMT_CBS_CFS: |
501 | /* codec is clock and frame slave */ | 286 | /* codec is clock and frame slave */ |
502 | mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); | 287 | mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); |
503 | mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); | 288 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE); |
504 | 289 | ||
505 | mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); | 290 | mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); |
506 | mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); | 291 | mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE); |
507 | 292 | ||
508 | mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, | 293 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); |
509 | ACLKX | ACLKR); | 294 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); |
510 | mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, | ||
511 | AFSX | AFSR); | ||
512 | break; | 295 | break; |
513 | case SND_SOC_DAIFMT_CBM_CFS: | 296 | case SND_SOC_DAIFMT_CBM_CFS: |
514 | /* codec is clock master and frame slave */ | 297 | /* codec is clock master and frame slave */ |
515 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); | 298 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); |
516 | mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); | 299 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE); |
517 | 300 | ||
518 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); | 301 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); |
519 | mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); | 302 | mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE); |
520 | 303 | ||
521 | mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, | 304 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); |
522 | ACLKX | ACLKR); | 305 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); |
523 | mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, | ||
524 | AFSX | AFSR); | ||
525 | break; | 306 | break; |
526 | case SND_SOC_DAIFMT_CBM_CFM: | 307 | case SND_SOC_DAIFMT_CBM_CFM: |
527 | /* codec is clock and frame master */ | 308 | /* codec is clock and frame master */ |
528 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); | 309 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); |
529 | mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); | 310 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE); |
530 | 311 | ||
531 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); | 312 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); |
532 | mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); | 313 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE); |
533 | 314 | ||
534 | mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, | 315 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, |
535 | ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); | 316 | ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); |
536 | break; | 317 | break; |
537 | 318 | ||
538 | default: | 319 | default: |
@@ -541,35 +322,35 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
541 | 322 | ||
542 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 323 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
543 | case SND_SOC_DAIFMT_IB_NF: | 324 | case SND_SOC_DAIFMT_IB_NF: |
544 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); | 325 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); |
545 | mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); | 326 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); |
546 | 327 | ||
547 | mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); | 328 | mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); |
548 | mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); | 329 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); |
549 | break; | 330 | break; |
550 | 331 | ||
551 | case SND_SOC_DAIFMT_NB_IF: | 332 | case SND_SOC_DAIFMT_NB_IF: |
552 | mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); | 333 | mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); |
553 | mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); | 334 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); |
554 | 335 | ||
555 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); | 336 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); |
556 | mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); | 337 | mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); |
557 | break; | 338 | break; |
558 | 339 | ||
559 | case SND_SOC_DAIFMT_IB_IF: | 340 | case SND_SOC_DAIFMT_IB_IF: |
560 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); | 341 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); |
561 | mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); | 342 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); |
562 | 343 | ||
563 | mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); | 344 | mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); |
564 | mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); | 345 | mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); |
565 | break; | 346 | break; |
566 | 347 | ||
567 | case SND_SOC_DAIFMT_NB_NF: | 348 | case SND_SOC_DAIFMT_NB_NF: |
568 | mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); | 349 | mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); |
569 | mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); | 350 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); |
570 | 351 | ||
571 | mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); | 352 | mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); |
572 | mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); | 353 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); |
573 | break; | 354 | break; |
574 | 355 | ||
575 | default: | 356 | default: |
@@ -581,25 +362,25 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
581 | 362 | ||
582 | static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) | 363 | static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) |
583 | { | 364 | { |
584 | struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai); | 365 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); |
585 | 366 | ||
586 | switch (div_id) { | 367 | switch (div_id) { |
587 | case 0: /* MCLK divider */ | 368 | case 0: /* MCLK divider */ |
588 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, | 369 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, |
589 | AHCLKXDIV(div - 1), AHCLKXDIV_MASK); | 370 | AHCLKXDIV(div - 1), AHCLKXDIV_MASK); |
590 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, | 371 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, |
591 | AHCLKRDIV(div - 1), AHCLKRDIV_MASK); | 372 | AHCLKRDIV(div - 1), AHCLKRDIV_MASK); |
592 | break; | 373 | break; |
593 | 374 | ||
594 | case 1: /* BCLK divider */ | 375 | case 1: /* BCLK divider */ |
595 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, | 376 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, |
596 | ACLKXDIV(div - 1), ACLKXDIV_MASK); | 377 | ACLKXDIV(div - 1), ACLKXDIV_MASK); |
597 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG, | 378 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, |
598 | ACLKRDIV(div - 1), ACLKRDIV_MASK); | 379 | ACLKRDIV(div - 1), ACLKRDIV_MASK); |
599 | break; | 380 | break; |
600 | 381 | ||
601 | case 2: /* BCLK/LRCLK ratio */ | 382 | case 2: /* BCLK/LRCLK ratio */ |
602 | dev->bclk_lrclk_ratio = div; | 383 | mcasp->bclk_lrclk_ratio = div; |
603 | break; | 384 | break; |
604 | 385 | ||
605 | default: | 386 | default: |
@@ -612,22 +393,22 @@ static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div | |||
612 | static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, | 393 | static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, |
613 | unsigned int freq, int dir) | 394 | unsigned int freq, int dir) |
614 | { | 395 | { |
615 | struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai); | 396 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); |
616 | 397 | ||
617 | if (dir == SND_SOC_CLOCK_OUT) { | 398 | if (dir == SND_SOC_CLOCK_OUT) { |
618 | mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); | 399 | mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); |
619 | mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE); | 400 | mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE); |
620 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX); | 401 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX); |
621 | } else { | 402 | } else { |
622 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); | 403 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); |
623 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE); | 404 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE); |
624 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX); | 405 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX); |
625 | } | 406 | } |
626 | 407 | ||
627 | return 0; | 408 | return 0; |
628 | } | 409 | } |
629 | 410 | ||
630 | static int davinci_config_channel_size(struct davinci_audio_dev *dev, | 411 | static int davinci_config_channel_size(struct davinci_mcasp *mcasp, |
631 | int word_length) | 412 | int word_length) |
632 | { | 413 | { |
633 | u32 fmt; | 414 | u32 fmt; |
@@ -644,71 +425,68 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev, | |||
644 | * both left and right channels), so it has to be divided by number of | 425 | * both left and right channels), so it has to be divided by number of |
645 | * tdm-slots (for I2S - divided by 2). | 426 | * tdm-slots (for I2S - divided by 2). |
646 | */ | 427 | */ |
647 | if (dev->bclk_lrclk_ratio) | 428 | if (mcasp->bclk_lrclk_ratio) |
648 | word_length = dev->bclk_lrclk_ratio / dev->tdm_slots; | 429 | word_length = mcasp->bclk_lrclk_ratio / mcasp->tdm_slots; |
649 | 430 | ||
650 | /* mapping of the XSSZ bit-field as described in the datasheet */ | 431 | /* mapping of the XSSZ bit-field as described in the datasheet */ |
651 | fmt = (word_length >> 1) - 1; | 432 | fmt = (word_length >> 1) - 1; |
652 | 433 | ||
653 | if (dev->op_mode != DAVINCI_MCASP_DIT_MODE) { | 434 | if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) { |
654 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, | 435 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt), |
655 | RXSSZ(fmt), RXSSZ(0x0F)); | 436 | RXSSZ(0x0F)); |
656 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, | 437 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt), |
657 | TXSSZ(fmt), TXSSZ(0x0F)); | 438 | TXSSZ(0x0F)); |
658 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, | 439 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate), |
659 | TXROT(tx_rotate), TXROT(7)); | 440 | TXROT(7)); |
660 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, | 441 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate), |
661 | RXROT(rx_rotate), RXROT(7)); | 442 | RXROT(7)); |
662 | mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, | 443 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask); |
663 | mask); | ||
664 | } | 444 | } |
665 | 445 | ||
666 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask); | 446 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); |
667 | 447 | ||
668 | return 0; | 448 | return 0; |
669 | } | 449 | } |
670 | 450 | ||
671 | static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream, | 451 | static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream, |
672 | int channels) | 452 | int channels) |
673 | { | 453 | { |
674 | int i; | 454 | int i; |
675 | u8 tx_ser = 0; | 455 | u8 tx_ser = 0; |
676 | u8 rx_ser = 0; | 456 | u8 rx_ser = 0; |
677 | u8 ser; | 457 | u8 ser; |
678 | u8 slots = dev->tdm_slots; | 458 | u8 slots = mcasp->tdm_slots; |
679 | u8 max_active_serializers = (channels + slots - 1) / slots; | 459 | u8 max_active_serializers = (channels + slots - 1) / slots; |
460 | u32 reg; | ||
680 | /* Default configuration */ | 461 | /* Default configuration */ |
681 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); | 462 | if (mcasp->version != MCASP_VERSION_4) |
463 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); | ||
682 | 464 | ||
683 | /* All PINS as McASP */ | 465 | /* All PINS as McASP */ |
684 | mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000); | 466 | mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); |
685 | 467 | ||
686 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 468 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
687 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); | 469 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); |
688 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, | 470 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); |
689 | TXDATADMADIS); | ||
690 | } else { | 471 | } else { |
691 | mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); | 472 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); |
692 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG, | 473 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_REVTCTL_REG, RXDATADMADIS); |
693 | RXDATADMADIS); | ||
694 | } | 474 | } |
695 | 475 | ||
696 | for (i = 0; i < dev->num_serializer; i++) { | 476 | for (i = 0; i < mcasp->num_serializer; i++) { |
697 | mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), | 477 | mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), |
698 | dev->serial_dir[i]); | 478 | mcasp->serial_dir[i]); |
699 | if (dev->serial_dir[i] == TX_MODE && | 479 | if (mcasp->serial_dir[i] == TX_MODE && |
700 | tx_ser < max_active_serializers) { | 480 | tx_ser < max_active_serializers) { |
701 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, | 481 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i)); |
702 | AXR(i)); | ||
703 | tx_ser++; | 482 | tx_ser++; |
704 | } else if (dev->serial_dir[i] == RX_MODE && | 483 | } else if (mcasp->serial_dir[i] == RX_MODE && |
705 | rx_ser < max_active_serializers) { | 484 | rx_ser < max_active_serializers) { |
706 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, | 485 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i)); |
707 | AXR(i)); | ||
708 | rx_ser++; | 486 | rx_ser++; |
709 | } else { | 487 | } else { |
710 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), | 488 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), |
711 | SRMOD_INACTIVE, SRMOD_MASK); | 489 | SRMOD_INACTIVE, SRMOD_MASK); |
712 | } | 490 | } |
713 | } | 491 | } |
714 | 492 | ||
@@ -718,127 +496,113 @@ static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream, | |||
718 | ser = rx_ser; | 496 | ser = rx_ser; |
719 | 497 | ||
720 | if (ser < max_active_serializers) { | 498 | if (ser < max_active_serializers) { |
721 | dev_warn(dev->dev, "stream has more channels (%d) than are " | 499 | dev_warn(mcasp->dev, "stream has more channels (%d) than are " |
722 | "enabled in mcasp (%d)\n", channels, ser * slots); | 500 | "enabled in mcasp (%d)\n", channels, ser * slots); |
723 | return -EINVAL; | 501 | return -EINVAL; |
724 | } | 502 | } |
725 | 503 | ||
726 | if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { | 504 | if (mcasp->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { |
727 | if (dev->txnumevt * tx_ser > 64) | 505 | if (mcasp->txnumevt * tx_ser > 64) |
728 | dev->txnumevt = 1; | 506 | mcasp->txnumevt = 1; |
729 | 507 | ||
730 | switch (dev->version) { | 508 | reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; |
731 | case MCASP_VERSION_3: | 509 | mcasp_mod_bits(mcasp, reg, tx_ser, NUMDMA_MASK); |
732 | mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, tx_ser, | 510 | mcasp_mod_bits(mcasp, reg, ((mcasp->txnumevt * tx_ser) << 8), |
733 | NUMDMA_MASK); | 511 | NUMEVT_MASK); |
734 | mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, | ||
735 | ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); | ||
736 | break; | ||
737 | default: | ||
738 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | ||
739 | tx_ser, NUMDMA_MASK); | ||
740 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | ||
741 | ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); | ||
742 | } | ||
743 | } | 512 | } |
744 | 513 | ||
745 | if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { | 514 | if (mcasp->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { |
746 | if (dev->rxnumevt * rx_ser > 64) | 515 | if (mcasp->rxnumevt * rx_ser > 64) |
747 | dev->rxnumevt = 1; | 516 | mcasp->rxnumevt = 1; |
748 | switch (dev->version) { | 517 | |
749 | case MCASP_VERSION_3: | 518 | reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; |
750 | mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, rx_ser, | 519 | mcasp_mod_bits(mcasp, reg, rx_ser, NUMDMA_MASK); |
751 | NUMDMA_MASK); | 520 | mcasp_mod_bits(mcasp, reg, ((mcasp->rxnumevt * rx_ser) << 8), |
752 | mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, | 521 | NUMEVT_MASK); |
753 | ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); | ||
754 | break; | ||
755 | default: | ||
756 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | ||
757 | rx_ser, NUMDMA_MASK); | ||
758 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | ||
759 | ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); | ||
760 | } | ||
761 | } | 522 | } |
762 | 523 | ||
763 | return 0; | 524 | return 0; |
764 | } | 525 | } |
765 | 526 | ||
766 | static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) | 527 | static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream) |
767 | { | 528 | { |
768 | int i, active_slots; | 529 | int i, active_slots; |
769 | u32 mask = 0; | 530 | u32 mask = 0; |
531 | u32 busel = 0; | ||
770 | 532 | ||
771 | active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots; | 533 | active_slots = (mcasp->tdm_slots > 31) ? 32 : mcasp->tdm_slots; |
772 | for (i = 0; i < active_slots; i++) | 534 | for (i = 0; i < active_slots; i++) |
773 | mask |= (1 << i); | 535 | mask |= (1 << i); |
774 | 536 | ||
775 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); | 537 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); |
538 | |||
539 | if (!mcasp->dat_port) | ||
540 | busel = TXSEL; | ||
776 | 541 | ||
777 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 542 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
778 | /* bit stream is MSB first with no delay */ | 543 | /* bit stream is MSB first with no delay */ |
779 | /* DSP_B mode */ | 544 | /* DSP_B mode */ |
780 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask); | 545 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask); |
781 | mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD); | 546 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD); |
782 | 547 | ||
783 | if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) | 548 | if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32)) |
784 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, | 549 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, |
785 | FSXMOD(dev->tdm_slots), FSXMOD(0x1FF)); | 550 | FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF)); |
786 | else | 551 | else |
787 | printk(KERN_ERR "playback tdm slot %d not supported\n", | 552 | printk(KERN_ERR "playback tdm slot %d not supported\n", |
788 | dev->tdm_slots); | 553 | mcasp->tdm_slots); |
789 | } else { | 554 | } else { |
790 | /* bit stream is MSB first with no delay */ | 555 | /* bit stream is MSB first with no delay */ |
791 | /* DSP_B mode */ | 556 | /* DSP_B mode */ |
792 | mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD); | 557 | mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD); |
793 | mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask); | 558 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask); |
794 | 559 | ||
795 | if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) | 560 | if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32)) |
796 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, | 561 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, |
797 | FSRMOD(dev->tdm_slots), FSRMOD(0x1FF)); | 562 | FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF)); |
798 | else | 563 | else |
799 | printk(KERN_ERR "capture tdm slot %d not supported\n", | 564 | printk(KERN_ERR "capture tdm slot %d not supported\n", |
800 | dev->tdm_slots); | 565 | mcasp->tdm_slots); |
801 | } | 566 | } |
802 | } | 567 | } |
803 | 568 | ||
804 | /* S/PDIF */ | 569 | /* S/PDIF */ |
805 | static void davinci_hw_dit_param(struct davinci_audio_dev *dev) | 570 | static void davinci_hw_dit_param(struct davinci_mcasp *mcasp) |
806 | { | 571 | { |
807 | /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 | 572 | /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 |
808 | and LSB first */ | 573 | and LSB first */ |
809 | mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, | 574 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15)); |
810 | TXROT(6) | TXSSZ(15)); | ||
811 | 575 | ||
812 | /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */ | 576 | /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */ |
813 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG, | 577 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE | FSXMOD(0x180)); |
814 | AFSXE | FSXMOD(0x180)); | ||
815 | 578 | ||
816 | /* Set the TX tdm : for all the slots */ | 579 | /* Set the TX tdm : for all the slots */ |
817 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF); | 580 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF); |
818 | 581 | ||
819 | /* Set the TX clock controls : div = 1 and internal */ | 582 | /* Set the TX clock controls : div = 1 and internal */ |
820 | mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, | 583 | mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE | TX_ASYNC); |
821 | ACLKXE | TX_ASYNC); | ||
822 | 584 | ||
823 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); | 585 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); |
824 | 586 | ||
825 | /* Only 44100 and 48000 are valid, both have the same setting */ | 587 | /* Only 44100 and 48000 are valid, both have the same setting */ |
826 | mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3)); | 588 | mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3)); |
827 | 589 | ||
828 | /* Enable the DIT */ | 590 | /* Enable the DIT */ |
829 | mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN); | 591 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); |
830 | } | 592 | } |
831 | 593 | ||
832 | static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | 594 | static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, |
833 | struct snd_pcm_hw_params *params, | 595 | struct snd_pcm_hw_params *params, |
834 | struct snd_soc_dai *cpu_dai) | 596 | struct snd_soc_dai *cpu_dai) |
835 | { | 597 | { |
836 | struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); | 598 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); |
837 | struct davinci_pcm_dma_params *dma_params = | 599 | struct davinci_pcm_dma_params *dma_params = |
838 | &dev->dma_params[substream->stream]; | 600 | &mcasp->dma_params[substream->stream]; |
601 | struct snd_dmaengine_dai_dma_data *dma_data = | ||
602 | &mcasp->dma_data[substream->stream]; | ||
839 | int word_length; | 603 | int word_length; |
840 | u8 fifo_level; | 604 | u8 fifo_level; |
841 | u8 slots = dev->tdm_slots; | 605 | u8 slots = mcasp->tdm_slots; |
842 | u8 active_serializers; | 606 | u8 active_serializers; |
843 | int channels; | 607 | int channels; |
844 | struct snd_interval *pcm_channels = hw_param_interval(params, | 608 | struct snd_interval *pcm_channels = hw_param_interval(params, |
@@ -847,17 +611,17 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
847 | 611 | ||
848 | active_serializers = (channels + slots - 1) / slots; | 612 | active_serializers = (channels + slots - 1) / slots; |
849 | 613 | ||
850 | if (davinci_hw_common_param(dev, substream->stream, channels) == -EINVAL) | 614 | if (davinci_hw_common_param(mcasp, substream->stream, channels) == -EINVAL) |
851 | return -EINVAL; | 615 | return -EINVAL; |
852 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 616 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
853 | fifo_level = dev->txnumevt * active_serializers; | 617 | fifo_level = mcasp->txnumevt * active_serializers; |
854 | else | 618 | else |
855 | fifo_level = dev->rxnumevt * active_serializers; | 619 | fifo_level = mcasp->rxnumevt * active_serializers; |
856 | 620 | ||
857 | if (dev->op_mode == DAVINCI_MCASP_DIT_MODE) | 621 | if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) |
858 | davinci_hw_dit_param(dev); | 622 | davinci_hw_dit_param(mcasp); |
859 | else | 623 | else |
860 | davinci_hw_param(dev, substream->stream); | 624 | davinci_hw_param(mcasp, substream->stream); |
861 | 625 | ||
862 | switch (params_format(params)) { | 626 | switch (params_format(params)) { |
863 | case SNDRV_PCM_FORMAT_U8: | 627 | case SNDRV_PCM_FORMAT_U8: |
@@ -891,13 +655,15 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
891 | return -EINVAL; | 655 | return -EINVAL; |
892 | } | 656 | } |
893 | 657 | ||
894 | if (dev->version == MCASP_VERSION_2 && !fifo_level) | 658 | if (mcasp->version == MCASP_VERSION_2 && !fifo_level) |
895 | dma_params->acnt = 4; | 659 | dma_params->acnt = 4; |
896 | else | 660 | else |
897 | dma_params->acnt = dma_params->data_type; | 661 | dma_params->acnt = dma_params->data_type; |
898 | 662 | ||
899 | dma_params->fifo_level = fifo_level; | 663 | dma_params->fifo_level = fifo_level; |
900 | davinci_config_channel_size(dev, word_length); | 664 | dma_data->maxburst = fifo_level; |
665 | |||
666 | davinci_config_channel_size(mcasp, word_length); | ||
901 | 667 | ||
902 | return 0; | 668 | return 0; |
903 | } | 669 | } |
@@ -905,29 +671,29 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
905 | static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, | 671 | static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, |
906 | int cmd, struct snd_soc_dai *cpu_dai) | 672 | int cmd, struct snd_soc_dai *cpu_dai) |
907 | { | 673 | { |
908 | struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); | 674 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); |
909 | int ret = 0; | 675 | int ret = 0; |
910 | 676 | ||
911 | switch (cmd) { | 677 | switch (cmd) { |
912 | case SNDRV_PCM_TRIGGER_RESUME: | 678 | case SNDRV_PCM_TRIGGER_RESUME: |
913 | case SNDRV_PCM_TRIGGER_START: | 679 | case SNDRV_PCM_TRIGGER_START: |
914 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 680 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
915 | ret = pm_runtime_get_sync(dev->dev); | 681 | ret = pm_runtime_get_sync(mcasp->dev); |
916 | if (IS_ERR_VALUE(ret)) | 682 | if (IS_ERR_VALUE(ret)) |
917 | dev_err(dev->dev, "pm_runtime_get_sync() failed\n"); | 683 | dev_err(mcasp->dev, "pm_runtime_get_sync() failed\n"); |
918 | davinci_mcasp_start(dev, substream->stream); | 684 | davinci_mcasp_start(mcasp, substream->stream); |
919 | break; | 685 | break; |
920 | 686 | ||
921 | case SNDRV_PCM_TRIGGER_SUSPEND: | 687 | case SNDRV_PCM_TRIGGER_SUSPEND: |
922 | davinci_mcasp_stop(dev, substream->stream); | 688 | davinci_mcasp_stop(mcasp, substream->stream); |
923 | ret = pm_runtime_put_sync(dev->dev); | 689 | ret = pm_runtime_put_sync(mcasp->dev); |
924 | if (IS_ERR_VALUE(ret)) | 690 | if (IS_ERR_VALUE(ret)) |
925 | dev_err(dev->dev, "pm_runtime_put_sync() failed\n"); | 691 | dev_err(mcasp->dev, "pm_runtime_put_sync() failed\n"); |
926 | break; | 692 | break; |
927 | 693 | ||
928 | case SNDRV_PCM_TRIGGER_STOP: | 694 | case SNDRV_PCM_TRIGGER_STOP: |
929 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 695 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
930 | davinci_mcasp_stop(dev, substream->stream); | 696 | davinci_mcasp_stop(mcasp, substream->stream); |
931 | break; | 697 | break; |
932 | 698 | ||
933 | default: | 699 | default: |
@@ -940,9 +706,14 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, | |||
940 | static int davinci_mcasp_startup(struct snd_pcm_substream *substream, | 706 | static int davinci_mcasp_startup(struct snd_pcm_substream *substream, |
941 | struct snd_soc_dai *dai) | 707 | struct snd_soc_dai *dai) |
942 | { | 708 | { |
943 | struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai); | 709 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); |
710 | |||
711 | if (mcasp->version == MCASP_VERSION_4) | ||
712 | snd_soc_dai_set_dma_data(dai, substream, | ||
713 | &mcasp->dma_data[substream->stream]); | ||
714 | else | ||
715 | snd_soc_dai_set_dma_data(dai, substream, mcasp->dma_params); | ||
944 | 716 | ||
945 | snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); | ||
946 | return 0; | 717 | return 0; |
947 | } | 718 | } |
948 | 719 | ||
@@ -955,6 +726,8 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { | |||
955 | .set_sysclk = davinci_mcasp_set_sysclk, | 726 | .set_sysclk = davinci_mcasp_set_sysclk, |
956 | }; | 727 | }; |
957 | 728 | ||
729 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000 | ||
730 | |||
958 | #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ | 731 | #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ |
959 | SNDRV_PCM_FMTBIT_U8 | \ | 732 | SNDRV_PCM_FMTBIT_U8 | \ |
960 | SNDRV_PCM_FMTBIT_S16_LE | \ | 733 | SNDRV_PCM_FMTBIT_S16_LE | \ |
@@ -985,7 +758,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | |||
985 | 758 | ||
986 | }, | 759 | }, |
987 | { | 760 | { |
988 | "davinci-mcasp.1", | 761 | .name = "davinci-mcasp.1", |
989 | .playback = { | 762 | .playback = { |
990 | .channels_min = 1, | 763 | .channels_min = 1, |
991 | .channels_max = 384, | 764 | .channels_max = 384, |
@@ -1016,13 +789,20 @@ static struct snd_platform_data da830_mcasp_pdata = { | |||
1016 | .version = MCASP_VERSION_2, | 789 | .version = MCASP_VERSION_2, |
1017 | }; | 790 | }; |
1018 | 791 | ||
1019 | static struct snd_platform_data omap2_mcasp_pdata = { | 792 | static struct snd_platform_data am33xx_mcasp_pdata = { |
1020 | .tx_dma_offset = 0, | 793 | .tx_dma_offset = 0, |
1021 | .rx_dma_offset = 0, | 794 | .rx_dma_offset = 0, |
1022 | .asp_chan_q = EVENTQ_0, | 795 | .asp_chan_q = EVENTQ_0, |
1023 | .version = MCASP_VERSION_3, | 796 | .version = MCASP_VERSION_3, |
1024 | }; | 797 | }; |
1025 | 798 | ||
799 | static struct snd_platform_data dra7_mcasp_pdata = { | ||
800 | .tx_dma_offset = 0x200, | ||
801 | .rx_dma_offset = 0x284, | ||
802 | .asp_chan_q = EVENTQ_0, | ||
803 | .version = MCASP_VERSION_4, | ||
804 | }; | ||
805 | |||
1026 | static const struct of_device_id mcasp_dt_ids[] = { | 806 | static const struct of_device_id mcasp_dt_ids[] = { |
1027 | { | 807 | { |
1028 | .compatible = "ti,dm646x-mcasp-audio", | 808 | .compatible = "ti,dm646x-mcasp-audio", |
@@ -1034,12 +814,56 @@ static const struct of_device_id mcasp_dt_ids[] = { | |||
1034 | }, | 814 | }, |
1035 | { | 815 | { |
1036 | .compatible = "ti,am33xx-mcasp-audio", | 816 | .compatible = "ti,am33xx-mcasp-audio", |
1037 | .data = &omap2_mcasp_pdata, | 817 | .data = &am33xx_mcasp_pdata, |
818 | }, | ||
819 | { | ||
820 | .compatible = "ti,dra7-mcasp-audio", | ||
821 | .data = &dra7_mcasp_pdata, | ||
1038 | }, | 822 | }, |
1039 | { /* sentinel */ } | 823 | { /* sentinel */ } |
1040 | }; | 824 | }; |
1041 | MODULE_DEVICE_TABLE(of, mcasp_dt_ids); | 825 | MODULE_DEVICE_TABLE(of, mcasp_dt_ids); |
1042 | 826 | ||
827 | static int mcasp_reparent_fck(struct platform_device *pdev) | ||
828 | { | ||
829 | struct device_node *node = pdev->dev.of_node; | ||
830 | struct clk *gfclk, *parent_clk; | ||
831 | const char *parent_name; | ||
832 | int ret; | ||
833 | |||
834 | if (!node) | ||
835 | return 0; | ||
836 | |||
837 | parent_name = of_get_property(node, "fck_parent", NULL); | ||
838 | if (!parent_name) | ||
839 | return 0; | ||
840 | |||
841 | gfclk = clk_get(&pdev->dev, "fck"); | ||
842 | if (IS_ERR(gfclk)) { | ||
843 | dev_err(&pdev->dev, "failed to get fck\n"); | ||
844 | return PTR_ERR(gfclk); | ||
845 | } | ||
846 | |||
847 | parent_clk = clk_get(NULL, parent_name); | ||
848 | if (IS_ERR(parent_clk)) { | ||
849 | dev_err(&pdev->dev, "failed to get parent clock\n"); | ||
850 | ret = PTR_ERR(parent_clk); | ||
851 | goto err1; | ||
852 | } | ||
853 | |||
854 | ret = clk_set_parent(gfclk, parent_clk); | ||
855 | if (ret) { | ||
856 | dev_err(&pdev->dev, "failed to reparent fck\n"); | ||
857 | goto err2; | ||
858 | } | ||
859 | |||
860 | err2: | ||
861 | clk_put(parent_clk); | ||
862 | err1: | ||
863 | clk_put(gfclk); | ||
864 | return ret; | ||
865 | } | ||
866 | |||
1043 | static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | 867 | static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( |
1044 | struct platform_device *pdev) | 868 | struct platform_device *pdev) |
1045 | { | 869 | { |
@@ -1152,7 +976,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1152 | struct davinci_pcm_dma_params *dma_data; | 976 | struct davinci_pcm_dma_params *dma_data; |
1153 | struct resource *mem, *ioarea, *res, *dat; | 977 | struct resource *mem, *ioarea, *res, *dat; |
1154 | struct snd_platform_data *pdata; | 978 | struct snd_platform_data *pdata; |
1155 | struct davinci_audio_dev *dev; | 979 | struct davinci_mcasp *mcasp; |
1156 | int ret; | 980 | int ret; |
1157 | 981 | ||
1158 | if (!pdev->dev.platform_data && !pdev->dev.of_node) { | 982 | if (!pdev->dev.platform_data && !pdev->dev.of_node) { |
@@ -1160,9 +984,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1160 | return -EINVAL; | 984 | return -EINVAL; |
1161 | } | 985 | } |
1162 | 986 | ||
1163 | dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), | 987 | mcasp = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcasp), |
1164 | GFP_KERNEL); | 988 | GFP_KERNEL); |
1165 | if (!dev) | 989 | if (!mcasp) |
1166 | return -ENOMEM; | 990 | return -ENOMEM; |
1167 | 991 | ||
1168 | pdata = davinci_mcasp_set_pdata_from_of(pdev); | 992 | pdata = davinci_mcasp_set_pdata_from_of(pdev); |
@@ -1173,7 +997,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1173 | 997 | ||
1174 | mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); | 998 | mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); |
1175 | if (!mem) { | 999 | if (!mem) { |
1176 | dev_warn(dev->dev, | 1000 | dev_warn(mcasp->dev, |
1177 | "\"mpu\" mem resource not found, using index 0\n"); | 1001 | "\"mpu\" mem resource not found, using index 0\n"); |
1178 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1002 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1179 | if (!mem) { | 1003 | if (!mem) { |
@@ -1197,32 +1021,39 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1197 | return ret; | 1021 | return ret; |
1198 | } | 1022 | } |
1199 | 1023 | ||
1200 | dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | 1024 | mcasp->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); |
1201 | if (!dev->base) { | 1025 | if (!mcasp->base) { |
1202 | dev_err(&pdev->dev, "ioremap failed\n"); | 1026 | dev_err(&pdev->dev, "ioremap failed\n"); |
1203 | ret = -ENOMEM; | 1027 | ret = -ENOMEM; |
1204 | goto err_release_clk; | 1028 | goto err_release_clk; |
1205 | } | 1029 | } |
1206 | 1030 | ||
1207 | dev->op_mode = pdata->op_mode; | 1031 | mcasp->op_mode = pdata->op_mode; |
1208 | dev->tdm_slots = pdata->tdm_slots; | 1032 | mcasp->tdm_slots = pdata->tdm_slots; |
1209 | dev->num_serializer = pdata->num_serializer; | 1033 | mcasp->num_serializer = pdata->num_serializer; |
1210 | dev->serial_dir = pdata->serial_dir; | 1034 | mcasp->serial_dir = pdata->serial_dir; |
1211 | dev->version = pdata->version; | 1035 | mcasp->version = pdata->version; |
1212 | dev->txnumevt = pdata->txnumevt; | 1036 | mcasp->txnumevt = pdata->txnumevt; |
1213 | dev->rxnumevt = pdata->rxnumevt; | 1037 | mcasp->rxnumevt = pdata->rxnumevt; |
1214 | dev->dev = &pdev->dev; | 1038 | |
1039 | mcasp->dev = &pdev->dev; | ||
1215 | 1040 | ||
1216 | dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); | 1041 | dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); |
1217 | if (!dat) | 1042 | if (dat) |
1218 | dat = mem; | 1043 | mcasp->dat_port = true; |
1219 | 1044 | ||
1220 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; | 1045 | dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; |
1221 | dma_data->asp_chan_q = pdata->asp_chan_q; | 1046 | dma_data->asp_chan_q = pdata->asp_chan_q; |
1222 | dma_data->ram_chan_q = pdata->ram_chan_q; | 1047 | dma_data->ram_chan_q = pdata->ram_chan_q; |
1223 | dma_data->sram_pool = pdata->sram_pool; | 1048 | dma_data->sram_pool = pdata->sram_pool; |
1224 | dma_data->sram_size = pdata->sram_size_playback; | 1049 | dma_data->sram_size = pdata->sram_size_playback; |
1225 | dma_data->dma_addr = dat->start + pdata->tx_dma_offset; | 1050 | if (dat) |
1051 | dma_data->dma_addr = dat->start; | ||
1052 | else | ||
1053 | dma_data->dma_addr = mem->start + pdata->tx_dma_offset; | ||
1054 | |||
1055 | /* Unconditional dmaengine stuff */ | ||
1056 | mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_data->dma_addr; | ||
1226 | 1057 | ||
1227 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 1058 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
1228 | if (res) | 1059 | if (res) |
@@ -1230,12 +1061,26 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1230 | else | 1061 | else |
1231 | dma_data->channel = pdata->tx_dma_channel; | 1062 | dma_data->channel = pdata->tx_dma_channel; |
1232 | 1063 | ||
1233 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; | 1064 | dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; |
1234 | dma_data->asp_chan_q = pdata->asp_chan_q; | 1065 | dma_data->asp_chan_q = pdata->asp_chan_q; |
1235 | dma_data->ram_chan_q = pdata->ram_chan_q; | 1066 | dma_data->ram_chan_q = pdata->ram_chan_q; |
1236 | dma_data->sram_pool = pdata->sram_pool; | 1067 | dma_data->sram_pool = pdata->sram_pool; |
1237 | dma_data->sram_size = pdata->sram_size_capture; | 1068 | dma_data->sram_size = pdata->sram_size_capture; |
1238 | dma_data->dma_addr = dat->start + pdata->rx_dma_offset; | 1069 | if (dat) |
1070 | dma_data->dma_addr = dat->start; | ||
1071 | else | ||
1072 | dma_data->dma_addr = mem->start + pdata->rx_dma_offset; | ||
1073 | |||
1074 | /* Unconditional dmaengine stuff */ | ||
1075 | mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_data->dma_addr; | ||
1076 | |||
1077 | if (mcasp->version < MCASP_VERSION_3) { | ||
1078 | mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE; | ||
1079 | /* dma_data->dma_addr is pointing to the data port address */ | ||
1080 | mcasp->dat_port = true; | ||
1081 | } else { | ||
1082 | mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE; | ||
1083 | } | ||
1239 | 1084 | ||
1240 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 1085 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
1241 | if (res) | 1086 | if (res) |
@@ -1243,17 +1088,26 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1243 | else | 1088 | else |
1244 | dma_data->channel = pdata->rx_dma_channel; | 1089 | dma_data->channel = pdata->rx_dma_channel; |
1245 | 1090 | ||
1246 | dev_set_drvdata(&pdev->dev, dev); | 1091 | /* Unconditional dmaengine stuff */ |
1092 | mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = "tx"; | ||
1093 | mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = "rx"; | ||
1094 | |||
1095 | dev_set_drvdata(&pdev->dev, mcasp); | ||
1096 | |||
1097 | mcasp_reparent_fck(pdev); | ||
1098 | |||
1247 | ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, | 1099 | ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, |
1248 | &davinci_mcasp_dai[pdata->op_mode], 1); | 1100 | &davinci_mcasp_dai[pdata->op_mode], 1); |
1249 | 1101 | ||
1250 | if (ret != 0) | 1102 | if (ret != 0) |
1251 | goto err_release_clk; | 1103 | goto err_release_clk; |
1252 | 1104 | ||
1253 | ret = davinci_soc_platform_register(&pdev->dev); | 1105 | if (mcasp->version != MCASP_VERSION_4) { |
1254 | if (ret) { | 1106 | ret = davinci_soc_platform_register(&pdev->dev); |
1255 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | 1107 | if (ret) { |
1256 | goto err_unregister_component; | 1108 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); |
1109 | goto err_unregister_component; | ||
1110 | } | ||
1257 | } | 1111 | } |
1258 | 1112 | ||
1259 | return 0; | 1113 | return 0; |
@@ -1268,9 +1122,11 @@ err_release_clk: | |||
1268 | 1122 | ||
1269 | static int davinci_mcasp_remove(struct platform_device *pdev) | 1123 | static int davinci_mcasp_remove(struct platform_device *pdev) |
1270 | { | 1124 | { |
1125 | struct davinci_mcasp *mcasp = dev_get_drvdata(&pdev->dev); | ||
1271 | 1126 | ||
1272 | snd_soc_unregister_component(&pdev->dev); | 1127 | snd_soc_unregister_component(&pdev->dev); |
1273 | davinci_soc_platform_unregister(&pdev->dev); | 1128 | if (mcasp->version != MCASP_VERSION_4) |
1129 | davinci_soc_platform_unregister(&pdev->dev); | ||
1274 | 1130 | ||
1275 | pm_runtime_put_sync(&pdev->dev); | 1131 | pm_runtime_put_sync(&pdev->dev); |
1276 | pm_runtime_disable(&pdev->dev); | 1132 | pm_runtime_disable(&pdev->dev); |
@@ -1281,32 +1137,30 @@ static int davinci_mcasp_remove(struct platform_device *pdev) | |||
1281 | #ifdef CONFIG_PM_SLEEP | 1137 | #ifdef CONFIG_PM_SLEEP |
1282 | static int davinci_mcasp_suspend(struct device *dev) | 1138 | static int davinci_mcasp_suspend(struct device *dev) |
1283 | { | 1139 | { |
1284 | struct davinci_audio_dev *a = dev_get_drvdata(dev); | 1140 | struct davinci_mcasp *mcasp = dev_get_drvdata(dev); |
1285 | void __iomem *base = a->base; | ||
1286 | 1141 | ||
1287 | a->context.txfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_TXFMCTL_REG); | 1142 | mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); |
1288 | a->context.rxfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_RXFMCTL_REG); | 1143 | mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); |
1289 | a->context.txfmt = mcasp_get_reg(base + DAVINCI_MCASP_TXFMT_REG); | 1144 | mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); |
1290 | a->context.rxfmt = mcasp_get_reg(base + DAVINCI_MCASP_RXFMT_REG); | 1145 | mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); |
1291 | a->context.aclkxctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKXCTL_REG); | 1146 | mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); |
1292 | a->context.aclkrctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKRCTL_REG); | 1147 | mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); |
1293 | a->context.pdir = mcasp_get_reg(base + DAVINCI_MCASP_PDIR_REG); | 1148 | mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); |
1294 | 1149 | ||
1295 | return 0; | 1150 | return 0; |
1296 | } | 1151 | } |
1297 | 1152 | ||
1298 | static int davinci_mcasp_resume(struct device *dev) | 1153 | static int davinci_mcasp_resume(struct device *dev) |
1299 | { | 1154 | { |
1300 | struct davinci_audio_dev *a = dev_get_drvdata(dev); | 1155 | struct davinci_mcasp *mcasp = dev_get_drvdata(dev); |
1301 | void __iomem *base = a->base; | 1156 | |
1302 | 1157 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl); | |
1303 | mcasp_set_reg(base + DAVINCI_MCASP_TXFMCTL_REG, a->context.txfmtctl); | 1158 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl); |
1304 | mcasp_set_reg(base + DAVINCI_MCASP_RXFMCTL_REG, a->context.rxfmtctl); | 1159 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt); |
1305 | mcasp_set_reg(base + DAVINCI_MCASP_TXFMT_REG, a->context.txfmt); | 1160 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt); |
1306 | mcasp_set_reg(base + DAVINCI_MCASP_RXFMT_REG, a->context.rxfmt); | 1161 | mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl); |
1307 | mcasp_set_reg(base + DAVINCI_MCASP_ACLKXCTL_REG, a->context.aclkxctl); | 1162 | mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl); |
1308 | mcasp_set_reg(base + DAVINCI_MCASP_ACLKRCTL_REG, a->context.aclkrctl); | 1163 | mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir); |
1309 | mcasp_set_reg(base + DAVINCI_MCASP_PDIR_REG, a->context.pdir); | ||
1310 | 1164 | ||
1311 | return 0; | 1165 | return 0; |
1312 | } | 1166 | } |
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index a2e27e1c32f3..8fed757d6087 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h | |||
@@ -18,43 +18,271 @@ | |||
18 | #ifndef DAVINCI_MCASP_H | 18 | #ifndef DAVINCI_MCASP_H |
19 | #define DAVINCI_MCASP_H | 19 | #define DAVINCI_MCASP_H |
20 | 20 | ||
21 | #include <linux/io.h> | 21 | /* |
22 | #include <linux/platform_data/davinci_asp.h> | 22 | * McASP register definitions |
23 | 23 | */ | |
24 | #include "davinci-pcm.h" | 24 | #define DAVINCI_MCASP_PID_REG 0x00 |
25 | 25 | #define DAVINCI_MCASP_PWREMUMGT_REG 0x04 | |
26 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000 | 26 | |
27 | #define DAVINCI_MCASP_I2S_DAI 0 | 27 | #define DAVINCI_MCASP_PFUNC_REG 0x10 |
28 | #define DAVINCI_MCASP_DIT_DAI 1 | 28 | #define DAVINCI_MCASP_PDIR_REG 0x14 |
29 | 29 | #define DAVINCI_MCASP_PDOUT_REG 0x18 | |
30 | struct davinci_audio_dev { | 30 | #define DAVINCI_MCASP_PDSET_REG 0x1c |
31 | struct davinci_pcm_dma_params dma_params[2]; | 31 | |
32 | void __iomem *base; | 32 | #define DAVINCI_MCASP_PDCLR_REG 0x20 |
33 | struct device *dev; | 33 | |
34 | 34 | #define DAVINCI_MCASP_TLGC_REG 0x30 | |
35 | /* McASP specific data */ | 35 | #define DAVINCI_MCASP_TLMR_REG 0x34 |
36 | int tdm_slots; | 36 | |
37 | u8 op_mode; | 37 | #define DAVINCI_MCASP_GBLCTL_REG 0x44 |
38 | u8 num_serializer; | 38 | #define DAVINCI_MCASP_AMUTE_REG 0x48 |
39 | u8 *serial_dir; | 39 | #define DAVINCI_MCASP_LBCTL_REG 0x4c |
40 | u8 version; | 40 | |
41 | u16 bclk_lrclk_ratio; | 41 | #define DAVINCI_MCASP_TXDITCTL_REG 0x50 |
42 | 42 | ||
43 | /* McASP FIFO related */ | 43 | #define DAVINCI_MCASP_GBLCTLR_REG 0x60 |
44 | u8 txnumevt; | 44 | #define DAVINCI_MCASP_RXMASK_REG 0x64 |
45 | u8 rxnumevt; | 45 | #define DAVINCI_MCASP_RXFMT_REG 0x68 |
46 | 46 | #define DAVINCI_MCASP_RXFMCTL_REG 0x6c | |
47 | #ifdef CONFIG_PM_SLEEP | 47 | |
48 | struct { | 48 | #define DAVINCI_MCASP_ACLKRCTL_REG 0x70 |
49 | u32 txfmtctl; | 49 | #define DAVINCI_MCASP_AHCLKRCTL_REG 0x74 |
50 | u32 rxfmtctl; | 50 | #define DAVINCI_MCASP_RXTDM_REG 0x78 |
51 | u32 txfmt; | 51 | #define DAVINCI_MCASP_EVTCTLR_REG 0x7c |
52 | u32 rxfmt; | 52 | |
53 | u32 aclkxctl; | 53 | #define DAVINCI_MCASP_RXSTAT_REG 0x80 |
54 | u32 aclkrctl; | 54 | #define DAVINCI_MCASP_RXTDMSLOT_REG 0x84 |
55 | u32 pdir; | 55 | #define DAVINCI_MCASP_RXCLKCHK_REG 0x88 |
56 | } context; | 56 | #define DAVINCI_MCASP_REVTCTL_REG 0x8c |
57 | #endif | 57 | |
58 | }; | 58 | #define DAVINCI_MCASP_GBLCTLX_REG 0xa0 |
59 | #define DAVINCI_MCASP_TXMASK_REG 0xa4 | ||
60 | #define DAVINCI_MCASP_TXFMT_REG 0xa8 | ||
61 | #define DAVINCI_MCASP_TXFMCTL_REG 0xac | ||
62 | |||
63 | #define DAVINCI_MCASP_ACLKXCTL_REG 0xb0 | ||
64 | #define DAVINCI_MCASP_AHCLKXCTL_REG 0xb4 | ||
65 | #define DAVINCI_MCASP_TXTDM_REG 0xb8 | ||
66 | #define DAVINCI_MCASP_EVTCTLX_REG 0xbc | ||
67 | |||
68 | #define DAVINCI_MCASP_TXSTAT_REG 0xc0 | ||
69 | #define DAVINCI_MCASP_TXTDMSLOT_REG 0xc4 | ||
70 | #define DAVINCI_MCASP_TXCLKCHK_REG 0xc8 | ||
71 | #define DAVINCI_MCASP_XEVTCTL_REG 0xcc | ||
72 | |||
73 | /* Left(even TDM Slot) Channel Status Register File */ | ||
74 | #define DAVINCI_MCASP_DITCSRA_REG 0x100 | ||
75 | /* Right(odd TDM slot) Channel Status Register File */ | ||
76 | #define DAVINCI_MCASP_DITCSRB_REG 0x118 | ||
77 | /* Left(even TDM slot) User Data Register File */ | ||
78 | #define DAVINCI_MCASP_DITUDRA_REG 0x130 | ||
79 | /* Right(odd TDM Slot) User Data Register File */ | ||
80 | #define DAVINCI_MCASP_DITUDRB_REG 0x148 | ||
81 | |||
82 | /* Serializer n Control Register */ | ||
83 | #define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180 | ||
84 | #define DAVINCI_MCASP_XRSRCTL_REG(n) (DAVINCI_MCASP_XRSRCTL_BASE_REG + \ | ||
85 | (n << 2)) | ||
86 | |||
87 | /* Transmit Buffer for Serializer n */ | ||
88 | #define DAVINCI_MCASP_TXBUF_REG 0x200 | ||
89 | /* Receive Buffer for Serializer n */ | ||
90 | #define DAVINCI_MCASP_RXBUF_REG 0x280 | ||
91 | |||
92 | /* McASP FIFO Registers */ | ||
93 | #define DAVINCI_MCASP_V2_AFIFO_BASE (0x1010) | ||
94 | #define DAVINCI_MCASP_V3_AFIFO_BASE (0x1000) | ||
95 | |||
96 | /* FIFO register offsets from AFIFO base */ | ||
97 | #define MCASP_WFIFOCTL_OFFSET (0x0) | ||
98 | #define MCASP_WFIFOSTS_OFFSET (0x4) | ||
99 | #define MCASP_RFIFOCTL_OFFSET (0x8) | ||
100 | #define MCASP_RFIFOSTS_OFFSET (0xc) | ||
101 | |||
102 | /* | ||
103 | * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management | ||
104 | * Register Bits | ||
105 | */ | ||
106 | #define MCASP_FREE BIT(0) | ||
107 | #define MCASP_SOFT BIT(1) | ||
108 | |||
109 | /* | ||
110 | * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits | ||
111 | */ | ||
112 | #define AXR(n) (1<<n) | ||
113 | #define PFUNC_AMUTE BIT(25) | ||
114 | #define ACLKX BIT(26) | ||
115 | #define AHCLKX BIT(27) | ||
116 | #define AFSX BIT(28) | ||
117 | #define ACLKR BIT(29) | ||
118 | #define AHCLKR BIT(30) | ||
119 | #define AFSR BIT(31) | ||
120 | |||
121 | /* | ||
122 | * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits | ||
123 | */ | ||
124 | #define AXR(n) (1<<n) | ||
125 | #define PDIR_AMUTE BIT(25) | ||
126 | #define ACLKX BIT(26) | ||
127 | #define AHCLKX BIT(27) | ||
128 | #define AFSX BIT(28) | ||
129 | #define ACLKR BIT(29) | ||
130 | #define AHCLKR BIT(30) | ||
131 | #define AFSR BIT(31) | ||
132 | |||
133 | /* | ||
134 | * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits | ||
135 | */ | ||
136 | #define DITEN BIT(0) /* Transmit DIT mode enable/disable */ | ||
137 | #define VA BIT(2) | ||
138 | #define VB BIT(3) | ||
139 | |||
140 | /* | ||
141 | * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits | ||
142 | */ | ||
143 | #define TXROT(val) (val) | ||
144 | #define TXSEL BIT(3) | ||
145 | #define TXSSZ(val) (val<<4) | ||
146 | #define TXPBIT(val) (val<<8) | ||
147 | #define TXPAD(val) (val<<13) | ||
148 | #define TXORD BIT(15) | ||
149 | #define FSXDLY(val) (val<<16) | ||
150 | |||
151 | /* | ||
152 | * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits | ||
153 | */ | ||
154 | #define RXROT(val) (val) | ||
155 | #define RXSEL BIT(3) | ||
156 | #define RXSSZ(val) (val<<4) | ||
157 | #define RXPBIT(val) (val<<8) | ||
158 | #define RXPAD(val) (val<<13) | ||
159 | #define RXORD BIT(15) | ||
160 | #define FSRDLY(val) (val<<16) | ||
161 | |||
162 | /* | ||
163 | * DAVINCI_MCASP_TXFMCTL_REG - Transmit Frame Control Register Bits | ||
164 | */ | ||
165 | #define FSXPOL BIT(0) | ||
166 | #define AFSXE BIT(1) | ||
167 | #define FSXDUR BIT(4) | ||
168 | #define FSXMOD(val) (val<<7) | ||
169 | |||
170 | /* | ||
171 | * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits | ||
172 | */ | ||
173 | #define FSRPOL BIT(0) | ||
174 | #define AFSRE BIT(1) | ||
175 | #define FSRDUR BIT(4) | ||
176 | #define FSRMOD(val) (val<<7) | ||
177 | |||
178 | /* | ||
179 | * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits | ||
180 | */ | ||
181 | #define ACLKXDIV(val) (val) | ||
182 | #define ACLKXE BIT(5) | ||
183 | #define TX_ASYNC BIT(6) | ||
184 | #define ACLKXPOL BIT(7) | ||
185 | #define ACLKXDIV_MASK 0x1f | ||
186 | |||
187 | /* | ||
188 | * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits | ||
189 | */ | ||
190 | #define ACLKRDIV(val) (val) | ||
191 | #define ACLKRE BIT(5) | ||
192 | #define RX_ASYNC BIT(6) | ||
193 | #define ACLKRPOL BIT(7) | ||
194 | #define ACLKRDIV_MASK 0x1f | ||
195 | |||
196 | /* | ||
197 | * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control | ||
198 | * Register Bits | ||
199 | */ | ||
200 | #define AHCLKXDIV(val) (val) | ||
201 | #define AHCLKXPOL BIT(14) | ||
202 | #define AHCLKXE BIT(15) | ||
203 | #define AHCLKXDIV_MASK 0xfff | ||
204 | |||
205 | /* | ||
206 | * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control | ||
207 | * Register Bits | ||
208 | */ | ||
209 | #define AHCLKRDIV(val) (val) | ||
210 | #define AHCLKRPOL BIT(14) | ||
211 | #define AHCLKRE BIT(15) | ||
212 | #define AHCLKRDIV_MASK 0xfff | ||
213 | |||
214 | /* | ||
215 | * DAVINCI_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits | ||
216 | */ | ||
217 | #define MODE(val) (val) | ||
218 | #define DISMOD (val)(val<<2) | ||
219 | #define TXSTATE BIT(4) | ||
220 | #define RXSTATE BIT(5) | ||
221 | #define SRMOD_MASK 3 | ||
222 | #define SRMOD_INACTIVE 0 | ||
223 | |||
224 | /* | ||
225 | * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits | ||
226 | */ | ||
227 | #define LBEN BIT(0) | ||
228 | #define LBORD BIT(1) | ||
229 | #define LBGENMODE(val) (val<<2) | ||
230 | |||
231 | /* | ||
232 | * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration | ||
233 | */ | ||
234 | #define TXTDMS(n) (1<<n) | ||
235 | |||
236 | /* | ||
237 | * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration | ||
238 | */ | ||
239 | #define RXTDMS(n) (1<<n) | ||
240 | |||
241 | /* | ||
242 | * DAVINCI_MCASP_GBLCTL_REG - Global Control Register Bits | ||
243 | */ | ||
244 | #define RXCLKRST BIT(0) /* Receiver Clock Divider Reset */ | ||
245 | #define RXHCLKRST BIT(1) /* Receiver High Frequency Clock Divider */ | ||
246 | #define RXSERCLR BIT(2) /* Receiver Serializer Clear */ | ||
247 | #define RXSMRST BIT(3) /* Receiver State Machine Reset */ | ||
248 | #define RXFSRST BIT(4) /* Frame Sync Generator Reset */ | ||
249 | #define TXCLKRST BIT(8) /* Transmitter Clock Divider Reset */ | ||
250 | #define TXHCLKRST BIT(9) /* Transmitter High Frequency Clock Divider*/ | ||
251 | #define TXSERCLR BIT(10) /* Transmit Serializer Clear */ | ||
252 | #define TXSMRST BIT(11) /* Transmitter State Machine Reset */ | ||
253 | #define TXFSRST BIT(12) /* Frame Sync Generator Reset */ | ||
254 | |||
255 | /* | ||
256 | * DAVINCI_MCASP_AMUTE_REG - Mute Control Register Bits | ||
257 | */ | ||
258 | #define MUTENA(val) (val) | ||
259 | #define MUTEINPOL BIT(2) | ||
260 | #define MUTEINENA BIT(3) | ||
261 | #define MUTEIN BIT(4) | ||
262 | #define MUTER BIT(5) | ||
263 | #define MUTEX BIT(6) | ||
264 | #define MUTEFSR BIT(7) | ||
265 | #define MUTEFSX BIT(8) | ||
266 | #define MUTEBADCLKR BIT(9) | ||
267 | #define MUTEBADCLKX BIT(10) | ||
268 | #define MUTERXDMAERR BIT(11) | ||
269 | #define MUTETXDMAERR BIT(12) | ||
270 | |||
271 | /* | ||
272 | * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits | ||
273 | */ | ||
274 | #define RXDATADMADIS BIT(0) | ||
275 | |||
276 | /* | ||
277 | * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits | ||
278 | */ | ||
279 | #define TXDATADMADIS BIT(0) | ||
280 | |||
281 | /* | ||
282 | * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits | ||
283 | */ | ||
284 | #define FIFO_ENABLE BIT(16) | ||
285 | #define NUMEVT_MASK (0xFF << 8) | ||
286 | #define NUMDMA_MASK (0xFF) | ||
59 | 287 | ||
60 | #endif /* DAVINCI_MCASP_H */ | 288 | #endif /* DAVINCI_MCASP_H */ |
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index fb5d107f5603..14145cdf8a11 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c | |||
@@ -46,33 +46,11 @@ static void print_buf_info(int slot, char *name) | |||
46 | } | 46 | } |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #define DAVINCI_PCM_FMTBITS (\ | ||
50 | SNDRV_PCM_FMTBIT_S8 |\ | ||
51 | SNDRV_PCM_FMTBIT_U8 |\ | ||
52 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
53 | SNDRV_PCM_FMTBIT_S16_BE |\ | ||
54 | SNDRV_PCM_FMTBIT_U16_LE |\ | ||
55 | SNDRV_PCM_FMTBIT_U16_BE |\ | ||
56 | SNDRV_PCM_FMTBIT_S24_LE |\ | ||
57 | SNDRV_PCM_FMTBIT_S24_BE |\ | ||
58 | SNDRV_PCM_FMTBIT_U24_LE |\ | ||
59 | SNDRV_PCM_FMTBIT_U24_BE |\ | ||
60 | SNDRV_PCM_FMTBIT_S32_LE |\ | ||
61 | SNDRV_PCM_FMTBIT_S32_BE |\ | ||
62 | SNDRV_PCM_FMTBIT_U32_LE |\ | ||
63 | SNDRV_PCM_FMTBIT_U32_BE) | ||
64 | |||
65 | static struct snd_pcm_hardware pcm_hardware_playback = { | 49 | static struct snd_pcm_hardware pcm_hardware_playback = { |
66 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 50 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
67 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 51 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
68 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME| | 52 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME| |
69 | SNDRV_PCM_INFO_BATCH), | 53 | SNDRV_PCM_INFO_BATCH), |
70 | .formats = DAVINCI_PCM_FMTBITS, | ||
71 | .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT, | ||
72 | .rate_min = 8000, | ||
73 | .rate_max = 192000, | ||
74 | .channels_min = 2, | ||
75 | .channels_max = 384, | ||
76 | .buffer_bytes_max = 128 * 1024, | 54 | .buffer_bytes_max = 128 * 1024, |
77 | .period_bytes_min = 32, | 55 | .period_bytes_min = 32, |
78 | .period_bytes_max = 8 * 1024, | 56 | .period_bytes_max = 8 * 1024, |
@@ -86,12 +64,6 @@ static struct snd_pcm_hardware pcm_hardware_capture = { | |||
86 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 64 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
87 | SNDRV_PCM_INFO_PAUSE | | 65 | SNDRV_PCM_INFO_PAUSE | |
88 | SNDRV_PCM_INFO_BATCH), | 66 | SNDRV_PCM_INFO_BATCH), |
89 | .formats = DAVINCI_PCM_FMTBITS, | ||
90 | .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT, | ||
91 | .rate_min = 8000, | ||
92 | .rate_max = 192000, | ||
93 | .channels_min = 2, | ||
94 | .channels_max = 384, | ||
95 | .buffer_bytes_max = 128 * 1024, | 67 | .buffer_bytes_max = 128 * 1024, |
96 | .period_bytes_min = 32, | 68 | .period_bytes_min = 32, |
97 | .period_bytes_max = 8 * 1024, | 69 | .period_bytes_max = 8 * 1024, |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index b7ab71f2ccc1..514c275c6108 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -1,3 +1,7 @@ | |||
1 | config SND_SOC_FSL_SAI | ||
2 | tristate | ||
3 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
4 | |||
1 | config SND_SOC_FSL_SSI | 5 | config SND_SOC_FSL_SSI |
2 | tristate | 6 | tristate |
3 | 7 | ||
@@ -197,7 +201,6 @@ config SND_SOC_IMX_SPDIF | |||
197 | tristate "SoC Audio support for i.MX boards with S/PDIF" | 201 | tristate "SoC Audio support for i.MX boards with S/PDIF" |
198 | select SND_SOC_IMX_PCM_DMA | 202 | select SND_SOC_IMX_PCM_DMA |
199 | select SND_SOC_FSL_SPDIF | 203 | select SND_SOC_FSL_SPDIF |
200 | select SND_SOC_SPDIF | ||
201 | select REGMAP_MMIO | 204 | select REGMAP_MMIO |
202 | help | 205 | help |
203 | SoC Audio support for i.MX boards with S/PDIF | 206 | SoC Audio support for i.MX boards with S/PDIF |
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 8db705b0fdf9..aaccbee17006 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
@@ -10,11 +10,13 @@ obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o | |||
10 | snd-soc-p1022-rdk-objs := p1022_rdk.o | 10 | snd-soc-p1022-rdk-objs := p1022_rdk.o |
11 | obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o | 11 | obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o |
12 | 12 | ||
13 | # Freescale PowerPC SSI/DMA Platform Support | 13 | # Freescale SSI/DMA/SAI/SPDIF Support |
14 | snd-soc-fsl-sai-objs := fsl_sai.o | ||
14 | snd-soc-fsl-ssi-objs := fsl_ssi.o | 15 | snd-soc-fsl-ssi-objs := fsl_ssi.o |
15 | snd-soc-fsl-spdif-objs := fsl_spdif.o | 16 | snd-soc-fsl-spdif-objs := fsl_spdif.o |
16 | snd-soc-fsl-utils-objs := fsl_utils.o | 17 | snd-soc-fsl-utils-objs := fsl_utils.o |
17 | snd-soc-fsl-dma-objs := fsl_dma.o | 18 | snd-soc-fsl-dma-objs := fsl_dma.o |
19 | obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o | ||
18 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o | 20 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o |
19 | obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o | 21 | obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o |
20 | obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o | 22 | obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o |
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index fb9bb9eb5ca3..d570f8c81dc6 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
@@ -852,7 +852,7 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm) | |||
852 | } | 852 | } |
853 | 853 | ||
854 | /** | 854 | /** |
855 | * find_ssi_node -- returns the SSI node that points to his DMA channel node | 855 | * find_ssi_node -- returns the SSI node that points to its DMA channel node |
856 | * | 856 | * |
857 | * Although this DMA driver attempts to operate independently of the other | 857 | * Although this DMA driver attempts to operate independently of the other |
858 | * devices, it still needs to determine some information about the SSI device | 858 | * devices, it still needs to determine some information about the SSI device |
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c new file mode 100644 index 000000000000..5d38a6749b9f --- /dev/null +++ b/sound/soc/fsl/fsl_sai.c | |||
@@ -0,0 +1,460 @@ | |||
1 | /* | ||
2 | * Freescale ALSA SoC Digital Audio Interface (SAI) driver. | ||
3 | * | ||
4 | * Copyright 2012-2013 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * This program is free software, you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation, either version 2 of the License, or(at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/dmaengine.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/of_address.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <sound/core.h> | ||
20 | #include <sound/dmaengine_pcm.h> | ||
21 | #include <sound/pcm_params.h> | ||
22 | |||
23 | #include "fsl_sai.h" | ||
24 | |||
25 | static inline u32 sai_readl(struct fsl_sai *sai, | ||
26 | const void __iomem *addr) | ||
27 | { | ||
28 | u32 val; | ||
29 | |||
30 | val = __raw_readl(addr); | ||
31 | |||
32 | if (likely(sai->big_endian_regs)) | ||
33 | val = be32_to_cpu(val); | ||
34 | else | ||
35 | val = le32_to_cpu(val); | ||
36 | rmb(); | ||
37 | |||
38 | return val; | ||
39 | } | ||
40 | |||
41 | static inline void sai_writel(struct fsl_sai *sai, | ||
42 | u32 val, void __iomem *addr) | ||
43 | { | ||
44 | wmb(); | ||
45 | if (likely(sai->big_endian_regs)) | ||
46 | val = cpu_to_be32(val); | ||
47 | else | ||
48 | val = cpu_to_le32(val); | ||
49 | |||
50 | __raw_writel(val, addr); | ||
51 | } | ||
52 | |||
53 | static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, | ||
54 | int clk_id, unsigned int freq, int fsl_dir) | ||
55 | { | ||
56 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
57 | u32 val_cr2, reg_cr2; | ||
58 | |||
59 | if (fsl_dir == FSL_FMT_TRANSMITTER) | ||
60 | reg_cr2 = FSL_SAI_TCR2; | ||
61 | else | ||
62 | reg_cr2 = FSL_SAI_RCR2; | ||
63 | |||
64 | val_cr2 = sai_readl(sai, sai->base + reg_cr2); | ||
65 | switch (clk_id) { | ||
66 | case FSL_SAI_CLK_BUS: | ||
67 | val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK; | ||
68 | val_cr2 |= FSL_SAI_CR2_MSEL_BUS; | ||
69 | break; | ||
70 | case FSL_SAI_CLK_MAST1: | ||
71 | val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK; | ||
72 | val_cr2 |= FSL_SAI_CR2_MSEL_MCLK1; | ||
73 | break; | ||
74 | case FSL_SAI_CLK_MAST2: | ||
75 | val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK; | ||
76 | val_cr2 |= FSL_SAI_CR2_MSEL_MCLK2; | ||
77 | break; | ||
78 | case FSL_SAI_CLK_MAST3: | ||
79 | val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK; | ||
80 | val_cr2 |= FSL_SAI_CR2_MSEL_MCLK3; | ||
81 | break; | ||
82 | default: | ||
83 | return -EINVAL; | ||
84 | } | ||
85 | sai_writel(sai, val_cr2, sai->base + reg_cr2); | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | ||
91 | int clk_id, unsigned int freq, int dir) | ||
92 | { | ||
93 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
94 | int ret; | ||
95 | |||
96 | if (dir == SND_SOC_CLOCK_IN) | ||
97 | return 0; | ||
98 | |||
99 | ret = clk_prepare_enable(sai->clk); | ||
100 | if (ret) | ||
101 | return ret; | ||
102 | |||
103 | ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, | ||
104 | FSL_FMT_TRANSMITTER); | ||
105 | if (ret) { | ||
106 | dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret); | ||
107 | goto err_clk; | ||
108 | } | ||
109 | |||
110 | ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, | ||
111 | FSL_FMT_RECEIVER); | ||
112 | if (ret) { | ||
113 | dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret); | ||
114 | goto err_clk; | ||
115 | } | ||
116 | |||
117 | err_clk: | ||
118 | clk_disable_unprepare(sai->clk); | ||
119 | |||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, | ||
124 | unsigned int fmt, int fsl_dir) | ||
125 | { | ||
126 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
127 | u32 val_cr2, val_cr4, reg_cr2, reg_cr4; | ||
128 | |||
129 | if (fsl_dir == FSL_FMT_TRANSMITTER) { | ||
130 | reg_cr2 = FSL_SAI_TCR2; | ||
131 | reg_cr4 = FSL_SAI_TCR4; | ||
132 | } else { | ||
133 | reg_cr2 = FSL_SAI_RCR2; | ||
134 | reg_cr4 = FSL_SAI_RCR4; | ||
135 | } | ||
136 | |||
137 | val_cr2 = sai_readl(sai, sai->base + reg_cr2); | ||
138 | val_cr4 = sai_readl(sai, sai->base + reg_cr4); | ||
139 | |||
140 | if (sai->big_endian_data) | ||
141 | val_cr4 &= ~FSL_SAI_CR4_MF; | ||
142 | else | ||
143 | val_cr4 |= FSL_SAI_CR4_MF; | ||
144 | |||
145 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
146 | case SND_SOC_DAIFMT_I2S: | ||
147 | val_cr4 |= FSL_SAI_CR4_FSE; | ||
148 | break; | ||
149 | default: | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | |||
153 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
154 | case SND_SOC_DAIFMT_IB_IF: | ||
155 | val_cr4 |= FSL_SAI_CR4_FSP; | ||
156 | val_cr2 &= ~FSL_SAI_CR2_BCP; | ||
157 | break; | ||
158 | case SND_SOC_DAIFMT_IB_NF: | ||
159 | val_cr4 &= ~FSL_SAI_CR4_FSP; | ||
160 | val_cr2 &= ~FSL_SAI_CR2_BCP; | ||
161 | break; | ||
162 | case SND_SOC_DAIFMT_NB_IF: | ||
163 | val_cr4 |= FSL_SAI_CR4_FSP; | ||
164 | val_cr2 |= FSL_SAI_CR2_BCP; | ||
165 | break; | ||
166 | case SND_SOC_DAIFMT_NB_NF: | ||
167 | val_cr4 &= ~FSL_SAI_CR4_FSP; | ||
168 | val_cr2 |= FSL_SAI_CR2_BCP; | ||
169 | break; | ||
170 | default: | ||
171 | return -EINVAL; | ||
172 | } | ||
173 | |||
174 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
175 | case SND_SOC_DAIFMT_CBS_CFS: | ||
176 | val_cr2 |= FSL_SAI_CR2_BCD_MSTR; | ||
177 | val_cr4 |= FSL_SAI_CR4_FSD_MSTR; | ||
178 | break; | ||
179 | case SND_SOC_DAIFMT_CBM_CFM: | ||
180 | val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR; | ||
181 | val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR; | ||
182 | break; | ||
183 | default: | ||
184 | return -EINVAL; | ||
185 | } | ||
186 | |||
187 | sai_writel(sai, val_cr2, sai->base + reg_cr2); | ||
188 | sai_writel(sai, val_cr4, sai->base + reg_cr4); | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | ||
194 | { | ||
195 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
196 | int ret; | ||
197 | |||
198 | ret = clk_prepare_enable(sai->clk); | ||
199 | if (ret) | ||
200 | return ret; | ||
201 | |||
202 | ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER); | ||
203 | if (ret) { | ||
204 | dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret); | ||
205 | goto err_clk; | ||
206 | } | ||
207 | |||
208 | ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER); | ||
209 | if (ret) { | ||
210 | dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret); | ||
211 | goto err_clk; | ||
212 | } | ||
213 | |||
214 | err_clk: | ||
215 | clk_disable_unprepare(sai->clk); | ||
216 | |||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | static int fsl_sai_hw_params(struct snd_pcm_substream *substream, | ||
221 | struct snd_pcm_hw_params *params, | ||
222 | struct snd_soc_dai *cpu_dai) | ||
223 | { | ||
224 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
225 | u32 val_cr4, val_cr5, val_mr, reg_cr4, reg_cr5, reg_mr; | ||
226 | unsigned int channels = params_channels(params); | ||
227 | u32 word_width = snd_pcm_format_width(params_format(params)); | ||
228 | |||
229 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
230 | reg_cr4 = FSL_SAI_TCR4; | ||
231 | reg_cr5 = FSL_SAI_TCR5; | ||
232 | reg_mr = FSL_SAI_TMR; | ||
233 | } else { | ||
234 | reg_cr4 = FSL_SAI_RCR4; | ||
235 | reg_cr5 = FSL_SAI_RCR5; | ||
236 | reg_mr = FSL_SAI_RMR; | ||
237 | } | ||
238 | |||
239 | val_cr4 = sai_readl(sai, sai->base + reg_cr4); | ||
240 | val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK; | ||
241 | val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK; | ||
242 | |||
243 | val_cr5 = sai_readl(sai, sai->base + reg_cr5); | ||
244 | val_cr5 &= ~FSL_SAI_CR5_WNW_MASK; | ||
245 | val_cr5 &= ~FSL_SAI_CR5_W0W_MASK; | ||
246 | val_cr5 &= ~FSL_SAI_CR5_FBT_MASK; | ||
247 | |||
248 | val_cr4 |= FSL_SAI_CR4_SYWD(word_width); | ||
249 | val_cr5 |= FSL_SAI_CR5_WNW(word_width); | ||
250 | val_cr5 |= FSL_SAI_CR5_W0W(word_width); | ||
251 | |||
252 | val_cr5 &= ~FSL_SAI_CR5_FBT_MASK; | ||
253 | if (sai->big_endian_data) | ||
254 | val_cr5 |= FSL_SAI_CR5_FBT(0); | ||
255 | else | ||
256 | val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1); | ||
257 | |||
258 | val_cr4 |= FSL_SAI_CR4_FRSZ(channels); | ||
259 | val_mr = ~0UL - ((1 << channels) - 1); | ||
260 | |||
261 | sai_writel(sai, val_cr4, sai->base + reg_cr4); | ||
262 | sai_writel(sai, val_cr5, sai->base + reg_cr5); | ||
263 | sai_writel(sai, val_mr, sai->base + reg_mr); | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | ||
269 | struct snd_soc_dai *cpu_dai) | ||
270 | { | ||
271 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
272 | u32 tcsr, rcsr, val_cr2, val_cr3, reg_cr3; | ||
273 | |||
274 | val_cr2 = sai_readl(sai, sai->base + FSL_SAI_TCR2); | ||
275 | val_cr2 &= ~FSL_SAI_CR2_SYNC; | ||
276 | sai_writel(sai, val_cr2, sai->base + FSL_SAI_TCR2); | ||
277 | |||
278 | val_cr2 = sai_readl(sai, sai->base + FSL_SAI_RCR2); | ||
279 | val_cr2 |= FSL_SAI_CR2_SYNC; | ||
280 | sai_writel(sai, val_cr2, sai->base + FSL_SAI_RCR2); | ||
281 | |||
282 | tcsr = sai_readl(sai, sai->base + FSL_SAI_TCSR); | ||
283 | rcsr = sai_readl(sai, sai->base + FSL_SAI_RCSR); | ||
284 | |||
285 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
286 | tcsr |= FSL_SAI_CSR_FRDE; | ||
287 | rcsr &= ~FSL_SAI_CSR_FRDE; | ||
288 | reg_cr3 = FSL_SAI_TCR3; | ||
289 | } else { | ||
290 | rcsr |= FSL_SAI_CSR_FRDE; | ||
291 | tcsr &= ~FSL_SAI_CSR_FRDE; | ||
292 | reg_cr3 = FSL_SAI_RCR3; | ||
293 | } | ||
294 | |||
295 | val_cr3 = sai_readl(sai, sai->base + reg_cr3); | ||
296 | |||
297 | switch (cmd) { | ||
298 | case SNDRV_PCM_TRIGGER_START: | ||
299 | case SNDRV_PCM_TRIGGER_RESUME: | ||
300 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
301 | tcsr |= FSL_SAI_CSR_TERE; | ||
302 | rcsr |= FSL_SAI_CSR_TERE; | ||
303 | val_cr3 |= FSL_SAI_CR3_TRCE; | ||
304 | |||
305 | sai_writel(sai, val_cr3, sai->base + reg_cr3); | ||
306 | sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); | ||
307 | sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); | ||
308 | break; | ||
309 | |||
310 | case SNDRV_PCM_TRIGGER_STOP: | ||
311 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
312 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
313 | if (!(cpu_dai->playback_active || cpu_dai->capture_active)) { | ||
314 | tcsr &= ~FSL_SAI_CSR_TERE; | ||
315 | rcsr &= ~FSL_SAI_CSR_TERE; | ||
316 | } | ||
317 | |||
318 | val_cr3 &= ~FSL_SAI_CR3_TRCE; | ||
319 | |||
320 | sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); | ||
321 | sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); | ||
322 | sai_writel(sai, val_cr3, sai->base + reg_cr3); | ||
323 | break; | ||
324 | default: | ||
325 | return -EINVAL; | ||
326 | } | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static int fsl_sai_startup(struct snd_pcm_substream *substream, | ||
332 | struct snd_soc_dai *cpu_dai) | ||
333 | { | ||
334 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
335 | |||
336 | return clk_prepare_enable(sai->clk); | ||
337 | } | ||
338 | |||
339 | static void fsl_sai_shutdown(struct snd_pcm_substream *substream, | ||
340 | struct snd_soc_dai *cpu_dai) | ||
341 | { | ||
342 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
343 | |||
344 | clk_disable_unprepare(sai->clk); | ||
345 | } | ||
346 | |||
347 | static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { | ||
348 | .set_sysclk = fsl_sai_set_dai_sysclk, | ||
349 | .set_fmt = fsl_sai_set_dai_fmt, | ||
350 | .hw_params = fsl_sai_hw_params, | ||
351 | .trigger = fsl_sai_trigger, | ||
352 | .startup = fsl_sai_startup, | ||
353 | .shutdown = fsl_sai_shutdown, | ||
354 | }; | ||
355 | |||
356 | static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) | ||
357 | { | ||
358 | struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); | ||
359 | int ret; | ||
360 | |||
361 | ret = clk_prepare_enable(sai->clk); | ||
362 | if (ret) | ||
363 | return ret; | ||
364 | |||
365 | sai_writel(sai, 0x0, sai->base + FSL_SAI_RCSR); | ||
366 | sai_writel(sai, 0x0, sai->base + FSL_SAI_TCSR); | ||
367 | sai_writel(sai, FSL_SAI_MAXBURST_TX * 2, sai->base + FSL_SAI_TCR1); | ||
368 | sai_writel(sai, FSL_SAI_MAXBURST_RX - 1, sai->base + FSL_SAI_RCR1); | ||
369 | |||
370 | clk_disable_unprepare(sai->clk); | ||
371 | |||
372 | snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, | ||
373 | &sai->dma_params_rx); | ||
374 | |||
375 | snd_soc_dai_set_drvdata(cpu_dai, sai); | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static struct snd_soc_dai_driver fsl_sai_dai = { | ||
381 | .probe = fsl_sai_dai_probe, | ||
382 | .playback = { | ||
383 | .channels_min = 1, | ||
384 | .channels_max = 2, | ||
385 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
386 | .formats = FSL_SAI_FORMATS, | ||
387 | }, | ||
388 | .capture = { | ||
389 | .channels_min = 1, | ||
390 | .channels_max = 2, | ||
391 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
392 | .formats = FSL_SAI_FORMATS, | ||
393 | }, | ||
394 | .ops = &fsl_sai_pcm_dai_ops, | ||
395 | }; | ||
396 | |||
397 | static const struct snd_soc_component_driver fsl_component = { | ||
398 | .name = "fsl-sai", | ||
399 | }; | ||
400 | |||
401 | static int fsl_sai_probe(struct platform_device *pdev) | ||
402 | { | ||
403 | struct device_node *np = pdev->dev.of_node; | ||
404 | struct fsl_sai *sai; | ||
405 | struct resource *res; | ||
406 | int ret; | ||
407 | |||
408 | sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); | ||
409 | if (!sai) | ||
410 | return -ENOMEM; | ||
411 | |||
412 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
413 | sai->base = devm_ioremap_resource(&pdev->dev, res); | ||
414 | if (IS_ERR(sai->base)) | ||
415 | return PTR_ERR(sai->base); | ||
416 | |||
417 | sai->clk = devm_clk_get(&pdev->dev, "sai"); | ||
418 | if (IS_ERR(sai->clk)) { | ||
419 | dev_err(&pdev->dev, "Cannot get SAI's clock\n"); | ||
420 | return PTR_ERR(sai->clk); | ||
421 | } | ||
422 | |||
423 | sai->dma_params_rx.addr = res->start + FSL_SAI_RDR; | ||
424 | sai->dma_params_tx.addr = res->start + FSL_SAI_TDR; | ||
425 | sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; | ||
426 | sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; | ||
427 | |||
428 | sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs"); | ||
429 | sai->big_endian_data = of_property_read_bool(np, "big-endian-data"); | ||
430 | |||
431 | platform_set_drvdata(pdev, sai); | ||
432 | |||
433 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, | ||
434 | &fsl_sai_dai, 1); | ||
435 | if (ret) | ||
436 | return ret; | ||
437 | |||
438 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, | ||
439 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE); | ||
440 | } | ||
441 | |||
442 | static const struct of_device_id fsl_sai_ids[] = { | ||
443 | { .compatible = "fsl,vf610-sai", }, | ||
444 | { /* sentinel */ } | ||
445 | }; | ||
446 | |||
447 | static struct platform_driver fsl_sai_driver = { | ||
448 | .probe = fsl_sai_probe, | ||
449 | .driver = { | ||
450 | .name = "fsl-sai", | ||
451 | .owner = THIS_MODULE, | ||
452 | .of_match_table = fsl_sai_ids, | ||
453 | }, | ||
454 | }; | ||
455 | module_platform_driver(fsl_sai_driver); | ||
456 | |||
457 | MODULE_DESCRIPTION("Freescale Soc SAI Interface"); | ||
458 | MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>"); | ||
459 | MODULE_ALIAS("platform:fsl-sai"); | ||
460 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h new file mode 100644 index 000000000000..41bb62e69361 --- /dev/null +++ b/sound/soc/fsl/fsl_sai.h | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * Copyright 2012-2013 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef __FSL_SAI_H | ||
10 | #define __FSL_SAI_H | ||
11 | |||
12 | #include <sound/dmaengine_pcm.h> | ||
13 | |||
14 | #define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ | ||
15 | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
16 | SNDRV_PCM_FMTBIT_S24_LE) | ||
17 | |||
18 | /* SAI Transmit/Recieve Control Register */ | ||
19 | #define FSL_SAI_TCSR 0x00 | ||
20 | #define FSL_SAI_RCSR 0x80 | ||
21 | #define FSL_SAI_CSR_TERE BIT(31) | ||
22 | #define FSL_SAI_CSR_FWF BIT(17) | ||
23 | #define FSL_SAI_CSR_FRIE BIT(8) | ||
24 | #define FSL_SAI_CSR_FRDE BIT(0) | ||
25 | |||
26 | /* SAI Transmit Data/FIFO/MASK Register */ | ||
27 | #define FSL_SAI_TDR 0x20 | ||
28 | #define FSL_SAI_TFR 0x40 | ||
29 | #define FSL_SAI_TMR 0x60 | ||
30 | |||
31 | /* SAI Recieve Data/FIFO/MASK Register */ | ||
32 | #define FSL_SAI_RDR 0xa0 | ||
33 | #define FSL_SAI_RFR 0xc0 | ||
34 | #define FSL_SAI_RMR 0xe0 | ||
35 | |||
36 | /* SAI Transmit and Recieve Configuration 1 Register */ | ||
37 | #define FSL_SAI_TCR1 0x04 | ||
38 | #define FSL_SAI_RCR1 0x84 | ||
39 | |||
40 | /* SAI Transmit and Recieve Configuration 2 Register */ | ||
41 | #define FSL_SAI_TCR2 0x08 | ||
42 | #define FSL_SAI_RCR2 0x88 | ||
43 | #define FSL_SAI_CR2_SYNC BIT(30) | ||
44 | #define FSL_SAI_CR2_MSEL_MASK (0xff << 26) | ||
45 | #define FSL_SAI_CR2_MSEL_BUS 0 | ||
46 | #define FSL_SAI_CR2_MSEL_MCLK1 BIT(26) | ||
47 | #define FSL_SAI_CR2_MSEL_MCLK2 BIT(27) | ||
48 | #define FSL_SAI_CR2_MSEL_MCLK3 (BIT(26) | BIT(27)) | ||
49 | #define FSL_SAI_CR2_BCP BIT(25) | ||
50 | #define FSL_SAI_CR2_BCD_MSTR BIT(24) | ||
51 | |||
52 | /* SAI Transmit and Recieve Configuration 3 Register */ | ||
53 | #define FSL_SAI_TCR3 0x0c | ||
54 | #define FSL_SAI_RCR3 0x8c | ||
55 | #define FSL_SAI_CR3_TRCE BIT(16) | ||
56 | #define FSL_SAI_CR3_WDFL(x) (x) | ||
57 | #define FSL_SAI_CR3_WDFL_MASK 0x1f | ||
58 | |||
59 | /* SAI Transmit and Recieve Configuration 4 Register */ | ||
60 | #define FSL_SAI_TCR4 0x10 | ||
61 | #define FSL_SAI_RCR4 0x90 | ||
62 | #define FSL_SAI_CR4_FRSZ(x) (((x) - 1) << 16) | ||
63 | #define FSL_SAI_CR4_FRSZ_MASK (0x1f << 16) | ||
64 | #define FSL_SAI_CR4_SYWD(x) (((x) - 1) << 8) | ||
65 | #define FSL_SAI_CR4_SYWD_MASK (0x1f << 8) | ||
66 | #define FSL_SAI_CR4_MF BIT(4) | ||
67 | #define FSL_SAI_CR4_FSE BIT(3) | ||
68 | #define FSL_SAI_CR4_FSP BIT(1) | ||
69 | #define FSL_SAI_CR4_FSD_MSTR BIT(0) | ||
70 | |||
71 | /* SAI Transmit and Recieve Configuration 5 Register */ | ||
72 | #define FSL_SAI_TCR5 0x14 | ||
73 | #define FSL_SAI_RCR5 0x94 | ||
74 | #define FSL_SAI_CR5_WNW(x) (((x) - 1) << 24) | ||
75 | #define FSL_SAI_CR5_WNW_MASK (0x1f << 24) | ||
76 | #define FSL_SAI_CR5_W0W(x) (((x) - 1) << 16) | ||
77 | #define FSL_SAI_CR5_W0W_MASK (0x1f << 16) | ||
78 | #define FSL_SAI_CR5_FBT(x) ((x) << 8) | ||
79 | #define FSL_SAI_CR5_FBT_MASK (0x1f << 8) | ||
80 | |||
81 | /* SAI type */ | ||
82 | #define FSL_SAI_DMA BIT(0) | ||
83 | #define FSL_SAI_USE_AC97 BIT(1) | ||
84 | #define FSL_SAI_NET BIT(2) | ||
85 | #define FSL_SAI_TRA_SYN BIT(3) | ||
86 | #define FSL_SAI_REC_SYN BIT(4) | ||
87 | #define FSL_SAI_USE_I2S_SLAVE BIT(5) | ||
88 | |||
89 | #define FSL_FMT_TRANSMITTER 0 | ||
90 | #define FSL_FMT_RECEIVER 1 | ||
91 | |||
92 | /* SAI clock sources */ | ||
93 | #define FSL_SAI_CLK_BUS 0 | ||
94 | #define FSL_SAI_CLK_MAST1 1 | ||
95 | #define FSL_SAI_CLK_MAST2 2 | ||
96 | #define FSL_SAI_CLK_MAST3 3 | ||
97 | |||
98 | /* SAI data transfer numbers per DMA request */ | ||
99 | #define FSL_SAI_MAXBURST_TX 6 | ||
100 | #define FSL_SAI_MAXBURST_RX 6 | ||
101 | |||
102 | struct fsl_sai { | ||
103 | struct clk *clk; | ||
104 | |||
105 | void __iomem *base; | ||
106 | |||
107 | bool big_endian_regs; | ||
108 | bool big_endian_data; | ||
109 | |||
110 | struct snd_dmaengine_dai_dma_data dma_params_rx; | ||
111 | struct snd_dmaengine_dai_dma_data dma_params_tx; | ||
112 | }; | ||
113 | |||
114 | #endif /* __FSL_SAI_H */ | ||
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 55193a5596ca..4d075f1abe78 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -1181,13 +1181,6 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
1181 | return ret; | 1181 | return ret; |
1182 | } | 1182 | } |
1183 | 1183 | ||
1184 | static int fsl_spdif_remove(struct platform_device *pdev) | ||
1185 | { | ||
1186 | imx_pcm_dma_exit(pdev); | ||
1187 | |||
1188 | return 0; | ||
1189 | } | ||
1190 | |||
1191 | static const struct of_device_id fsl_spdif_dt_ids[] = { | 1184 | static const struct of_device_id fsl_spdif_dt_ids[] = { |
1192 | { .compatible = "fsl,imx35-spdif", }, | 1185 | { .compatible = "fsl,imx35-spdif", }, |
1193 | {} | 1186 | {} |
@@ -1201,7 +1194,6 @@ static struct platform_driver fsl_spdif_driver = { | |||
1201 | .of_match_table = fsl_spdif_dt_ids, | 1194 | .of_match_table = fsl_spdif_dt_ids, |
1202 | }, | 1195 | }, |
1203 | .probe = fsl_spdif_probe, | 1196 | .probe = fsl_spdif_probe, |
1204 | .remove = fsl_spdif_remove, | ||
1205 | }; | 1197 | }; |
1206 | 1198 | ||
1207 | module_platform_driver(fsl_spdif_driver); | 1199 | module_platform_driver(fsl_spdif_driver); |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 35e277379b86..b2ebaf811599 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/device.h> | 38 | #include <linux/device.h> |
39 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <linux/spinlock.h> | ||
41 | #include <linux/of_address.h> | 42 | #include <linux/of_address.h> |
42 | #include <linux/of_irq.h> | 43 | #include <linux/of_irq.h> |
43 | #include <linux/of_platform.h> | 44 | #include <linux/of_platform.h> |
@@ -119,8 +120,6 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set) | |||
119 | * @ssi: pointer to the SSI's registers | 120 | * @ssi: pointer to the SSI's registers |
120 | * @ssi_phys: physical address of the SSI registers | 121 | * @ssi_phys: physical address of the SSI registers |
121 | * @irq: IRQ of this SSI | 122 | * @irq: IRQ of this SSI |
122 | * @first_stream: pointer to the stream that was opened first | ||
123 | * @second_stream: pointer to second stream | ||
124 | * @playback: the number of playback streams opened | 123 | * @playback: the number of playback streams opened |
125 | * @capture: the number of capture streams opened | 124 | * @capture: the number of capture streams opened |
126 | * @cpu_dai: the CPU DAI for this device | 125 | * @cpu_dai: the CPU DAI for this device |
@@ -132,8 +131,6 @@ struct fsl_ssi_private { | |||
132 | struct ccsr_ssi __iomem *ssi; | 131 | struct ccsr_ssi __iomem *ssi; |
133 | dma_addr_t ssi_phys; | 132 | dma_addr_t ssi_phys; |
134 | unsigned int irq; | 133 | unsigned int irq; |
135 | struct snd_pcm_substream *first_stream; | ||
136 | struct snd_pcm_substream *second_stream; | ||
137 | unsigned int fifo_depth; | 134 | unsigned int fifo_depth; |
138 | struct snd_soc_dai_driver cpu_dai_drv; | 135 | struct snd_soc_dai_driver cpu_dai_drv; |
139 | struct device_attribute dev_attr; | 136 | struct device_attribute dev_attr; |
@@ -143,6 +140,10 @@ struct fsl_ssi_private { | |||
143 | bool ssi_on_imx; | 140 | bool ssi_on_imx; |
144 | bool imx_ac97; | 141 | bool imx_ac97; |
145 | bool use_dma; | 142 | bool use_dma; |
143 | bool baudclk_locked; | ||
144 | u8 i2s_mode; | ||
145 | spinlock_t baudclk_lock; | ||
146 | struct clk *baudclk; | ||
146 | struct clk *clk; | 147 | struct clk *clk; |
147 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 148 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
148 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 149 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
@@ -321,17 +322,46 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
321 | return ret; | 322 | return ret; |
322 | } | 323 | } |
323 | 324 | ||
325 | static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) | ||
326 | { | ||
327 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
328 | |||
329 | /* | ||
330 | * Setup the clock control register | ||
331 | */ | ||
332 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
333 | &ssi->stccr); | ||
334 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
335 | &ssi->srccr); | ||
336 | |||
337 | /* | ||
338 | * Enable AC97 mode and startup the SSI | ||
339 | */ | ||
340 | write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV, | ||
341 | &ssi->sacnt); | ||
342 | write_ssi(0xff, &ssi->saccdis); | ||
343 | write_ssi(0x300, &ssi->saccen); | ||
344 | |||
345 | /* | ||
346 | * Enable SSI, Transmit and Receive. AC97 has to communicate with the | ||
347 | * codec before a stream is started. | ||
348 | */ | ||
349 | write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN | | ||
350 | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE); | ||
351 | |||
352 | write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor); | ||
353 | } | ||
354 | |||
324 | static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) | 355 | static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) |
325 | { | 356 | { |
326 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 357 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
327 | u8 i2s_mode; | ||
328 | u8 wm; | 358 | u8 wm; |
329 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; | 359 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; |
330 | 360 | ||
331 | if (ssi_private->imx_ac97) | 361 | if (ssi_private->imx_ac97) |
332 | i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; | 362 | ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; |
333 | else | 363 | else |
334 | i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; | 364 | ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; |
335 | 365 | ||
336 | /* | 366 | /* |
337 | * Section 16.5 of the MPC8610 reference manual says that the SSI needs | 367 | * Section 16.5 of the MPC8610 reference manual says that the SSI needs |
@@ -348,7 +378,7 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) | |||
348 | write_ssi_mask(&ssi->scr, | 378 | write_ssi_mask(&ssi->scr, |
349 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, | 379 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, |
350 | CCSR_SSI_SCR_TFR_CLK_DIS | | 380 | CCSR_SSI_SCR_TFR_CLK_DIS | |
351 | i2s_mode | | 381 | ssi_private->i2s_mode | |
352 | (synchronous ? CCSR_SSI_SCR_SYN : 0)); | 382 | (synchronous ? CCSR_SSI_SCR_SYN : 0)); |
353 | 383 | ||
354 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | | 384 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | |
@@ -387,31 +417,8 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) | |||
387 | * because it is also running without an active substream. Normally SSI | 417 | * because it is also running without an active substream. Normally SSI |
388 | * is only enabled when there is a substream. | 418 | * is only enabled when there is a substream. |
389 | */ | 419 | */ |
390 | if (ssi_private->imx_ac97) { | 420 | if (ssi_private->imx_ac97) |
391 | /* | 421 | fsl_ssi_setup_ac97(ssi_private); |
392 | * Setup the clock control register | ||
393 | */ | ||
394 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
395 | &ssi->stccr); | ||
396 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
397 | &ssi->srccr); | ||
398 | |||
399 | /* | ||
400 | * Enable AC97 mode and startup the SSI | ||
401 | */ | ||
402 | write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV, | ||
403 | &ssi->sacnt); | ||
404 | write_ssi(0xff, &ssi->saccdis); | ||
405 | write_ssi(0x300, &ssi->saccen); | ||
406 | |||
407 | /* | ||
408 | * Enable SSI, Transmit and Receive | ||
409 | */ | ||
410 | write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN | | ||
411 | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE); | ||
412 | |||
413 | write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor); | ||
414 | } | ||
415 | 422 | ||
416 | return 0; | 423 | return 0; |
417 | } | 424 | } |
@@ -431,53 +438,17 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
431 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 438 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
432 | struct fsl_ssi_private *ssi_private = | 439 | struct fsl_ssi_private *ssi_private = |
433 | snd_soc_dai_get_drvdata(rtd->cpu_dai); | 440 | snd_soc_dai_get_drvdata(rtd->cpu_dai); |
434 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; | 441 | unsigned long flags; |
435 | 442 | ||
436 | /* | 443 | /* First, we only do fsl_ssi_setup() when SSI is going to be active. |
437 | * If this is the first stream opened, then request the IRQ | 444 | * Second, fsl_ssi_setup was already called by ac97_init earlier if |
438 | * and initialize the SSI registers. | 445 | * the driver is in ac97 mode. |
439 | */ | 446 | */ |
440 | if (!ssi_private->first_stream) { | 447 | if (!dai->active && !ssi_private->imx_ac97) { |
441 | ssi_private->first_stream = substream; | 448 | fsl_ssi_setup(ssi_private); |
442 | 449 | spin_lock_irqsave(&ssi_private->baudclk_lock, flags); | |
443 | /* | 450 | ssi_private->baudclk_locked = false; |
444 | * fsl_ssi_setup was already called by ac97_init earlier if | 451 | spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); |
445 | * the driver is in ac97 mode. | ||
446 | */ | ||
447 | if (!ssi_private->imx_ac97) | ||
448 | fsl_ssi_setup(ssi_private); | ||
449 | } else { | ||
450 | if (synchronous) { | ||
451 | struct snd_pcm_runtime *first_runtime = | ||
452 | ssi_private->first_stream->runtime; | ||
453 | /* | ||
454 | * This is the second stream open, and we're in | ||
455 | * synchronous mode, so we need to impose sample | ||
456 | * sample size constraints. This is because STCCR is | ||
457 | * used for playback and capture in synchronous mode, | ||
458 | * so there's no way to specify different word | ||
459 | * lengths. | ||
460 | * | ||
461 | * Note that this can cause a race condition if the | ||
462 | * second stream is opened before the first stream is | ||
463 | * fully initialized. We provide some protection by | ||
464 | * checking to make sure the first stream is | ||
465 | * initialized, but it's not perfect. ALSA sometimes | ||
466 | * re-initializes the driver with a different sample | ||
467 | * rate or size. If the second stream is opened | ||
468 | * before the first stream has received its final | ||
469 | * parameters, then the second stream may be | ||
470 | * constrained to the wrong sample rate or size. | ||
471 | */ | ||
472 | if (first_runtime->sample_bits) { | ||
473 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
474 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | ||
475 | first_runtime->sample_bits, | ||
476 | first_runtime->sample_bits); | ||
477 | } | ||
478 | } | ||
479 | |||
480 | ssi_private->second_stream = substream; | ||
481 | } | 452 | } |
482 | 453 | ||
483 | return 0; | 454 | return 0; |
@@ -501,6 +472,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | |||
501 | { | 472 | { |
502 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); | 473 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); |
503 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 474 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
475 | unsigned int channels = params_channels(hw_params); | ||
504 | unsigned int sample_size = | 476 | unsigned int sample_size = |
505 | snd_pcm_format_width(params_format(hw_params)); | 477 | snd_pcm_format_width(params_format(hw_params)); |
506 | u32 wl = CCSR_SSI_SxCCR_WL(sample_size); | 478 | u32 wl = CCSR_SSI_SxCCR_WL(sample_size); |
@@ -530,6 +502,248 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | |||
530 | else | 502 | else |
531 | write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); | 503 | write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); |
532 | 504 | ||
505 | if (!ssi_private->imx_ac97) | ||
506 | write_ssi_mask(&ssi->scr, | ||
507 | CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK, | ||
508 | channels == 1 ? 0 : ssi_private->i2s_mode); | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | /** | ||
514 | * fsl_ssi_set_dai_fmt - configure Digital Audio Interface Format. | ||
515 | */ | ||
516 | static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | ||
517 | { | ||
518 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); | ||
519 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
520 | u32 strcr = 0, stcr, srcr, scr, mask; | ||
521 | |||
522 | scr = read_ssi(&ssi->scr) & ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK); | ||
523 | scr |= CCSR_SSI_SCR_NET; | ||
524 | |||
525 | mask = CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR | | ||
526 | CCSR_SSI_STCR_TSCKP | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TFSL | | ||
527 | CCSR_SSI_STCR_TEFS; | ||
528 | stcr = read_ssi(&ssi->stcr) & ~mask; | ||
529 | srcr = read_ssi(&ssi->srcr) & ~mask; | ||
530 | |||
531 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
532 | case SND_SOC_DAIFMT_I2S: | ||
533 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
534 | case SND_SOC_DAIFMT_CBS_CFS: | ||
535 | ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_MASTER; | ||
536 | break; | ||
537 | case SND_SOC_DAIFMT_CBM_CFM: | ||
538 | ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; | ||
539 | break; | ||
540 | default: | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | scr |= ssi_private->i2s_mode; | ||
544 | |||
545 | /* Data on rising edge of bclk, frame low, 1clk before data */ | ||
546 | strcr |= CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TSCKP | | ||
547 | CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS; | ||
548 | break; | ||
549 | case SND_SOC_DAIFMT_LEFT_J: | ||
550 | /* Data on rising edge of bclk, frame high */ | ||
551 | strcr |= CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TSCKP; | ||
552 | break; | ||
553 | case SND_SOC_DAIFMT_DSP_A: | ||
554 | /* Data on rising edge of bclk, frame high, 1clk before data */ | ||
555 | strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP | | ||
556 | CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS; | ||
557 | break; | ||
558 | case SND_SOC_DAIFMT_DSP_B: | ||
559 | /* Data on rising edge of bclk, frame high */ | ||
560 | strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP | | ||
561 | CCSR_SSI_STCR_TXBIT0; | ||
562 | break; | ||
563 | default: | ||
564 | return -EINVAL; | ||
565 | } | ||
566 | |||
567 | /* DAI clock inversion */ | ||
568 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
569 | case SND_SOC_DAIFMT_NB_NF: | ||
570 | /* Nothing to do for both normal cases */ | ||
571 | break; | ||
572 | case SND_SOC_DAIFMT_IB_NF: | ||
573 | /* Invert bit clock */ | ||
574 | strcr ^= CCSR_SSI_STCR_TSCKP; | ||
575 | break; | ||
576 | case SND_SOC_DAIFMT_NB_IF: | ||
577 | /* Invert frame clock */ | ||
578 | strcr ^= CCSR_SSI_STCR_TFSI; | ||
579 | break; | ||
580 | case SND_SOC_DAIFMT_IB_IF: | ||
581 | /* Invert both clocks */ | ||
582 | strcr ^= CCSR_SSI_STCR_TSCKP; | ||
583 | strcr ^= CCSR_SSI_STCR_TFSI; | ||
584 | break; | ||
585 | default: | ||
586 | return -EINVAL; | ||
587 | } | ||
588 | |||
589 | /* DAI clock master masks */ | ||
590 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
591 | case SND_SOC_DAIFMT_CBS_CFS: | ||
592 | strcr |= CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR; | ||
593 | scr |= CCSR_SSI_SCR_SYS_CLK_EN; | ||
594 | break; | ||
595 | case SND_SOC_DAIFMT_CBM_CFM: | ||
596 | scr &= ~CCSR_SSI_SCR_SYS_CLK_EN; | ||
597 | break; | ||
598 | default: | ||
599 | return -EINVAL; | ||
600 | } | ||
601 | |||
602 | stcr |= strcr; | ||
603 | srcr |= strcr; | ||
604 | |||
605 | if (ssi_private->cpu_dai_drv.symmetric_rates) { | ||
606 | /* Need to clear RXDIR when using SYNC mode */ | ||
607 | srcr &= ~CCSR_SSI_SRCR_RXDIR; | ||
608 | scr |= CCSR_SSI_SCR_SYN; | ||
609 | } | ||
610 | |||
611 | write_ssi(stcr, &ssi->stcr); | ||
612 | write_ssi(srcr, &ssi->srcr); | ||
613 | write_ssi(scr, &ssi->scr); | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | /** | ||
619 | * fsl_ssi_set_dai_sysclk - configure Digital Audio Interface bit clock | ||
620 | * | ||
621 | * Note: This function can be only called when using SSI as DAI master | ||
622 | * | ||
623 | * Quick instruction for parameters: | ||
624 | * freq: Output BCLK frequency = samplerate * 32 (fixed) * channels | ||
625 | * dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK. | ||
626 | */ | ||
627 | static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | ||
628 | int clk_id, unsigned int freq, int dir) | ||
629 | { | ||
630 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); | ||
631 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
632 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret; | ||
633 | u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i; | ||
634 | unsigned long flags, clkrate, baudrate, tmprate; | ||
635 | u64 sub, savesub = 100000; | ||
636 | |||
637 | /* Don't apply it to any non-baudclk circumstance */ | ||
638 | if (IS_ERR(ssi_private->baudclk)) | ||
639 | return -EINVAL; | ||
640 | |||
641 | /* It should be already enough to divide clock by setting pm alone */ | ||
642 | psr = 0; | ||
643 | div2 = 0; | ||
644 | |||
645 | factor = (div2 + 1) * (7 * psr + 1) * 2; | ||
646 | |||
647 | for (i = 0; i < 255; i++) { | ||
648 | /* The bclk rate must be smaller than 1/5 sysclk rate */ | ||
649 | if (factor * (i + 1) < 5) | ||
650 | continue; | ||
651 | |||
652 | tmprate = freq * factor * (i + 2); | ||
653 | clkrate = clk_round_rate(ssi_private->baudclk, tmprate); | ||
654 | |||
655 | do_div(clkrate, factor); | ||
656 | afreq = (u32)clkrate / (i + 1); | ||
657 | |||
658 | if (freq == afreq) | ||
659 | sub = 0; | ||
660 | else if (freq / afreq == 1) | ||
661 | sub = freq - afreq; | ||
662 | else if (afreq / freq == 1) | ||
663 | sub = afreq - freq; | ||
664 | else | ||
665 | continue; | ||
666 | |||
667 | /* Calculate the fraction */ | ||
668 | sub *= 100000; | ||
669 | do_div(sub, freq); | ||
670 | |||
671 | if (sub < savesub) { | ||
672 | baudrate = tmprate; | ||
673 | savesub = sub; | ||
674 | pm = i; | ||
675 | } | ||
676 | |||
677 | /* We are lucky */ | ||
678 | if (savesub == 0) | ||
679 | break; | ||
680 | } | ||
681 | |||
682 | /* No proper pm found if it is still remaining the initial value */ | ||
683 | if (pm == 999) { | ||
684 | dev_err(cpu_dai->dev, "failed to handle the required sysclk\n"); | ||
685 | return -EINVAL; | ||
686 | } | ||
687 | |||
688 | stccr = CCSR_SSI_SxCCR_PM(pm + 1) | (div2 ? CCSR_SSI_SxCCR_DIV2 : 0) | | ||
689 | (psr ? CCSR_SSI_SxCCR_PSR : 0); | ||
690 | mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 | CCSR_SSI_SxCCR_PSR; | ||
691 | |||
692 | if (dir == SND_SOC_CLOCK_OUT || synchronous) | ||
693 | write_ssi_mask(&ssi->stccr, mask, stccr); | ||
694 | else | ||
695 | write_ssi_mask(&ssi->srccr, mask, stccr); | ||
696 | |||
697 | spin_lock_irqsave(&ssi_private->baudclk_lock, flags); | ||
698 | if (!ssi_private->baudclk_locked) { | ||
699 | ret = clk_set_rate(ssi_private->baudclk, baudrate); | ||
700 | if (ret) { | ||
701 | spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); | ||
702 | dev_err(cpu_dai->dev, "failed to set baudclk rate\n"); | ||
703 | return -EINVAL; | ||
704 | } | ||
705 | ssi_private->baudclk_locked = true; | ||
706 | } | ||
707 | spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); | ||
708 | |||
709 | return 0; | ||
710 | } | ||
711 | |||
712 | /** | ||
713 | * fsl_ssi_set_dai_tdm_slot - set TDM slot number | ||
714 | * | ||
715 | * Note: This function can be only called when using SSI as DAI master | ||
716 | */ | ||
717 | static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask, | ||
718 | u32 rx_mask, int slots, int slot_width) | ||
719 | { | ||
720 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); | ||
721 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
722 | u32 val; | ||
723 | |||
724 | /* The slot number should be >= 2 if using Network mode or I2S mode */ | ||
725 | val = read_ssi(&ssi->scr) & (CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET); | ||
726 | if (val && slots < 2) { | ||
727 | dev_err(cpu_dai->dev, "slot number should be >= 2 in I2S or NET\n"); | ||
728 | return -EINVAL; | ||
729 | } | ||
730 | |||
731 | write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK, | ||
732 | CCSR_SSI_SxCCR_DC(slots)); | ||
733 | write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK, | ||
734 | CCSR_SSI_SxCCR_DC(slots)); | ||
735 | |||
736 | /* The register SxMSKs needs SSI to provide essential clock due to | ||
737 | * hardware design. So we here temporarily enable SSI to set them. | ||
738 | */ | ||
739 | val = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN; | ||
740 | write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN); | ||
741 | |||
742 | write_ssi(tx_mask, &ssi->stmsk); | ||
743 | write_ssi(rx_mask, &ssi->srmsk); | ||
744 | |||
745 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, val); | ||
746 | |||
533 | return 0; | 747 | return 0; |
534 | } | 748 | } |
535 | 749 | ||
@@ -549,6 +763,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
549 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 763 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
550 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 764 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
551 | unsigned int sier_bits; | 765 | unsigned int sier_bits; |
766 | unsigned long flags; | ||
552 | 767 | ||
553 | /* | 768 | /* |
554 | * Enable only the interrupts and DMA requests | 769 | * Enable only the interrupts and DMA requests |
@@ -589,8 +804,12 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
589 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); | 804 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); |
590 | 805 | ||
591 | if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & | 806 | if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & |
592 | (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) | 807 | (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) { |
593 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | 808 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); |
809 | spin_lock_irqsave(&ssi_private->baudclk_lock, flags); | ||
810 | ssi_private->baudclk_locked = false; | ||
811 | spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); | ||
812 | } | ||
594 | break; | 813 | break; |
595 | 814 | ||
596 | default: | 815 | default: |
@@ -602,23 +821,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
602 | return 0; | 821 | return 0; |
603 | } | 822 | } |
604 | 823 | ||
605 | /** | ||
606 | * fsl_ssi_shutdown: shutdown the SSI | ||
607 | * | ||
608 | * Shutdown the SSI if there are no other substreams open. | ||
609 | */ | ||
610 | static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, | ||
611 | struct snd_soc_dai *dai) | ||
612 | { | ||
613 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
614 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
615 | |||
616 | if (ssi_private->first_stream == substream) | ||
617 | ssi_private->first_stream = ssi_private->second_stream; | ||
618 | |||
619 | ssi_private->second_stream = NULL; | ||
620 | } | ||
621 | |||
622 | static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) | 824 | static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) |
623 | { | 825 | { |
624 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); | 826 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); |
@@ -634,7 +836,9 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) | |||
634 | static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { | 836 | static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { |
635 | .startup = fsl_ssi_startup, | 837 | .startup = fsl_ssi_startup, |
636 | .hw_params = fsl_ssi_hw_params, | 838 | .hw_params = fsl_ssi_hw_params, |
637 | .shutdown = fsl_ssi_shutdown, | 839 | .set_fmt = fsl_ssi_set_dai_fmt, |
840 | .set_sysclk = fsl_ssi_set_dai_sysclk, | ||
841 | .set_tdm_slot = fsl_ssi_set_dai_tdm_slot, | ||
638 | .trigger = fsl_ssi_trigger, | 842 | .trigger = fsl_ssi_trigger, |
639 | }; | 843 | }; |
640 | 844 | ||
@@ -642,14 +846,13 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { | |||
642 | static struct snd_soc_dai_driver fsl_ssi_dai_template = { | 846 | static struct snd_soc_dai_driver fsl_ssi_dai_template = { |
643 | .probe = fsl_ssi_dai_probe, | 847 | .probe = fsl_ssi_dai_probe, |
644 | .playback = { | 848 | .playback = { |
645 | /* The SSI does not support monaural audio. */ | 849 | .channels_min = 1, |
646 | .channels_min = 2, | ||
647 | .channels_max = 2, | 850 | .channels_max = 2, |
648 | .rates = FSLSSI_I2S_RATES, | 851 | .rates = FSLSSI_I2S_RATES, |
649 | .formats = FSLSSI_I2S_FORMATS, | 852 | .formats = FSLSSI_I2S_FORMATS, |
650 | }, | 853 | }, |
651 | .capture = { | 854 | .capture = { |
652 | .channels_min = 2, | 855 | .channels_min = 1, |
653 | .channels_max = 2, | 856 | .channels_max = 2, |
654 | .rates = FSLSSI_I2S_RATES, | 857 | .rates = FSLSSI_I2S_RATES, |
655 | .formats = FSLSSI_I2S_FORMATS, | 858 | .formats = FSLSSI_I2S_FORMATS, |
@@ -710,7 +913,6 @@ static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
710 | 913 | ||
711 | static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { | 914 | static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { |
712 | .startup = fsl_ssi_startup, | 915 | .startup = fsl_ssi_startup, |
713 | .shutdown = fsl_ssi_shutdown, | ||
714 | .trigger = fsl_ssi_ac97_trigger, | 916 | .trigger = fsl_ssi_ac97_trigger, |
715 | }; | 917 | }; |
716 | 918 | ||
@@ -935,8 +1137,11 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
935 | } | 1137 | } |
936 | 1138 | ||
937 | /* Are the RX and the TX clocks locked? */ | 1139 | /* Are the RX and the TX clocks locked? */ |
938 | if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) | 1140 | if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) { |
939 | ssi_private->cpu_dai_drv.symmetric_rates = 1; | 1141 | ssi_private->cpu_dai_drv.symmetric_rates = 1; |
1142 | ssi_private->cpu_dai_drv.symmetric_channels = 1; | ||
1143 | ssi_private->cpu_dai_drv.symmetric_samplebits = 1; | ||
1144 | } | ||
940 | 1145 | ||
941 | /* Determine the FIFO depth. */ | 1146 | /* Determine the FIFO depth. */ |
942 | iprop = of_get_property(np, "fsl,fifo-depth", NULL); | 1147 | iprop = of_get_property(np, "fsl,fifo-depth", NULL); |
@@ -946,6 +1151,9 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
946 | /* Older 8610 DTs didn't have the fifo-depth property */ | 1151 | /* Older 8610 DTs didn't have the fifo-depth property */ |
947 | ssi_private->fifo_depth = 8; | 1152 | ssi_private->fifo_depth = 8; |
948 | 1153 | ||
1154 | ssi_private->baudclk_locked = false; | ||
1155 | spin_lock_init(&ssi_private->baudclk_lock); | ||
1156 | |||
949 | if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) { | 1157 | if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) { |
950 | u32 dma_events[2]; | 1158 | u32 dma_events[2]; |
951 | ssi_private->ssi_on_imx = true; | 1159 | ssi_private->ssi_on_imx = true; |
@@ -963,6 +1171,15 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
963 | goto error_irqmap; | 1171 | goto error_irqmap; |
964 | } | 1172 | } |
965 | 1173 | ||
1174 | /* For those SLAVE implementations, we ingore non-baudclk cases | ||
1175 | * and, instead, abandon MASTER mode that needs baud clock. | ||
1176 | */ | ||
1177 | ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud"); | ||
1178 | if (IS_ERR(ssi_private->baudclk)) | ||
1179 | dev_warn(&pdev->dev, "could not get baud clock: %d\n", ret); | ||
1180 | else | ||
1181 | clk_prepare_enable(ssi_private->baudclk); | ||
1182 | |||
966 | /* | 1183 | /* |
967 | * We have burstsize be "fifo_depth - 2" to match the SSI | 1184 | * We have burstsize be "fifo_depth - 2" to match the SSI |
968 | * watermark setting in fsl_ssi_startup(). | 1185 | * watermark setting in fsl_ssi_startup(). |
@@ -1102,16 +1319,17 @@ done: | |||
1102 | return 0; | 1319 | return 0; |
1103 | 1320 | ||
1104 | error_dai: | 1321 | error_dai: |
1105 | if (ssi_private->ssi_on_imx) | ||
1106 | imx_pcm_dma_exit(pdev); | ||
1107 | snd_soc_unregister_component(&pdev->dev); | 1322 | snd_soc_unregister_component(&pdev->dev); |
1108 | 1323 | ||
1109 | error_dev: | 1324 | error_dev: |
1110 | device_remove_file(&pdev->dev, dev_attr); | 1325 | device_remove_file(&pdev->dev, dev_attr); |
1111 | 1326 | ||
1112 | error_clk: | 1327 | error_clk: |
1113 | if (ssi_private->ssi_on_imx) | 1328 | if (ssi_private->ssi_on_imx) { |
1329 | if (!IS_ERR(ssi_private->baudclk)) | ||
1330 | clk_disable_unprepare(ssi_private->baudclk); | ||
1114 | clk_disable_unprepare(ssi_private->clk); | 1331 | clk_disable_unprepare(ssi_private->clk); |
1332 | } | ||
1115 | 1333 | ||
1116 | error_irqmap: | 1334 | error_irqmap: |
1117 | irq_dispose_mapping(ssi_private->irq); | 1335 | irq_dispose_mapping(ssi_private->irq); |
@@ -1125,12 +1343,13 @@ static int fsl_ssi_remove(struct platform_device *pdev) | |||
1125 | 1343 | ||
1126 | if (!ssi_private->new_binding) | 1344 | if (!ssi_private->new_binding) |
1127 | platform_device_unregister(ssi_private->pdev); | 1345 | platform_device_unregister(ssi_private->pdev); |
1128 | if (ssi_private->ssi_on_imx) | ||
1129 | imx_pcm_dma_exit(pdev); | ||
1130 | snd_soc_unregister_component(&pdev->dev); | 1346 | snd_soc_unregister_component(&pdev->dev); |
1131 | device_remove_file(&pdev->dev, &ssi_private->dev_attr); | 1347 | device_remove_file(&pdev->dev, &ssi_private->dev_attr); |
1132 | if (ssi_private->ssi_on_imx) | 1348 | if (ssi_private->ssi_on_imx) { |
1349 | if (!IS_ERR(ssi_private->baudclk)) | ||
1350 | clk_disable_unprepare(ssi_private->baudclk); | ||
1133 | clk_disable_unprepare(ssi_private->clk); | 1351 | clk_disable_unprepare(ssi_private->clk); |
1352 | } | ||
1134 | irq_dispose_mapping(ssi_private->irq); | 1353 | irq_dispose_mapping(ssi_private->irq); |
1135 | 1354 | ||
1136 | return 0; | 1355 | return 0; |
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h index e6b9a69e2a68..e6b63240a3d7 100644 --- a/sound/soc/fsl/fsl_ssi.h +++ b/sound/soc/fsl/fsl_ssi.h | |||
@@ -125,7 +125,9 @@ struct ccsr_ssi { | |||
125 | #define CCSR_SSI_SRCR_REFS 0x00000001 | 125 | #define CCSR_SSI_SRCR_REFS 0x00000001 |
126 | 126 | ||
127 | /* STCCR and SRCCR */ | 127 | /* STCCR and SRCCR */ |
128 | #define CCSR_SSI_SxCCR_DIV2_SHIFT 18 | ||
128 | #define CCSR_SSI_SxCCR_DIV2 0x00040000 | 129 | #define CCSR_SSI_SxCCR_DIV2 0x00040000 |
130 | #define CCSR_SSI_SxCCR_PSR_SHIFT 17 | ||
129 | #define CCSR_SSI_SxCCR_PSR 0x00020000 | 131 | #define CCSR_SSI_SxCCR_PSR 0x00020000 |
130 | #define CCSR_SSI_SxCCR_WL_SHIFT 13 | 132 | #define CCSR_SSI_SxCCR_WL_SHIFT 13 |
131 | #define CCSR_SSI_SxCCR_WL_MASK 0x0001E000 | 133 | #define CCSR_SSI_SxCCR_WL_MASK 0x0001E000 |
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index aee23077080a..c5e47f866b4b 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c | |||
@@ -61,16 +61,11 @@ static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = { | |||
61 | 61 | ||
62 | int imx_pcm_dma_init(struct platform_device *pdev) | 62 | int imx_pcm_dma_init(struct platform_device *pdev) |
63 | { | 63 | { |
64 | return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config, | 64 | return devm_snd_dmaengine_pcm_register(&pdev->dev, |
65 | &imx_dmaengine_pcm_config, | ||
65 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | 66 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | |
66 | SND_DMAENGINE_PCM_FLAG_COMPAT); | 67 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
67 | } | 68 | } |
68 | EXPORT_SYMBOL_GPL(imx_pcm_dma_init); | 69 | EXPORT_SYMBOL_GPL(imx_pcm_dma_init); |
69 | 70 | ||
70 | void imx_pcm_dma_exit(struct platform_device *pdev) | ||
71 | { | ||
72 | snd_dmaengine_pcm_unregister(&pdev->dev); | ||
73 | } | ||
74 | EXPORT_SYMBOL_GPL(imx_pcm_dma_exit); | ||
75 | |||
76 | MODULE_LICENSE("GPL"); | 71 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h index 5d5b73303e11..c79cb27473be 100644 --- a/sound/soc/fsl/imx-pcm.h +++ b/sound/soc/fsl/imx-pcm.h | |||
@@ -40,16 +40,11 @@ struct imx_pcm_fiq_params { | |||
40 | 40 | ||
41 | #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA) | 41 | #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA) |
42 | int imx_pcm_dma_init(struct platform_device *pdev); | 42 | int imx_pcm_dma_init(struct platform_device *pdev); |
43 | void imx_pcm_dma_exit(struct platform_device *pdev); | ||
44 | #else | 43 | #else |
45 | static inline int imx_pcm_dma_init(struct platform_device *pdev) | 44 | static inline int imx_pcm_dma_init(struct platform_device *pdev) |
46 | { | 45 | { |
47 | return -ENODEV; | 46 | return -ENODEV; |
48 | } | 47 | } |
49 | |||
50 | static inline void imx_pcm_dma_exit(struct platform_device *pdev) | ||
51 | { | ||
52 | } | ||
53 | #endif | 48 | #endif |
54 | 49 | ||
55 | #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_FIQ) | 50 | #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_FIQ) |
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 8499d5292f08..e1dc40143600 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c | |||
@@ -14,17 +14,15 @@ | |||
14 | #include <sound/soc.h> | 14 | #include <sound/soc.h> |
15 | 15 | ||
16 | struct imx_spdif_data { | 16 | struct imx_spdif_data { |
17 | struct snd_soc_dai_link dai[2]; | 17 | struct snd_soc_dai_link dai; |
18 | struct snd_soc_card card; | 18 | struct snd_soc_card card; |
19 | struct platform_device *txdev; | ||
20 | struct platform_device *rxdev; | ||
21 | }; | 19 | }; |
22 | 20 | ||
23 | static int imx_spdif_audio_probe(struct platform_device *pdev) | 21 | static int imx_spdif_audio_probe(struct platform_device *pdev) |
24 | { | 22 | { |
25 | struct device_node *spdif_np, *np = pdev->dev.of_node; | 23 | struct device_node *spdif_np, *np = pdev->dev.of_node; |
26 | struct imx_spdif_data *data; | 24 | struct imx_spdif_data *data; |
27 | int ret = 0, num_links = 0; | 25 | int ret = 0; |
28 | 26 | ||
29 | spdif_np = of_parse_phandle(np, "spdif-controller", 0); | 27 | spdif_np = of_parse_phandle(np, "spdif-controller", 0); |
30 | if (!spdif_np) { | 28 | if (!spdif_np) { |
@@ -35,74 +33,46 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) | |||
35 | 33 | ||
36 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | 34 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); |
37 | if (!data) { | 35 | if (!data) { |
38 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
39 | ret = -ENOMEM; | 36 | ret = -ENOMEM; |
40 | goto end; | 37 | goto end; |
41 | } | 38 | } |
42 | 39 | ||
43 | if (of_property_read_bool(np, "spdif-out")) { | 40 | data->dai.name = "S/PDIF PCM"; |
44 | data->dai[num_links].name = "S/PDIF TX"; | 41 | data->dai.stream_name = "S/PDIF PCM"; |
45 | data->dai[num_links].stream_name = "S/PDIF PCM Playback"; | 42 | data->dai.codec_dai_name = "snd-soc-dummy-dai"; |
46 | data->dai[num_links].codec_dai_name = "dit-hifi"; | 43 | data->dai.codec_name = "snd-soc-dummy"; |
47 | data->dai[num_links].codec_name = "spdif-dit"; | 44 | data->dai.cpu_of_node = spdif_np; |
48 | data->dai[num_links].cpu_of_node = spdif_np; | 45 | data->dai.platform_of_node = spdif_np; |
49 | data->dai[num_links].platform_of_node = spdif_np; | 46 | data->dai.playback_only = true; |
50 | num_links++; | 47 | data->dai.capture_only = true; |
51 | |||
52 | data->txdev = platform_device_register_simple("spdif-dit", -1, NULL, 0); | ||
53 | if (IS_ERR(data->txdev)) { | ||
54 | ret = PTR_ERR(data->txdev); | ||
55 | dev_err(&pdev->dev, "register dit failed: %d\n", ret); | ||
56 | goto end; | ||
57 | } | ||
58 | } | ||
59 | 48 | ||
60 | if (of_property_read_bool(np, "spdif-in")) { | 49 | if (of_property_read_bool(np, "spdif-out")) |
61 | data->dai[num_links].name = "S/PDIF RX"; | 50 | data->dai.capture_only = false; |
62 | data->dai[num_links].stream_name = "S/PDIF PCM Capture"; | 51 | |
63 | data->dai[num_links].codec_dai_name = "dir-hifi"; | 52 | if (of_property_read_bool(np, "spdif-in")) |
64 | data->dai[num_links].codec_name = "spdif-dir"; | 53 | data->dai.playback_only = false; |
65 | data->dai[num_links].cpu_of_node = spdif_np; | ||
66 | data->dai[num_links].platform_of_node = spdif_np; | ||
67 | num_links++; | ||
68 | |||
69 | data->rxdev = platform_device_register_simple("spdif-dir", -1, NULL, 0); | ||
70 | if (IS_ERR(data->rxdev)) { | ||
71 | ret = PTR_ERR(data->rxdev); | ||
72 | dev_err(&pdev->dev, "register dir failed: %d\n", ret); | ||
73 | goto error_dit; | ||
74 | } | ||
75 | } | ||
76 | 54 | ||
77 | if (!num_links) { | 55 | if (data->dai.playback_only && data->dai.capture_only) { |
78 | dev_err(&pdev->dev, "no enabled S/PDIF DAI link\n"); | 56 | dev_err(&pdev->dev, "no enabled S/PDIF DAI link\n"); |
79 | goto error_dir; | 57 | goto end; |
80 | } | 58 | } |
81 | 59 | ||
82 | data->card.dev = &pdev->dev; | 60 | data->card.dev = &pdev->dev; |
83 | data->card.num_links = num_links; | 61 | data->card.dai_link = &data->dai; |
84 | data->card.dai_link = data->dai; | 62 | data->card.num_links = 1; |
85 | 63 | ||
86 | ret = snd_soc_of_parse_card_name(&data->card, "model"); | 64 | ret = snd_soc_of_parse_card_name(&data->card, "model"); |
87 | if (ret) | 65 | if (ret) |
88 | goto error_dir; | 66 | goto end; |
89 | 67 | ||
90 | ret = devm_snd_soc_register_card(&pdev->dev, &data->card); | 68 | ret = devm_snd_soc_register_card(&pdev->dev, &data->card); |
91 | if (ret) { | 69 | if (ret) { |
92 | dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret); | 70 | dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret); |
93 | goto error_dir; | 71 | goto end; |
94 | } | 72 | } |
95 | 73 | ||
96 | platform_set_drvdata(pdev, data); | 74 | platform_set_drvdata(pdev, data); |
97 | 75 | ||
98 | goto end; | ||
99 | |||
100 | error_dir: | ||
101 | if (data->rxdev) | ||
102 | platform_device_unregister(data->rxdev); | ||
103 | error_dit: | ||
104 | if (data->txdev) | ||
105 | platform_device_unregister(data->txdev); | ||
106 | end: | 76 | end: |
107 | if (spdif_np) | 77 | if (spdif_np) |
108 | of_node_put(spdif_np); | 78 | of_node_put(spdif_np); |
@@ -110,18 +80,6 @@ end: | |||
110 | return ret; | 80 | return ret; |
111 | } | 81 | } |
112 | 82 | ||
113 | static int imx_spdif_audio_remove(struct platform_device *pdev) | ||
114 | { | ||
115 | struct imx_spdif_data *data = platform_get_drvdata(pdev); | ||
116 | |||
117 | if (data->rxdev) | ||
118 | platform_device_unregister(data->rxdev); | ||
119 | if (data->txdev) | ||
120 | platform_device_unregister(data->txdev); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static const struct of_device_id imx_spdif_dt_ids[] = { | 83 | static const struct of_device_id imx_spdif_dt_ids[] = { |
126 | { .compatible = "fsl,imx-audio-spdif", }, | 84 | { .compatible = "fsl,imx-audio-spdif", }, |
127 | { /* sentinel */ } | 85 | { /* sentinel */ } |
@@ -135,7 +93,6 @@ static struct platform_driver imx_spdif_driver = { | |||
135 | .of_match_table = imx_spdif_dt_ids, | 93 | .of_match_table = imx_spdif_dt_ids, |
136 | }, | 94 | }, |
137 | .probe = imx_spdif_audio_probe, | 95 | .probe = imx_spdif_audio_probe, |
138 | .remove = imx_spdif_audio_remove, | ||
139 | }; | 96 | }; |
140 | 97 | ||
141 | module_platform_driver(imx_spdif_driver); | 98 | module_platform_driver(imx_spdif_driver); |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index f5f248c91c16..df552fa1aa65 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -304,8 +304,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
304 | scr |= SSI_SCR_RE; | 304 | scr |= SSI_SCR_RE; |
305 | sier |= sier_bits; | 305 | sier |= sier_bits; |
306 | 306 | ||
307 | if (++ssi->enabled == 1) | 307 | scr |= SSI_SCR_SSIEN; |
308 | scr |= SSI_SCR_SSIEN; | ||
309 | 308 | ||
310 | break; | 309 | break; |
311 | 310 | ||
@@ -318,7 +317,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
318 | scr &= ~SSI_SCR_RE; | 317 | scr &= ~SSI_SCR_RE; |
319 | sier &= ~sier_bits; | 318 | sier &= ~sier_bits; |
320 | 319 | ||
321 | if (--ssi->enabled == 0) | 320 | if (!(scr & (SSI_SCR_TE | SSI_SCR_RE))) |
322 | scr &= ~SSI_SCR_SSIEN; | 321 | scr &= ~SSI_SCR_SSIEN; |
323 | 322 | ||
324 | break; | 323 | break; |
@@ -536,7 +535,9 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
536 | ret); | 535 | ret); |
537 | goto failed_clk; | 536 | goto failed_clk; |
538 | } | 537 | } |
539 | clk_prepare_enable(ssi->clk); | 538 | ret = clk_prepare_enable(ssi->clk); |
539 | if (ret) | ||
540 | goto failed_clk; | ||
540 | 541 | ||
541 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 542 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
542 | ssi->base = devm_ioremap_resource(&pdev->dev, res); | 543 | ssi->base = devm_ioremap_resource(&pdev->dev, res); |
@@ -624,9 +625,6 @@ static int imx_ssi_remove(struct platform_device *pdev) | |||
624 | { | 625 | { |
625 | struct imx_ssi *ssi = platform_get_drvdata(pdev); | 626 | struct imx_ssi *ssi = platform_get_drvdata(pdev); |
626 | 627 | ||
627 | if (!ssi->dma_init) | ||
628 | imx_pcm_dma_exit(pdev); | ||
629 | |||
630 | if (!ssi->fiq_init) | 628 | if (!ssi->fiq_init) |
631 | imx_pcm_fiq_exit(pdev); | 629 | imx_pcm_fiq_exit(pdev); |
632 | 630 | ||
diff --git a/sound/soc/fsl/imx-ssi.h b/sound/soc/fsl/imx-ssi.h index 560c40fc9ebb..be6562365b6a 100644 --- a/sound/soc/fsl/imx-ssi.h +++ b/sound/soc/fsl/imx-ssi.h | |||
@@ -213,7 +213,6 @@ struct imx_ssi { | |||
213 | 213 | ||
214 | int fiq_init; | 214 | int fiq_init; |
215 | int dma_init; | 215 | int dma_init; |
216 | int enabled; | ||
217 | }; | 216 | }; |
218 | 217 | ||
219 | #endif /* _IMX_SSI_H */ | 218 | #endif /* _IMX_SSI_H */ |
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index 61e48852b9e8..3fd76bc391de 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c | |||
@@ -130,8 +130,6 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card, | |||
130 | break; | 130 | break; |
131 | } | 131 | } |
132 | 132 | ||
133 | dapm->bias_level = level; | ||
134 | |||
135 | return 0; | 133 | return 0; |
136 | } | 134 | } |
137 | 135 | ||
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index eb4373840bb6..3665f612819d 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c | |||
@@ -69,7 +69,6 @@ static int pcm030_fabric_probe(struct platform_device *op) | |||
69 | return -ENOMEM; | 69 | return -ENOMEM; |
70 | 70 | ||
71 | card->dev = &op->dev; | 71 | card->dev = &op->dev; |
72 | platform_set_drvdata(op, pdata); | ||
73 | 72 | ||
74 | pdata->card = card; | 73 | pdata->card = card; |
75 | 74 | ||
@@ -98,6 +97,8 @@ static int pcm030_fabric_probe(struct platform_device *op) | |||
98 | if (ret) | 97 | if (ret) |
99 | dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); | 98 | dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); |
100 | 99 | ||
100 | platform_set_drvdata(op, pdata); | ||
101 | |||
101 | return ret; | 102 | return ret; |
102 | } | 103 | } |
103 | 104 | ||
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index b2fbb7075a6c..c0d928138c88 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -8,7 +8,8 @@ | |||
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | #include <linux/clk.h> | |
12 | #include <linux/of.h> | ||
12 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <sound/simple_card.h> | 15 | #include <sound/simple_card.h> |
@@ -24,7 +25,7 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, | |||
24 | 25 | ||
25 | daifmt |= set->fmt; | 26 | daifmt |= set->fmt; |
26 | 27 | ||
27 | if (!ret && daifmt) | 28 | if (daifmt) |
28 | ret = snd_soc_dai_set_fmt(dai, daifmt); | 29 | ret = snd_soc_dai_set_fmt(dai, daifmt); |
29 | 30 | ||
30 | if (ret == -ENOTSUPP) { | 31 | if (ret == -ENOTSUPP) { |
@@ -57,11 +58,170 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
57 | return 0; | 58 | return 0; |
58 | } | 59 | } |
59 | 60 | ||
61 | static int | ||
62 | asoc_simple_card_sub_parse_of(struct device_node *np, | ||
63 | struct asoc_simple_dai *dai, | ||
64 | struct device_node **node) | ||
65 | { | ||
66 | struct clk *clk; | ||
67 | int ret; | ||
68 | |||
69 | /* | ||
70 | * get node via "sound-dai = <&phandle port>" | ||
71 | * it will be used as xxx_of_node on soc_bind_dai_link() | ||
72 | */ | ||
73 | *node = of_parse_phandle(np, "sound-dai", 0); | ||
74 | if (!*node) | ||
75 | return -ENODEV; | ||
76 | |||
77 | /* get dai->name */ | ||
78 | ret = snd_soc_of_get_dai_name(np, &dai->name); | ||
79 | if (ret < 0) | ||
80 | goto parse_error; | ||
81 | |||
82 | /* | ||
83 | * bitclock-inversion, frame-inversion | ||
84 | * bitclock-master, frame-master | ||
85 | * and specific "format" if it has | ||
86 | */ | ||
87 | dai->fmt = snd_soc_of_parse_daifmt(np, NULL); | ||
88 | |||
89 | /* | ||
90 | * dai->sysclk come from | ||
91 | * "clocks = <&xxx>" (if system has common clock) | ||
92 | * or "system-clock-frequency = <xxx>" | ||
93 | * or device's module clock. | ||
94 | */ | ||
95 | if (of_property_read_bool(np, "clocks")) { | ||
96 | clk = of_clk_get(np, 0); | ||
97 | if (IS_ERR(clk)) { | ||
98 | ret = PTR_ERR(clk); | ||
99 | goto parse_error; | ||
100 | } | ||
101 | |||
102 | dai->sysclk = clk_get_rate(clk); | ||
103 | } else if (of_property_read_bool(np, "system-clock-frequency")) { | ||
104 | of_property_read_u32(np, | ||
105 | "system-clock-frequency", | ||
106 | &dai->sysclk); | ||
107 | } else { | ||
108 | clk = of_clk_get(*node, 0); | ||
109 | if (IS_ERR(clk)) { | ||
110 | ret = PTR_ERR(clk); | ||
111 | goto parse_error; | ||
112 | } | ||
113 | |||
114 | dai->sysclk = clk_get_rate(clk); | ||
115 | } | ||
116 | |||
117 | ret = 0; | ||
118 | |||
119 | parse_error: | ||
120 | of_node_put(*node); | ||
121 | |||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static int asoc_simple_card_parse_of(struct device_node *node, | ||
126 | struct asoc_simple_card_info *info, | ||
127 | struct device *dev, | ||
128 | struct device_node **of_cpu, | ||
129 | struct device_node **of_codec, | ||
130 | struct device_node **of_platform) | ||
131 | { | ||
132 | struct device_node *np; | ||
133 | char *name; | ||
134 | int ret; | ||
135 | |||
136 | /* get CPU/CODEC common format via simple-audio-card,format */ | ||
137 | info->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & | ||
138 | (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); | ||
139 | |||
140 | /* DAPM routes */ | ||
141 | ret = snd_soc_of_parse_audio_routing(&info->snd_card, | ||
142 | "simple-audio-routing"); | ||
143 | if (ret) | ||
144 | return ret; | ||
145 | |||
146 | /* CPU sub-node */ | ||
147 | ret = -EINVAL; | ||
148 | np = of_get_child_by_name(node, "simple-audio-card,cpu"); | ||
149 | if (np) | ||
150 | ret = asoc_simple_card_sub_parse_of(np, | ||
151 | &info->cpu_dai, | ||
152 | of_cpu); | ||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | |||
156 | /* CODEC sub-node */ | ||
157 | ret = -EINVAL; | ||
158 | np = of_get_child_by_name(node, "simple-audio-card,codec"); | ||
159 | if (np) | ||
160 | ret = asoc_simple_card_sub_parse_of(np, | ||
161 | &info->codec_dai, | ||
162 | of_codec); | ||
163 | if (ret < 0) | ||
164 | return ret; | ||
165 | |||
166 | if (!info->cpu_dai.name || !info->codec_dai.name) | ||
167 | return -EINVAL; | ||
168 | |||
169 | /* card name is created from CPU/CODEC dai name */ | ||
170 | name = devm_kzalloc(dev, | ||
171 | strlen(info->cpu_dai.name) + | ||
172 | strlen(info->codec_dai.name) + 2, | ||
173 | GFP_KERNEL); | ||
174 | sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); | ||
175 | info->name = info->card = name; | ||
176 | |||
177 | /* simple-card assumes platform == cpu */ | ||
178 | *of_platform = *of_cpu; | ||
179 | |||
180 | dev_dbg(dev, "card-name : %s\n", info->card); | ||
181 | dev_dbg(dev, "platform : %04x\n", info->daifmt); | ||
182 | dev_dbg(dev, "cpu : %s / %04x / %d\n", | ||
183 | info->cpu_dai.name, | ||
184 | info->cpu_dai.fmt, | ||
185 | info->cpu_dai.sysclk); | ||
186 | dev_dbg(dev, "codec : %s / %04x / %d\n", | ||
187 | info->codec_dai.name, | ||
188 | info->codec_dai.fmt, | ||
189 | info->codec_dai.sysclk); | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
60 | static int asoc_simple_card_probe(struct platform_device *pdev) | 194 | static int asoc_simple_card_probe(struct platform_device *pdev) |
61 | { | 195 | { |
62 | struct asoc_simple_card_info *cinfo = pdev->dev.platform_data; | 196 | struct asoc_simple_card_info *cinfo; |
197 | struct device_node *np = pdev->dev.of_node; | ||
198 | struct device_node *of_cpu, *of_codec, *of_platform; | ||
63 | struct device *dev = &pdev->dev; | 199 | struct device *dev = &pdev->dev; |
64 | 200 | ||
201 | cinfo = NULL; | ||
202 | of_cpu = NULL; | ||
203 | of_codec = NULL; | ||
204 | of_platform = NULL; | ||
205 | if (np && of_device_is_available(np)) { | ||
206 | cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL); | ||
207 | if (cinfo) { | ||
208 | int ret; | ||
209 | cinfo->snd_card.dev = &pdev->dev; | ||
210 | ret = asoc_simple_card_parse_of(np, cinfo, dev, | ||
211 | &of_cpu, | ||
212 | &of_codec, | ||
213 | &of_platform); | ||
214 | if (ret < 0) { | ||
215 | if (ret != -EPROBE_DEFER) | ||
216 | dev_err(dev, "parse error %d\n", ret); | ||
217 | return ret; | ||
218 | } | ||
219 | } | ||
220 | } else { | ||
221 | cinfo->snd_card.dev = &pdev->dev; | ||
222 | cinfo = pdev->dev.platform_data; | ||
223 | } | ||
224 | |||
65 | if (!cinfo) { | 225 | if (!cinfo) { |
66 | dev_err(dev, "no info for asoc-simple-card\n"); | 226 | dev_err(dev, "no info for asoc-simple-card\n"); |
67 | return -EINVAL; | 227 | return -EINVAL; |
@@ -69,10 +229,10 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
69 | 229 | ||
70 | if (!cinfo->name || | 230 | if (!cinfo->name || |
71 | !cinfo->card || | 231 | !cinfo->card || |
72 | !cinfo->codec || | 232 | !cinfo->codec_dai.name || |
73 | !cinfo->platform || | 233 | !(cinfo->codec || of_codec) || |
74 | !cinfo->cpu_dai.name || | 234 | !(cinfo->platform || of_platform) || |
75 | !cinfo->codec_dai.name) { | 235 | !(cinfo->cpu_dai.name || of_cpu)) { |
76 | dev_err(dev, "insufficient asoc_simple_card_info settings\n"); | 236 | dev_err(dev, "insufficient asoc_simple_card_info settings\n"); |
77 | return -EINVAL; | 237 | return -EINVAL; |
78 | } | 238 | } |
@@ -86,6 +246,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
86 | cinfo->snd_link.platform_name = cinfo->platform; | 246 | cinfo->snd_link.platform_name = cinfo->platform; |
87 | cinfo->snd_link.codec_name = cinfo->codec; | 247 | cinfo->snd_link.codec_name = cinfo->codec; |
88 | cinfo->snd_link.codec_dai_name = cinfo->codec_dai.name; | 248 | cinfo->snd_link.codec_dai_name = cinfo->codec_dai.name; |
249 | cinfo->snd_link.cpu_of_node = of_cpu; | ||
250 | cinfo->snd_link.codec_of_node = of_codec; | ||
251 | cinfo->snd_link.platform_of_node = of_platform; | ||
89 | cinfo->snd_link.init = asoc_simple_card_dai_init; | 252 | cinfo->snd_link.init = asoc_simple_card_dai_init; |
90 | 253 | ||
91 | /* | 254 | /* |
@@ -95,25 +258,23 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
95 | cinfo->snd_card.owner = THIS_MODULE; | 258 | cinfo->snd_card.owner = THIS_MODULE; |
96 | cinfo->snd_card.dai_link = &cinfo->snd_link; | 259 | cinfo->snd_card.dai_link = &cinfo->snd_link; |
97 | cinfo->snd_card.num_links = 1; | 260 | cinfo->snd_card.num_links = 1; |
98 | cinfo->snd_card.dev = &pdev->dev; | ||
99 | 261 | ||
100 | return snd_soc_register_card(&cinfo->snd_card); | 262 | return devm_snd_soc_register_card(&pdev->dev, &cinfo->snd_card); |
101 | } | 263 | } |
102 | 264 | ||
103 | static int asoc_simple_card_remove(struct platform_device *pdev) | 265 | static const struct of_device_id asoc_simple_of_match[] = { |
104 | { | 266 | { .compatible = "simple-audio-card", }, |
105 | struct asoc_simple_card_info *cinfo = pdev->dev.platform_data; | 267 | {}, |
106 | 268 | }; | |
107 | return snd_soc_unregister_card(&cinfo->snd_card); | 269 | MODULE_DEVICE_TABLE(of, asoc_simple_of_match); |
108 | } | ||
109 | 270 | ||
110 | static struct platform_driver asoc_simple_card = { | 271 | static struct platform_driver asoc_simple_card = { |
111 | .driver = { | 272 | .driver = { |
112 | .name = "asoc-simple-card", | 273 | .name = "asoc-simple-card", |
113 | .owner = THIS_MODULE, | 274 | .owner = THIS_MODULE, |
275 | .of_match_table = asoc_simple_of_match, | ||
114 | }, | 276 | }, |
115 | .probe = asoc_simple_card_probe, | 277 | .probe = asoc_simple_card_probe, |
116 | .remove = asoc_simple_card_remove, | ||
117 | }; | 278 | }; |
118 | 279 | ||
119 | module_platform_driver(asoc_simple_card); | 280 | module_platform_driver(asoc_simple_card); |
diff --git a/sound/soc/mid-x86/Kconfig b/sound/soc/intel/Kconfig index 61c10bf503d2..61c10bf503d2 100644 --- a/sound/soc/mid-x86/Kconfig +++ b/sound/soc/intel/Kconfig | |||
diff --git a/sound/soc/mid-x86/Makefile b/sound/soc/intel/Makefile index 639883339465..639883339465 100644 --- a/sound/soc/mid-x86/Makefile +++ b/sound/soc/intel/Makefile | |||
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/intel/mfld_machine.c index d3d4c32434f7..d3d4c32434f7 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/intel/mfld_machine.c | |||
diff --git a/sound/soc/mid-x86/sst_dsp.h b/sound/soc/intel/sst_dsp.h index 0fce1de284ff..0fce1de284ff 100644 --- a/sound/soc/mid-x86/sst_dsp.h +++ b/sound/soc/intel/sst_dsp.h | |||
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/intel/sst_platform.c index b6b5eb698d33..b6b5eb698d33 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/intel/sst_platform.c | |||
diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/intel/sst_platform.h index cacc9066ec52..cacc9066ec52 100644 --- a/sound/soc/mid-x86/sst_platform.h +++ b/sound/soc/intel/sst_platform.h | |||
diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig index 5351cba66c9e..29f76af5d963 100644 --- a/sound/soc/jz4740/Kconfig +++ b/sound/soc/jz4740/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config SND_JZ4740_SOC | 1 | config SND_JZ4740_SOC |
2 | tristate "SoC Audio for Ingenic JZ4740 SoC" | 2 | tristate "SoC Audio for Ingenic JZ4740 SoC" |
3 | depends on MACH_JZ4740 && SND_SOC | 3 | depends on MACH_JZ4740 && SND_SOC |
4 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
4 | help | 5 | help |
5 | Say Y or M if you want to add support for codecs attached to | 6 | Say Y or M if you want to add support for codecs attached to |
6 | the JZ4740 I2S interface. You will also need to select the audio | 7 | the JZ4740 I2S interface. You will also need to select the audio |
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 4c849a49c72a..8f220009e0f6 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c | |||
@@ -29,9 +29,11 @@ | |||
29 | #include <sound/pcm_params.h> | 29 | #include <sound/pcm_params.h> |
30 | #include <sound/soc.h> | 30 | #include <sound/soc.h> |
31 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
32 | #include <sound/dmaengine_pcm.h> | ||
33 | |||
34 | #include <asm/mach-jz4740/dma.h> | ||
32 | 35 | ||
33 | #include "jz4740-i2s.h" | 36 | #include "jz4740-i2s.h" |
34 | #include "jz4740-pcm.h" | ||
35 | 37 | ||
36 | #define JZ_REG_AIC_CONF 0x00 | 38 | #define JZ_REG_AIC_CONF 0x00 |
37 | #define JZ_REG_AIC_CTRL 0x04 | 39 | #define JZ_REG_AIC_CTRL 0x04 |
@@ -89,8 +91,8 @@ struct jz4740_i2s { | |||
89 | struct clk *clk_aic; | 91 | struct clk *clk_aic; |
90 | struct clk *clk_i2s; | 92 | struct clk *clk_i2s; |
91 | 93 | ||
92 | struct jz4740_pcm_config pcm_config_playback; | 94 | struct snd_dmaengine_dai_dma_data playback_dma_data; |
93 | struct jz4740_pcm_config pcm_config_capture; | 95 | struct snd_dmaengine_dai_dma_data capture_dma_data; |
94 | }; | 96 | }; |
95 | 97 | ||
96 | static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s, | 98 | static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s, |
@@ -233,8 +235,6 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
233 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 235 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
234 | { | 236 | { |
235 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 237 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
236 | enum jz4740_dma_width dma_width; | ||
237 | struct jz4740_pcm_config *pcm_config; | ||
238 | unsigned int sample_size; | 238 | unsigned int sample_size; |
239 | uint32_t ctrl; | 239 | uint32_t ctrl; |
240 | 240 | ||
@@ -243,11 +243,9 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
243 | switch (params_format(params)) { | 243 | switch (params_format(params)) { |
244 | case SNDRV_PCM_FORMAT_S8: | 244 | case SNDRV_PCM_FORMAT_S8: |
245 | sample_size = 0; | 245 | sample_size = 0; |
246 | dma_width = JZ4740_DMA_WIDTH_8BIT; | ||
247 | break; | 246 | break; |
248 | case SNDRV_PCM_FORMAT_S16: | 247 | case SNDRV_PCM_FORMAT_S16: |
249 | sample_size = 1; | 248 | sample_size = 1; |
250 | dma_width = JZ4740_DMA_WIDTH_16BIT; | ||
251 | break; | 249 | break; |
252 | default: | 250 | default: |
253 | return -EINVAL; | 251 | return -EINVAL; |
@@ -260,22 +258,13 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
260 | ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO; | 258 | ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO; |
261 | else | 259 | else |
262 | ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO; | 260 | ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO; |
263 | |||
264 | pcm_config = &i2s->pcm_config_playback; | ||
265 | pcm_config->dma_config.dst_width = dma_width; | ||
266 | |||
267 | } else { | 261 | } else { |
268 | ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; | 262 | ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; |
269 | ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; | 263 | ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; |
270 | |||
271 | pcm_config = &i2s->pcm_config_capture; | ||
272 | pcm_config->dma_config.src_width = dma_width; | ||
273 | } | 264 | } |
274 | 265 | ||
275 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); | 266 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); |
276 | 267 | ||
277 | snd_soc_dai_set_dma_data(dai, substream, pcm_config); | ||
278 | |||
279 | return 0; | 268 | return 0; |
280 | } | 269 | } |
281 | 270 | ||
@@ -342,25 +331,19 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai) | |||
342 | 331 | ||
343 | static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s) | 332 | static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s) |
344 | { | 333 | { |
345 | struct jz4740_dma_config *dma_config; | 334 | struct snd_dmaengine_dai_dma_data *dma_data; |
346 | 335 | ||
347 | /* Playback */ | 336 | /* Playback */ |
348 | dma_config = &i2s->pcm_config_playback.dma_config; | 337 | dma_data = &i2s->playback_dma_data; |
349 | dma_config->src_width = JZ4740_DMA_WIDTH_32BIT; | 338 | dma_data->maxburst = 16; |
350 | dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; | 339 | dma_data->slave_id = JZ4740_DMA_TYPE_AIC_TRANSMIT; |
351 | dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT; | 340 | dma_data->addr = i2s->phys_base + JZ_REG_AIC_FIFO; |
352 | dma_config->flags = JZ4740_DMA_SRC_AUTOINC; | ||
353 | dma_config->mode = JZ4740_DMA_MODE_SINGLE; | ||
354 | i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; | ||
355 | 341 | ||
356 | /* Capture */ | 342 | /* Capture */ |
357 | dma_config = &i2s->pcm_config_capture.dma_config; | 343 | dma_data = &i2s->capture_dma_data; |
358 | dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT; | 344 | dma_data->maxburst = 16; |
359 | dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; | 345 | dma_data->slave_id = JZ4740_DMA_TYPE_AIC_RECEIVE; |
360 | dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE; | 346 | dma_data->addr = i2s->phys_base + JZ_REG_AIC_FIFO; |
361 | dma_config->flags = JZ4740_DMA_DST_AUTOINC; | ||
362 | dma_config->mode = JZ4740_DMA_MODE_SINGLE; | ||
363 | i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; | ||
364 | } | 347 | } |
365 | 348 | ||
366 | static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) | 349 | static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) |
@@ -371,6 +354,8 @@ static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) | |||
371 | clk_prepare_enable(i2s->clk_aic); | 354 | clk_prepare_enable(i2s->clk_aic); |
372 | 355 | ||
373 | jz4740_i2c_init_pcm_config(i2s); | 356 | jz4740_i2c_init_pcm_config(i2s); |
357 | snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, | ||
358 | &i2s->capture_dma_data); | ||
374 | 359 | ||
375 | conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | | 360 | conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | |
376 | (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | | 361 | (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | |
@@ -432,91 +417,41 @@ static const struct snd_soc_component_driver jz4740_i2s_component = { | |||
432 | static int jz4740_i2s_dev_probe(struct platform_device *pdev) | 417 | static int jz4740_i2s_dev_probe(struct platform_device *pdev) |
433 | { | 418 | { |
434 | struct jz4740_i2s *i2s; | 419 | struct jz4740_i2s *i2s; |
420 | struct resource *mem; | ||
435 | int ret; | 421 | int ret; |
436 | 422 | ||
437 | i2s = kzalloc(sizeof(*i2s), GFP_KERNEL); | 423 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); |
438 | |||
439 | if (!i2s) | 424 | if (!i2s) |
440 | return -ENOMEM; | 425 | return -ENOMEM; |
441 | 426 | ||
442 | i2s->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 427 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
443 | if (!i2s->mem) { | 428 | i2s->base = devm_ioremap_resource(&pdev->dev, mem); |
444 | ret = -ENOENT; | 429 | if (IS_ERR(i2s->base)) |
445 | goto err_free; | 430 | return PTR_ERR(i2s->base); |
446 | } | ||
447 | |||
448 | i2s->mem = request_mem_region(i2s->mem->start, resource_size(i2s->mem), | ||
449 | pdev->name); | ||
450 | if (!i2s->mem) { | ||
451 | ret = -EBUSY; | ||
452 | goto err_free; | ||
453 | } | ||
454 | 431 | ||
455 | i2s->base = ioremap_nocache(i2s->mem->start, resource_size(i2s->mem)); | 432 | i2s->phys_base = mem->start; |
456 | if (!i2s->base) { | ||
457 | ret = -EBUSY; | ||
458 | goto err_release_mem_region; | ||
459 | } | ||
460 | 433 | ||
461 | i2s->phys_base = i2s->mem->start; | 434 | i2s->clk_aic = devm_clk_get(&pdev->dev, "aic"); |
435 | if (IS_ERR(i2s->clk_aic)) | ||
436 | return PTR_ERR(i2s->clk_aic); | ||
462 | 437 | ||
463 | i2s->clk_aic = clk_get(&pdev->dev, "aic"); | 438 | i2s->clk_i2s = devm_clk_get(&pdev->dev, "i2s"); |
464 | if (IS_ERR(i2s->clk_aic)) { | 439 | if (IS_ERR(i2s->clk_i2s)) |
465 | ret = PTR_ERR(i2s->clk_aic); | 440 | return PTR_ERR(i2s->clk_i2s); |
466 | goto err_iounmap; | ||
467 | } | ||
468 | |||
469 | i2s->clk_i2s = clk_get(&pdev->dev, "i2s"); | ||
470 | if (IS_ERR(i2s->clk_i2s)) { | ||
471 | ret = PTR_ERR(i2s->clk_i2s); | ||
472 | goto err_clk_put_aic; | ||
473 | } | ||
474 | 441 | ||
475 | platform_set_drvdata(pdev, i2s); | 442 | platform_set_drvdata(pdev, i2s); |
476 | ret = snd_soc_register_component(&pdev->dev, &jz4740_i2s_component, | ||
477 | &jz4740_i2s_dai, 1); | ||
478 | 443 | ||
479 | if (ret) { | 444 | ret = devm_snd_soc_register_component(&pdev->dev, |
480 | dev_err(&pdev->dev, "Failed to register DAI\n"); | 445 | &jz4740_i2s_component, &jz4740_i2s_dai, 1); |
481 | goto err_clk_put_i2s; | 446 | if (ret) |
482 | } | 447 | return ret; |
483 | |||
484 | return 0; | ||
485 | |||
486 | err_clk_put_i2s: | ||
487 | clk_put(i2s->clk_i2s); | ||
488 | err_clk_put_aic: | ||
489 | clk_put(i2s->clk_aic); | ||
490 | err_iounmap: | ||
491 | iounmap(i2s->base); | ||
492 | err_release_mem_region: | ||
493 | release_mem_region(i2s->mem->start, resource_size(i2s->mem)); | ||
494 | err_free: | ||
495 | kfree(i2s); | ||
496 | |||
497 | return ret; | ||
498 | } | ||
499 | 448 | ||
500 | static int jz4740_i2s_dev_remove(struct platform_device *pdev) | 449 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, |
501 | { | 450 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
502 | struct jz4740_i2s *i2s = platform_get_drvdata(pdev); | ||
503 | |||
504 | snd_soc_unregister_component(&pdev->dev); | ||
505 | |||
506 | clk_put(i2s->clk_i2s); | ||
507 | clk_put(i2s->clk_aic); | ||
508 | |||
509 | iounmap(i2s->base); | ||
510 | release_mem_region(i2s->mem->start, resource_size(i2s->mem)); | ||
511 | |||
512 | kfree(i2s); | ||
513 | |||
514 | return 0; | ||
515 | } | 451 | } |
516 | 452 | ||
517 | static struct platform_driver jz4740_i2s_driver = { | 453 | static struct platform_driver jz4740_i2s_driver = { |
518 | .probe = jz4740_i2s_dev_probe, | 454 | .probe = jz4740_i2s_dev_probe, |
519 | .remove = jz4740_i2s_dev_remove, | ||
520 | .driver = { | 455 | .driver = { |
521 | .name = "jz4740-i2s", | 456 | .name = "jz4740-i2s", |
522 | .owner = THIS_MODULE, | 457 | .owner = THIS_MODULE, |
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c deleted file mode 100644 index 1d7ef28585e1..000000000000 --- a/sound/soc/jz4740/jz4740-pcm.c +++ /dev/null | |||
@@ -1,358 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * You should have received a copy of the GNU General Public License along | ||
10 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
11 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include <linux/dma-mapping.h> | ||
23 | |||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/soc.h> | ||
28 | |||
29 | #include <asm/mach-jz4740/dma.h> | ||
30 | #include "jz4740-pcm.h" | ||
31 | |||
32 | struct jz4740_runtime_data { | ||
33 | unsigned long dma_period; | ||
34 | dma_addr_t dma_start; | ||
35 | dma_addr_t dma_pos; | ||
36 | dma_addr_t dma_end; | ||
37 | |||
38 | struct jz4740_dma_chan *dma; | ||
39 | |||
40 | dma_addr_t fifo_addr; | ||
41 | }; | ||
42 | |||
43 | /* identify hardware playback capabilities */ | ||
44 | static const struct snd_pcm_hardware jz4740_pcm_hardware = { | ||
45 | .info = SNDRV_PCM_INFO_MMAP | | ||
46 | SNDRV_PCM_INFO_MMAP_VALID | | ||
47 | SNDRV_PCM_INFO_INTERLEAVED | | ||
48 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
49 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, | ||
50 | |||
51 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
52 | .channels_min = 1, | ||
53 | .channels_max = 2, | ||
54 | .period_bytes_min = 16, | ||
55 | .period_bytes_max = 2 * PAGE_SIZE, | ||
56 | .periods_min = 2, | ||
57 | .periods_max = 128, | ||
58 | .buffer_bytes_max = 128 * 2 * PAGE_SIZE, | ||
59 | .fifo_size = 32, | ||
60 | }; | ||
61 | |||
62 | static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd, | ||
63 | struct snd_pcm_substream *substream) | ||
64 | { | ||
65 | unsigned long count; | ||
66 | |||
67 | if (prtd->dma_pos == prtd->dma_end) | ||
68 | prtd->dma_pos = prtd->dma_start; | ||
69 | |||
70 | if (prtd->dma_pos + prtd->dma_period > prtd->dma_end) | ||
71 | count = prtd->dma_end - prtd->dma_pos; | ||
72 | else | ||
73 | count = prtd->dma_period; | ||
74 | |||
75 | jz4740_dma_disable(prtd->dma); | ||
76 | |||
77 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
78 | jz4740_dma_set_src_addr(prtd->dma, prtd->dma_pos); | ||
79 | jz4740_dma_set_dst_addr(prtd->dma, prtd->fifo_addr); | ||
80 | } else { | ||
81 | jz4740_dma_set_src_addr(prtd->dma, prtd->fifo_addr); | ||
82 | jz4740_dma_set_dst_addr(prtd->dma, prtd->dma_pos); | ||
83 | } | ||
84 | |||
85 | jz4740_dma_set_transfer_count(prtd->dma, count); | ||
86 | |||
87 | prtd->dma_pos += count; | ||
88 | |||
89 | jz4740_dma_enable(prtd->dma); | ||
90 | } | ||
91 | |||
92 | static void jz4740_pcm_dma_transfer_done(struct jz4740_dma_chan *dma, int err, | ||
93 | void *dev_id) | ||
94 | { | ||
95 | struct snd_pcm_substream *substream = dev_id; | ||
96 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
97 | struct jz4740_runtime_data *prtd = runtime->private_data; | ||
98 | |||
99 | snd_pcm_period_elapsed(substream); | ||
100 | |||
101 | jz4740_pcm_start_transfer(prtd, substream); | ||
102 | } | ||
103 | |||
104 | static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream, | ||
105 | struct snd_pcm_hw_params *params) | ||
106 | { | ||
107 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
108 | struct jz4740_runtime_data *prtd = runtime->private_data; | ||
109 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
110 | struct jz4740_pcm_config *config; | ||
111 | |||
112 | config = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
113 | |||
114 | if (!config) | ||
115 | return 0; | ||
116 | |||
117 | if (!prtd->dma) { | ||
118 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
119 | prtd->dma = jz4740_dma_request(substream, "PCM Capture"); | ||
120 | else | ||
121 | prtd->dma = jz4740_dma_request(substream, "PCM Playback"); | ||
122 | } | ||
123 | |||
124 | if (!prtd->dma) | ||
125 | return -EBUSY; | ||
126 | |||
127 | jz4740_dma_configure(prtd->dma, &config->dma_config); | ||
128 | prtd->fifo_addr = config->fifo_addr; | ||
129 | |||
130 | jz4740_dma_set_complete_cb(prtd->dma, jz4740_pcm_dma_transfer_done); | ||
131 | |||
132 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
133 | runtime->dma_bytes = params_buffer_bytes(params); | ||
134 | |||
135 | prtd->dma_period = params_period_bytes(params); | ||
136 | prtd->dma_start = runtime->dma_addr; | ||
137 | prtd->dma_pos = prtd->dma_start; | ||
138 | prtd->dma_end = prtd->dma_start + runtime->dma_bytes; | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream) | ||
144 | { | ||
145 | struct jz4740_runtime_data *prtd = substream->runtime->private_data; | ||
146 | |||
147 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
148 | if (prtd->dma) { | ||
149 | jz4740_dma_free(prtd->dma); | ||
150 | prtd->dma = NULL; | ||
151 | } | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static int jz4740_pcm_prepare(struct snd_pcm_substream *substream) | ||
157 | { | ||
158 | struct jz4740_runtime_data *prtd = substream->runtime->private_data; | ||
159 | |||
160 | if (!prtd->dma) | ||
161 | return -EBUSY; | ||
162 | |||
163 | prtd->dma_pos = prtd->dma_start; | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
169 | { | ||
170 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
171 | struct jz4740_runtime_data *prtd = runtime->private_data; | ||
172 | |||
173 | switch (cmd) { | ||
174 | case SNDRV_PCM_TRIGGER_START: | ||
175 | case SNDRV_PCM_TRIGGER_RESUME: | ||
176 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
177 | jz4740_pcm_start_transfer(prtd, substream); | ||
178 | break; | ||
179 | case SNDRV_PCM_TRIGGER_STOP: | ||
180 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
181 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
182 | jz4740_dma_disable(prtd->dma); | ||
183 | break; | ||
184 | default: | ||
185 | break; | ||
186 | } | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static snd_pcm_uframes_t jz4740_pcm_pointer(struct snd_pcm_substream *substream) | ||
192 | { | ||
193 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
194 | struct jz4740_runtime_data *prtd = runtime->private_data; | ||
195 | unsigned long byte_offset; | ||
196 | snd_pcm_uframes_t offset; | ||
197 | struct jz4740_dma_chan *dma = prtd->dma; | ||
198 | |||
199 | /* prtd->dma_pos points to the end of the current transfer. So by | ||
200 | * subtracting prdt->dma_start we get the offset to the end of the | ||
201 | * current period in bytes. By subtracting the residue of the transfer | ||
202 | * we get the current offset in bytes. */ | ||
203 | byte_offset = prtd->dma_pos - prtd->dma_start; | ||
204 | byte_offset -= jz4740_dma_get_residue(dma); | ||
205 | |||
206 | offset = bytes_to_frames(runtime, byte_offset); | ||
207 | if (offset >= runtime->buffer_size) | ||
208 | offset = 0; | ||
209 | |||
210 | return offset; | ||
211 | } | ||
212 | |||
213 | static int jz4740_pcm_open(struct snd_pcm_substream *substream) | ||
214 | { | ||
215 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
216 | struct jz4740_runtime_data *prtd; | ||
217 | |||
218 | prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); | ||
219 | if (prtd == NULL) | ||
220 | return -ENOMEM; | ||
221 | |||
222 | snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware); | ||
223 | |||
224 | runtime->private_data = prtd; | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int jz4740_pcm_close(struct snd_pcm_substream *substream) | ||
230 | { | ||
231 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
232 | struct jz4740_runtime_data *prtd = runtime->private_data; | ||
233 | |||
234 | kfree(prtd); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int jz4740_pcm_mmap(struct snd_pcm_substream *substream, | ||
240 | struct vm_area_struct *vma) | ||
241 | { | ||
242 | return remap_pfn_range(vma, vma->vm_start, | ||
243 | substream->dma_buffer.addr >> PAGE_SHIFT, | ||
244 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
245 | } | ||
246 | |||
247 | static struct snd_pcm_ops jz4740_pcm_ops = { | ||
248 | .open = jz4740_pcm_open, | ||
249 | .close = jz4740_pcm_close, | ||
250 | .ioctl = snd_pcm_lib_ioctl, | ||
251 | .hw_params = jz4740_pcm_hw_params, | ||
252 | .hw_free = jz4740_pcm_hw_free, | ||
253 | .prepare = jz4740_pcm_prepare, | ||
254 | .trigger = jz4740_pcm_trigger, | ||
255 | .pointer = jz4740_pcm_pointer, | ||
256 | .mmap = jz4740_pcm_mmap, | ||
257 | }; | ||
258 | |||
259 | static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
260 | { | ||
261 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
262 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
263 | size_t size = jz4740_pcm_hardware.buffer_bytes_max; | ||
264 | |||
265 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
266 | buf->dev.dev = pcm->card->dev; | ||
267 | buf->private_data = NULL; | ||
268 | |||
269 | buf->area = dma_alloc_noncoherent(pcm->card->dev, size, | ||
270 | &buf->addr, GFP_KERNEL); | ||
271 | if (!buf->area) | ||
272 | return -ENOMEM; | ||
273 | |||
274 | buf->bytes = size; | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static void jz4740_pcm_free(struct snd_pcm *pcm) | ||
280 | { | ||
281 | struct snd_pcm_substream *substream; | ||
282 | struct snd_dma_buffer *buf; | ||
283 | int stream; | ||
284 | |||
285 | for (stream = 0; stream < SNDRV_PCM_STREAM_LAST; ++stream) { | ||
286 | substream = pcm->streams[stream].substream; | ||
287 | if (!substream) | ||
288 | continue; | ||
289 | |||
290 | buf = &substream->dma_buffer; | ||
291 | if (!buf->area) | ||
292 | continue; | ||
293 | |||
294 | dma_free_noncoherent(pcm->card->dev, buf->bytes, buf->area, | ||
295 | buf->addr); | ||
296 | buf->area = NULL; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | static int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
301 | { | ||
302 | struct snd_card *card = rtd->card->snd_card; | ||
303 | struct snd_pcm *pcm = rtd->pcm; | ||
304 | int ret; | ||
305 | |||
306 | ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); | ||
307 | if (ret) | ||
308 | return ret; | ||
309 | |||
310 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
311 | ret = jz4740_pcm_preallocate_dma_buffer(pcm, | ||
312 | SNDRV_PCM_STREAM_PLAYBACK); | ||
313 | if (ret) | ||
314 | goto err; | ||
315 | } | ||
316 | |||
317 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
318 | ret = jz4740_pcm_preallocate_dma_buffer(pcm, | ||
319 | SNDRV_PCM_STREAM_CAPTURE); | ||
320 | if (ret) | ||
321 | goto err; | ||
322 | } | ||
323 | |||
324 | err: | ||
325 | return ret; | ||
326 | } | ||
327 | |||
328 | static struct snd_soc_platform_driver jz4740_soc_platform = { | ||
329 | .ops = &jz4740_pcm_ops, | ||
330 | .pcm_new = jz4740_pcm_new, | ||
331 | .pcm_free = jz4740_pcm_free, | ||
332 | }; | ||
333 | |||
334 | static int jz4740_pcm_probe(struct platform_device *pdev) | ||
335 | { | ||
336 | return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform); | ||
337 | } | ||
338 | |||
339 | static int jz4740_pcm_remove(struct platform_device *pdev) | ||
340 | { | ||
341 | snd_soc_unregister_platform(&pdev->dev); | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static struct platform_driver jz4740_pcm_driver = { | ||
346 | .probe = jz4740_pcm_probe, | ||
347 | .remove = jz4740_pcm_remove, | ||
348 | .driver = { | ||
349 | .name = "jz4740-pcm-audio", | ||
350 | .owner = THIS_MODULE, | ||
351 | }, | ||
352 | }; | ||
353 | |||
354 | module_platform_driver(jz4740_pcm_driver); | ||
355 | |||
356 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
357 | MODULE_DESCRIPTION("Ingenic SoC JZ4740 PCM driver"); | ||
358 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h deleted file mode 100644 index 1220cbb4382c..000000000000 --- a/sound/soc/jz4740/jz4740-pcm.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 as | ||
5 | * published by the Free Software Foundation. | ||
6 | */ | ||
7 | |||
8 | #ifndef _JZ4740_PCM_H | ||
9 | #define _JZ4740_PCM_H | ||
10 | |||
11 | #include <linux/dma-mapping.h> | ||
12 | #include <asm/mach-jz4740/dma.h> | ||
13 | |||
14 | |||
15 | struct jz4740_pcm_config { | ||
16 | struct jz4740_dma_config dma_config; | ||
17 | phys_addr_t fifo_addr; | ||
18 | }; | ||
19 | |||
20 | #endif | ||
diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c index 55fd6b5df55f..82b5f37cd2c7 100644 --- a/sound/soc/jz4740/qi_lb60.c +++ b/sound/soc/jz4740/qi_lb60.c | |||
@@ -73,7 +73,7 @@ static struct snd_soc_dai_link qi_lb60_dai = { | |||
73 | .name = "jz4740", | 73 | .name = "jz4740", |
74 | .stream_name = "jz4740", | 74 | .stream_name = "jz4740", |
75 | .cpu_dai_name = "jz4740-i2s", | 75 | .cpu_dai_name = "jz4740-i2s", |
76 | .platform_name = "jz4740-pcm-audio", | 76 | .platform_name = "jz4740-i2s", |
77 | .codec_dai_name = "jz4740-hifi", | 77 | .codec_dai_name = "jz4740-hifi", |
78 | .codec_name = "jz4740-codec", | 78 | .codec_name = "jz4740-codec", |
79 | .init = qi_lb60_codec_init, | 79 | .init = qi_lb60_codec_init, |
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index d34d91743e3f..3920a5e8125f 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c | |||
@@ -33,6 +33,10 @@ | |||
33 | SNDRV_PCM_FMTBIT_S24_LE | \ | 33 | SNDRV_PCM_FMTBIT_S24_LE | \ |
34 | SNDRV_PCM_FMTBIT_S32_LE) | 34 | SNDRV_PCM_FMTBIT_S32_LE) |
35 | 35 | ||
36 | #define KIRKWOOD_SPDIF_FORMATS \ | ||
37 | (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
38 | SNDRV_PCM_FMTBIT_S24_LE) | ||
39 | |||
36 | static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | 40 | static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai, |
37 | unsigned int fmt) | 41 | unsigned int fmt) |
38 | { | 42 | { |
@@ -244,15 +248,15 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | |||
244 | ctl); | 248 | ctl); |
245 | } | 249 | } |
246 | 250 | ||
247 | if (dai->id == 0) | ||
248 | ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */ | ||
249 | else | ||
250 | ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */ | ||
251 | |||
252 | switch (cmd) { | 251 | switch (cmd) { |
253 | case SNDRV_PCM_TRIGGER_START: | 252 | case SNDRV_PCM_TRIGGER_START: |
254 | /* configure */ | 253 | /* configure */ |
255 | ctl = priv->ctl_play; | 254 | ctl = priv->ctl_play; |
255 | if (dai->id == 0) | ||
256 | ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */ | ||
257 | else | ||
258 | ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */ | ||
259 | |||
256 | value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; | 260 | value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; |
257 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | 261 | writel(value, priv->io + KIRKWOOD_PLAYCTL); |
258 | 262 | ||
@@ -449,14 +453,14 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = { | |||
449 | .channels_max = 2, | 453 | .channels_max = 2, |
450 | .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | | 454 | .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
451 | SNDRV_PCM_RATE_96000, | 455 | SNDRV_PCM_RATE_96000, |
452 | .formats = KIRKWOOD_I2S_FORMATS, | 456 | .formats = KIRKWOOD_SPDIF_FORMATS, |
453 | }, | 457 | }, |
454 | .capture = { | 458 | .capture = { |
455 | .channels_min = 1, | 459 | .channels_min = 1, |
456 | .channels_max = 2, | 460 | .channels_max = 2, |
457 | .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | | 461 | .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
458 | SNDRV_PCM_RATE_96000, | 462 | SNDRV_PCM_RATE_96000, |
459 | .formats = KIRKWOOD_I2S_FORMATS, | 463 | .formats = KIRKWOOD_SPDIF_FORMATS, |
460 | }, | 464 | }, |
461 | .ops = &kirkwood_i2s_dai_ops, | 465 | .ops = &kirkwood_i2s_dai_ops, |
462 | }, | 466 | }, |
@@ -469,17 +473,17 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = { | |||
469 | .playback = { | 473 | .playback = { |
470 | .channels_min = 1, | 474 | .channels_min = 1, |
471 | .channels_max = 2, | 475 | .channels_max = 2, |
472 | .rates = SNDRV_PCM_RATE_8000_192000 | | 476 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
473 | SNDRV_PCM_RATE_CONTINUOUS | | 477 | .rate_min = 5512, |
474 | SNDRV_PCM_RATE_KNOT, | 478 | .rate_max = 192000, |
475 | .formats = KIRKWOOD_I2S_FORMATS, | 479 | .formats = KIRKWOOD_I2S_FORMATS, |
476 | }, | 480 | }, |
477 | .capture = { | 481 | .capture = { |
478 | .channels_min = 1, | 482 | .channels_min = 1, |
479 | .channels_max = 2, | 483 | .channels_max = 2, |
480 | .rates = SNDRV_PCM_RATE_8000_192000 | | 484 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
481 | SNDRV_PCM_RATE_CONTINUOUS | | 485 | .rate_min = 5512, |
482 | SNDRV_PCM_RATE_KNOT, | 486 | .rate_max = 192000, |
483 | .formats = KIRKWOOD_I2S_FORMATS, | 487 | .formats = KIRKWOOD_I2S_FORMATS, |
484 | }, | 488 | }, |
485 | .ops = &kirkwood_i2s_dai_ops, | 489 | .ops = &kirkwood_i2s_dai_ops, |
@@ -490,18 +494,18 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = { | |||
490 | .playback = { | 494 | .playback = { |
491 | .channels_min = 1, | 495 | .channels_min = 1, |
492 | .channels_max = 2, | 496 | .channels_max = 2, |
493 | .rates = SNDRV_PCM_RATE_8000_192000 | | 497 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
494 | SNDRV_PCM_RATE_CONTINUOUS | | 498 | .rate_min = 5512, |
495 | SNDRV_PCM_RATE_KNOT, | 499 | .rate_max = 192000, |
496 | .formats = KIRKWOOD_I2S_FORMATS, | 500 | .formats = KIRKWOOD_SPDIF_FORMATS, |
497 | }, | 501 | }, |
498 | .capture = { | 502 | .capture = { |
499 | .channels_min = 1, | 503 | .channels_min = 1, |
500 | .channels_max = 2, | 504 | .channels_max = 2, |
501 | .rates = SNDRV_PCM_RATE_8000_192000 | | 505 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
502 | SNDRV_PCM_RATE_CONTINUOUS | | 506 | .rate_min = 5512, |
503 | SNDRV_PCM_RATE_KNOT, | 507 | .rate_max = 192000, |
504 | .formats = KIRKWOOD_I2S_FORMATS, | 508 | .formats = KIRKWOOD_SPDIF_FORMATS, |
505 | }, | 509 | }, |
506 | .ops = &kirkwood_i2s_dai_ops, | 510 | .ops = &kirkwood_i2s_dai_ops, |
507 | }, | 511 | }, |
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index b16abbbf7764..04a6b0d60944 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c | |||
@@ -56,16 +56,10 @@ static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = { | |||
56 | 56 | ||
57 | int mxs_pcm_platform_register(struct device *dev) | 57 | int mxs_pcm_platform_register(struct device *dev) |
58 | { | 58 | { |
59 | return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config, | 59 | return devm_snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config, |
60 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | 60 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | |
61 | SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX); | 61 | SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX); |
62 | } | 62 | } |
63 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); | 63 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); |
64 | 64 | ||
65 | void mxs_pcm_platform_unregister(struct device *dev) | ||
66 | { | ||
67 | snd_dmaengine_pcm_unregister(dev); | ||
68 | } | ||
69 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister); | ||
70 | |||
71 | MODULE_LICENSE("GPL"); | 65 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h index bc685b67cac7..035ea0436ca5 100644 --- a/sound/soc/mxs/mxs-pcm.h +++ b/sound/soc/mxs/mxs-pcm.h | |||
@@ -20,6 +20,5 @@ | |||
20 | #define _MXS_PCM_H | 20 | #define _MXS_PCM_H |
21 | 21 | ||
22 | int mxs_pcm_platform_register(struct device *dev); | 22 | int mxs_pcm_platform_register(struct device *dev); |
23 | void mxs_pcm_platform_unregister(struct device *dev); | ||
24 | 23 | ||
25 | #endif | 24 | #endif |
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 54e622acac33..231d7e7b0711 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
@@ -50,9 +50,9 @@ static struct mxs_saif *mxs_saif[2]; | |||
50 | * This also means that both SAIFs must operate at the same sample rate. | 50 | * This also means that both SAIFs must operate at the same sample rate. |
51 | * | 51 | * |
52 | * We abstract this as each saif has a master, the master could be | 52 | * We abstract this as each saif has a master, the master could be |
53 | * himself or other saifs. In the generic saif driver, saif does not need | 53 | * itself or other saifs. In the generic saif driver, saif does not need |
54 | * to know the different clkmux. Saif only needs to know who is his master | 54 | * to know the different clkmux. Saif only needs to know who is its master |
55 | * and operating his master to generate the proper clock rate for him. | 55 | * and operating its master to generate the proper clock rate for it. |
56 | * The master id is provided in mach-specific layer according to different | 56 | * The master id is provided in mach-specific layer according to different |
57 | * clkmux setting. | 57 | * clkmux setting. |
58 | */ | 58 | */ |
@@ -76,7 +76,7 @@ static int mxs_saif_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
76 | * Since SAIF may work on EXTMASTER mode, IOW, it's working BITCLK&LRCLK | 76 | * Since SAIF may work on EXTMASTER mode, IOW, it's working BITCLK&LRCLK |
77 | * is provided by other SAIF, we provide a interface here to get its master | 77 | * is provided by other SAIF, we provide a interface here to get its master |
78 | * from its master_id. | 78 | * from its master_id. |
79 | * Note that the master could be himself. | 79 | * Note that the master could be itself. |
80 | */ | 80 | */ |
81 | static inline struct mxs_saif *mxs_saif_get_master(struct mxs_saif * saif) | 81 | static inline struct mxs_saif *mxs_saif_get_master(struct mxs_saif * saif) |
82 | { | 82 | { |
@@ -516,7 +516,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, | |||
516 | } | 516 | } |
517 | 517 | ||
518 | /* | 518 | /* |
519 | * If the saif's master is not himself, we also need to enable | 519 | * If the saif's master is not itself, we also need to enable |
520 | * itself clk for its internal basic logic to work. | 520 | * itself clk for its internal basic logic to work. |
521 | */ | 521 | */ |
522 | if (saif != master_saif) { | 522 | if (saif != master_saif) { |
@@ -804,13 +804,6 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
804 | return 0; | 804 | return 0; |
805 | } | 805 | } |
806 | 806 | ||
807 | static int mxs_saif_remove(struct platform_device *pdev) | ||
808 | { | ||
809 | mxs_pcm_platform_unregister(&pdev->dev); | ||
810 | |||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | static const struct of_device_id mxs_saif_dt_ids[] = { | 807 | static const struct of_device_id mxs_saif_dt_ids[] = { |
815 | { .compatible = "fsl,imx28-saif", }, | 808 | { .compatible = "fsl,imx28-saif", }, |
816 | { /* sentinel */ } | 809 | { /* sentinel */ } |
@@ -819,7 +812,6 @@ MODULE_DEVICE_TABLE(of, mxs_saif_dt_ids); | |||
819 | 812 | ||
820 | static struct platform_driver mxs_saif_driver = { | 813 | static struct platform_driver mxs_saif_driver = { |
821 | .probe = mxs_saif_probe, | 814 | .probe = mxs_saif_probe, |
822 | .remove = mxs_saif_remove, | ||
823 | 815 | ||
824 | .driver = { | 816 | .driver = { |
825 | .name = "mxs-saif", | 817 | .name = "mxs-saif", |
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 83433fdea32a..86c75384c3c8 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c | |||
@@ -36,10 +36,10 @@ static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) | |||
36 | 36 | ||
37 | if (mcbsp->pdata->reg_size == 2) { | 37 | if (mcbsp->pdata->reg_size == 2) { |
38 | ((u16 *)mcbsp->reg_cache)[reg] = (u16)val; | 38 | ((u16 *)mcbsp->reg_cache)[reg] = (u16)val; |
39 | __raw_writew((u16)val, addr); | 39 | writew_relaxed((u16)val, addr); |
40 | } else { | 40 | } else { |
41 | ((u32 *)mcbsp->reg_cache)[reg] = val; | 41 | ((u32 *)mcbsp->reg_cache)[reg] = val; |
42 | __raw_writel(val, addr); | 42 | writel_relaxed(val, addr); |
43 | } | 43 | } |
44 | } | 44 | } |
45 | 45 | ||
@@ -48,22 +48,22 @@ static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache) | |||
48 | void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step; | 48 | void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step; |
49 | 49 | ||
50 | if (mcbsp->pdata->reg_size == 2) { | 50 | if (mcbsp->pdata->reg_size == 2) { |
51 | return !from_cache ? __raw_readw(addr) : | 51 | return !from_cache ? readw_relaxed(addr) : |
52 | ((u16 *)mcbsp->reg_cache)[reg]; | 52 | ((u16 *)mcbsp->reg_cache)[reg]; |
53 | } else { | 53 | } else { |
54 | return !from_cache ? __raw_readl(addr) : | 54 | return !from_cache ? readl_relaxed(addr) : |
55 | ((u32 *)mcbsp->reg_cache)[reg]; | 55 | ((u32 *)mcbsp->reg_cache)[reg]; |
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) | 59 | static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) |
60 | { | 60 | { |
61 | __raw_writel(val, mcbsp->st_data->io_base_st + reg); | 61 | writel_relaxed(val, mcbsp->st_data->io_base_st + reg); |
62 | } | 62 | } |
63 | 63 | ||
64 | static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg) | 64 | static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg) |
65 | { | 65 | { |
66 | return __raw_readl(mcbsp->st_data->io_base_st + reg); | 66 | return readl_relaxed(mcbsp->st_data->io_base_st + reg); |
67 | } | 67 | } |
68 | 68 | ||
69 | #define MCBSP_READ(mcbsp, reg) \ | 69 | #define MCBSP_READ(mcbsp, reg) \ |
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 6d216cb6c19b..3fde9e402710 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c | |||
@@ -100,12 +100,12 @@ static int n810_startup(struct snd_pcm_substream *substream) | |||
100 | SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); | 100 | SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); |
101 | 101 | ||
102 | n810_ext_control(&codec->dapm); | 102 | n810_ext_control(&codec->dapm); |
103 | return clk_enable(sys_clkout2); | 103 | return clk_prepare_enable(sys_clkout2); |
104 | } | 104 | } |
105 | 105 | ||
106 | static void n810_shutdown(struct snd_pcm_substream *substream) | 106 | static void n810_shutdown(struct snd_pcm_substream *substream) |
107 | { | 107 | { |
108 | clk_disable(sys_clkout2); | 108 | clk_disable_unprepare(sys_clkout2); |
109 | } | 109 | } |
110 | 110 | ||
111 | static int n810_hw_params(struct snd_pcm_substream *substream, | 111 | static int n810_hw_params(struct snd_pcm_substream *substream, |
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 12e566be3793..1bd531d718f9 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c | |||
@@ -61,12 +61,12 @@ struct omap_dmic { | |||
61 | 61 | ||
62 | static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) | 62 | static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) |
63 | { | 63 | { |
64 | __raw_writel(val, dmic->io_base + reg); | 64 | writel_relaxed(val, dmic->io_base + reg); |
65 | } | 65 | } |
66 | 66 | ||
67 | static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg) | 67 | static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg) |
68 | { | 68 | { |
69 | return __raw_readl(dmic->io_base + reg); | 69 | return readl_relaxed(dmic->io_base + reg); |
70 | } | 70 | } |
71 | 71 | ||
72 | static inline void omap_dmic_start(struct omap_dmic *dmic) | 72 | static inline void omap_dmic_start(struct omap_dmic *dmic) |
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index cd9ee167959d..2f5b1536477e 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c | |||
@@ -74,12 +74,12 @@ struct omap_mcpdm { | |||
74 | 74 | ||
75 | static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val) | 75 | static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val) |
76 | { | 76 | { |
77 | __raw_writel(val, mcpdm->io_base + reg); | 77 | writel_relaxed(val, mcpdm->io_base + reg); |
78 | } | 78 | } |
79 | 79 | ||
80 | static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg) | 80 | static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg) |
81 | { | 81 | { |
82 | return __raw_readl(mcpdm->io_base + reg); | 82 | return readl_relaxed(mcpdm->io_base + reg); |
83 | } | 83 | } |
84 | 84 | ||
85 | #ifdef DEBUG | 85 | #ifdef DEBUG |
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index b8fa9862e54c..07b8b7bc9d20 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -45,8 +45,6 @@ static const struct snd_pcm_hardware omap_pcm_hardware = { | |||
45 | SNDRV_PCM_INFO_PAUSE | | 45 | SNDRV_PCM_INFO_PAUSE | |
46 | SNDRV_PCM_INFO_RESUME | | 46 | SNDRV_PCM_INFO_RESUME | |
47 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | 47 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, |
48 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
49 | SNDRV_PCM_FMTBIT_S32_LE, | ||
50 | .period_bytes_min = 32, | 48 | .period_bytes_min = 32, |
51 | .period_bytes_max = 64 * 1024, | 49 | .period_bytes_max = 64 * 1024, |
52 | .periods_min = 2, | 50 | .periods_min = 2, |
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 4db74a083db1..6473052b6899 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -11,7 +11,7 @@ config SND_PXA2XX_SOC | |||
11 | config SND_MMP_SOC | 11 | config SND_MMP_SOC |
12 | bool "Soc Audio for Marvell MMP chips" | 12 | bool "Soc Audio for Marvell MMP chips" |
13 | depends on ARCH_MMP | 13 | depends on ARCH_MMP |
14 | select SND_DMAENGINE_PCM | 14 | select SND_SOC_GENERIC_DMAENGINE_PCM |
15 | select SND_ARM | 15 | select SND_ARM |
16 | help | 16 | help |
17 | Say Y if you want to add support for codecs attached to | 17 | Say Y if you want to add support for codecs attached to |
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c index 7929e19b0ef5..5e8d81330173 100644 --- a/sound/soc/pxa/mmp-pcm.c +++ b/sound/soc/pxa/mmp-pcm.c | |||
@@ -36,14 +36,9 @@ struct mmp_dma_data { | |||
36 | SNDRV_PCM_INFO_PAUSE | \ | 36 | SNDRV_PCM_INFO_PAUSE | \ |
37 | SNDRV_PCM_INFO_RESUME) | 37 | SNDRV_PCM_INFO_RESUME) |
38 | 38 | ||
39 | #define MMP_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
40 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
41 | SNDRV_PCM_FMTBIT_S32_LE) | ||
42 | |||
43 | static struct snd_pcm_hardware mmp_pcm_hardware[] = { | 39 | static struct snd_pcm_hardware mmp_pcm_hardware[] = { |
44 | { | 40 | { |
45 | .info = MMP_PCM_INFO, | 41 | .info = MMP_PCM_INFO, |
46 | .formats = MMP_PCM_FORMATS, | ||
47 | .period_bytes_min = 1024, | 42 | .period_bytes_min = 1024, |
48 | .period_bytes_max = 2048, | 43 | .period_bytes_max = 2048, |
49 | .periods_min = 2, | 44 | .periods_min = 2, |
@@ -53,7 +48,6 @@ static struct snd_pcm_hardware mmp_pcm_hardware[] = { | |||
53 | }, | 48 | }, |
54 | { | 49 | { |
55 | .info = MMP_PCM_INFO, | 50 | .info = MMP_PCM_INFO, |
56 | .formats = MMP_PCM_FORMATS, | ||
57 | .period_bytes_min = 1024, | 51 | .period_bytes_min = 1024, |
58 | .period_bytes_max = 2048, | 52 | .period_bytes_max = 2048, |
59 | .periods_min = 2, | 53 | .periods_min = 2, |
@@ -67,27 +61,15 @@ static int mmp_pcm_hw_params(struct snd_pcm_substream *substream, | |||
67 | struct snd_pcm_hw_params *params) | 61 | struct snd_pcm_hw_params *params) |
68 | { | 62 | { |
69 | struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); | 63 | struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); |
70 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
71 | struct snd_dmaengine_dai_dma_data *dma_params; | ||
72 | struct dma_slave_config slave_config; | 64 | struct dma_slave_config slave_config; |
73 | int ret; | 65 | int ret; |
74 | 66 | ||
75 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 67 | ret = |
76 | if (!dma_params) | 68 | snd_dmaengine_pcm_prepare_slave_config(substream, params, |
77 | return 0; | 69 | &slave_config); |
78 | |||
79 | ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config); | ||
80 | if (ret) | 70 | if (ret) |
81 | return ret; | 71 | return ret; |
82 | 72 | ||
83 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
84 | slave_config.dst_addr = dma_params->addr; | ||
85 | slave_config.dst_maxburst = 4; | ||
86 | } else { | ||
87 | slave_config.src_addr = dma_params->addr; | ||
88 | slave_config.src_maxburst = 4; | ||
89 | } | ||
90 | |||
91 | ret = dmaengine_slave_config(chan, &slave_config); | 73 | ret = dmaengine_slave_config(chan, &slave_config); |
92 | if (ret) | 74 | if (ret) |
93 | return ret; | 75 | return ret; |
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c index d219880815c0..fb8461e1b1f6 100644 --- a/sound/soc/s6000/s6000-pcm.c +++ b/sound/soc/s6000/s6000-pcm.c | |||
@@ -33,13 +33,6 @@ static struct snd_pcm_hardware s6000_pcm_hardware = { | |||
33 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 33 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
34 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 34 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
35 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_JOINT_DUPLEX), | 35 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_JOINT_DUPLEX), |
36 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE), | ||
37 | .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_5512 | \ | ||
38 | SNDRV_PCM_RATE_8000_192000), | ||
39 | .rate_min = 0, | ||
40 | .rate_max = 1562500, | ||
41 | .channels_min = 2, | ||
42 | .channels_max = 8, | ||
43 | .buffer_bytes_max = 0x7ffffff0, | 36 | .buffer_bytes_max = 0x7ffffff0, |
44 | .period_bytes_min = 16, | 37 | .period_bytes_min = 16, |
45 | .period_bytes_max = 0xfffff0, | 38 | .period_bytes_max = 0xfffff0, |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 37459dfd168d..27930fc432dc 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -1,13 +1,22 @@ | |||
1 | config SND_SOC_SAMSUNG | 1 | config SND_SOC_SAMSUNG |
2 | tristate "ASoC support for Samsung" | 2 | tristate "ASoC support for Samsung" |
3 | depends on PLAT_SAMSUNG | 3 | depends on PLAT_SAMSUNG |
4 | select S3C64XX_DMA if ARCH_S3C64XX | 4 | select S3C2410_DMA if ARCH_S3C24XX |
5 | select S3C24XX_DMA if ARCH_S3C24XX | 5 | select S3C64XX_PL080 if ARCH_S3C64XX |
6 | select SND_S3C_DMA if !ARCH_S3C24XX | ||
7 | select SND_S3C_DMA_LEGACY if ARCH_S3C24XX | ||
8 | select SND_SOC_GENERIC_DMAENGINE_PCM if !ARCH_S3C24XX | ||
6 | help | 9 | help |
7 | Say Y or M if you want to add support for codecs attached to | 10 | Say Y or M if you want to add support for codecs attached to |
8 | the Samsung SoCs' Audio interfaces. You will also need to | 11 | the Samsung SoCs' Audio interfaces. You will also need to |
9 | select the audio interfaces to support below. | 12 | select the audio interfaces to support below. |
10 | 13 | ||
14 | config SND_S3C_DMA | ||
15 | tristate | ||
16 | |||
17 | config SND_S3C_DMA_LEGACY | ||
18 | tristate | ||
19 | |||
11 | config SND_S3C24XX_I2S | 20 | config SND_S3C24XX_I2S |
12 | tristate | 21 | tristate |
13 | select S3C2410_DMA | 22 | select S3C2410_DMA |
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 709f6059ad67..86715d8efee6 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | # S3c24XX Platform Support | 1 | # S3c24XX Platform Support |
2 | snd-soc-s3c24xx-objs := dma.o | 2 | snd-soc-s3c-dma-objs := dmaengine.o |
3 | snd-soc-s3c-dma-legacy-objs := dma.o | ||
3 | snd-soc-idma-objs := idma.o | 4 | snd-soc-idma-objs := idma.o |
4 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o | 5 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o |
5 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o | 6 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o |
@@ -9,7 +10,8 @@ snd-soc-samsung-spdif-objs := spdif.o | |||
9 | snd-soc-pcm-objs := pcm.o | 10 | snd-soc-pcm-objs := pcm.o |
10 | snd-soc-i2s-objs := i2s.o | 11 | snd-soc-i2s-objs := i2s.o |
11 | 12 | ||
12 | obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c24xx.o | 13 | obj-$(CONFIG_SND_S3C_DMA) += snd-soc-s3c-dma.o |
14 | obj-$(CONFIG_SND_S3C_DMA_LEGACY) += snd-soc-s3c-dma-legacy.o | ||
13 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o | 15 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o |
14 | obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o | 16 | obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o |
15 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o | 17 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o |
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 350ba23a9893..4a88e36c82ec 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
@@ -221,24 +221,6 @@ static struct snd_ac97_bus_ops s3c_ac97_ops = { | |||
221 | .reset = s3c_ac97_cold_reset, | 221 | .reset = s3c_ac97_cold_reset, |
222 | }; | 222 | }; |
223 | 223 | ||
224 | static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, | ||
225 | struct snd_pcm_hw_params *params, | ||
226 | struct snd_soc_dai *dai) | ||
227 | { | ||
228 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
229 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
230 | struct s3c_dma_params *dma_data; | ||
231 | |||
232 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
233 | dma_data = &s3c_ac97_pcm_out; | ||
234 | else | ||
235 | dma_data = &s3c_ac97_pcm_in; | ||
236 | |||
237 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | 224 | static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, |
243 | struct snd_soc_dai *dai) | 225 | struct snd_soc_dai *dai) |
244 | { | 226 | { |
@@ -279,21 +261,6 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
279 | return 0; | 261 | return 0; |
280 | } | 262 | } |
281 | 263 | ||
282 | static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream, | ||
283 | struct snd_pcm_hw_params *params, | ||
284 | struct snd_soc_dai *dai) | ||
285 | { | ||
286 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
287 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
288 | |||
289 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
290 | return -ENODEV; | ||
291 | else | ||
292 | snd_soc_dai_set_dma_data(cpu_dai, substream, &s3c_ac97_mic_in); | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, | 264 | static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, |
298 | int cmd, struct snd_soc_dai *dai) | 265 | int cmd, struct snd_soc_dai *dai) |
299 | { | 266 | { |
@@ -329,15 +296,27 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, | |||
329 | } | 296 | } |
330 | 297 | ||
331 | static const struct snd_soc_dai_ops s3c_ac97_dai_ops = { | 298 | static const struct snd_soc_dai_ops s3c_ac97_dai_ops = { |
332 | .hw_params = s3c_ac97_hw_params, | ||
333 | .trigger = s3c_ac97_trigger, | 299 | .trigger = s3c_ac97_trigger, |
334 | }; | 300 | }; |
335 | 301 | ||
336 | static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = { | 302 | static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = { |
337 | .hw_params = s3c_ac97_hw_mic_params, | ||
338 | .trigger = s3c_ac97_mic_trigger, | 303 | .trigger = s3c_ac97_mic_trigger, |
339 | }; | 304 | }; |
340 | 305 | ||
306 | static int s3c_ac97_dai_probe(struct snd_soc_dai *dai) | ||
307 | { | ||
308 | samsung_asoc_init_dma_data(dai, &s3c_ac97_pcm_out, &s3c_ac97_pcm_in); | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int s3c_ac97_mic_dai_probe(struct snd_soc_dai *dai) | ||
314 | { | ||
315 | samsung_asoc_init_dma_data(dai, NULL, &s3c_ac97_mic_in); | ||
316 | |||
317 | return 0; | ||
318 | } | ||
319 | |||
341 | static struct snd_soc_dai_driver s3c_ac97_dai[] = { | 320 | static struct snd_soc_dai_driver s3c_ac97_dai[] = { |
342 | [S3C_AC97_DAI_PCM] = { | 321 | [S3C_AC97_DAI_PCM] = { |
343 | .name = "samsung-ac97", | 322 | .name = "samsung-ac97", |
@@ -354,6 +333,7 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = { | |||
354 | .channels_max = 2, | 333 | .channels_max = 2, |
355 | .rates = SNDRV_PCM_RATE_8000_48000, | 334 | .rates = SNDRV_PCM_RATE_8000_48000, |
356 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 335 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
336 | .probe = s3c_ac97_dai_probe, | ||
357 | .ops = &s3c_ac97_dai_ops, | 337 | .ops = &s3c_ac97_dai_ops, |
358 | }, | 338 | }, |
359 | [S3C_AC97_DAI_MIC] = { | 339 | [S3C_AC97_DAI_MIC] = { |
@@ -365,6 +345,7 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = { | |||
365 | .channels_max = 1, | 345 | .channels_max = 1, |
366 | .rates = SNDRV_PCM_RATE_8000_48000, | 346 | .rates = SNDRV_PCM_RATE_8000_48000, |
367 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 347 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
348 | .probe = s3c_ac97_mic_dai_probe, | ||
368 | .ops = &s3c_ac97_mic_dai_ops, | 349 | .ops = &s3c_ac97_mic_dai_ops, |
369 | }, | 350 | }, |
370 | }; | 351 | }; |
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index fe2748b494d4..dc09b71b7d9f 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c | |||
@@ -35,12 +35,6 @@ static const struct snd_pcm_hardware dma_hardware = { | |||
35 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 35 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
36 | SNDRV_PCM_INFO_MMAP | | 36 | SNDRV_PCM_INFO_MMAP | |
37 | SNDRV_PCM_INFO_MMAP_VALID, | 37 | SNDRV_PCM_INFO_MMAP_VALID, |
38 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
39 | SNDRV_PCM_FMTBIT_U16_LE | | ||
40 | SNDRV_PCM_FMTBIT_U8 | | ||
41 | SNDRV_PCM_FMTBIT_S8, | ||
42 | .channels_min = 2, | ||
43 | .channels_max = 2, | ||
44 | .buffer_bytes_max = 128*1024, | 38 | .buffer_bytes_max = 128*1024, |
45 | .period_bytes_min = PAGE_SIZE, | 39 | .period_bytes_min = PAGE_SIZE, |
46 | .period_bytes_max = PAGE_SIZE*2, | 40 | .period_bytes_max = PAGE_SIZE*2, |
@@ -441,6 +435,14 @@ static struct snd_soc_platform_driver samsung_asoc_platform = { | |||
441 | .pcm_free = dma_free_dma_buffers, | 435 | .pcm_free = dma_free_dma_buffers, |
442 | }; | 436 | }; |
443 | 437 | ||
438 | void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, | ||
439 | struct s3c_dma_params *playback, | ||
440 | struct s3c_dma_params *capture) | ||
441 | { | ||
442 | snd_soc_dai_init_dma_data(dai, playback, capture); | ||
443 | } | ||
444 | EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); | ||
445 | |||
444 | int samsung_asoc_dma_platform_register(struct device *dev) | 446 | int samsung_asoc_dma_platform_register(struct device *dev) |
445 | { | 447 | { |
446 | return snd_soc_register_platform(dev, &samsung_asoc_platform); | 448 | return snd_soc_register_platform(dev, &samsung_asoc_platform); |
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h index 0e86315a3eaf..225e5378014e 100644 --- a/sound/soc/samsung/dma.h +++ b/sound/soc/samsung/dma.h | |||
@@ -12,6 +12,8 @@ | |||
12 | #ifndef _S3C_AUDIO_H | 12 | #ifndef _S3C_AUDIO_H |
13 | #define _S3C_AUDIO_H | 13 | #define _S3C_AUDIO_H |
14 | 14 | ||
15 | #include <sound/dmaengine_pcm.h> | ||
16 | |||
15 | struct s3c_dma_params { | 17 | struct s3c_dma_params { |
16 | struct s3c2410_dma_client *client; /* stream identifier */ | 18 | struct s3c2410_dma_client *client; /* stream identifier */ |
17 | int channel; /* Channel ID */ | 19 | int channel; /* Channel ID */ |
@@ -20,8 +22,12 @@ struct s3c_dma_params { | |||
20 | unsigned ch; | 22 | unsigned ch; |
21 | struct samsung_dma_ops *ops; | 23 | struct samsung_dma_ops *ops; |
22 | char *ch_name; | 24 | char *ch_name; |
25 | struct snd_dmaengine_dai_dma_data dma_data; | ||
23 | }; | 26 | }; |
24 | 27 | ||
28 | void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, | ||
29 | struct s3c_dma_params *playback, | ||
30 | struct s3c_dma_params *capture); | ||
25 | int samsung_asoc_dma_platform_register(struct device *dev); | 31 | int samsung_asoc_dma_platform_register(struct device *dev); |
26 | void samsung_asoc_dma_platform_unregister(struct device *dev); | 32 | void samsung_asoc_dma_platform_unregister(struct device *dev); |
27 | 33 | ||
diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c new file mode 100644 index 000000000000..3be479d51b9b --- /dev/null +++ b/sound/soc/samsung/dmaengine.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * dmaengine.c - Samsung dmaengine wrapper | ||
3 | * | ||
4 | * Author: Mark Brown <broonie@linaro.org> | ||
5 | * Copyright 2013 Linaro | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/amba/pl08x.h> | ||
20 | |||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/dmaengine_pcm.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/soc-dai.h> | ||
27 | |||
28 | #include "dma.h" | ||
29 | |||
30 | #ifdef CONFIG_ARCH_S3C64XX | ||
31 | #define filter_fn pl08x_filter_id | ||
32 | #else | ||
33 | #define filter_fn NULL | ||
34 | #endif | ||
35 | |||
36 | static const struct snd_dmaengine_pcm_config samsung_dmaengine_pcm_config = { | ||
37 | .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, | ||
38 | .compat_filter_fn = filter_fn, | ||
39 | }; | ||
40 | |||
41 | void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, | ||
42 | struct s3c_dma_params *playback, | ||
43 | struct s3c_dma_params *capture) | ||
44 | { | ||
45 | struct snd_dmaengine_dai_dma_data *playback_data = NULL; | ||
46 | struct snd_dmaengine_dai_dma_data *capture_data = NULL; | ||
47 | |||
48 | if (playback) { | ||
49 | playback_data = &playback->dma_data; | ||
50 | playback_data->filter_data = (void *)playback->channel; | ||
51 | playback_data->chan_name = playback->ch_name; | ||
52 | playback_data->addr = playback->dma_addr; | ||
53 | playback_data->addr_width = playback->dma_size; | ||
54 | } | ||
55 | if (capture) { | ||
56 | capture_data = &capture->dma_data; | ||
57 | capture_data->filter_data = (void *)capture->channel; | ||
58 | capture_data->chan_name = capture->ch_name; | ||
59 | capture_data->addr = capture->dma_addr; | ||
60 | capture_data->addr_width = capture->dma_size; | ||
61 | } | ||
62 | |||
63 | snd_soc_dai_init_dma_data(dai, playback_data, capture_data); | ||
64 | } | ||
65 | EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); | ||
66 | |||
67 | int samsung_asoc_dma_platform_register(struct device *dev) | ||
68 | { | ||
69 | return snd_dmaengine_pcm_register(dev, &samsung_dmaengine_pcm_config, | ||
70 | SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME | | ||
71 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | ||
72 | SND_DMAENGINE_PCM_FLAG_COMPAT); | ||
73 | } | ||
74 | EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); | ||
75 | |||
76 | void samsung_asoc_dma_platform_unregister(struct device *dev) | ||
77 | { | ||
78 | return snd_dmaengine_pcm_unregister(dev); | ||
79 | } | ||
80 | EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_unregister); | ||
81 | |||
82 | MODULE_AUTHOR("Mark Brown <broonie@linaro.org>"); | ||
83 | MODULE_DESCRIPTION("Samsung dmaengine ASoC driver"); | ||
84 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index a5cbdb4f1655..92f64363427d 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
@@ -702,6 +702,8 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, | |||
702 | } | 702 | } |
703 | writel(mod, i2s->addr + I2SMOD); | 703 | writel(mod, i2s->addr + I2SMOD); |
704 | 704 | ||
705 | samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); | ||
706 | |||
705 | i2s->frmclk = params_rate(params); | 707 | i2s->frmclk = params_rate(params); |
706 | 708 | ||
707 | return 0; | 709 | return 0; |
@@ -946,8 +948,11 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) | |||
946 | struct i2s_dai *i2s = to_info(dai); | 948 | struct i2s_dai *i2s = to_info(dai); |
947 | struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; | 949 | struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; |
948 | 950 | ||
949 | if (other && other->clk) /* If this is probe on secondary */ | 951 | if (other && other->clk) { /* If this is probe on secondary */ |
952 | samsung_asoc_init_dma_data(dai, &other->sec_dai->dma_playback, | ||
953 | NULL); | ||
950 | goto probe_exit; | 954 | goto probe_exit; |
955 | } | ||
951 | 956 | ||
952 | i2s->addr = ioremap(i2s->base, 0x100); | 957 | i2s->addr = ioremap(i2s->base, 0x100); |
953 | if (i2s->addr == NULL) { | 958 | if (i2s->addr == NULL) { |
@@ -963,7 +968,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) | |||
963 | } | 968 | } |
964 | clk_prepare_enable(i2s->clk); | 969 | clk_prepare_enable(i2s->clk); |
965 | 970 | ||
966 | snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); | 971 | samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); |
967 | 972 | ||
968 | if (other) { | 973 | if (other) { |
969 | other->addr = i2s->addr; | 974 | other->addr = i2s->addr; |
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c index e4f318fc2f82..3d5cf1530b6f 100644 --- a/sound/soc/samsung/idma.c +++ b/sound/soc/samsung/idma.c | |||
@@ -35,14 +35,6 @@ static const struct snd_pcm_hardware idma_hardware = { | |||
35 | SNDRV_PCM_INFO_MMAP_VALID | | 35 | SNDRV_PCM_INFO_MMAP_VALID | |
36 | SNDRV_PCM_INFO_PAUSE | | 36 | SNDRV_PCM_INFO_PAUSE | |
37 | SNDRV_PCM_INFO_RESUME, | 37 | SNDRV_PCM_INFO_RESUME, |
38 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
39 | SNDRV_PCM_FMTBIT_U16_LE | | ||
40 | SNDRV_PCM_FMTBIT_S24_LE | | ||
41 | SNDRV_PCM_FMTBIT_U24_LE | | ||
42 | SNDRV_PCM_FMTBIT_U8 | | ||
43 | SNDRV_PCM_FMTBIT_S8, | ||
44 | .channels_min = 2, | ||
45 | .channels_max = 2, | ||
46 | .buffer_bytes_max = MAX_IDMA_BUFFER, | 38 | .buffer_bytes_max = MAX_IDMA_BUFFER, |
47 | .period_bytes_min = 128, | 39 | .period_bytes_min = 128, |
48 | .period_bytes_max = MAX_IDMA_PERIOD, | 40 | .period_bytes_max = MAX_IDMA_PERIOD, |
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index e54256fc4b2c..6a5e4bf6ac96 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c | |||
@@ -275,7 +275,6 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, | |||
275 | { | 275 | { |
276 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 276 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
277 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 277 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
278 | struct s3c_dma_params *dma_data; | ||
279 | void __iomem *regs = pcm->regs; | 278 | void __iomem *regs = pcm->regs; |
280 | struct clk *clk; | 279 | struct clk *clk; |
281 | int sclk_div, sync_div; | 280 | int sclk_div, sync_div; |
@@ -284,13 +283,6 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, | |||
284 | 283 | ||
285 | dev_dbg(pcm->dev, "Entered %s\n", __func__); | 284 | dev_dbg(pcm->dev, "Entered %s\n", __func__); |
286 | 285 | ||
287 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
288 | dma_data = pcm->dma_playback; | ||
289 | else | ||
290 | dma_data = pcm->dma_capture; | ||
291 | |||
292 | snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); | ||
293 | |||
294 | /* Strictly check for sample size */ | 286 | /* Strictly check for sample size */ |
295 | switch (params_format(params)) { | 287 | switch (params_format(params)) { |
296 | case SNDRV_PCM_FORMAT_S16_LE: | 288 | case SNDRV_PCM_FORMAT_S16_LE: |
@@ -461,10 +453,20 @@ static const struct snd_soc_dai_ops s3c_pcm_dai_ops = { | |||
461 | .set_fmt = s3c_pcm_set_fmt, | 453 | .set_fmt = s3c_pcm_set_fmt, |
462 | }; | 454 | }; |
463 | 455 | ||
456 | static int s3c_pcm_dai_probe(struct snd_soc_dai *dai) | ||
457 | { | ||
458 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(dai); | ||
459 | |||
460 | snd_soc_dai_init_dma_data(dai, pcm->dma_playback, pcm->dma_capture); | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
464 | #define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000 | 465 | #define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000 |
465 | 466 | ||
466 | #define S3C_PCM_DAI_DECLARE \ | 467 | #define S3C_PCM_DAI_DECLARE \ |
467 | .symmetric_rates = 1, \ | 468 | .symmetric_rates = 1, \ |
469 | .probe = s3c_pcm_dai_probe, \ | ||
468 | .ops = &s3c_pcm_dai_ops, \ | 470 | .ops = &s3c_pcm_dai_ops, \ |
469 | .playback = { \ | 471 | .playback = { \ |
470 | .channels_min = 2, \ | 472 | .channels_min = 2, \ |
diff --git a/sound/soc/samsung/regs-ac97.h b/sound/soc/samsung/regs-ac97.h index c3878f7acb83..a71be45bbffc 100644 --- a/sound/soc/samsung/regs-ac97.h +++ b/sound/soc/samsung/regs-ac97.h | |||
@@ -1,5 +1,4 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/regs-ac97.h | 1 | /* |
2 | * | ||
3 | * Copyright (c) 2006 Simtec Electronics <linux@simtec.co.uk> | 2 | * Copyright (c) 2006 Simtec Electronics <linux@simtec.co.uk> |
4 | * http://www.simtec.co.uk/products/SWLINUX/ | 3 | * http://www.simtec.co.uk/products/SWLINUX/ |
5 | * | 4 | * |
@@ -10,8 +9,8 @@ | |||
10 | * S3C2440 AC97 Controller | 9 | * S3C2440 AC97 Controller |
11 | */ | 10 | */ |
12 | 11 | ||
13 | #ifndef __ASM_ARCH_REGS_AC97_H | 12 | #ifndef __SAMSUNG_REGS_AC97_H__ |
14 | #define __ASM_ARCH_REGS_AC97_H __FILE__ | 13 | #define __SAMSUNG_REGS_AC97_H__ |
15 | 14 | ||
16 | #define S3C_AC97_GLBCTRL (0x00) | 15 | #define S3C_AC97_GLBCTRL (0x00) |
17 | 16 | ||
@@ -64,4 +63,4 @@ | |||
64 | #define S3C_AC97_PCM_DATA (0x18) | 63 | #define S3C_AC97_PCM_DATA (0x18) |
65 | #define S3C_AC97_MIC_DATA (0x1C) | 64 | #define S3C_AC97_MIC_DATA (0x1C) |
66 | 65 | ||
67 | #endif /* __ASM_ARCH_REGS_AC97_H */ | 66 | #endif /* __SAMSUNG_REGS_AC97_H__ */ |
diff --git a/sound/soc/samsung/regs-iis.h b/sound/soc/samsung/regs-iis.h index a18d35e7a735..dc6cbbe9c4f0 100644 --- a/sound/soc/samsung/regs-iis.h +++ b/sound/soc/samsung/regs-iis.h | |||
@@ -1,5 +1,4 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/regs-iis.h | 1 | /* |
2 | * | ||
3 | * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk> | 2 | * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk> |
4 | * http://www.simtec.co.uk/products/SWLINUX/ | 3 | * http://www.simtec.co.uk/products/SWLINUX/ |
5 | * | 4 | * |
@@ -10,8 +9,8 @@ | |||
10 | * S3C2410 IIS register definition | 9 | * S3C2410 IIS register definition |
11 | */ | 10 | */ |
12 | 11 | ||
13 | #ifndef __ASM_ARCH_REGS_IIS_H | 12 | #ifndef __SAMSUNG_REGS_IIS_H__ |
14 | #define __ASM_ARCH_REGS_IIS_H | 13 | #define __SAMSUNG_REGS_IIS_H__ |
15 | 14 | ||
16 | #define S3C2410_IISCON (0x00) | 15 | #define S3C2410_IISCON (0x00) |
17 | 16 | ||
@@ -67,4 +66,4 @@ | |||
67 | 66 | ||
68 | #define S3C2410_IISFIFO (0x10) | 67 | #define S3C2410_IISFIFO (0x10) |
69 | 68 | ||
70 | #endif /* __ASM_ARCH_REGS_IIS_H */ | 69 | #endif /* __SAMSUNG_REGS_IIS_H__ */ |
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 14011d90d70a..ff60e11ecb56 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig | |||
@@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU | |||
37 | config SND_SOC_RCAR | 37 | config SND_SOC_RCAR |
38 | tristate "R-Car series SRU/SCU/SSIU/SSI support" | 38 | tristate "R-Car series SRU/SCU/SSIU/SSI support" |
39 | select SND_SIMPLE_CARD | 39 | select SND_SIMPLE_CARD |
40 | select REGMAP | ||
40 | help | 41 | help |
41 | This option enables R-Car SUR/SCU/SSIU/SSI sound support | 42 | This option enables R-Car SUR/SCU/SSIU/SSI sound support |
42 | 43 | ||
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index b33ca7cd085b..6101055aae1d 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -232,9 +232,9 @@ struct fsi_stream { | |||
232 | * these are for DMAEngine | 232 | * these are for DMAEngine |
233 | */ | 233 | */ |
234 | struct dma_chan *chan; | 234 | struct dma_chan *chan; |
235 | struct sh_dmae_slave slave; /* see fsi_handler_init() */ | ||
236 | struct work_struct work; | 235 | struct work_struct work; |
237 | dma_addr_t dma; | 236 | dma_addr_t dma; |
237 | int dma_id; | ||
238 | int loop_cnt; | 238 | int loop_cnt; |
239 | int additional_pos; | 239 | int additional_pos; |
240 | }; | 240 | }; |
@@ -1410,15 +1410,6 @@ static void fsi_dma_do_work(struct work_struct *work) | |||
1410 | } | 1410 | } |
1411 | } | 1411 | } |
1412 | 1412 | ||
1413 | static bool fsi_dma_filter(struct dma_chan *chan, void *param) | ||
1414 | { | ||
1415 | struct sh_dmae_slave *slave = param; | ||
1416 | |||
1417 | chan->private = slave; | ||
1418 | |||
1419 | return true; | ||
1420 | } | ||
1421 | |||
1422 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) | 1413 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) |
1423 | { | 1414 | { |
1424 | schedule_work(&io->work); | 1415 | schedule_work(&io->work); |
@@ -1446,15 +1437,34 @@ static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | |||
1446 | static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev) | 1437 | static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev) |
1447 | { | 1438 | { |
1448 | dma_cap_mask_t mask; | 1439 | dma_cap_mask_t mask; |
1440 | int is_play = fsi_stream_is_play(fsi, io); | ||
1449 | 1441 | ||
1450 | dma_cap_zero(mask); | 1442 | dma_cap_zero(mask); |
1451 | dma_cap_set(DMA_SLAVE, mask); | 1443 | dma_cap_set(DMA_SLAVE, mask); |
1452 | 1444 | ||
1453 | io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave); | 1445 | io->chan = dma_request_slave_channel_compat(mask, |
1446 | shdma_chan_filter, (void *)io->dma_id, | ||
1447 | dev, is_play ? "tx" : "rx"); | ||
1448 | if (io->chan) { | ||
1449 | struct dma_slave_config cfg; | ||
1450 | int ret; | ||
1451 | |||
1452 | cfg.slave_id = io->dma_id; | ||
1453 | cfg.dst_addr = 0; /* use default addr */ | ||
1454 | cfg.src_addr = 0; /* use default addr */ | ||
1455 | cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; | ||
1456 | |||
1457 | ret = dmaengine_slave_config(io->chan, &cfg); | ||
1458 | if (ret < 0) { | ||
1459 | dma_release_channel(io->chan); | ||
1460 | io->chan = NULL; | ||
1461 | } | ||
1462 | } | ||
1463 | |||
1454 | if (!io->chan) { | 1464 | if (!io->chan) { |
1455 | 1465 | ||
1456 | /* switch to PIO handler */ | 1466 | /* switch to PIO handler */ |
1457 | if (fsi_stream_is_play(fsi, io)) | 1467 | if (is_play) |
1458 | fsi->playback.handler = &fsi_pio_push_handler; | 1468 | fsi->playback.handler = &fsi_pio_push_handler; |
1459 | else | 1469 | else |
1460 | fsi->capture.handler = &fsi_pio_pop_handler; | 1470 | fsi->capture.handler = &fsi_pio_pop_handler; |
@@ -1960,7 +1970,7 @@ static void fsi_handler_init(struct fsi_priv *fsi, | |||
1960 | fsi->capture.priv = fsi; | 1970 | fsi->capture.priv = fsi; |
1961 | 1971 | ||
1962 | if (info->tx_id) { | 1972 | if (info->tx_id) { |
1963 | fsi->playback.slave.shdma_slave.slave_id = info->tx_id; | 1973 | fsi->playback.dma_id = info->tx_id; |
1964 | fsi->playback.handler = &fsi_dma_push_handler; | 1974 | fsi->playback.handler = &fsi_dma_push_handler; |
1965 | } | 1975 | } |
1966 | } | 1976 | } |
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 9430097979a5..a53235c4d1b0 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c | |||
@@ -19,8 +19,8 @@ | |||
19 | struct rsnd_adg { | 19 | struct rsnd_adg { |
20 | struct clk *clk[CLKMAX]; | 20 | struct clk *clk[CLKMAX]; |
21 | 21 | ||
22 | int rate_of_441khz_div_6; | 22 | int rbga_rate_for_441khz_div_6; /* RBGA */ |
23 | int rate_of_48khz_div_6; | 23 | int rbgb_rate_for_48khz_div_6; /* RBGB */ |
24 | u32 ckr; | 24 | u32 ckr; |
25 | }; | 25 | }; |
26 | 26 | ||
@@ -30,41 +30,114 @@ struct rsnd_adg { | |||
30 | i++, (pos) = adg->clk[i]) | 30 | i++, (pos) = adg->clk[i]) |
31 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) | 31 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) |
32 | 32 | ||
33 | static enum rsnd_reg rsnd_adg_ssi_reg_get(int id) | 33 | static int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, |
34 | struct rsnd_mod *mod, | ||
35 | unsigned int src_rate, | ||
36 | unsigned int dst_rate) | ||
34 | { | 37 | { |
35 | enum rsnd_reg reg; | 38 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); |
39 | struct device *dev = rsnd_priv_to_dev(priv); | ||
40 | int idx, sel, div, shift; | ||
41 | u32 mask, val; | ||
42 | int id = rsnd_mod_id(mod); | ||
43 | unsigned int sel_rate [] = { | ||
44 | clk_get_rate(adg->clk[CLKA]), /* 000: CLKA */ | ||
45 | clk_get_rate(adg->clk[CLKB]), /* 001: CLKB */ | ||
46 | clk_get_rate(adg->clk[CLKC]), /* 010: CLKC */ | ||
47 | 0, /* 011: MLBCLK (not used) */ | ||
48 | adg->rbga_rate_for_441khz_div_6,/* 100: RBGA */ | ||
49 | adg->rbgb_rate_for_48khz_div_6, /* 101: RBGB */ | ||
50 | }; | ||
51 | |||
52 | /* find div (= 1/128, 1/256, 1/512, 1/1024, 1/2048 */ | ||
53 | for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { | ||
54 | for (div = 128, idx = 0; | ||
55 | div <= 2048; | ||
56 | div *= 2, idx++) { | ||
57 | if (src_rate == sel_rate[sel] / div) { | ||
58 | val = (idx << 4) | sel; | ||
59 | goto find_rate; | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | dev_err(dev, "can't find convert src clk\n"); | ||
64 | return -EINVAL; | ||
65 | |||
66 | find_rate: | ||
67 | shift = (id % 4) * 8; | ||
68 | mask = 0xFF << shift; | ||
69 | val = val << shift; | ||
70 | |||
71 | dev_dbg(dev, "adg convert src clk = %02x\n", val); | ||
72 | |||
73 | switch (id / 4) { | ||
74 | case 0: | ||
75 | rsnd_mod_bset(mod, AUDIO_CLK_SEL3, mask, val); | ||
76 | break; | ||
77 | case 1: | ||
78 | rsnd_mod_bset(mod, AUDIO_CLK_SEL4, mask, val); | ||
79 | break; | ||
80 | case 2: | ||
81 | rsnd_mod_bset(mod, AUDIO_CLK_SEL5, mask, val); | ||
82 | break; | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * Gen1 doesn't need dst_rate settings, | ||
87 | * since it uses SSI WS pin. | ||
88 | * see also rsnd_src_set_route_if_gen1() | ||
89 | */ | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, | ||
95 | struct rsnd_mod *mod, | ||
96 | unsigned int src_rate, | ||
97 | unsigned int dst_rate) | ||
98 | { | ||
99 | if (rsnd_is_gen1(priv)) | ||
100 | return rsnd_adg_set_convert_clk_gen1(priv, mod, | ||
101 | src_rate, dst_rate); | ||
102 | |||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val) | ||
107 | { | ||
108 | int id = rsnd_mod_id(mod); | ||
109 | int shift = (id % 4) * 8; | ||
110 | u32 mask = 0xFF << shift; | ||
111 | |||
112 | val = val << shift; | ||
36 | 113 | ||
37 | /* | 114 | /* |
38 | * SSI 8 is not connected to ADG. | 115 | * SSI 8 is not connected to ADG. |
39 | * it works with SSI 7 | 116 | * it works with SSI 7 |
40 | */ | 117 | */ |
41 | if (id == 8) | 118 | if (id == 8) |
42 | return RSND_REG_MAX; | 119 | return; |
43 | 120 | ||
44 | if (0 <= id && id <= 3) | 121 | switch (id / 4) { |
45 | reg = RSND_REG_AUDIO_CLK_SEL0; | 122 | case 0: |
46 | else if (4 <= id && id <= 7) | 123 | rsnd_mod_bset(mod, AUDIO_CLK_SEL0, mask, val); |
47 | reg = RSND_REG_AUDIO_CLK_SEL1; | 124 | break; |
48 | else | 125 | case 1: |
49 | reg = RSND_REG_AUDIO_CLK_SEL2; | 126 | rsnd_mod_bset(mod, AUDIO_CLK_SEL1, mask, val); |
50 | 127 | break; | |
51 | return reg; | 128 | case 2: |
129 | rsnd_mod_bset(mod, AUDIO_CLK_SEL2, mask, val); | ||
130 | break; | ||
131 | } | ||
52 | } | 132 | } |
53 | 133 | ||
54 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod) | 134 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod) |
55 | { | 135 | { |
56 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
57 | enum rsnd_reg reg; | ||
58 | int id; | ||
59 | |||
60 | /* | 136 | /* |
61 | * "mod" = "ssi" here. | 137 | * "mod" = "ssi" here. |
62 | * we can get "ssi id" from mod | 138 | * we can get "ssi id" from mod |
63 | */ | 139 | */ |
64 | id = rsnd_mod_id(mod); | 140 | rsnd_adg_set_ssi_clk(mod, 0); |
65 | reg = rsnd_adg_ssi_reg_get(id); | ||
66 | |||
67 | rsnd_write(priv, mod, reg, 0); | ||
68 | 141 | ||
69 | return 0; | 142 | return 0; |
70 | } | 143 | } |
@@ -75,8 +148,7 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) | |||
75 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); | 148 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); |
76 | struct device *dev = rsnd_priv_to_dev(priv); | 149 | struct device *dev = rsnd_priv_to_dev(priv); |
77 | struct clk *clk; | 150 | struct clk *clk; |
78 | enum rsnd_reg reg; | 151 | int i; |
79 | int id, shift, i; | ||
80 | u32 data; | 152 | u32 data; |
81 | int sel_table[] = { | 153 | int sel_table[] = { |
82 | [CLKA] = 0x1, | 154 | [CLKA] = 0x1, |
@@ -102,12 +174,12 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) | |||
102 | /* | 174 | /* |
103 | * find 1/6 clock from BRGA/BRGB | 175 | * find 1/6 clock from BRGA/BRGB |
104 | */ | 176 | */ |
105 | if (rate == adg->rate_of_441khz_div_6) { | 177 | if (rate == adg->rbga_rate_for_441khz_div_6) { |
106 | data = 0x10; | 178 | data = 0x10; |
107 | goto found_clock; | 179 | goto found_clock; |
108 | } | 180 | } |
109 | 181 | ||
110 | if (rate == adg->rate_of_48khz_div_6) { | 182 | if (rate == adg->rbgb_rate_for_48khz_div_6) { |
111 | data = 0x20; | 183 | data = 0x20; |
112 | goto found_clock; | 184 | goto found_clock; |
113 | } | 185 | } |
@@ -125,19 +197,10 @@ found_clock: | |||
125 | * This "mod" = "ssi" here. | 197 | * This "mod" = "ssi" here. |
126 | * we can get "ssi id" from mod | 198 | * we can get "ssi id" from mod |
127 | */ | 199 | */ |
128 | id = rsnd_mod_id(mod); | 200 | rsnd_adg_set_ssi_clk(mod, data); |
129 | reg = rsnd_adg_ssi_reg_get(id); | ||
130 | |||
131 | dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", id, i, rate); | ||
132 | |||
133 | /* | ||
134 | * Enable SSIx clock | ||
135 | */ | ||
136 | shift = (id % 4) * 8; | ||
137 | 201 | ||
138 | rsnd_bset(priv, mod, reg, | 202 | dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", |
139 | 0xFF << shift, | 203 | rsnd_mod_id(mod), i, rate); |
140 | data << shift); | ||
141 | 204 | ||
142 | return 0; | 205 | return 0; |
143 | } | 206 | } |
@@ -166,8 +229,8 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) | |||
166 | * rsnd_adg_ssi_clk_try_start() | 229 | * rsnd_adg_ssi_clk_try_start() |
167 | */ | 230 | */ |
168 | ckr = 0; | 231 | ckr = 0; |
169 | adg->rate_of_441khz_div_6 = 0; | 232 | adg->rbga_rate_for_441khz_div_6 = 0; |
170 | adg->rate_of_48khz_div_6 = 0; | 233 | adg->rbgb_rate_for_48khz_div_6 = 0; |
171 | for_each_rsnd_clk(clk, adg, i) { | 234 | for_each_rsnd_clk(clk, adg, i) { |
172 | rate = clk_get_rate(clk); | 235 | rate = clk_get_rate(clk); |
173 | 236 | ||
@@ -175,14 +238,14 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) | |||
175 | continue; | 238 | continue; |
176 | 239 | ||
177 | /* RBGA */ | 240 | /* RBGA */ |
178 | if (!adg->rate_of_441khz_div_6 && (0 == rate % 44100)) { | 241 | if (!adg->rbga_rate_for_441khz_div_6 && (0 == rate % 44100)) { |
179 | adg->rate_of_441khz_div_6 = rate / 6; | 242 | adg->rbga_rate_for_441khz_div_6 = rate / 6; |
180 | ckr |= brg_table[i] << 20; | 243 | ckr |= brg_table[i] << 20; |
181 | } | 244 | } |
182 | 245 | ||
183 | /* RBGB */ | 246 | /* RBGB */ |
184 | if (!adg->rate_of_48khz_div_6 && (0 == rate % 48000)) { | 247 | if (!adg->rbgb_rate_for_48khz_div_6 && (0 == rate % 48000)) { |
185 | adg->rate_of_48khz_div_6 = rate / 6; | 248 | adg->rbgb_rate_for_48khz_div_6 = rate / 6; |
186 | ckr |= brg_table[i] << 16; | 249 | ckr |= brg_table[i] << 16; |
187 | } | 250 | } |
188 | } | 251 | } |
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 61212ee97c28..add088bd4b2a 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -10,20 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | #include "rsnd.h" | 11 | #include "rsnd.h" |
12 | 12 | ||
13 | struct rsnd_gen_ops { | ||
14 | int (*probe)(struct platform_device *pdev, | ||
15 | struct rcar_snd_info *info, | ||
16 | struct rsnd_priv *priv); | ||
17 | void (*remove)(struct platform_device *pdev, | ||
18 | struct rsnd_priv *priv); | ||
19 | int (*path_init)(struct rsnd_priv *priv, | ||
20 | struct rsnd_dai *rdai, | ||
21 | struct rsnd_dai_stream *io); | ||
22 | int (*path_exit)(struct rsnd_priv *priv, | ||
23 | struct rsnd_dai *rdai, | ||
24 | struct rsnd_dai_stream *io); | ||
25 | }; | ||
26 | |||
27 | struct rsnd_gen { | 13 | struct rsnd_gen { |
28 | void __iomem *base[RSND_BASE_MAX]; | 14 | void __iomem *base[RSND_BASE_MAX]; |
29 | 15 | ||
@@ -86,12 +72,28 @@ static struct regmap_bus rsnd_regmap_bus = { | |||
86 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, | 72 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, |
87 | }; | 73 | }; |
88 | 74 | ||
75 | static int rsnd_is_accessible_reg(struct rsnd_priv *priv, | ||
76 | struct rsnd_gen *gen, enum rsnd_reg reg) | ||
77 | { | ||
78 | if (!gen->regs[reg]) { | ||
79 | struct device *dev = rsnd_priv_to_dev(priv); | ||
80 | |||
81 | dev_err(dev, "unsupported register access %x\n", reg); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | return 1; | ||
86 | } | ||
87 | |||
89 | u32 rsnd_read(struct rsnd_priv *priv, | 88 | u32 rsnd_read(struct rsnd_priv *priv, |
90 | struct rsnd_mod *mod, enum rsnd_reg reg) | 89 | struct rsnd_mod *mod, enum rsnd_reg reg) |
91 | { | 90 | { |
92 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 91 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
93 | u32 val; | 92 | u32 val; |
94 | 93 | ||
94 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | ||
95 | return 0; | ||
96 | |||
95 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); | 97 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); |
96 | 98 | ||
97 | return val; | 99 | return val; |
@@ -103,6 +105,9 @@ void rsnd_write(struct rsnd_priv *priv, | |||
103 | { | 105 | { |
104 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 106 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
105 | 107 | ||
108 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | ||
109 | return; | ||
110 | |||
106 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); | 111 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); |
107 | } | 112 | } |
108 | 113 | ||
@@ -111,21 +116,48 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | |||
111 | { | 116 | { |
112 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 117 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
113 | 118 | ||
119 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | ||
120 | return; | ||
121 | |||
114 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), | 122 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), |
115 | mask, data); | 123 | mask, data); |
116 | } | 124 | } |
117 | 125 | ||
118 | /* | 126 | static int rsnd_gen_regmap_init(struct rsnd_priv *priv, |
119 | * Gen2 | 127 | struct rsnd_gen *gen, |
120 | * will be filled in the future | 128 | struct reg_field *regf) |
121 | */ | 129 | { |
130 | int i; | ||
131 | struct device *dev = rsnd_priv_to_dev(priv); | ||
132 | struct regmap_config regc; | ||
122 | 133 | ||
123 | /* | 134 | memset(®c, 0, sizeof(regc)); |
124 | * Gen1 | 135 | regc.reg_bits = 32; |
125 | */ | 136 | regc.val_bits = 32; |
126 | static int rsnd_gen1_path_init(struct rsnd_priv *priv, | 137 | |
127 | struct rsnd_dai *rdai, | 138 | gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, ®c); |
128 | struct rsnd_dai_stream *io) | 139 | if (IS_ERR(gen->regmap)) { |
140 | dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap)); | ||
141 | return PTR_ERR(gen->regmap); | ||
142 | } | ||
143 | |||
144 | for (i = 0; i < RSND_REG_MAX; i++) { | ||
145 | gen->regs[i] = NULL; | ||
146 | if (!regf[i].reg) | ||
147 | continue; | ||
148 | |||
149 | gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]); | ||
150 | if (IS_ERR(gen->regs[i])) | ||
151 | return PTR_ERR(gen->regs[i]); | ||
152 | |||
153 | } | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | int rsnd_gen_path_init(struct rsnd_priv *priv, | ||
159 | struct rsnd_dai *rdai, | ||
160 | struct rsnd_dai_stream *io) | ||
129 | { | 161 | { |
130 | struct rsnd_mod *mod; | 162 | struct rsnd_mod *mod; |
131 | int ret; | 163 | int ret; |
@@ -163,9 +195,9 @@ static int rsnd_gen1_path_init(struct rsnd_priv *priv, | |||
163 | return ret; | 195 | return ret; |
164 | } | 196 | } |
165 | 197 | ||
166 | static int rsnd_gen1_path_exit(struct rsnd_priv *priv, | 198 | int rsnd_gen_path_exit(struct rsnd_priv *priv, |
167 | struct rsnd_dai *rdai, | 199 | struct rsnd_dai *rdai, |
168 | struct rsnd_dai_stream *io) | 200 | struct rsnd_dai_stream *io) |
169 | { | 201 | { |
170 | struct rsnd_mod *mod, *n; | 202 | struct rsnd_mod *mod, *n; |
171 | int ret = 0; | 203 | int ret = 0; |
@@ -179,6 +211,94 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv, | |||
179 | return ret; | 211 | return ret; |
180 | } | 212 | } |
181 | 213 | ||
214 | /* | ||
215 | * Gen2 | ||
216 | */ | ||
217 | |||
218 | /* single address mapping */ | ||
219 | #define RSND_GEN2_S_REG(gen, reg, id, offset) \ | ||
220 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10) | ||
221 | |||
222 | /* multi address mapping */ | ||
223 | #define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset) \ | ||
224 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10) | ||
225 | |||
226 | static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | ||
227 | { | ||
228 | struct reg_field regf[RSND_REG_MAX] = { | ||
229 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), | ||
230 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), | ||
231 | /* FIXME: it needs SSI_MODE2/3 in the future */ | ||
232 | RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), | ||
233 | |||
234 | RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), | ||
235 | RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), | ||
236 | RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), | ||
237 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), | ||
238 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), | ||
239 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), | ||
240 | |||
241 | RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), | ||
242 | RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), | ||
243 | RSND_GEN2_M_REG(gen, SSI, SSITDR, 0x08, 0x40), | ||
244 | RSND_GEN2_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), | ||
245 | RSND_GEN2_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), | ||
246 | }; | ||
247 | |||
248 | return rsnd_gen_regmap_init(priv, gen, regf); | ||
249 | } | ||
250 | |||
251 | static int rsnd_gen2_probe(struct platform_device *pdev, | ||
252 | struct rcar_snd_info *info, | ||
253 | struct rsnd_priv *priv) | ||
254 | { | ||
255 | struct device *dev = rsnd_priv_to_dev(priv); | ||
256 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
257 | struct resource *scu_res; | ||
258 | struct resource *adg_res; | ||
259 | struct resource *ssiu_res; | ||
260 | struct resource *ssi_res; | ||
261 | int ret; | ||
262 | |||
263 | /* | ||
264 | * map address | ||
265 | */ | ||
266 | scu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SCU); | ||
267 | adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_ADG); | ||
268 | ssiu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSIU); | ||
269 | ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSI); | ||
270 | |||
271 | gen->base[RSND_GEN2_SCU] = devm_ioremap_resource(dev, scu_res); | ||
272 | gen->base[RSND_GEN2_ADG] = devm_ioremap_resource(dev, adg_res); | ||
273 | gen->base[RSND_GEN2_SSIU] = devm_ioremap_resource(dev, ssiu_res); | ||
274 | gen->base[RSND_GEN2_SSI] = devm_ioremap_resource(dev, ssi_res); | ||
275 | if (IS_ERR(gen->base[RSND_GEN2_SCU]) || | ||
276 | IS_ERR(gen->base[RSND_GEN2_ADG]) || | ||
277 | IS_ERR(gen->base[RSND_GEN2_SSIU]) || | ||
278 | IS_ERR(gen->base[RSND_GEN2_SSI])) | ||
279 | return -ENODEV; | ||
280 | |||
281 | ret = rsnd_gen2_regmap_init(priv, gen); | ||
282 | if (ret < 0) | ||
283 | return ret; | ||
284 | |||
285 | dev_dbg(dev, "Gen2 device probed\n"); | ||
286 | dev_dbg(dev, "SRU : %08x => %p\n", scu_res->start, | ||
287 | gen->base[RSND_GEN2_SCU]); | ||
288 | dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, | ||
289 | gen->base[RSND_GEN2_ADG]); | ||
290 | dev_dbg(dev, "SSIU : %08x => %p\n", ssiu_res->start, | ||
291 | gen->base[RSND_GEN2_SSIU]); | ||
292 | dev_dbg(dev, "SSI : %08x => %p\n", ssi_res->start, | ||
293 | gen->base[RSND_GEN2_SSI]); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * Gen1 | ||
300 | */ | ||
301 | |||
182 | /* single address mapping */ | 302 | /* single address mapping */ |
183 | #define RSND_GEN1_S_REG(gen, reg, id, offset) \ | 303 | #define RSND_GEN1_S_REG(gen, reg, id, offset) \ |
184 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9) | 304 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9) |
@@ -189,19 +309,23 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv, | |||
189 | 309 | ||
190 | static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | 310 | static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) |
191 | { | 311 | { |
192 | int i; | ||
193 | struct device *dev = rsnd_priv_to_dev(priv); | ||
194 | struct regmap_config regc; | ||
195 | struct reg_field regf[RSND_REG_MAX] = { | 312 | struct reg_field regf[RSND_REG_MAX] = { |
196 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_SEL, 0x00), | 313 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_SEL, 0x00), |
197 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08), | 314 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08), |
198 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL1, 0x0c), | 315 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL1, 0x0c), |
199 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL2, 0x10), | 316 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL2, 0x10), |
200 | RSND_GEN1_S_REG(gen, SRU, SRC_CTRL, 0xc0), | 317 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_CTRL, 0xc0), |
201 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), | 318 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), |
202 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), | 319 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), |
203 | RSND_GEN1_M_REG(gen, SRU, BUSIF_MODE, 0x20, 0x4), | 320 | RSND_GEN1_M_REG(gen, SRU, BUSIF_MODE, 0x20, 0x4), |
204 | RSND_GEN1_M_REG(gen, SRU, BUSIF_ADINR, 0x214, 0x40), | 321 | RSND_GEN1_M_REG(gen, SRU, SRC_ROUTE_MODE0,0x50, 0x8), |
322 | RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), | ||
323 | RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), | ||
324 | RSND_GEN1_M_REG(gen, SRU, SRC_ADINR, 0x214, 0x40), | ||
325 | RSND_GEN1_M_REG(gen, SRU, SRC_IFSCR, 0x21c, 0x40), | ||
326 | RSND_GEN1_M_REG(gen, SRU, SRC_IFSVR, 0x220, 0x40), | ||
327 | RSND_GEN1_M_REG(gen, SRU, SRC_SRCCR, 0x224, 0x40), | ||
328 | RSND_GEN1_M_REG(gen, SRU, SRC_MNFSR, 0x228, 0x40), | ||
205 | 329 | ||
206 | RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00), | 330 | RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00), |
207 | RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04), | 331 | RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04), |
@@ -219,24 +343,7 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | |||
219 | RSND_GEN1_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), | 343 | RSND_GEN1_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), |
220 | }; | 344 | }; |
221 | 345 | ||
222 | memset(®c, 0, sizeof(regc)); | 346 | return rsnd_gen_regmap_init(priv, gen, regf); |
223 | regc.reg_bits = 32; | ||
224 | regc.val_bits = 32; | ||
225 | |||
226 | gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, ®c); | ||
227 | if (IS_ERR(gen->regmap)) { | ||
228 | dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap)); | ||
229 | return PTR_ERR(gen->regmap); | ||
230 | } | ||
231 | |||
232 | for (i = 0; i < RSND_REG_MAX; i++) { | ||
233 | gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]); | ||
234 | if (IS_ERR(gen->regs[i])) | ||
235 | return PTR_ERR(gen->regs[i]); | ||
236 | |||
237 | } | ||
238 | |||
239 | return 0; | ||
240 | } | 347 | } |
241 | 348 | ||
242 | static int rsnd_gen1_probe(struct platform_device *pdev, | 349 | static int rsnd_gen1_probe(struct platform_device *pdev, |
@@ -281,45 +388,16 @@ static int rsnd_gen1_probe(struct platform_device *pdev, | |||
281 | 388 | ||
282 | } | 389 | } |
283 | 390 | ||
284 | static void rsnd_gen1_remove(struct platform_device *pdev, | ||
285 | struct rsnd_priv *priv) | ||
286 | { | ||
287 | } | ||
288 | |||
289 | static struct rsnd_gen_ops rsnd_gen1_ops = { | ||
290 | .probe = rsnd_gen1_probe, | ||
291 | .remove = rsnd_gen1_remove, | ||
292 | .path_init = rsnd_gen1_path_init, | ||
293 | .path_exit = rsnd_gen1_path_exit, | ||
294 | }; | ||
295 | |||
296 | /* | 391 | /* |
297 | * Gen | 392 | * Gen |
298 | */ | 393 | */ |
299 | int rsnd_gen_path_init(struct rsnd_priv *priv, | ||
300 | struct rsnd_dai *rdai, | ||
301 | struct rsnd_dai_stream *io) | ||
302 | { | ||
303 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
304 | |||
305 | return gen->ops->path_init(priv, rdai, io); | ||
306 | } | ||
307 | |||
308 | int rsnd_gen_path_exit(struct rsnd_priv *priv, | ||
309 | struct rsnd_dai *rdai, | ||
310 | struct rsnd_dai_stream *io) | ||
311 | { | ||
312 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
313 | |||
314 | return gen->ops->path_exit(priv, rdai, io); | ||
315 | } | ||
316 | |||
317 | int rsnd_gen_probe(struct platform_device *pdev, | 394 | int rsnd_gen_probe(struct platform_device *pdev, |
318 | struct rcar_snd_info *info, | 395 | struct rcar_snd_info *info, |
319 | struct rsnd_priv *priv) | 396 | struct rsnd_priv *priv) |
320 | { | 397 | { |
321 | struct device *dev = rsnd_priv_to_dev(priv); | 398 | struct device *dev = rsnd_priv_to_dev(priv); |
322 | struct rsnd_gen *gen; | 399 | struct rsnd_gen *gen; |
400 | int ret; | ||
323 | 401 | ||
324 | gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); | 402 | gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); |
325 | if (!gen) { | 403 | if (!gen) { |
@@ -327,23 +405,21 @@ int rsnd_gen_probe(struct platform_device *pdev, | |||
327 | return -ENOMEM; | 405 | return -ENOMEM; |
328 | } | 406 | } |
329 | 407 | ||
408 | priv->gen = gen; | ||
409 | |||
410 | ret = -ENODEV; | ||
330 | if (rsnd_is_gen1(priv)) | 411 | if (rsnd_is_gen1(priv)) |
331 | gen->ops = &rsnd_gen1_ops; | 412 | ret = rsnd_gen1_probe(pdev, info, priv); |
413 | else if (rsnd_is_gen2(priv)) | ||
414 | ret = rsnd_gen2_probe(pdev, info, priv); | ||
332 | 415 | ||
333 | if (!gen->ops) { | 416 | if (ret < 0) |
334 | dev_err(dev, "unknown generation R-Car sound device\n"); | 417 | dev_err(dev, "unknown generation R-Car sound device\n"); |
335 | return -ENODEV; | ||
336 | } | ||
337 | |||
338 | priv->gen = gen; | ||
339 | 418 | ||
340 | return gen->ops->probe(pdev, info, priv); | 419 | return ret; |
341 | } | 420 | } |
342 | 421 | ||
343 | void rsnd_gen_remove(struct platform_device *pdev, | 422 | void rsnd_gen_remove(struct platform_device *pdev, |
344 | struct rsnd_priv *priv) | 423 | struct rsnd_priv *priv) |
345 | { | 424 | { |
346 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
347 | |||
348 | gen->ops->remove(pdev, priv); | ||
349 | } | 425 | } |
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 9e463e50e7e6..4ca66cd899c8 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -31,16 +31,24 @@ | |||
31 | * see gen1/gen2 for detail | 31 | * see gen1/gen2 for detail |
32 | */ | 32 | */ |
33 | enum rsnd_reg { | 33 | enum rsnd_reg { |
34 | /* SRU/SCU */ | 34 | /* SRU/SCU/SSIU */ |
35 | RSND_REG_SRC_ROUTE_SEL, | 35 | RSND_REG_SRC_ROUTE_SEL, /* for Gen1 */ |
36 | RSND_REG_SRC_TMG_SEL0, | 36 | RSND_REG_SRC_TMG_SEL0, /* for Gen1 */ |
37 | RSND_REG_SRC_TMG_SEL1, | 37 | RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ |
38 | RSND_REG_SRC_TMG_SEL2, | 38 | RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ |
39 | RSND_REG_SRC_CTRL, | 39 | RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ |
40 | RSND_REG_SSI_MODE0, | 40 | RSND_REG_SSI_MODE0, |
41 | RSND_REG_SSI_MODE1, | 41 | RSND_REG_SSI_MODE1, |
42 | RSND_REG_BUSIF_MODE, | 42 | RSND_REG_BUSIF_MODE, |
43 | RSND_REG_BUSIF_ADINR, | 43 | RSND_REG_INT_ENABLE, /* for Gen2 */ |
44 | RSND_REG_SRC_ROUTE_MODE0, | ||
45 | RSND_REG_SRC_SWRSR, | ||
46 | RSND_REG_SRC_SRCIR, | ||
47 | RSND_REG_SRC_ADINR, | ||
48 | RSND_REG_SRC_IFSCR, | ||
49 | RSND_REG_SRC_IFSVR, | ||
50 | RSND_REG_SRC_SRCCR, | ||
51 | RSND_REG_SRC_MNFSR, | ||
44 | 52 | ||
45 | /* ADG */ | 53 | /* ADG */ |
46 | RSND_REG_BRRA, | 54 | RSND_REG_BRRA, |
@@ -49,9 +57,9 @@ enum rsnd_reg { | |||
49 | RSND_REG_AUDIO_CLK_SEL0, | 57 | RSND_REG_AUDIO_CLK_SEL0, |
50 | RSND_REG_AUDIO_CLK_SEL1, | 58 | RSND_REG_AUDIO_CLK_SEL1, |
51 | RSND_REG_AUDIO_CLK_SEL2, | 59 | RSND_REG_AUDIO_CLK_SEL2, |
52 | RSND_REG_AUDIO_CLK_SEL3, | 60 | RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ |
53 | RSND_REG_AUDIO_CLK_SEL4, | 61 | RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ |
54 | RSND_REG_AUDIO_CLK_SEL5, | 62 | RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ |
55 | 63 | ||
56 | /* SSI */ | 64 | /* SSI */ |
57 | RSND_REG_SSICR, | 65 | RSND_REG_SSICR, |
@@ -174,11 +182,11 @@ struct rsnd_dai { | |||
174 | struct rsnd_dai_stream playback; | 182 | struct rsnd_dai_stream playback; |
175 | struct rsnd_dai_stream capture; | 183 | struct rsnd_dai_stream capture; |
176 | 184 | ||
177 | int clk_master:1; | 185 | unsigned int clk_master:1; |
178 | int bit_clk_inv:1; | 186 | unsigned int bit_clk_inv:1; |
179 | int frm_clk_inv:1; | 187 | unsigned int frm_clk_inv:1; |
180 | int sys_delay:1; | 188 | unsigned int sys_delay:1; |
181 | int data_alignment:1; | 189 | unsigned int data_alignment:1; |
182 | }; | 190 | }; |
183 | 191 | ||
184 | #define rsnd_dai_nr(priv) ((priv)->dai_nr) | 192 | #define rsnd_dai_nr(priv) ((priv)->dai_nr) |
@@ -229,6 +237,10 @@ int rsnd_adg_probe(struct platform_device *pdev, | |||
229 | struct rsnd_priv *priv); | 237 | struct rsnd_priv *priv); |
230 | void rsnd_adg_remove(struct platform_device *pdev, | 238 | void rsnd_adg_remove(struct platform_device *pdev, |
231 | struct rsnd_priv *priv); | 239 | struct rsnd_priv *priv); |
240 | int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, | ||
241 | struct rsnd_mod *mod, | ||
242 | unsigned int src_rate, | ||
243 | unsigned int dst_rate); | ||
232 | 244 | ||
233 | /* | 245 | /* |
234 | * R-Car sound priv | 246 | * R-Car sound priv |
@@ -282,6 +294,10 @@ void rsnd_scu_remove(struct platform_device *pdev, | |||
282 | struct rsnd_priv *priv); | 294 | struct rsnd_priv *priv); |
283 | struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); | 295 | struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); |
284 | bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod); | 296 | bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod); |
297 | unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, | ||
298 | struct rsnd_mod *ssi_mod, | ||
299 | struct snd_pcm_runtime *runtime); | ||
300 | |||
285 | #define rsnd_scu_nr(priv) ((priv)->scu_nr) | 301 | #define rsnd_scu_nr(priv) ((priv)->scu_nr) |
286 | 302 | ||
287 | /* | 303 | /* |
diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index fa8fa15860b9..9bb08bb1d455 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c | |||
@@ -13,9 +13,13 @@ | |||
13 | struct rsnd_scu { | 13 | struct rsnd_scu { |
14 | struct rsnd_scu_platform_info *info; /* rcar_snd.h */ | 14 | struct rsnd_scu_platform_info *info; /* rcar_snd.h */ |
15 | struct rsnd_mod mod; | 15 | struct rsnd_mod mod; |
16 | struct clk *clk; | ||
16 | }; | 17 | }; |
17 | 18 | ||
18 | #define rsnd_scu_mode_flags(p) ((p)->info->flags) | 19 | #define rsnd_scu_mode_flags(p) ((p)->info->flags) |
20 | #define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) | ||
21 | |||
22 | #define RSND_SCU_NAME_SIZE 16 | ||
19 | 23 | ||
20 | /* | 24 | /* |
21 | * ADINR | 25 | * ADINR |
@@ -26,6 +30,15 @@ struct rsnd_scu { | |||
26 | #define OTBL_18 (6 << 16) | 30 | #define OTBL_18 (6 << 16) |
27 | #define OTBL_16 (8 << 16) | 31 | #define OTBL_16 (8 << 16) |
28 | 32 | ||
33 | /* | ||
34 | * image of SRC (Sampling Rate Converter) | ||
35 | * | ||
36 | * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ | ||
37 | * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | | ||
38 | * 44.1kHz <-> +-----+ +-----+ +-------+ | ||
39 | * ... | ||
40 | * | ||
41 | */ | ||
29 | 42 | ||
30 | #define rsnd_mod_to_scu(_mod) \ | 43 | #define rsnd_mod_to_scu(_mod) \ |
31 | container_of((_mod), struct rsnd_scu, mod) | 44 | container_of((_mod), struct rsnd_scu, mod) |
@@ -36,7 +49,8 @@ struct rsnd_scu { | |||
36 | ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ | 49 | ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ |
37 | i++) | 50 | i++) |
38 | 51 | ||
39 | static int rsnd_scu_set_route(struct rsnd_priv *priv, | 52 | /* Gen1 only */ |
53 | static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, | ||
40 | struct rsnd_mod *mod, | 54 | struct rsnd_mod *mod, |
41 | struct rsnd_dai *rdai, | 55 | struct rsnd_dai *rdai, |
42 | struct rsnd_dai_stream *io) | 56 | struct rsnd_dai_stream *io) |
@@ -55,7 +69,7 @@ static int rsnd_scu_set_route(struct rsnd_priv *priv, | |||
55 | { 0x3, 28, }, /* 7 */ | 69 | { 0x3, 28, }, /* 7 */ |
56 | { 0x3, 30, }, /* 8 */ | 70 | { 0x3, 30, }, /* 8 */ |
57 | }; | 71 | }; |
58 | 72 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | |
59 | u32 mask; | 73 | u32 mask; |
60 | u32 val; | 74 | u32 val; |
61 | int shift; | 75 | int shift; |
@@ -85,9 +99,18 @@ static int rsnd_scu_set_route(struct rsnd_priv *priv, | |||
85 | */ | 99 | */ |
86 | shift = (id % 4) * 8; | 100 | shift = (id % 4) * 8; |
87 | mask = 0x1F << shift; | 101 | mask = 0x1F << shift; |
88 | if (8 == id) /* SRU8 is very special */ | 102 | |
103 | /* | ||
104 | * ADG is used as source clock if SRC was used, | ||
105 | * then, SSI WS is used as destination clock. | ||
106 | * SSI WS is used as source clock if SRC is not used | ||
107 | * (when playback, source/destination become reverse when capture) | ||
108 | */ | ||
109 | if (rsnd_scu_convert_rate(scu)) /* use ADG */ | ||
110 | val = 0; | ||
111 | else if (8 == id) /* use SSI WS, but SRU8 is special */ | ||
89 | val = id << shift; | 112 | val = id << shift; |
90 | else | 113 | else /* use SSI WS */ |
91 | val = (id + 1) << shift; | 114 | val = (id + 1) << shift; |
92 | 115 | ||
93 | switch (id / 4) { | 116 | switch (id / 4) { |
@@ -105,30 +128,45 @@ static int rsnd_scu_set_route(struct rsnd_priv *priv, | |||
105 | return 0; | 128 | return 0; |
106 | } | 129 | } |
107 | 130 | ||
108 | static int rsnd_scu_set_mode(struct rsnd_priv *priv, | 131 | unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, |
109 | struct rsnd_mod *mod, | 132 | struct rsnd_mod *ssi_mod, |
110 | struct rsnd_dai *rdai, | 133 | struct snd_pcm_runtime *runtime) |
111 | struct rsnd_dai_stream *io) | ||
112 | { | 134 | { |
113 | int id = rsnd_mod_id(mod); | 135 | struct rsnd_scu *scu; |
114 | u32 val; | 136 | unsigned int rate; |
115 | 137 | ||
116 | if (rsnd_is_gen1(priv)) { | 138 | /* this function is assuming SSI id = SCU id here */ |
117 | val = (1 << id); | 139 | scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); |
118 | rsnd_mod_bset(mod, SRC_CTRL, val, val); | ||
119 | } | ||
120 | 140 | ||
121 | return 0; | 141 | /* |
142 | * return convert rate if SRC is used, | ||
143 | * otherwise, return runtime->rate as usual | ||
144 | */ | ||
145 | rate = rsnd_scu_convert_rate(scu); | ||
146 | if (!rate) | ||
147 | rate = runtime->rate; | ||
148 | |||
149 | return rate; | ||
122 | } | 150 | } |
123 | 151 | ||
124 | static int rsnd_scu_set_hpbif(struct rsnd_priv *priv, | 152 | static int rsnd_scu_convert_rate_ctrl(struct rsnd_priv *priv, |
125 | struct rsnd_mod *mod, | 153 | struct rsnd_mod *mod, |
126 | struct rsnd_dai *rdai, | 154 | struct rsnd_dai *rdai, |
127 | struct rsnd_dai_stream *io) | 155 | struct rsnd_dai_stream *io) |
128 | { | 156 | { |
129 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 157 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
158 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
159 | u32 convert_rate = rsnd_scu_convert_rate(scu); | ||
130 | u32 adinr = runtime->channels; | 160 | u32 adinr = runtime->channels; |
131 | 161 | ||
162 | /* set/clear soft reset */ | ||
163 | rsnd_mod_write(mod, SRC_SWRSR, 0); | ||
164 | rsnd_mod_write(mod, SRC_SWRSR, 1); | ||
165 | |||
166 | /* Initialize the operation of the SRC internal circuits */ | ||
167 | rsnd_mod_write(mod, SRC_SRCIR, 1); | ||
168 | |||
169 | /* Set channel number and output bit length */ | ||
132 | switch (runtime->sample_bits) { | 170 | switch (runtime->sample_bits) { |
133 | case 16: | 171 | case 16: |
134 | adinr |= OTBL_16; | 172 | adinr |= OTBL_16; |
@@ -139,9 +177,81 @@ static int rsnd_scu_set_hpbif(struct rsnd_priv *priv, | |||
139 | default: | 177 | default: |
140 | return -EIO; | 178 | return -EIO; |
141 | } | 179 | } |
180 | rsnd_mod_write(mod, SRC_ADINR, adinr); | ||
181 | |||
182 | if (convert_rate) { | ||
183 | u32 fsrate = 0x0400000 / convert_rate * runtime->rate; | ||
184 | int ret; | ||
185 | |||
186 | /* Enable the initial value of IFS */ | ||
187 | rsnd_mod_write(mod, SRC_IFSCR, 1); | ||
188 | |||
189 | /* Set initial value of IFS */ | ||
190 | rsnd_mod_write(mod, SRC_IFSVR, fsrate); | ||
191 | |||
192 | /* Select SRC mode (fixed value) */ | ||
193 | rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); | ||
194 | |||
195 | /* Set the restriction value of the FS ratio (98%) */ | ||
196 | rsnd_mod_write(mod, SRC_MNFSR, fsrate / 100 * 98); | ||
197 | |||
198 | if (rsnd_is_gen1(priv)) { | ||
199 | /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ | ||
200 | } | ||
142 | 201 | ||
202 | /* set convert clock */ | ||
203 | ret = rsnd_adg_set_convert_clk(priv, mod, | ||
204 | runtime->rate, | ||
205 | convert_rate); | ||
206 | if (ret < 0) | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | /* Cancel the initialization and operate the SRC function */ | ||
211 | rsnd_mod_write(mod, SRC_SRCIR, 0); | ||
212 | |||
213 | /* use DMA transfer */ | ||
143 | rsnd_mod_write(mod, BUSIF_MODE, 1); | 214 | rsnd_mod_write(mod, BUSIF_MODE, 1); |
144 | rsnd_mod_write(mod, BUSIF_ADINR, adinr); | 215 | |
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int rsnd_scu_transfer_start(struct rsnd_priv *priv, | ||
220 | struct rsnd_mod *mod, | ||
221 | struct rsnd_dai *rdai, | ||
222 | struct rsnd_dai_stream *io) | ||
223 | { | ||
224 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
225 | int id = rsnd_mod_id(mod); | ||
226 | u32 val; | ||
227 | |||
228 | if (rsnd_is_gen1(priv)) { | ||
229 | val = (1 << id); | ||
230 | rsnd_mod_bset(mod, SRC_ROUTE_CTRL, val, val); | ||
231 | } | ||
232 | |||
233 | if (rsnd_scu_convert_rate(scu)) | ||
234 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int rsnd_scu_transfer_stop(struct rsnd_priv *priv, | ||
240 | struct rsnd_mod *mod, | ||
241 | struct rsnd_dai *rdai, | ||
242 | struct rsnd_dai_stream *io) | ||
243 | { | ||
244 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
245 | int id = rsnd_mod_id(mod); | ||
246 | u32 mask; | ||
247 | |||
248 | if (rsnd_is_gen1(priv)) { | ||
249 | mask = (1 << id); | ||
250 | rsnd_mod_bset(mod, SRC_ROUTE_CTRL, mask, 0); | ||
251 | } | ||
252 | |||
253 | if (rsnd_scu_convert_rate(scu)) | ||
254 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); | ||
145 | 255 | ||
146 | return 0; | 256 | return 0; |
147 | } | 257 | } |
@@ -159,6 +269,7 @@ static int rsnd_scu_start(struct rsnd_mod *mod, | |||
159 | struct rsnd_dai_stream *io) | 269 | struct rsnd_dai_stream *io) |
160 | { | 270 | { |
161 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 271 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
272 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
162 | struct device *dev = rsnd_priv_to_dev(priv); | 273 | struct device *dev = rsnd_priv_to_dev(priv); |
163 | int ret; | 274 | int ret; |
164 | 275 | ||
@@ -173,16 +284,19 @@ static int rsnd_scu_start(struct rsnd_mod *mod, | |||
173 | return 0; | 284 | return 0; |
174 | } | 285 | } |
175 | 286 | ||
287 | clk_enable(scu->clk); | ||
288 | |||
176 | /* it use DMA transter */ | 289 | /* it use DMA transter */ |
177 | ret = rsnd_scu_set_route(priv, mod, rdai, io); | 290 | |
291 | ret = rsnd_src_set_route_if_gen1(priv, mod, rdai, io); | ||
178 | if (ret < 0) | 292 | if (ret < 0) |
179 | return ret; | 293 | return ret; |
180 | 294 | ||
181 | ret = rsnd_scu_set_mode(priv, mod, rdai, io); | 295 | ret = rsnd_scu_convert_rate_ctrl(priv, mod, rdai, io); |
182 | if (ret < 0) | 296 | if (ret < 0) |
183 | return ret; | 297 | return ret; |
184 | 298 | ||
185 | ret = rsnd_scu_set_hpbif(priv, mod, rdai, io); | 299 | ret = rsnd_scu_transfer_start(priv, mod, rdai, io); |
186 | if (ret < 0) | 300 | if (ret < 0) |
187 | return ret; | 301 | return ret; |
188 | 302 | ||
@@ -191,9 +305,27 @@ static int rsnd_scu_start(struct rsnd_mod *mod, | |||
191 | return 0; | 305 | return 0; |
192 | } | 306 | } |
193 | 307 | ||
308 | static int rsnd_scu_stop(struct rsnd_mod *mod, | ||
309 | struct rsnd_dai *rdai, | ||
310 | struct rsnd_dai_stream *io) | ||
311 | { | ||
312 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
313 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
314 | |||
315 | if (!rsnd_scu_hpbif_is_enable(mod)) | ||
316 | return 0; | ||
317 | |||
318 | rsnd_scu_transfer_stop(priv, mod, rdai, io); | ||
319 | |||
320 | clk_disable(scu->clk); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
194 | static struct rsnd_mod_ops rsnd_scu_ops = { | 325 | static struct rsnd_mod_ops rsnd_scu_ops = { |
195 | .name = "scu", | 326 | .name = "scu", |
196 | .start = rsnd_scu_start, | 327 | .start = rsnd_scu_start, |
328 | .stop = rsnd_scu_stop, | ||
197 | }; | 329 | }; |
198 | 330 | ||
199 | struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) | 331 | struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) |
@@ -210,6 +342,8 @@ int rsnd_scu_probe(struct platform_device *pdev, | |||
210 | { | 342 | { |
211 | struct device *dev = rsnd_priv_to_dev(priv); | 343 | struct device *dev = rsnd_priv_to_dev(priv); |
212 | struct rsnd_scu *scu; | 344 | struct rsnd_scu *scu; |
345 | struct clk *clk; | ||
346 | char name[RSND_SCU_NAME_SIZE]; | ||
213 | int i, nr; | 347 | int i, nr; |
214 | 348 | ||
215 | /* | 349 | /* |
@@ -226,9 +360,16 @@ int rsnd_scu_probe(struct platform_device *pdev, | |||
226 | priv->scu = scu; | 360 | priv->scu = scu; |
227 | 361 | ||
228 | for_each_rsnd_scu(scu, priv, i) { | 362 | for_each_rsnd_scu(scu, priv, i) { |
363 | snprintf(name, RSND_SCU_NAME_SIZE, "scu.%d", i); | ||
364 | |||
365 | clk = devm_clk_get(dev, name); | ||
366 | if (IS_ERR(clk)) | ||
367 | return PTR_ERR(clk); | ||
368 | |||
229 | rsnd_mod_init(priv, &scu->mod, | 369 | rsnd_mod_init(priv, &scu->mod, |
230 | &rsnd_scu_ops, i); | 370 | &rsnd_scu_ops, i); |
231 | scu->info = &info->scu_info[i]; | 371 | scu->info = &info->scu_info[i]; |
372 | scu->clk = clk; | ||
232 | 373 | ||
233 | dev_dbg(dev, "SCU%d probed\n", i); | 374 | dev_dbg(dev, "SCU%d probed\n", i); |
234 | } | 375 | } |
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 5ac20cd5e006..4b8cf7ca9d19 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -187,9 +187,10 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod, | |||
187 | } | 187 | } |
188 | 188 | ||
189 | static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, | 189 | static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, |
190 | unsigned int rate) | 190 | struct rsnd_dai_stream *io) |
191 | { | 191 | { |
192 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); | 192 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); |
193 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
193 | struct device *dev = rsnd_priv_to_dev(priv); | 194 | struct device *dev = rsnd_priv_to_dev(priv); |
194 | int i, j, ret; | 195 | int i, j, ret; |
195 | int adg_clk_div_table[] = { | 196 | int adg_clk_div_table[] = { |
@@ -199,6 +200,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, | |||
199 | 1, 2, 4, 8, 16, 6, 12, | 200 | 1, 2, 4, 8, 16, 6, 12, |
200 | }; | 201 | }; |
201 | unsigned int main_rate; | 202 | unsigned int main_rate; |
203 | unsigned int rate = rsnd_scu_get_ssi_rate(priv, &ssi->mod, runtime); | ||
202 | 204 | ||
203 | /* | 205 | /* |
204 | * Find best clock, and try to start ADG | 206 | * Find best clock, and try to start ADG |
@@ -209,7 +211,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, | |||
209 | /* | 211 | /* |
210 | * this driver is assuming that | 212 | * this driver is assuming that |
211 | * system word is 64fs (= 2 x 32bit) | 213 | * system word is 64fs (= 2 x 32bit) |
212 | * see rsnd_ssi_start() | 214 | * see rsnd_ssi_init() |
213 | */ | 215 | */ |
214 | main_rate = rate / adg_clk_div_table[i] | 216 | main_rate = rate / adg_clk_div_table[i] |
215 | * 32 * 2 * ssi_clk_mul_table[j]; | 217 | * 32 * 2 * ssi_clk_mul_table[j]; |
@@ -251,14 +253,10 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | |||
251 | clk_enable(ssi->clk); | 253 | clk_enable(ssi->clk); |
252 | 254 | ||
253 | if (rsnd_rdai_is_clk_master(rdai)) { | 255 | if (rsnd_rdai_is_clk_master(rdai)) { |
254 | struct snd_pcm_runtime *runtime; | ||
255 | |||
256 | runtime = rsnd_io_to_runtime(io); | ||
257 | |||
258 | if (rsnd_ssi_clk_from_parent(ssi)) | 256 | if (rsnd_ssi_clk_from_parent(ssi)) |
259 | rsnd_ssi_hw_start(ssi->parent, rdai, io); | 257 | rsnd_ssi_hw_start(ssi->parent, rdai, io); |
260 | else | 258 | else |
261 | rsnd_ssi_master_clk_start(ssi, runtime->rate); | 259 | rsnd_ssi_master_clk_start(ssi, io); |
262 | } | 260 | } |
263 | } | 261 | } |
264 | 262 | ||
@@ -457,6 +455,10 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, | |||
457 | /* enable PIO IRQ */ | 455 | /* enable PIO IRQ */ |
458 | ssi->cr_etc = UIEN | OIEN | DIEN; | 456 | ssi->cr_etc = UIEN | OIEN | DIEN; |
459 | 457 | ||
458 | /* enable PIO interrupt if gen2 */ | ||
459 | if (rsnd_is_gen2(priv)) | ||
460 | rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000); | ||
461 | |||
460 | rsnd_ssi_hw_start(ssi, rdai, io); | 462 | rsnd_ssi_hw_start(ssi, rdai, io); |
461 | 463 | ||
462 | dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); | 464 | dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); |
@@ -650,7 +652,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, | |||
650 | 652 | ||
651 | snprintf(name, RSND_SSI_NAME_SIZE, "ssi.%d", i); | 653 | snprintf(name, RSND_SSI_NAME_SIZE, "ssi.%d", i); |
652 | 654 | ||
653 | clk = clk_get(dev, name); | 655 | clk = devm_clk_get(dev, name); |
654 | if (IS_ERR(clk)) | 656 | if (IS_ERR(clk)) |
655 | return PTR_ERR(clk); | 657 | return PTR_ERR(clk); |
656 | 658 | ||
@@ -711,7 +713,6 @@ void rsnd_ssi_remove(struct platform_device *pdev, | |||
711 | int i; | 713 | int i; |
712 | 714 | ||
713 | for_each_rsnd_ssi(ssi, priv, i) { | 715 | for_each_rsnd_ssi(ssi, priv, i) { |
714 | clk_put(ssi->clk); | ||
715 | if (rsnd_ssi_dma_available(ssi)) | 716 | if (rsnd_ssi_dma_available(ssi)) |
716 | rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod)); | 717 | rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod)); |
717 | } | 718 | } |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4e53d87e881d..be88df5eeaf7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -3212,11 +3212,11 @@ int snd_soc_bytes_get(struct snd_kcontrol *kcontrol, | |||
3212 | break; | 3212 | break; |
3213 | case 2: | 3213 | case 2: |
3214 | ((u16 *)(&ucontrol->value.bytes.data))[0] | 3214 | ((u16 *)(&ucontrol->value.bytes.data))[0] |
3215 | &= ~params->mask; | 3215 | &= cpu_to_be16(~params->mask); |
3216 | break; | 3216 | break; |
3217 | case 4: | 3217 | case 4: |
3218 | ((u32 *)(&ucontrol->value.bytes.data))[0] | 3218 | ((u32 *)(&ucontrol->value.bytes.data))[0] |
3219 | &= ~params->mask; | 3219 | &= cpu_to_be32(~params->mask); |
3220 | break; | 3220 | break; |
3221 | default: | 3221 | default: |
3222 | return -EINVAL; | 3222 | return -EINVAL; |
@@ -4617,10 +4617,14 @@ int snd_soc_of_get_dai_name(struct device_node *of_node, | |||
4617 | 4617 | ||
4618 | if (id < 0 || id >= pos->num_dai) { | 4618 | if (id < 0 || id >= pos->num_dai) { |
4619 | ret = -EINVAL; | 4619 | ret = -EINVAL; |
4620 | } else { | 4620 | break; |
4621 | *dai_name = pos->dai_drv[id].name; | ||
4622 | ret = 0; | ||
4623 | } | 4621 | } |
4622 | |||
4623 | ret = 0; | ||
4624 | |||
4625 | *dai_name = pos->dai_drv[id].name; | ||
4626 | if (!*dai_name) | ||
4627 | *dai_name = pos->name; | ||
4624 | } | 4628 | } |
4625 | 4629 | ||
4626 | break; | 4630 | break; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dcade130157f..67e63ab1f11e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -2868,6 +2868,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2868 | unsigned int val; | 2868 | unsigned int val; |
2869 | int connect, change; | 2869 | int connect, change; |
2870 | struct snd_soc_dapm_update update; | 2870 | struct snd_soc_dapm_update update; |
2871 | int ret = 0; | ||
2871 | 2872 | ||
2872 | if (snd_soc_volsw_is_stereo(mc)) | 2873 | if (snd_soc_volsw_is_stereo(mc)) |
2873 | dev_warn(codec->dapm.dev, | 2874 | dev_warn(codec->dapm.dev, |
@@ -2901,12 +2902,16 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2901 | card->update = &update; | 2902 | card->update = &update; |
2902 | } | 2903 | } |
2903 | 2904 | ||
2904 | soc_dapm_mixer_update_power(card, kcontrol, connect); | 2905 | ret = soc_dapm_mixer_update_power(card, kcontrol, connect); |
2905 | 2906 | ||
2906 | card->update = NULL; | 2907 | card->update = NULL; |
2907 | } | 2908 | } |
2908 | 2909 | ||
2909 | mutex_unlock(&card->dapm_mutex); | 2910 | mutex_unlock(&card->dapm_mutex); |
2911 | |||
2912 | if (ret > 0) | ||
2913 | soc_dpcm_runtime_update(card); | ||
2914 | |||
2910 | return change; | 2915 | return change; |
2911 | } | 2916 | } |
2912 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | 2917 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); |
@@ -2955,6 +2960,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2955 | unsigned int val, mux, change; | 2960 | unsigned int val, mux, change; |
2956 | unsigned int mask; | 2961 | unsigned int mask; |
2957 | struct snd_soc_dapm_update update; | 2962 | struct snd_soc_dapm_update update; |
2963 | int ret = 0; | ||
2958 | 2964 | ||
2959 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2965 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
2960 | return -EINVAL; | 2966 | return -EINVAL; |
@@ -2978,12 +2984,16 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2978 | update.val = val; | 2984 | update.val = val; |
2979 | card->update = &update; | 2985 | card->update = &update; |
2980 | 2986 | ||
2981 | soc_dapm_mux_update_power(card, kcontrol, mux, e); | 2987 | ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); |
2982 | 2988 | ||
2983 | card->update = NULL; | 2989 | card->update = NULL; |
2984 | } | 2990 | } |
2985 | 2991 | ||
2986 | mutex_unlock(&card->dapm_mutex); | 2992 | mutex_unlock(&card->dapm_mutex); |
2993 | |||
2994 | if (ret > 0) | ||
2995 | soc_dpcm_runtime_update(card); | ||
2996 | |||
2987 | return change; | 2997 | return change; |
2988 | } | 2998 | } |
2989 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); | 2999 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); |
@@ -3019,6 +3029,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, | |||
3019 | struct soc_enum *e = | 3029 | struct soc_enum *e = |
3020 | (struct soc_enum *)kcontrol->private_value; | 3030 | (struct soc_enum *)kcontrol->private_value; |
3021 | int change; | 3031 | int change; |
3032 | int ret = 0; | ||
3022 | 3033 | ||
3023 | if (ucontrol->value.enumerated.item[0] >= e->max) | 3034 | if (ucontrol->value.enumerated.item[0] >= e->max) |
3024 | return -EINVAL; | 3035 | return -EINVAL; |
@@ -3028,9 +3039,13 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, | |||
3028 | value = ucontrol->value.enumerated.item[0]; | 3039 | value = ucontrol->value.enumerated.item[0]; |
3029 | change = dapm_kcontrol_set_value(kcontrol, value); | 3040 | change = dapm_kcontrol_set_value(kcontrol, value); |
3030 | if (change) | 3041 | if (change) |
3031 | soc_dapm_mux_update_power(card, kcontrol, value, e); | 3042 | ret = soc_dapm_mux_update_power(card, kcontrol, value, e); |
3032 | 3043 | ||
3033 | mutex_unlock(&card->dapm_mutex); | 3044 | mutex_unlock(&card->dapm_mutex); |
3045 | |||
3046 | if (ret > 0) | ||
3047 | soc_dpcm_runtime_update(card); | ||
3048 | |||
3034 | return change; | 3049 | return change; |
3035 | } | 3050 | } |
3036 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); | 3051 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); |
@@ -3097,6 +3112,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
3097 | unsigned int val, mux, change; | 3112 | unsigned int val, mux, change; |
3098 | unsigned int mask; | 3113 | unsigned int mask; |
3099 | struct snd_soc_dapm_update update; | 3114 | struct snd_soc_dapm_update update; |
3115 | int ret = 0; | ||
3100 | 3116 | ||
3101 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 3117 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
3102 | return -EINVAL; | 3118 | return -EINVAL; |
@@ -3120,12 +3136,16 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
3120 | update.val = val; | 3136 | update.val = val; |
3121 | card->update = &update; | 3137 | card->update = &update; |
3122 | 3138 | ||
3123 | soc_dapm_mux_update_power(card, kcontrol, mux, e); | 3139 | ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); |
3124 | 3140 | ||
3125 | card->update = NULL; | 3141 | card->update = NULL; |
3126 | } | 3142 | } |
3127 | 3143 | ||
3128 | mutex_unlock(&card->dapm_mutex); | 3144 | mutex_unlock(&card->dapm_mutex); |
3145 | |||
3146 | if (ret > 0) | ||
3147 | soc_dpcm_runtime_update(card); | ||
3148 | |||
3129 | return change; | 3149 | return change; |
3130 | } | 3150 | } |
3131 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); | 3151 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); |
diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c index b1d732255c02..7ac745df1412 100644 --- a/sound/soc/soc-devres.c +++ b/sound/soc/soc-devres.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/moduleparam.h> | 13 | #include <linux/moduleparam.h> |
14 | #include <sound/soc.h> | 14 | #include <sound/soc.h> |
15 | #include <sound/dmaengine_pcm.h> | ||
15 | 16 | ||
16 | static void devm_component_release(struct device *dev, void *res) | 17 | static void devm_component_release(struct device *dev, void *res) |
17 | { | 18 | { |
@@ -66,7 +67,7 @@ static void devm_card_release(struct device *dev, void *res) | |||
66 | */ | 67 | */ |
67 | int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card) | 68 | int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card) |
68 | { | 69 | { |
69 | struct device **ptr; | 70 | struct snd_soc_card **ptr; |
70 | int ret; | 71 | int ret; |
71 | 72 | ||
72 | ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL); | 73 | ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL); |
@@ -75,7 +76,7 @@ int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card) | |||
75 | 76 | ||
76 | ret = snd_soc_register_card(card); | 77 | ret = snd_soc_register_card(card); |
77 | if (ret == 0) { | 78 | if (ret == 0) { |
78 | *ptr = dev; | 79 | *ptr = card; |
79 | devres_add(dev, ptr); | 80 | devres_add(dev, ptr); |
80 | } else { | 81 | } else { |
81 | devres_free(ptr); | 82 | devres_free(ptr); |
@@ -84,3 +85,43 @@ int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card) | |||
84 | return ret; | 85 | return ret; |
85 | } | 86 | } |
86 | EXPORT_SYMBOL_GPL(devm_snd_soc_register_card); | 87 | EXPORT_SYMBOL_GPL(devm_snd_soc_register_card); |
88 | |||
89 | #ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM | ||
90 | |||
91 | static void devm_dmaengine_pcm_release(struct device *dev, void *res) | ||
92 | { | ||
93 | snd_dmaengine_pcm_unregister(*(struct device **)res); | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration | ||
98 | * @dev: The parent device for the PCM device | ||
99 | * @config: Platform specific PCM configuration | ||
100 | * @flags: Platform specific quirks | ||
101 | * | ||
102 | * Register a dmaengine based PCM device with automatic unregistration when the | ||
103 | * device is unregistered. | ||
104 | */ | ||
105 | int devm_snd_dmaengine_pcm_register(struct device *dev, | ||
106 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) | ||
107 | { | ||
108 | struct device **ptr; | ||
109 | int ret; | ||
110 | |||
111 | ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL); | ||
112 | if (!ptr) | ||
113 | return -ENOMEM; | ||
114 | |||
115 | ret = snd_dmaengine_pcm_register(dev, config, flags); | ||
116 | if (ret == 0) { | ||
117 | *ptr = dev; | ||
118 | devres_add(dev, ptr); | ||
119 | } else { | ||
120 | devres_free(ptr); | ||
121 | } | ||
122 | |||
123 | return ret; | ||
124 | } | ||
125 | EXPORT_SYMBOL_GPL(devm_snd_dmaengine_pcm_register); | ||
126 | |||
127 | #endif | ||
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index cbc9c96ce1f4..2a6c569d991f 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -137,6 +137,9 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea | |||
137 | hw.buffer_bytes_max = SIZE_MAX; | 137 | hw.buffer_bytes_max = SIZE_MAX; |
138 | hw.fifo_size = dma_data->fifo_size; | 138 | hw.fifo_size = dma_data->fifo_size; |
139 | 139 | ||
140 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) | ||
141 | hw.info |= SNDRV_PCM_INFO_BATCH; | ||
142 | |||
140 | ret = dma_get_slave_caps(chan, &dma_caps); | 143 | ret = dma_get_slave_caps(chan, &dma_caps); |
141 | if (ret == 0) { | 144 | if (ret == 0) { |
142 | if (dma_caps.cmd_pause) | 145 | if (dma_caps.cmd_pause) |
@@ -284,24 +287,67 @@ static const char * const dmaengine_pcm_dma_channel_names[] = { | |||
284 | [SNDRV_PCM_STREAM_CAPTURE] = "rx", | 287 | [SNDRV_PCM_STREAM_CAPTURE] = "rx", |
285 | }; | 288 | }; |
286 | 289 | ||
287 | static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, | 290 | static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, |
288 | struct device *dev) | 291 | struct device *dev, const struct snd_dmaengine_pcm_config *config) |
289 | { | 292 | { |
290 | unsigned int i; | 293 | unsigned int i; |
294 | const char *name; | ||
295 | struct dma_chan *chan; | ||
291 | 296 | ||
292 | if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT | | 297 | if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT | |
293 | SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) || | 298 | SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) || |
294 | !dev->of_node) | 299 | !dev->of_node) |
295 | return; | 300 | return 0; |
301 | |||
302 | if (config && config->dma_dev) { | ||
303 | /* | ||
304 | * If this warning is seen, it probably means that your Linux | ||
305 | * device structure does not match your HW device structure. | ||
306 | * It would be best to refactor the Linux device structure to | ||
307 | * correctly match the HW structure. | ||
308 | */ | ||
309 | dev_warn(dev, "DMA channels sourced from device %s", | ||
310 | dev_name(config->dma_dev)); | ||
311 | dev = config->dma_dev; | ||
312 | } | ||
296 | 313 | ||
297 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) { | 314 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; |
298 | pcm->chan[0] = dma_request_slave_channel(dev, "rx-tx"); | 315 | i++) { |
299 | pcm->chan[1] = pcm->chan[0]; | 316 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) |
300 | } else { | 317 | name = "rx-tx"; |
301 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { | 318 | else |
302 | pcm->chan[i] = dma_request_slave_channel(dev, | 319 | name = dmaengine_pcm_dma_channel_names[i]; |
303 | dmaengine_pcm_dma_channel_names[i]); | 320 | if (config && config->chan_names[i]) |
321 | name = config->chan_names[i]; | ||
322 | chan = dma_request_slave_channel_reason(dev, name); | ||
323 | if (IS_ERR(chan)) { | ||
324 | if (PTR_ERR(chan) == -EPROBE_DEFER) | ||
325 | return -EPROBE_DEFER; | ||
326 | pcm->chan[i] = NULL; | ||
327 | } else { | ||
328 | pcm->chan[i] = chan; | ||
304 | } | 329 | } |
330 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
331 | break; | ||
332 | } | ||
333 | |||
334 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
335 | pcm->chan[1] = pcm->chan[0]; | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) | ||
341 | { | ||
342 | unsigned int i; | ||
343 | |||
344 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; | ||
345 | i++) { | ||
346 | if (!pcm->chan[i]) | ||
347 | continue; | ||
348 | dma_release_channel(pcm->chan[i]); | ||
349 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
350 | break; | ||
305 | } | 351 | } |
306 | } | 352 | } |
307 | 353 | ||
@@ -315,6 +361,7 @@ int snd_dmaengine_pcm_register(struct device *dev, | |||
315 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) | 361 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) |
316 | { | 362 | { |
317 | struct dmaengine_pcm *pcm; | 363 | struct dmaengine_pcm *pcm; |
364 | int ret; | ||
318 | 365 | ||
319 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); | 366 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
320 | if (!pcm) | 367 | if (!pcm) |
@@ -323,14 +370,25 @@ int snd_dmaengine_pcm_register(struct device *dev, | |||
323 | pcm->config = config; | 370 | pcm->config = config; |
324 | pcm->flags = flags; | 371 | pcm->flags = flags; |
325 | 372 | ||
326 | dmaengine_pcm_request_chan_of(pcm, dev); | 373 | ret = dmaengine_pcm_request_chan_of(pcm, dev, config); |
374 | if (ret) | ||
375 | goto err_free_dma; | ||
327 | 376 | ||
328 | if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) | 377 | if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) |
329 | return snd_soc_add_platform(dev, &pcm->platform, | 378 | ret = snd_soc_add_platform(dev, &pcm->platform, |
330 | &dmaengine_no_residue_pcm_platform); | 379 | &dmaengine_no_residue_pcm_platform); |
331 | else | 380 | else |
332 | return snd_soc_add_platform(dev, &pcm->platform, | 381 | ret = snd_soc_add_platform(dev, &pcm->platform, |
333 | &dmaengine_pcm_platform); | 382 | &dmaengine_pcm_platform); |
383 | if (ret) | ||
384 | goto err_free_dma; | ||
385 | |||
386 | return 0; | ||
387 | |||
388 | err_free_dma: | ||
389 | dmaengine_pcm_release_chan(pcm); | ||
390 | kfree(pcm); | ||
391 | return ret; | ||
334 | } | 392 | } |
335 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register); | 393 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register); |
336 | 394 | ||
@@ -345,7 +403,6 @@ void snd_dmaengine_pcm_unregister(struct device *dev) | |||
345 | { | 403 | { |
346 | struct snd_soc_platform *platform; | 404 | struct snd_soc_platform *platform; |
347 | struct dmaengine_pcm *pcm; | 405 | struct dmaengine_pcm *pcm; |
348 | unsigned int i; | ||
349 | 406 | ||
350 | platform = snd_soc_lookup_platform(dev); | 407 | platform = snd_soc_lookup_platform(dev); |
351 | if (!platform) | 408 | if (!platform) |
@@ -353,15 +410,8 @@ void snd_dmaengine_pcm_unregister(struct device *dev) | |||
353 | 410 | ||
354 | pcm = soc_platform_to_pcm(platform); | 411 | pcm = soc_platform_to_pcm(platform); |
355 | 412 | ||
356 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { | ||
357 | if (pcm->chan[i]) { | ||
358 | dma_release_channel(pcm->chan[i]); | ||
359 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
360 | break; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | snd_soc_remove_platform(platform); | 413 | snd_soc_remove_platform(platform); |
414 | dmaengine_pcm_release_chan(pcm); | ||
365 | kfree(pcm); | 415 | kfree(pcm); |
366 | } | 416 | } |
367 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); | 417 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); |
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index 4f11d23f2062..aa886cca3ecf 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c | |||
@@ -99,14 +99,14 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | |||
99 | config.val_bits = data_bits; | 99 | config.val_bits = data_bits; |
100 | 100 | ||
101 | switch (control) { | 101 | switch (control) { |
102 | #if defined(CONFIG_REGMAP_I2C) || defined(CONFIG_REGMAP_I2C_MODULE) | 102 | #if IS_ENABLED(CONFIG_REGMAP_I2C) |
103 | case SND_SOC_I2C: | 103 | case SND_SOC_I2C: |
104 | codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev), | 104 | codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev), |
105 | &config); | 105 | &config); |
106 | break; | 106 | break; |
107 | #endif | 107 | #endif |
108 | 108 | ||
109 | #if defined(CONFIG_REGMAP_SPI) || defined(CONFIG_REGMAP_SPI_MODULE) | 109 | #if IS_ENABLED(CONFIG_REGMAP_SPI) |
110 | case SND_SOC_SPI: | 110 | case SND_SOC_SPI: |
111 | codec->control_data = regmap_init_spi(to_spi_device(codec->dev), | 111 | codec->control_data = regmap_init_spi(to_spi_device(codec->dev), |
112 | &config); | 112 | &config); |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 42782c01e413..604e7e9a2ef8 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -84,35 +84,117 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, | |||
84 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 84 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
85 | int ret; | 85 | int ret; |
86 | 86 | ||
87 | if (!soc_dai->driver->symmetric_rates && | 87 | if (soc_dai->rate && (soc_dai->driver->symmetric_rates || |
88 | !rtd->dai_link->symmetric_rates) | 88 | rtd->dai_link->symmetric_rates)) { |
89 | return 0; | 89 | dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", |
90 | soc_dai->rate); | ||
91 | |||
92 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, | ||
93 | SNDRV_PCM_HW_PARAM_RATE, | ||
94 | soc_dai->rate, soc_dai->rate); | ||
95 | if (ret < 0) { | ||
96 | dev_err(soc_dai->dev, | ||
97 | "ASoC: Unable to apply rate constraint: %d\n", | ||
98 | ret); | ||
99 | return ret; | ||
100 | } | ||
101 | } | ||
90 | 102 | ||
91 | /* This can happen if multiple streams are starting simultaneously - | 103 | if (soc_dai->channels && (soc_dai->driver->symmetric_channels || |
92 | * the second can need to get its constraints before the first has | 104 | rtd->dai_link->symmetric_channels)) { |
93 | * picked a rate. Complain and allow the application to carry on. | 105 | dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n", |
94 | */ | 106 | soc_dai->channels); |
95 | if (!soc_dai->rate) { | 107 | |
96 | dev_warn(soc_dai->dev, | 108 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, |
97 | "ASoC: Not enforcing symmetric_rates due to race\n"); | 109 | SNDRV_PCM_HW_PARAM_CHANNELS, |
98 | return 0; | 110 | soc_dai->channels, |
111 | soc_dai->channels); | ||
112 | if (ret < 0) { | ||
113 | dev_err(soc_dai->dev, | ||
114 | "ASoC: Unable to apply channel symmetry constraint: %d\n", | ||
115 | ret); | ||
116 | return ret; | ||
117 | } | ||
99 | } | 118 | } |
100 | 119 | ||
101 | dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", soc_dai->rate); | 120 | if (soc_dai->sample_bits && (soc_dai->driver->symmetric_samplebits || |
121 | rtd->dai_link->symmetric_samplebits)) { | ||
122 | dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n", | ||
123 | soc_dai->sample_bits); | ||
102 | 124 | ||
103 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, | 125 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, |
104 | SNDRV_PCM_HW_PARAM_RATE, | 126 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, |
105 | soc_dai->rate, soc_dai->rate); | 127 | soc_dai->sample_bits, |
106 | if (ret < 0) { | 128 | soc_dai->sample_bits); |
107 | dev_err(soc_dai->dev, | 129 | if (ret < 0) { |
108 | "ASoC: Unable to apply rate symmetry constraint: %d\n", | 130 | dev_err(soc_dai->dev, |
109 | ret); | 131 | "ASoC: Unable to apply sample bits symmetry constraint: %d\n", |
110 | return ret; | 132 | ret); |
133 | return ret; | ||
134 | } | ||
111 | } | 135 | } |
112 | 136 | ||
113 | return 0; | 137 | return 0; |
114 | } | 138 | } |
115 | 139 | ||
140 | static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | ||
141 | struct snd_pcm_hw_params *params) | ||
142 | { | ||
143 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
144 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
145 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
146 | unsigned int rate, channels, sample_bits, symmetry; | ||
147 | |||
148 | rate = params_rate(params); | ||
149 | channels = params_channels(params); | ||
150 | sample_bits = snd_pcm_format_physical_width(params_format(params)); | ||
151 | |||
152 | /* reject unmatched parameters when applying symmetry */ | ||
153 | symmetry = cpu_dai->driver->symmetric_rates || | ||
154 | codec_dai->driver->symmetric_rates || | ||
155 | rtd->dai_link->symmetric_rates; | ||
156 | if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) { | ||
157 | dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", | ||
158 | cpu_dai->rate, rate); | ||
159 | return -EINVAL; | ||
160 | } | ||
161 | |||
162 | symmetry = cpu_dai->driver->symmetric_channels || | ||
163 | codec_dai->driver->symmetric_channels || | ||
164 | rtd->dai_link->symmetric_channels; | ||
165 | if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) { | ||
166 | dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", | ||
167 | cpu_dai->channels, channels); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | symmetry = cpu_dai->driver->symmetric_samplebits || | ||
172 | codec_dai->driver->symmetric_samplebits || | ||
173 | rtd->dai_link->symmetric_samplebits; | ||
174 | if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) { | ||
175 | dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", | ||
176 | cpu_dai->sample_bits, sample_bits); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) | ||
184 | { | ||
185 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
186 | struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver; | ||
187 | struct snd_soc_dai_driver *codec_driver = rtd->codec_dai->driver; | ||
188 | struct snd_soc_dai_link *link = rtd->dai_link; | ||
189 | |||
190 | return cpu_driver->symmetric_rates || codec_driver->symmetric_rates || | ||
191 | link->symmetric_rates || cpu_driver->symmetric_channels || | ||
192 | codec_driver->symmetric_channels || link->symmetric_channels || | ||
193 | cpu_driver->symmetric_samplebits || | ||
194 | codec_driver->symmetric_samplebits || | ||
195 | link->symmetric_samplebits; | ||
196 | } | ||
197 | |||
116 | /* | 198 | /* |
117 | * List of sample sizes that might go over the bus for parameter | 199 | * List of sample sizes that might go over the bus for parameter |
118 | * application. There ought to be a wildcard sample size for things | 200 | * application. There ought to be a wildcard sample size for things |
@@ -148,12 +230,12 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream, | |||
148 | } | 230 | } |
149 | } | 231 | } |
150 | 232 | ||
151 | static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw, | 233 | static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime, |
152 | struct snd_soc_pcm_stream *codec_stream, | 234 | struct snd_soc_pcm_stream *codec_stream, |
153 | struct snd_soc_pcm_stream *cpu_stream) | 235 | struct snd_soc_pcm_stream *cpu_stream) |
154 | { | 236 | { |
155 | hw->rate_min = max(codec_stream->rate_min, cpu_stream->rate_min); | 237 | struct snd_pcm_hardware *hw = &runtime->hw; |
156 | hw->rate_max = max(codec_stream->rate_max, cpu_stream->rate_max); | 238 | |
157 | hw->channels_min = max(codec_stream->channels_min, | 239 | hw->channels_min = max(codec_stream->channels_min, |
158 | cpu_stream->channels_min); | 240 | cpu_stream->channels_min); |
159 | hw->channels_max = min(codec_stream->channels_max, | 241 | hw->channels_max = min(codec_stream->channels_max, |
@@ -166,6 +248,13 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw, | |||
166 | if (cpu_stream->rates | 248 | if (cpu_stream->rates |
167 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | 249 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) |
168 | hw->rates |= codec_stream->rates; | 250 | hw->rates |= codec_stream->rates; |
251 | |||
252 | snd_pcm_limit_hw_rates(runtime); | ||
253 | |||
254 | hw->rate_min = max(hw->rate_min, cpu_stream->rate_min); | ||
255 | hw->rate_min = max(hw->rate_min, codec_stream->rate_min); | ||
256 | hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max); | ||
257 | hw->rate_max = min_not_zero(hw->rate_max, codec_stream->rate_max); | ||
169 | } | 258 | } |
170 | 259 | ||
171 | /* | 260 | /* |
@@ -235,15 +324,17 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
235 | 324 | ||
236 | /* Check that the codec and cpu DAIs are compatible */ | 325 | /* Check that the codec and cpu DAIs are compatible */ |
237 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 326 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
238 | soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->playback, | 327 | soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->playback, |
239 | &cpu_dai_drv->playback); | 328 | &cpu_dai_drv->playback); |
240 | } else { | 329 | } else { |
241 | soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->capture, | 330 | soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->capture, |
242 | &cpu_dai_drv->capture); | 331 | &cpu_dai_drv->capture); |
243 | } | 332 | } |
244 | 333 | ||
334 | if (soc_pcm_has_symmetry(substream)) | ||
335 | runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; | ||
336 | |||
245 | ret = -EINVAL; | 337 | ret = -EINVAL; |
246 | snd_pcm_limit_hw_rates(runtime); | ||
247 | if (!runtime->hw.rates) { | 338 | if (!runtime->hw.rates) { |
248 | printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n", | 339 | printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n", |
249 | codec_dai->name, cpu_dai->name); | 340 | codec_dai->name, cpu_dai->name); |
@@ -390,11 +481,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
390 | if (!codec_dai->active) | 481 | if (!codec_dai->active) |
391 | codec_dai->rate = 0; | 482 | codec_dai->rate = 0; |
392 | 483 | ||
393 | /* Muting the DAC suppresses artifacts caused during digital | ||
394 | * shutdown, for example from stopping clocks. | ||
395 | */ | ||
396 | snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); | ||
397 | |||
398 | if (cpu_dai->driver->ops->shutdown) | 484 | if (cpu_dai->driver->ops->shutdown) |
399 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | 485 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
400 | 486 | ||
@@ -525,6 +611,10 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
525 | 611 | ||
526 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 612 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
527 | 613 | ||
614 | ret = soc_pcm_params_symmetry(substream, params); | ||
615 | if (ret) | ||
616 | goto out; | ||
617 | |||
528 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { | 618 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { |
529 | ret = rtd->dai_link->ops->hw_params(substream, params); | 619 | ret = rtd->dai_link->ops->hw_params(substream, params); |
530 | if (ret < 0) { | 620 | if (ret < 0) { |
@@ -561,9 +651,16 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
561 | } | 651 | } |
562 | } | 652 | } |
563 | 653 | ||
564 | /* store the rate for each DAIs */ | 654 | /* store the parameters for each DAIs */ |
565 | cpu_dai->rate = params_rate(params); | 655 | cpu_dai->rate = params_rate(params); |
656 | cpu_dai->channels = params_channels(params); | ||
657 | cpu_dai->sample_bits = | ||
658 | snd_pcm_format_physical_width(params_format(params)); | ||
659 | |||
566 | codec_dai->rate = params_rate(params); | 660 | codec_dai->rate = params_rate(params); |
661 | codec_dai->channels = params_channels(params); | ||
662 | codec_dai->sample_bits = | ||
663 | snd_pcm_format_physical_width(params_format(params)); | ||
567 | 664 | ||
568 | out: | 665 | out: |
569 | mutex_unlock(&rtd->pcm_mutex); | 666 | mutex_unlock(&rtd->pcm_mutex); |
@@ -594,12 +691,26 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
594 | struct snd_soc_platform *platform = rtd->platform; | 691 | struct snd_soc_platform *platform = rtd->platform; |
595 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 692 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
596 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 693 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
597 | struct snd_soc_codec *codec = rtd->codec; | 694 | bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
598 | 695 | ||
599 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 696 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
600 | 697 | ||
698 | /* clear the corresponding DAIs parameters when going to be inactive */ | ||
699 | if (cpu_dai->active == 1) { | ||
700 | cpu_dai->rate = 0; | ||
701 | cpu_dai->channels = 0; | ||
702 | cpu_dai->sample_bits = 0; | ||
703 | } | ||
704 | |||
705 | if (codec_dai->active == 1) { | ||
706 | codec_dai->rate = 0; | ||
707 | codec_dai->channels = 0; | ||
708 | codec_dai->sample_bits = 0; | ||
709 | } | ||
710 | |||
601 | /* apply codec digital mute */ | 711 | /* apply codec digital mute */ |
602 | if (!codec->active) | 712 | if ((playback && codec_dai->playback_active == 1) || |
713 | (!playback && codec_dai->capture_active == 1)) | ||
603 | snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); | 714 | snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); |
604 | 715 | ||
605 | /* free any machine hw params */ | 716 | /* free any machine hw params */ |
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 5e633659c1b3..6ebdfd9a1a1d 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c | |||
@@ -59,10 +59,6 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params) | |||
59 | EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk); | 59 | EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk); |
60 | 60 | ||
61 | static const struct snd_pcm_hardware dummy_dma_hardware = { | 61 | static const struct snd_pcm_hardware dummy_dma_hardware = { |
62 | .formats = 0xffffffff, | ||
63 | .channels_min = 1, | ||
64 | .channels_max = UINT_MAX, | ||
65 | |||
66 | /* Random values to keep userspace happy when checking constraints */ | 62 | /* Random values to keep userspace happy when checking constraints */ |
67 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 63 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
68 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | 64 | SNDRV_PCM_INFO_BLOCK_TRANSFER, |
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c index 21a8c954af1c..4ab442a63d7e 100644 --- a/sound/soc/spear/spdif_in.c +++ b/sound/soc/spear/spdif_in.c | |||
@@ -18,12 +18,14 @@ | |||
18 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <sound/dmaengine_pcm.h> | ||
21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
22 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
23 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
24 | #include <sound/spear_dma.h> | 25 | #include <sound/spear_dma.h> |
25 | #include <sound/spear_spdif.h> | 26 | #include <sound/spear_spdif.h> |
26 | #include "spdif_in_regs.h" | 27 | #include "spdif_in_regs.h" |
28 | #include "spear_pcm.h" | ||
27 | 29 | ||
28 | struct spdif_in_params { | 30 | struct spdif_in_params { |
29 | u32 format; | 31 | u32 format; |
@@ -37,6 +39,8 @@ struct spdif_in_dev { | |||
37 | struct device *dev; | 39 | struct device *dev; |
38 | void (*reset_perip)(void); | 40 | void (*reset_perip)(void); |
39 | int irq; | 41 | int irq; |
42 | struct snd_dmaengine_dai_dma_data dma_params_rx; | ||
43 | struct snd_dmaengine_pcm_config config; | ||
40 | }; | 44 | }; |
41 | 45 | ||
42 | static void spdif_in_configure(struct spdif_in_dev *host) | 46 | static void spdif_in_configure(struct spdif_in_dev *host) |
@@ -53,7 +57,8 @@ static int spdif_in_dai_probe(struct snd_soc_dai *dai) | |||
53 | { | 57 | { |
54 | struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai); | 58 | struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai); |
55 | 59 | ||
56 | dai->capture_dma_data = &host->dma_params; | 60 | host->dma_params_rx.filter_data = &host->dma_params; |
61 | dai->capture_dma_data = &host->dma_params_rx; | ||
57 | 62 | ||
58 | return 0; | 63 | return 0; |
59 | } | 64 | } |
@@ -244,7 +249,6 @@ static int spdif_in_probe(struct platform_device *pdev) | |||
244 | host->dma_params.addr = res_fifo->start; | 249 | host->dma_params.addr = res_fifo->start; |
245 | host->dma_params.max_burst = 16; | 250 | host->dma_params.max_burst = 16; |
246 | host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | 251 | host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
247 | host->dma_params.filter = pdata->filter; | ||
248 | host->reset_perip = pdata->reset_perip; | 252 | host->reset_perip = pdata->reset_perip; |
249 | 253 | ||
250 | host->dev = &pdev->dev; | 254 | host->dev = &pdev->dev; |
@@ -257,8 +261,13 @@ static int spdif_in_probe(struct platform_device *pdev) | |||
257 | return ret; | 261 | return ret; |
258 | } | 262 | } |
259 | 263 | ||
260 | return devm_snd_soc_register_component(&pdev->dev, &spdif_in_component, | 264 | ret = devm_snd_soc_register_component(&pdev->dev, &spdif_in_component, |
261 | &spdif_in_dai, 1); | 265 | &spdif_in_dai, 1); |
266 | if (ret) | ||
267 | return ret; | ||
268 | |||
269 | return devm_spear_pcm_platform_register(&pdev->dev, &host->config, | ||
270 | pdata->filter); | ||
262 | } | 271 | } |
263 | 272 | ||
264 | static struct platform_driver spdif_in_driver = { | 273 | static struct platform_driver spdif_in_driver = { |
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c index b6ef6f78dc78..fe99f461aff0 100644 --- a/sound/soc/spear/spdif_out.c +++ b/sound/soc/spear/spdif_out.c | |||
@@ -18,10 +18,12 @@ | |||
18 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <sound/dmaengine_pcm.h> | ||
21 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
22 | #include <sound/spear_dma.h> | 23 | #include <sound/spear_dma.h> |
23 | #include <sound/spear_spdif.h> | 24 | #include <sound/spear_spdif.h> |
24 | #include "spdif_out_regs.h" | 25 | #include "spdif_out_regs.h" |
26 | #include "spear_pcm.h" | ||
25 | 27 | ||
26 | struct spdif_out_params { | 28 | struct spdif_out_params { |
27 | u32 rate; | 29 | u32 rate; |
@@ -35,6 +37,8 @@ struct spdif_out_dev { | |||
35 | struct spdif_out_params saved_params; | 37 | struct spdif_out_params saved_params; |
36 | u32 running; | 38 | u32 running; |
37 | void __iomem *io_base; | 39 | void __iomem *io_base; |
40 | struct snd_dmaengine_dai_dma_data dma_params_tx; | ||
41 | struct snd_dmaengine_pcm_config config; | ||
38 | }; | 42 | }; |
39 | 43 | ||
40 | static void spdif_out_configure(struct spdif_out_dev *host) | 44 | static void spdif_out_configure(struct spdif_out_dev *host) |
@@ -244,7 +248,8 @@ static int spdif_soc_dai_probe(struct snd_soc_dai *dai) | |||
244 | { | 248 | { |
245 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai); | 249 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai); |
246 | 250 | ||
247 | dai->playback_dma_data = &host->dma_params; | 251 | host->dma_params_tx.filter_data = &host->dma_params; |
252 | dai->playback_dma_data = &host->dma_params_tx; | ||
248 | 253 | ||
249 | return snd_soc_add_dai_controls(dai, spdif_out_controls, | 254 | return snd_soc_add_dai_controls(dai, spdif_out_controls, |
250 | ARRAY_SIZE(spdif_out_controls)); | 255 | ARRAY_SIZE(spdif_out_controls)); |
@@ -280,6 +285,7 @@ static int spdif_out_probe(struct platform_device *pdev) | |||
280 | struct spdif_out_dev *host; | 285 | struct spdif_out_dev *host; |
281 | struct spear_spdif_platform_data *pdata; | 286 | struct spear_spdif_platform_data *pdata; |
282 | struct resource *res; | 287 | struct resource *res; |
288 | int ret; | ||
283 | 289 | ||
284 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); | 290 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); |
285 | if (!host) { | 291 | if (!host) { |
@@ -302,12 +308,16 @@ static int spdif_out_probe(struct platform_device *pdev) | |||
302 | host->dma_params.addr = res->start + SPDIF_OUT_FIFO_DATA; | 308 | host->dma_params.addr = res->start + SPDIF_OUT_FIFO_DATA; |
303 | host->dma_params.max_burst = 16; | 309 | host->dma_params.max_burst = 16; |
304 | host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | 310 | host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
305 | host->dma_params.filter = pdata->filter; | ||
306 | 311 | ||
307 | dev_set_drvdata(&pdev->dev, host); | 312 | dev_set_drvdata(&pdev->dev, host); |
308 | 313 | ||
309 | return devm_snd_soc_register_component(&pdev->dev, &spdif_out_component, | 314 | ret = devm_snd_soc_register_component(&pdev->dev, &spdif_out_component, |
310 | &spdif_out_dai, 1); | 315 | &spdif_out_dai, 1); |
316 | if (ret) | ||
317 | return ret; | ||
318 | |||
319 | return devm_spear_pcm_platform_register(&pdev->dev, &host->config, | ||
320 | pdata->filter); | ||
311 | } | 321 | } |
312 | 322 | ||
313 | #ifdef CONFIG_PM | 323 | #ifdef CONFIG_PM |
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c index 4707f2b862c3..0e5a8f35d0ad 100644 --- a/sound/soc/spear/spear_pcm.c +++ b/sound/soc/spear/spear_pcm.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <sound/pcm.h> | 18 | #include <sound/pcm.h> |
19 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
20 | #include <sound/spear_dma.h> | 20 | #include <sound/spear_dma.h> |
21 | #include "spear_pcm.h" | ||
21 | 22 | ||
22 | static const struct snd_pcm_hardware spear_pcm_hardware = { | 23 | static const struct snd_pcm_hardware spear_pcm_hardware = { |
23 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 24 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
@@ -31,49 +32,24 @@ static const struct snd_pcm_hardware spear_pcm_hardware = { | |||
31 | .fifo_size = 0, /* fifo size in bytes */ | 32 | .fifo_size = 0, /* fifo size in bytes */ |
32 | }; | 33 | }; |
33 | 34 | ||
34 | static struct dma_chan *spear_pcm_request_chan(struct snd_soc_pcm_runtime *rtd, | ||
35 | struct snd_pcm_substream *substream) | ||
36 | { | ||
37 | struct spear_dma_data *dma_data; | ||
38 | |||
39 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
40 | |||
41 | return snd_dmaengine_pcm_request_channel(dma_data->filter, dma_data); | ||
42 | } | ||
43 | |||
44 | static const struct snd_dmaengine_pcm_config spear_dmaengine_pcm_config = { | 35 | static const struct snd_dmaengine_pcm_config spear_dmaengine_pcm_config = { |
45 | .pcm_hardware = &spear_pcm_hardware, | 36 | .pcm_hardware = &spear_pcm_hardware, |
46 | .compat_request_channel = spear_pcm_request_chan, | ||
47 | .prealloc_buffer_size = 16 * 1024, | 37 | .prealloc_buffer_size = 16 * 1024, |
48 | }; | 38 | }; |
49 | 39 | ||
50 | static int spear_soc_platform_probe(struct platform_device *pdev) | 40 | int devm_spear_pcm_platform_register(struct device *dev, |
41 | struct snd_dmaengine_pcm_config *config, | ||
42 | bool (*filter)(struct dma_chan *chan, void *slave)) | ||
51 | { | 43 | { |
52 | return snd_dmaengine_pcm_register(&pdev->dev, | 44 | *config = spear_dmaengine_pcm_config; |
53 | &spear_dmaengine_pcm_config, | 45 | config->compat_filter_fn = filter; |
46 | |||
47 | return snd_dmaengine_pcm_register(dev, config, | ||
54 | SND_DMAENGINE_PCM_FLAG_NO_DT | | 48 | SND_DMAENGINE_PCM_FLAG_NO_DT | |
55 | SND_DMAENGINE_PCM_FLAG_COMPAT); | 49 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
56 | } | 50 | } |
57 | 51 | EXPORT_SYMBOL_GPL(devm_spear_pcm_platform_register); | |
58 | static int spear_soc_platform_remove(struct platform_device *pdev) | ||
59 | { | ||
60 | snd_dmaengine_pcm_unregister(&pdev->dev); | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static struct platform_driver spear_pcm_driver = { | ||
65 | .driver = { | ||
66 | .name = "spear-pcm-audio", | ||
67 | .owner = THIS_MODULE, | ||
68 | }, | ||
69 | |||
70 | .probe = spear_soc_platform_probe, | ||
71 | .remove = spear_soc_platform_remove, | ||
72 | }; | ||
73 | |||
74 | module_platform_driver(spear_pcm_driver); | ||
75 | 52 | ||
76 | MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>"); | 53 | MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>"); |
77 | MODULE_DESCRIPTION("SPEAr PCM DMA module"); | 54 | MODULE_DESCRIPTION("SPEAr PCM DMA module"); |
78 | MODULE_LICENSE("GPL"); | 55 | MODULE_LICENSE("GPL"); |
79 | MODULE_ALIAS("platform:spear-pcm-audio"); | ||
diff --git a/sound/soc/spear/spear_pcm.h b/sound/soc/spear/spear_pcm.h new file mode 100644 index 000000000000..9b0ca62d6f02 --- /dev/null +++ b/sound/soc/spear/spear_pcm.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #ifndef __SPEAR_PCM_H__ | ||
18 | #define __SPEAR_PCM_H__ | ||
19 | |||
20 | int devm_spear_pcm_platform_register(struct device *dev, | ||
21 | struct snd_dmaengine_pcm_config *config, | ||
22 | bool (*filter)(struct dma_chan *chan, void *slave)); | ||
23 | |||
24 | #endif | ||
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 8fc653ca3ab4..65a85f542521 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig | |||
@@ -116,3 +116,13 @@ config SND_SOC_TEGRA_ALC5632 | |||
116 | help | 116 | help |
117 | Say Y or M here if you want to add support for SoC audio on the | 117 | Say Y or M here if you want to add support for SoC audio on the |
118 | Toshiba AC100 netbook. | 118 | Toshiba AC100 netbook. |
119 | |||
120 | config SND_SOC_TEGRA_MAX98090 | ||
121 | tristate "SoC Audio support for Tegra boards using a MAX98090 codec" | ||
122 | depends on SND_SOC_TEGRA && I2C && GPIOLIB | ||
123 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC | ||
124 | select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC | ||
125 | select SND_SOC_MAX98090 | ||
126 | help | ||
127 | Say Y or M here if you want to add support for SoC audio on Tegra | ||
128 | boards using the MAX98090 codec, such as Venice2. | ||
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index 21d2550a08a4..5ae588cd96c4 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile | |||
@@ -24,6 +24,7 @@ snd-soc-tegra-wm8903-objs := tegra_wm8903.o | |||
24 | snd-soc-tegra-wm9712-objs := tegra_wm9712.o | 24 | snd-soc-tegra-wm9712-objs := tegra_wm9712.o |
25 | snd-soc-tegra-trimslice-objs := trimslice.o | 25 | snd-soc-tegra-trimslice-objs := trimslice.o |
26 | snd-soc-tegra-alc5632-objs := tegra_alc5632.o | 26 | snd-soc-tegra-alc5632-objs := tegra_alc5632.o |
27 | snd-soc-tegra-max98090-objs := tegra_max98090.o | ||
27 | 28 | ||
28 | obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o | 29 | obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o |
29 | obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o | 30 | obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o |
@@ -31,3 +32,4 @@ obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o | |||
31 | obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o | 32 | obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o |
32 | obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o | 33 | obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o |
33 | obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o | 34 | obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o |
35 | obj-$(CONFIG_SND_SOC_TEGRA_MAX98090) += snd-soc-tegra-max98090.o | ||
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index ae27bcd586d2..088518d7694a 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c | |||
@@ -404,7 +404,7 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
404 | ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops); | 404 | ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops); |
405 | if (ret) { | 405 | if (ret) { |
406 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | 406 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); |
407 | goto err_asoc_utils_fini; | 407 | goto err_clk_disable_unprepare; |
408 | } | 408 | } |
409 | 409 | ||
410 | ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, | 410 | ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, |
@@ -412,7 +412,7 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
412 | if (ret) { | 412 | if (ret) { |
413 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); | 413 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); |
414 | ret = -ENOMEM; | 414 | ret = -ENOMEM; |
415 | goto err_asoc_utils_fini; | 415 | goto err_clk_disable_unprepare; |
416 | } | 416 | } |
417 | 417 | ||
418 | ret = tegra_pcm_platform_register(&pdev->dev); | 418 | ret = tegra_pcm_platform_register(&pdev->dev); |
@@ -428,6 +428,8 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
428 | 428 | ||
429 | err_unregister_component: | 429 | err_unregister_component: |
430 | snd_soc_unregister_component(&pdev->dev); | 430 | snd_soc_unregister_component(&pdev->dev); |
431 | err_clk_disable_unprepare: | ||
432 | clk_disable_unprepare(ac97->clk_ac97); | ||
431 | err_asoc_utils_fini: | 433 | err_asoc_utils_fini: |
432 | tegra_asoc_utils_fini(&ac97->util_data); | 434 | tegra_asoc_utils_fini(&ac97->util_data); |
433 | err_clk_put: | 435 | err_clk_put: |
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 364bf6a907e1..8c819f811470 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c | |||
@@ -74,7 +74,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, | |||
74 | unsigned int fmt) | 74 | unsigned int fmt) |
75 | { | 75 | { |
76 | struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 76 | struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
77 | unsigned int mask, val; | 77 | unsigned int mask = 0, val = 0; |
78 | 78 | ||
79 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 79 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
80 | case SND_SOC_DAIFMT_NB_NF: | 80 | case SND_SOC_DAIFMT_NB_NF: |
@@ -83,10 +83,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, | |||
83 | return -EINVAL; | 83 | return -EINVAL; |
84 | } | 84 | } |
85 | 85 | ||
86 | mask = TEGRA20_I2S_CTRL_MASTER_ENABLE; | 86 | mask |= TEGRA20_I2S_CTRL_MASTER_ENABLE; |
87 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 87 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
88 | case SND_SOC_DAIFMT_CBS_CFS: | 88 | case SND_SOC_DAIFMT_CBS_CFS: |
89 | val = TEGRA20_I2S_CTRL_MASTER_ENABLE; | 89 | val |= TEGRA20_I2S_CTRL_MASTER_ENABLE; |
90 | break; | 90 | break; |
91 | case SND_SOC_DAIFMT_CBM_CFM: | 91 | case SND_SOC_DAIFMT_CBM_CFM: |
92 | break; | 92 | break; |
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 08bc6931c7c7..8c7c1028e579 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c | |||
@@ -67,15 +67,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, | |||
67 | { | 67 | { |
68 | struct device *dev = dai->dev; | 68 | struct device *dev = dai->dev; |
69 | struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); | 69 | struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); |
70 | unsigned int mask, val; | 70 | unsigned int mask = 0, val = 0; |
71 | int ret, spdifclock; | 71 | int ret, spdifclock; |
72 | 72 | ||
73 | mask = TEGRA20_SPDIF_CTRL_PACK | | 73 | mask |= TEGRA20_SPDIF_CTRL_PACK | |
74 | TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; | 74 | TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; |
75 | switch (params_format(params)) { | 75 | switch (params_format(params)) { |
76 | case SNDRV_PCM_FORMAT_S16_LE: | 76 | case SNDRV_PCM_FORMAT_S16_LE: |
77 | val = TEGRA20_SPDIF_CTRL_PACK | | 77 | val |= TEGRA20_SPDIF_CTRL_PACK | |
78 | TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; | 78 | TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; |
79 | break; | 79 | break; |
80 | default: | 80 | default: |
81 | return -EINVAL; | 81 | return -EINVAL; |
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 231a785b3921..02247fee1cf7 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c | |||
@@ -118,7 +118,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, | |||
118 | unsigned int fmt) | 118 | unsigned int fmt) |
119 | { | 119 | { |
120 | struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 120 | struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
121 | unsigned int mask, val; | 121 | unsigned int mask = 0, val = 0; |
122 | 122 | ||
123 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 123 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
124 | case SND_SOC_DAIFMT_NB_NF: | 124 | case SND_SOC_DAIFMT_NB_NF: |
@@ -127,10 +127,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, | |||
127 | return -EINVAL; | 127 | return -EINVAL; |
128 | } | 128 | } |
129 | 129 | ||
130 | mask = TEGRA30_I2S_CTRL_MASTER_ENABLE; | 130 | mask |= TEGRA30_I2S_CTRL_MASTER_ENABLE; |
131 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 131 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
132 | case SND_SOC_DAIFMT_CBS_CFS: | 132 | case SND_SOC_DAIFMT_CBS_CFS: |
133 | val = TEGRA30_I2S_CTRL_MASTER_ENABLE; | 133 | val |= TEGRA30_I2S_CTRL_MASTER_ENABLE; |
134 | break; | 134 | break; |
135 | case SND_SOC_DAIFMT_CBM_CFM: | 135 | case SND_SOC_DAIFMT_CBM_CFM: |
136 | break; | 136 | break; |
diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c new file mode 100644 index 000000000000..0283cfb7c031 --- /dev/null +++ b/sound/soc/tegra/tegra_max98090.c | |||
@@ -0,0 +1,275 @@ | |||
1 | /* | ||
2 | * Tegra machine ASoC driver for boards using a MAX90809 CODEC. | ||
3 | * | ||
4 | * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * Based on code copyright/by: | ||
19 | * | ||
20 | * Copyright (C) 2010-2012 - NVIDIA, Inc. | ||
21 | * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net> | ||
22 | * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd. | ||
23 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/gpio.h> | ||
30 | #include <linux/of_gpio.h> | ||
31 | |||
32 | #include <sound/core.h> | ||
33 | #include <sound/jack.h> | ||
34 | #include <sound/pcm.h> | ||
35 | #include <sound/pcm_params.h> | ||
36 | #include <sound/soc.h> | ||
37 | |||
38 | #include "tegra_asoc_utils.h" | ||
39 | |||
40 | #define DRV_NAME "tegra-snd-max98090" | ||
41 | |||
42 | struct tegra_max98090 { | ||
43 | struct tegra_asoc_utils_data util_data; | ||
44 | int gpio_hp_det; | ||
45 | }; | ||
46 | |||
47 | static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream, | ||
48 | struct snd_pcm_hw_params *params) | ||
49 | { | ||
50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
51 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
52 | struct snd_soc_codec *codec = codec_dai->codec; | ||
53 | struct snd_soc_card *card = codec->card; | ||
54 | struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card); | ||
55 | int srate, mclk; | ||
56 | int err; | ||
57 | |||
58 | srate = params_rate(params); | ||
59 | switch (srate) { | ||
60 | case 8000: | ||
61 | case 16000: | ||
62 | case 24000: | ||
63 | case 32000: | ||
64 | case 48000: | ||
65 | case 64000: | ||
66 | case 96000: | ||
67 | mclk = 12288000; | ||
68 | break; | ||
69 | case 11025: | ||
70 | case 22050: | ||
71 | case 44100: | ||
72 | case 88200: | ||
73 | mclk = 11289600; | ||
74 | break; | ||
75 | default: | ||
76 | mclk = 12000000; | ||
77 | break; | ||
78 | } | ||
79 | |||
80 | err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); | ||
81 | if (err < 0) { | ||
82 | dev_err(card->dev, "Can't configure clocks\n"); | ||
83 | return err; | ||
84 | } | ||
85 | |||
86 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | ||
87 | SND_SOC_CLOCK_IN); | ||
88 | if (err < 0) { | ||
89 | dev_err(card->dev, "codec_dai clock not set\n"); | ||
90 | return err; | ||
91 | } | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static struct snd_soc_ops tegra_max98090_ops = { | ||
97 | .hw_params = tegra_max98090_asoc_hw_params, | ||
98 | }; | ||
99 | |||
100 | static struct snd_soc_jack tegra_max98090_hp_jack; | ||
101 | |||
102 | static struct snd_soc_jack_pin tegra_max98090_hp_jack_pins[] = { | ||
103 | { | ||
104 | .pin = "Headphones", | ||
105 | .mask = SND_JACK_HEADPHONE, | ||
106 | }, | ||
107 | }; | ||
108 | |||
109 | static struct snd_soc_jack_gpio tegra_max98090_hp_jack_gpio = { | ||
110 | .name = "Headphone detection", | ||
111 | .report = SND_JACK_HEADPHONE, | ||
112 | .debounce_time = 150, | ||
113 | .invert = 1, | ||
114 | }; | ||
115 | |||
116 | static const struct snd_soc_dapm_widget tegra_max98090_dapm_widgets[] = { | ||
117 | SND_SOC_DAPM_HP("Headphones", NULL), | ||
118 | SND_SOC_DAPM_SPK("Speakers", NULL), | ||
119 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
120 | }; | ||
121 | |||
122 | static const struct snd_kcontrol_new tegra_max98090_controls[] = { | ||
123 | SOC_DAPM_PIN_SWITCH("Speakers"), | ||
124 | }; | ||
125 | |||
126 | static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd) | ||
127 | { | ||
128 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
129 | struct snd_soc_codec *codec = codec_dai->codec; | ||
130 | struct tegra_max98090 *machine = snd_soc_card_get_drvdata(codec->card); | ||
131 | |||
132 | if (gpio_is_valid(machine->gpio_hp_det)) { | ||
133 | snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, | ||
134 | &tegra_max98090_hp_jack); | ||
135 | snd_soc_jack_add_pins(&tegra_max98090_hp_jack, | ||
136 | ARRAY_SIZE(tegra_max98090_hp_jack_pins), | ||
137 | tegra_max98090_hp_jack_pins); | ||
138 | |||
139 | tegra_max98090_hp_jack_gpio.gpio = machine->gpio_hp_det; | ||
140 | snd_soc_jack_add_gpios(&tegra_max98090_hp_jack, | ||
141 | 1, | ||
142 | &tegra_max98090_hp_jack_gpio); | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static struct snd_soc_dai_link tegra_max98090_dai = { | ||
149 | .name = "max98090", | ||
150 | .stream_name = "max98090 PCM", | ||
151 | .codec_dai_name = "HiFi", | ||
152 | .init = tegra_max98090_asoc_init, | ||
153 | .ops = &tegra_max98090_ops, | ||
154 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
155 | SND_SOC_DAIFMT_CBS_CFS, | ||
156 | }; | ||
157 | |||
158 | static struct snd_soc_card snd_soc_tegra_max98090 = { | ||
159 | .name = "tegra-max98090", | ||
160 | .owner = THIS_MODULE, | ||
161 | .dai_link = &tegra_max98090_dai, | ||
162 | .num_links = 1, | ||
163 | .controls = tegra_max98090_controls, | ||
164 | .num_controls = ARRAY_SIZE(tegra_max98090_controls), | ||
165 | .dapm_widgets = tegra_max98090_dapm_widgets, | ||
166 | .num_dapm_widgets = ARRAY_SIZE(tegra_max98090_dapm_widgets), | ||
167 | .fully_routed = true, | ||
168 | }; | ||
169 | |||
170 | static int tegra_max98090_probe(struct platform_device *pdev) | ||
171 | { | ||
172 | struct device_node *np = pdev->dev.of_node; | ||
173 | struct snd_soc_card *card = &snd_soc_tegra_max98090; | ||
174 | struct tegra_max98090 *machine; | ||
175 | int ret; | ||
176 | |||
177 | machine = devm_kzalloc(&pdev->dev, | ||
178 | sizeof(struct tegra_max98090), GFP_KERNEL); | ||
179 | if (!machine) { | ||
180 | dev_err(&pdev->dev, "Can't allocate tegra_max98090\n"); | ||
181 | return -ENOMEM; | ||
182 | } | ||
183 | |||
184 | card->dev = &pdev->dev; | ||
185 | platform_set_drvdata(pdev, card); | ||
186 | snd_soc_card_set_drvdata(card, machine); | ||
187 | |||
188 | machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); | ||
189 | if (machine->gpio_hp_det == -EPROBE_DEFER) | ||
190 | return -EPROBE_DEFER; | ||
191 | |||
192 | ret = snd_soc_of_parse_card_name(card, "nvidia,model"); | ||
193 | if (ret) | ||
194 | goto err; | ||
195 | |||
196 | ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); | ||
197 | if (ret) | ||
198 | goto err; | ||
199 | |||
200 | tegra_max98090_dai.codec_of_node = of_parse_phandle(np, | ||
201 | "nvidia,audio-codec", 0); | ||
202 | if (!tegra_max98090_dai.codec_of_node) { | ||
203 | dev_err(&pdev->dev, | ||
204 | "Property 'nvidia,audio-codec' missing or invalid\n"); | ||
205 | ret = -EINVAL; | ||
206 | goto err; | ||
207 | } | ||
208 | |||
209 | tegra_max98090_dai.cpu_of_node = of_parse_phandle(np, | ||
210 | "nvidia,i2s-controller", 0); | ||
211 | if (!tegra_max98090_dai.cpu_of_node) { | ||
212 | dev_err(&pdev->dev, | ||
213 | "Property 'nvidia,i2s-controller' missing or invalid\n"); | ||
214 | ret = -EINVAL; | ||
215 | goto err; | ||
216 | } | ||
217 | |||
218 | tegra_max98090_dai.platform_of_node = tegra_max98090_dai.cpu_of_node; | ||
219 | |||
220 | ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); | ||
221 | if (ret) | ||
222 | goto err; | ||
223 | |||
224 | ret = snd_soc_register_card(card); | ||
225 | if (ret) { | ||
226 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", | ||
227 | ret); | ||
228 | goto err_fini_utils; | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | |||
233 | err_fini_utils: | ||
234 | tegra_asoc_utils_fini(&machine->util_data); | ||
235 | err: | ||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | static int tegra_max98090_remove(struct platform_device *pdev) | ||
240 | { | ||
241 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
242 | struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card); | ||
243 | |||
244 | snd_soc_jack_free_gpios(&tegra_max98090_hp_jack, 1, | ||
245 | &tegra_max98090_hp_jack_gpio); | ||
246 | |||
247 | snd_soc_unregister_card(card); | ||
248 | |||
249 | tegra_asoc_utils_fini(&machine->util_data); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static const struct of_device_id tegra_max98090_of_match[] = { | ||
255 | { .compatible = "nvidia,tegra-audio-max98090", }, | ||
256 | {}, | ||
257 | }; | ||
258 | |||
259 | static struct platform_driver tegra_max98090_driver = { | ||
260 | .driver = { | ||
261 | .name = DRV_NAME, | ||
262 | .owner = THIS_MODULE, | ||
263 | .pm = &snd_soc_pm_ops, | ||
264 | .of_match_table = tegra_max98090_of_match, | ||
265 | }, | ||
266 | .probe = tegra_max98090_probe, | ||
267 | .remove = tegra_max98090_remove, | ||
268 | }; | ||
269 | module_platform_driver(tegra_max98090_driver); | ||
270 | |||
271 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
272 | MODULE_DESCRIPTION("Tegra max98090 machine ASoC driver"); | ||
273 | MODULE_LICENSE("GPL v2"); | ||
274 | MODULE_ALIAS("platform:" DRV_NAME); | ||
275 | MODULE_DEVICE_TABLE(of, tegra_max98090_of_match); | ||
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 7b2d23ba69b3..c09ffd18791b 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c | |||
@@ -42,9 +42,6 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = { | |||
42 | .info = SNDRV_PCM_INFO_MMAP | | 42 | .info = SNDRV_PCM_INFO_MMAP | |
43 | SNDRV_PCM_INFO_MMAP_VALID | | 43 | SNDRV_PCM_INFO_MMAP_VALID | |
44 | SNDRV_PCM_INFO_INTERLEAVED, | 44 | SNDRV_PCM_INFO_INTERLEAVED, |
45 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
46 | .channels_min = 2, | ||
47 | .channels_max = 2, | ||
48 | .period_bytes_min = 1024, | 45 | .period_bytes_min = 1024, |
49 | .period_bytes_max = PAGE_SIZE, | 46 | .period_bytes_max = PAGE_SIZE, |
50 | .periods_min = 2, | 47 | .periods_min = 2, |
diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c index 5e119630b0e0..45b57892b6a5 100644 --- a/sound/soc/tegra/tegra_wm9712.c +++ b/sound/soc/tegra/tegra_wm9712.c | |||
@@ -55,7 +55,6 @@ static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd) | |||
55 | static struct snd_soc_dai_link tegra_wm9712_dai = { | 55 | static struct snd_soc_dai_link tegra_wm9712_dai = { |
56 | .name = "AC97 HiFi", | 56 | .name = "AC97 HiFi", |
57 | .stream_name = "AC97 HiFi", | 57 | .stream_name = "AC97 HiFi", |
58 | .cpu_dai_name = "tegra20-ac97", | ||
59 | .codec_dai_name = "wm9712-hifi", | 58 | .codec_dai_name = "wm9712-hifi", |
60 | .codec_name = "wm9712-codec", | 59 | .codec_name = "wm9712-codec", |
61 | .init = tegra_wm9712_init, | 60 | .init = tegra_wm9712_init, |
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index fbd077f4de72..f0829de28708 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c | |||
@@ -40,11 +40,6 @@ static const struct snd_pcm_hardware txx9aclc_pcm_hardware = { | |||
40 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 40 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
41 | SNDRV_PCM_INFO_BATCH | | 41 | SNDRV_PCM_INFO_BATCH | |
42 | SNDRV_PCM_INFO_PAUSE, | 42 | SNDRV_PCM_INFO_PAUSE, |
43 | #ifdef __BIG_ENDIAN | ||
44 | .formats = SNDRV_PCM_FMTBIT_S16_BE, | ||
45 | #else | ||
46 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
47 | #endif | ||
48 | .period_bytes_min = 1024, | 43 | .period_bytes_min = 1024, |
49 | .period_bytes_max = 8 * 1024, | 44 | .period_bytes_max = 8 * 1024, |
50 | .periods_min = 2, | 45 | .periods_min = 2, |