diff options
Diffstat (limited to 'sound/soc')
178 files changed, 8642 insertions, 3886 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..6058c1fd5070 --- /dev/null +++ b/sound/soc/adi/axi-i2s.c | |||
@@ -0,0 +1,276 @@ | |||
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, 0); | ||
240 | if (ret) | ||
241 | goto err_clk_disable; | ||
242 | |||
243 | err_clk_disable: | ||
244 | clk_disable_unprepare(i2s->clk); | ||
245 | return ret; | ||
246 | } | ||
247 | |||
248 | static int axi_i2s_dev_remove(struct platform_device *pdev) | ||
249 | { | ||
250 | struct axi_i2s *i2s = platform_get_drvdata(pdev); | ||
251 | |||
252 | clk_disable_unprepare(i2s->clk); | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static const struct of_device_id axi_i2s_of_match[] = { | ||
258 | { .compatible = "adi,axi-i2s-1.00.a", }, | ||
259 | {}, | ||
260 | }; | ||
261 | MODULE_DEVICE_TABLE(of, axi_i2s_of_match); | ||
262 | |||
263 | static struct platform_driver axi_i2s_driver = { | ||
264 | .driver = { | ||
265 | .name = "axi-i2s", | ||
266 | .owner = THIS_MODULE, | ||
267 | .of_match_table = axi_i2s_of_match, | ||
268 | }, | ||
269 | .probe = axi_i2s_probe, | ||
270 | .remove = axi_i2s_dev_remove, | ||
271 | }; | ||
272 | module_platform_driver(axi_i2s_driver); | ||
273 | |||
274 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
275 | MODULE_DESCRIPTION("AXI I2S driver"); | ||
276 | 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..198e3a4640f6 --- /dev/null +++ b/sound/soc/adi/axi-spdif.c | |||
@@ -0,0 +1,271 @@ | |||
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, 0); | ||
233 | if (ret) | ||
234 | goto err_clk_disable; | ||
235 | |||
236 | return 0; | ||
237 | |||
238 | err_clk_disable: | ||
239 | clk_disable_unprepare(spdif->clk); | ||
240 | return ret; | ||
241 | } | ||
242 | |||
243 | static int axi_spdif_dev_remove(struct platform_device *pdev) | ||
244 | { | ||
245 | struct axi_spdif *spdif = platform_get_drvdata(pdev); | ||
246 | |||
247 | clk_disable_unprepare(spdif->clk); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static const struct of_device_id axi_spdif_of_match[] = { | ||
253 | { .compatible = "adi,axi-spdif-tx-1.00.a", }, | ||
254 | {}, | ||
255 | }; | ||
256 | MODULE_DEVICE_TABLE(of, axi_spdif_of_match); | ||
257 | |||
258 | static struct platform_driver axi_spdif_driver = { | ||
259 | .driver = { | ||
260 | .name = "axi-spdif", | ||
261 | .owner = THIS_MODULE, | ||
262 | .of_match_table = axi_spdif_of_match, | ||
263 | }, | ||
264 | .probe = axi_spdif_probe, | ||
265 | .remove = axi_spdif_dev_remove, | ||
266 | }; | ||
267 | module_platform_driver(axi_spdif_driver); | ||
268 | |||
269 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
270 | MODULE_DESCRIPTION("AXI SPDIF driver"); | ||
271 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c index 06082e5e5dcb..b79a2a864513 100644 --- a/sound/soc/atmel/atmel-pcm-dma.c +++ b/sound/soc/atmel/atmel-pcm-dma.c | |||
@@ -50,7 +50,6 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = { | |||
50 | SNDRV_PCM_INFO_INTERLEAVED | | 50 | SNDRV_PCM_INFO_INTERLEAVED | |
51 | SNDRV_PCM_INFO_RESUME | | 51 | SNDRV_PCM_INFO_RESUME | |
52 | SNDRV_PCM_INFO_PAUSE, | 52 | SNDRV_PCM_INFO_PAUSE, |
53 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
54 | .period_bytes_min = 256, /* lighting DMA overhead */ | 53 | .period_bytes_min = 256, /* lighting DMA overhead */ |
55 | .period_bytes_max = 2 * 0xffff, /* if 2 bytes format */ | 54 | .period_bytes_max = 2 * 0xffff, /* if 2 bytes format */ |
56 | .periods_min = 8, | 55 | .periods_min = 8, |
diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c index 054ea4d9326a..33ec592ecd75 100644 --- a/sound/soc/atmel/atmel-pcm-pdc.c +++ b/sound/soc/atmel/atmel-pcm-pdc.c | |||
@@ -58,7 +58,6 @@ static const struct snd_pcm_hardware atmel_pcm_hardware = { | |||
58 | SNDRV_PCM_INFO_MMAP_VALID | | 58 | SNDRV_PCM_INFO_MMAP_VALID | |
59 | SNDRV_PCM_INFO_INTERLEAVED | | 59 | SNDRV_PCM_INFO_INTERLEAVED | |
60 | SNDRV_PCM_INFO_PAUSE, | 60 | SNDRV_PCM_INFO_PAUSE, |
61 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
62 | .period_bytes_min = 32, | 61 | .period_bytes_min = 32, |
63 | .period_bytes_max = 8192, | 62 | .period_bytes_max = 8192, |
64 | .periods_min = 2, | 63 | .periods_min = 2, |
diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c index 7d6a9055874b..3188036a18f0 100644 --- a/sound/soc/atmel/sam9x5_wm8731.c +++ b/sound/soc/atmel/sam9x5_wm8731.c | |||
@@ -155,8 +155,6 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) | |||
155 | of_node_put(codec_np); | 155 | of_node_put(codec_np); |
156 | of_node_put(cpu_np); | 156 | of_node_put(cpu_np); |
157 | 157 | ||
158 | platform_set_drvdata(pdev, card); | ||
159 | |||
160 | ret = snd_soc_register_card(card); | 158 | ret = snd_soc_register_card(card); |
161 | if (ret) { | 159 | if (ret) { |
162 | 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..6a834e109f1d --- /dev/null +++ b/sound/soc/bcm/Kconfig | |||
@@ -0,0 +1,9 @@ | |||
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_GENERIC_DMAENGINE_PCM | ||
5 | select REGMAP_MMIO | ||
6 | help | ||
7 | Say Y or M if you want to add support for codecs attached to | ||
8 | the BCM2835 I2S interface. You will also need | ||
9 | 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..77f459868579 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -168,17 +168,19 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
168 | int word_len = 0; | 168 | int word_len = 0; |
169 | 169 | ||
170 | /* bit size */ | 170 | /* bit size */ |
171 | switch (params_format(params)) { | 171 | switch (params_width(params)) { |
172 | case SNDRV_PCM_FORMAT_S16_LE: | 172 | case 16: |
173 | word_len = AD1836_WORD_LEN_16; | 173 | word_len = AD1836_WORD_LEN_16; |
174 | break; | 174 | break; |
175 | case SNDRV_PCM_FORMAT_S20_3LE: | 175 | case 20: |
176 | word_len = AD1836_WORD_LEN_20; | 176 | word_len = AD1836_WORD_LEN_20; |
177 | break; | 177 | break; |
178 | case SNDRV_PCM_FORMAT_S24_LE: | 178 | case 24: |
179 | case SNDRV_PCM_FORMAT_S32_LE: | 179 | case 32: |
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..5a42dca535b7 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -249,15 +249,15 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, | |||
249 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); | 249 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); |
250 | 250 | ||
251 | /* bit size */ | 251 | /* bit size */ |
252 | switch (params_format(params)) { | 252 | switch (params_width(params)) { |
253 | case SNDRV_PCM_FORMAT_S16_LE: | 253 | case 16: |
254 | word_len = 3; | 254 | word_len = 3; |
255 | break; | 255 | break; |
256 | case SNDRV_PCM_FORMAT_S20_3LE: | 256 | case 20: |
257 | word_len = 1; | 257 | word_len = 1; |
258 | break; | 258 | break; |
259 | case SNDRV_PCM_FORMAT_S24_LE: | 259 | case 24: |
260 | case SNDRV_PCM_FORMAT_S32_LE: | 260 | case 32: |
261 | word_len = 0; | 261 | word_len = 0; |
262 | break; | 262 | break; |
263 | } | 263 | } |
@@ -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/adau1373.c b/sound/soc/codecs/adau1373.c index 59654b1e7f3f..eb836ed5271f 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -1078,17 +1078,17 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream, | |||
1078 | ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK, | 1078 | ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK, |
1079 | (div << 2) | ADAU1373_BCLKDIV_64); | 1079 | (div << 2) | ADAU1373_BCLKDIV_64); |
1080 | 1080 | ||
1081 | switch (params_format(params)) { | 1081 | switch (params_width(params)) { |
1082 | case SNDRV_PCM_FORMAT_S16_LE: | 1082 | case 16: |
1083 | ctrl = ADAU1373_DAI_WLEN_16; | 1083 | ctrl = ADAU1373_DAI_WLEN_16; |
1084 | break; | 1084 | break; |
1085 | case SNDRV_PCM_FORMAT_S20_3LE: | 1085 | case 20: |
1086 | ctrl = ADAU1373_DAI_WLEN_20; | 1086 | ctrl = ADAU1373_DAI_WLEN_20; |
1087 | break; | 1087 | break; |
1088 | case SNDRV_PCM_FORMAT_S24_LE: | 1088 | case 24: |
1089 | ctrl = ADAU1373_DAI_WLEN_24; | 1089 | ctrl = ADAU1373_DAI_WLEN_24; |
1090 | break; | 1090 | break; |
1091 | case SNDRV_PCM_FORMAT_S32_LE: | 1091 | case 32: |
1092 | ctrl = ADAU1373_DAI_WLEN_32; | 1092 | ctrl = ADAU1373_DAI_WLEN_32; |
1093 | break; | 1093 | break; |
1094 | default: | 1094 | default: |
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index ebff1128be59..d71c59cf7bdd 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
@@ -71,7 +71,7 @@ | |||
71 | 71 | ||
72 | #define ADAU1701_SEROCTL_WORD_LEN_24 0x0000 | 72 | #define ADAU1701_SEROCTL_WORD_LEN_24 0x0000 |
73 | #define ADAU1701_SEROCTL_WORD_LEN_20 0x0001 | 73 | #define ADAU1701_SEROCTL_WORD_LEN_20 0x0001 |
74 | #define ADAU1701_SEROCTL_WORD_LEN_16 0x0010 | 74 | #define ADAU1701_SEROCTL_WORD_LEN_16 0x0002 |
75 | #define ADAU1701_SEROCTL_WORD_LEN_MASK 0x0003 | 75 | #define ADAU1701_SEROCTL_WORD_LEN_MASK 0x0003 |
76 | 76 | ||
77 | #define ADAU1701_AUXNPOW_VBPD 0x40 | 77 | #define ADAU1701_AUXNPOW_VBPD 0x40 |
@@ -299,20 +299,20 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv) | |||
299 | } | 299 | } |
300 | 300 | ||
301 | static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, | 301 | static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, |
302 | snd_pcm_format_t format) | 302 | struct snd_pcm_hw_params *params) |
303 | { | 303 | { |
304 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | 304 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); |
305 | unsigned int mask = ADAU1701_SEROCTL_WORD_LEN_MASK; | 305 | unsigned int mask = ADAU1701_SEROCTL_WORD_LEN_MASK; |
306 | unsigned int val; | 306 | unsigned int val; |
307 | 307 | ||
308 | switch (format) { | 308 | switch (params_width(params)) { |
309 | case SNDRV_PCM_FORMAT_S16_LE: | 309 | case 16: |
310 | val = ADAU1701_SEROCTL_WORD_LEN_16; | 310 | val = ADAU1701_SEROCTL_WORD_LEN_16; |
311 | break; | 311 | break; |
312 | case SNDRV_PCM_FORMAT_S20_3LE: | 312 | case 20: |
313 | val = ADAU1701_SEROCTL_WORD_LEN_20; | 313 | val = ADAU1701_SEROCTL_WORD_LEN_20; |
314 | break; | 314 | break; |
315 | case SNDRV_PCM_FORMAT_S24_LE: | 315 | case 24: |
316 | val = ADAU1701_SEROCTL_WORD_LEN_24; | 316 | val = ADAU1701_SEROCTL_WORD_LEN_24; |
317 | break; | 317 | break; |
318 | default: | 318 | default: |
@@ -320,14 +320,14 @@ static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, | |||
320 | } | 320 | } |
321 | 321 | ||
322 | if (adau1701->dai_fmt == SND_SOC_DAIFMT_RIGHT_J) { | 322 | if (adau1701->dai_fmt == SND_SOC_DAIFMT_RIGHT_J) { |
323 | switch (format) { | 323 | switch (params_width(params)) { |
324 | case SNDRV_PCM_FORMAT_S16_LE: | 324 | case 16: |
325 | val |= ADAU1701_SEROCTL_MSB_DEALY16; | 325 | val |= ADAU1701_SEROCTL_MSB_DEALY16; |
326 | break; | 326 | break; |
327 | case SNDRV_PCM_FORMAT_S20_3LE: | 327 | case 20: |
328 | val |= ADAU1701_SEROCTL_MSB_DEALY12; | 328 | val |= ADAU1701_SEROCTL_MSB_DEALY12; |
329 | break; | 329 | break; |
330 | case SNDRV_PCM_FORMAT_S24_LE: | 330 | case 24: |
331 | val |= ADAU1701_SEROCTL_MSB_DEALY8; | 331 | val |= ADAU1701_SEROCTL_MSB_DEALY8; |
332 | break; | 332 | break; |
333 | } | 333 | } |
@@ -340,7 +340,7 @@ static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, | |||
340 | } | 340 | } |
341 | 341 | ||
342 | static int adau1701_set_playback_pcm_format(struct snd_soc_codec *codec, | 342 | static int adau1701_set_playback_pcm_format(struct snd_soc_codec *codec, |
343 | snd_pcm_format_t format) | 343 | struct snd_pcm_hw_params *params) |
344 | { | 344 | { |
345 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | 345 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); |
346 | unsigned int val; | 346 | unsigned int val; |
@@ -348,14 +348,14 @@ static int adau1701_set_playback_pcm_format(struct snd_soc_codec *codec, | |||
348 | if (adau1701->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) | 348 | if (adau1701->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) |
349 | return 0; | 349 | return 0; |
350 | 350 | ||
351 | switch (format) { | 351 | switch (params_width(params)) { |
352 | case SNDRV_PCM_FORMAT_S16_LE: | 352 | case 16: |
353 | val = ADAU1701_SERICTL_RIGHTJ_16; | 353 | val = ADAU1701_SERICTL_RIGHTJ_16; |
354 | break; | 354 | break; |
355 | case SNDRV_PCM_FORMAT_S20_3LE: | 355 | case 20: |
356 | val = ADAU1701_SERICTL_RIGHTJ_20; | 356 | val = ADAU1701_SERICTL_RIGHTJ_20; |
357 | break; | 357 | break; |
358 | case SNDRV_PCM_FORMAT_S24_LE: | 358 | case 24: |
359 | val = ADAU1701_SERICTL_RIGHTJ_24; | 359 | val = ADAU1701_SERICTL_RIGHTJ_24; |
360 | break; | 360 | break; |
361 | default: | 361 | default: |
@@ -374,7 +374,6 @@ static int adau1701_hw_params(struct snd_pcm_substream *substream, | |||
374 | struct snd_soc_codec *codec = dai->codec; | 374 | struct snd_soc_codec *codec = dai->codec; |
375 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | 375 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); |
376 | unsigned int clkdiv = adau1701->sysclk / params_rate(params); | 376 | unsigned int clkdiv = adau1701->sysclk / params_rate(params); |
377 | snd_pcm_format_t format; | ||
378 | unsigned int val; | 377 | unsigned int val; |
379 | int ret; | 378 | int ret; |
380 | 379 | ||
@@ -406,11 +405,10 @@ static int adau1701_hw_params(struct snd_pcm_substream *substream, | |||
406 | regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL, | 405 | regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL, |
407 | ADAU1701_DSPCTRL_SR_MASK, val); | 406 | ADAU1701_DSPCTRL_SR_MASK, val); |
408 | 407 | ||
409 | format = params_format(params); | ||
410 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 408 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
411 | return adau1701_set_playback_pcm_format(codec, format); | 409 | return adau1701_set_playback_pcm_format(codec, params); |
412 | else | 410 | else |
413 | return adau1701_set_capture_pcm_format(codec, format); | 411 | return adau1701_set_capture_pcm_format(codec, params); |
414 | } | 412 | } |
415 | 413 | ||
416 | static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai, | 414 | static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai, |
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index 14a7c169d004..f78b27a7c461 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
@@ -453,22 +453,22 @@ static int adav80x_set_dac_clock(struct snd_soc_codec *codec, | |||
453 | } | 453 | } |
454 | 454 | ||
455 | static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec, | 455 | static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec, |
456 | struct snd_soc_dai *dai, snd_pcm_format_t format) | 456 | struct snd_soc_dai *dai, struct snd_pcm_hw_params *params) |
457 | { | 457 | { |
458 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 458 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
459 | unsigned int val; | 459 | unsigned int val; |
460 | 460 | ||
461 | switch (format) { | 461 | switch (params_width(params)) { |
462 | case SNDRV_PCM_FORMAT_S16_LE: | 462 | case 16: |
463 | val = ADAV80X_CAPTURE_WORD_LEN16; | 463 | val = ADAV80X_CAPTURE_WORD_LEN16; |
464 | break; | 464 | break; |
465 | case SNDRV_PCM_FORMAT_S18_3LE: | 465 | case 18: |
466 | val = ADAV80X_CAPTRUE_WORD_LEN18; | 466 | val = ADAV80X_CAPTRUE_WORD_LEN18; |
467 | break; | 467 | break; |
468 | case SNDRV_PCM_FORMAT_S20_3LE: | 468 | case 20: |
469 | val = ADAV80X_CAPTURE_WORD_LEN20; | 469 | val = ADAV80X_CAPTURE_WORD_LEN20; |
470 | break; | 470 | break; |
471 | case SNDRV_PCM_FORMAT_S24_LE: | 471 | case 24: |
472 | val = ADAV80X_CAPTURE_WORD_LEN24; | 472 | val = ADAV80X_CAPTURE_WORD_LEN24; |
473 | break; | 473 | break; |
474 | default: | 474 | default: |
@@ -482,7 +482,7 @@ static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec, | |||
482 | } | 482 | } |
483 | 483 | ||
484 | static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec, | 484 | static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec, |
485 | struct snd_soc_dai *dai, snd_pcm_format_t format) | 485 | struct snd_soc_dai *dai, struct snd_pcm_hw_params *params) |
486 | { | 486 | { |
487 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 487 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
488 | unsigned int val; | 488 | unsigned int val; |
@@ -490,17 +490,17 @@ static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec, | |||
490 | if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J) | 490 | if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J) |
491 | return 0; | 491 | return 0; |
492 | 492 | ||
493 | switch (format) { | 493 | switch (params_width(params)) { |
494 | case SNDRV_PCM_FORMAT_S16_LE: | 494 | case 16: |
495 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16; | 495 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16; |
496 | break; | 496 | break; |
497 | case SNDRV_PCM_FORMAT_S18_3LE: | 497 | case 18: |
498 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18; | 498 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18; |
499 | break; | 499 | break; |
500 | case SNDRV_PCM_FORMAT_S20_3LE: | 500 | case 20: |
501 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20; | 501 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20; |
502 | break; | 502 | break; |
503 | case SNDRV_PCM_FORMAT_S24_LE: | 503 | case 24: |
504 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24; | 504 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24; |
505 | break; | 505 | break; |
506 | default: | 506 | default: |
@@ -524,12 +524,10 @@ static int adav80x_hw_params(struct snd_pcm_substream *substream, | |||
524 | return -EINVAL; | 524 | return -EINVAL; |
525 | 525 | ||
526 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 526 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
527 | adav80x_set_playback_pcm_format(codec, dai, | 527 | adav80x_set_playback_pcm_format(codec, dai, params); |
528 | params_format(params)); | ||
529 | adav80x_set_dac_clock(codec, rate); | 528 | adav80x_set_dac_clock(codec, rate); |
530 | } else { | 529 | } else { |
531 | adav80x_set_capture_pcm_format(codec, dai, | 530 | adav80x_set_capture_pcm_format(codec, dai, params); |
532 | params_format(params)); | ||
533 | adav80x_set_adc_clock(codec, rate); | 531 | adav80x_set_adc_clock(codec, rate); |
534 | } | 532 | } |
535 | adav80x->rate = rate; | 533 | adav80x->rate = rate; |
@@ -939,7 +937,7 @@ static struct spi_driver adav80x_spi_driver = { | |||
939 | }; | 937 | }; |
940 | #endif | 938 | #endif |
941 | 939 | ||
942 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 940 | #if IS_ENABLED(CONFIG_I2C) |
943 | static const struct regmap_config adav80x_i2c_regmap_config = { | 941 | static const struct regmap_config adav80x_i2c_regmap_config = { |
944 | .val_bits = 8, | 942 | .val_bits = 8, |
945 | .pad_bits = 1, | 943 | .pad_bits = 1, |
@@ -985,7 +983,7 @@ static int __init adav80x_init(void) | |||
985 | { | 983 | { |
986 | int ret = 0; | 984 | int ret = 0; |
987 | 985 | ||
988 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 986 | #if IS_ENABLED(CONFIG_I2C) |
989 | ret = i2c_add_driver(&adav80x_i2c_driver); | 987 | ret = i2c_add_driver(&adav80x_i2c_driver); |
990 | if (ret) | 988 | if (ret) |
991 | return ret; | 989 | return ret; |
@@ -1001,7 +999,7 @@ module_init(adav80x_init); | |||
1001 | 999 | ||
1002 | static void __exit adav80x_exit(void) | 1000 | static void __exit adav80x_exit(void) |
1003 | { | 1001 | { |
1004 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1002 | #if IS_ENABLED(CONFIG_I2C) |
1005 | i2c_del_driver(&adav80x_i2c_driver); | 1003 | i2c_del_driver(&adav80x_i2c_driver); |
1006 | #endif | 1004 | #endif |
1007 | #if defined(CONFIG_SPI_MASTER) | 1005 | #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/alc5623.c b/sound/soc/codecs/alc5623.c index 256c364193a5..d3036283482a 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c | |||
@@ -714,17 +714,17 @@ static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream, | |||
714 | iface &= ~ALC5623_DAI_I2S_DL_MASK; | 714 | iface &= ~ALC5623_DAI_I2S_DL_MASK; |
715 | 715 | ||
716 | /* bit size */ | 716 | /* bit size */ |
717 | switch (params_format(params)) { | 717 | switch (params_width(params)) { |
718 | case SNDRV_PCM_FORMAT_S16_LE: | 718 | case 16: |
719 | iface |= ALC5623_DAI_I2S_DL_16; | 719 | iface |= ALC5623_DAI_I2S_DL_16; |
720 | break; | 720 | break; |
721 | case SNDRV_PCM_FORMAT_S20_3LE: | 721 | case 20: |
722 | iface |= ALC5623_DAI_I2S_DL_20; | 722 | iface |= ALC5623_DAI_I2S_DL_20; |
723 | break; | 723 | break; |
724 | case SNDRV_PCM_FORMAT_S24_LE: | 724 | case 24: |
725 | iface |= ALC5623_DAI_I2S_DL_24; | 725 | iface |= ALC5623_DAI_I2S_DL_24; |
726 | break; | 726 | break; |
727 | case SNDRV_PCM_FORMAT_S32_LE: | 727 | case 32: |
728 | iface |= ALC5623_DAI_I2S_DL_32; | 728 | iface |= ALC5623_DAI_I2S_DL_32; |
729 | break; | 729 | break; |
730 | default: | 730 | default: |
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index 19e9f222d09c..fb001c56cf8d 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c | |||
@@ -869,14 +869,14 @@ static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream, | |||
869 | iface &= ~ALC5632_DAI_I2S_DL_MASK; | 869 | iface &= ~ALC5632_DAI_I2S_DL_MASK; |
870 | 870 | ||
871 | /* bit size */ | 871 | /* bit size */ |
872 | switch (params_format(params)) { | 872 | switch (params_width(params)) { |
873 | case SNDRV_PCM_FORMAT_S16_LE: | 873 | case 16: |
874 | iface |= ALC5632_DAI_I2S_DL_16; | 874 | iface |= ALC5632_DAI_I2S_DL_16; |
875 | break; | 875 | break; |
876 | case SNDRV_PCM_FORMAT_S20_3LE: | 876 | case 20: |
877 | iface |= ALC5632_DAI_I2S_DL_20; | 877 | iface |= ALC5632_DAI_I2S_DL_20; |
878 | break; | 878 | break; |
879 | case SNDRV_PCM_FORMAT_S24_LE: | 879 | case 24: |
880 | iface |= ALC5632_DAI_I2S_DL_24; | 880 | iface |= ALC5632_DAI_I2S_DL_24; |
881 | break; | 881 | break; |
882 | default: | 882 | default: |
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..16df0f913353 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]; |
@@ -166,26 +166,29 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; | |||
166 | ARIZONA_MIXER_INPUT_ROUTES(name " Input 4") | 166 | ARIZONA_MIXER_INPUT_ROUTES(name " Input 4") |
167 | 167 | ||
168 | #define ARIZONA_DSP_ROUTES(name) \ | 168 | #define ARIZONA_DSP_ROUTES(name) \ |
169 | { name, NULL, name " Aux 1" }, \ | 169 | { name, NULL, name " Preloader"}, \ |
170 | { name, NULL, name " Aux 2" }, \ | 170 | { name " Preloader", NULL, name " Aux 1" }, \ |
171 | { name, NULL, name " Aux 3" }, \ | 171 | { name " Preloader", NULL, name " Aux 2" }, \ |
172 | { name, NULL, name " Aux 4" }, \ | 172 | { name " Preloader", NULL, name " Aux 3" }, \ |
173 | { name, NULL, name " Aux 5" }, \ | 173 | { name " Preloader", NULL, name " Aux 4" }, \ |
174 | { name, NULL, name " Aux 6" }, \ | 174 | { name " Preloader", NULL, name " Aux 5" }, \ |
175 | { name " Preloader", NULL, name " Aux 6" }, \ | ||
175 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \ | 176 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \ |
176 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \ | 177 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \ |
177 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \ | 178 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \ |
178 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \ | 179 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \ |
179 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \ | 180 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \ |
180 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \ | 181 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \ |
181 | ARIZONA_MIXER_ROUTES(name, name "L"), \ | 182 | ARIZONA_MIXER_ROUTES(name " Preloader", name "L"), \ |
182 | ARIZONA_MIXER_ROUTES(name, name "R") | 183 | ARIZONA_MIXER_ROUTES(name " Preloader", name "R") |
183 | 184 | ||
184 | #define ARIZONA_RATE_ENUM_SIZE 4 | 185 | #define ARIZONA_RATE_ENUM_SIZE 4 |
185 | extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; | 186 | extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; |
186 | extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE]; | 187 | extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE]; |
187 | 188 | ||
188 | extern const struct soc_enum arizona_isrc_fsl[]; | 189 | extern const struct soc_enum arizona_isrc_fsl[]; |
190 | extern const struct soc_enum arizona_isrc_fsh[]; | ||
191 | extern const struct soc_enum arizona_asrc_rate1; | ||
189 | 192 | ||
190 | extern const struct soc_enum arizona_in_vi_ramp; | 193 | extern const struct soc_enum arizona_in_vi_ramp; |
191 | extern const struct soc_enum arizona_in_vd_ramp; | 194 | extern const struct soc_enum arizona_in_vd_ramp; |
@@ -199,6 +202,7 @@ extern const struct soc_enum arizona_lhpf3_mode; | |||
199 | extern const struct soc_enum arizona_lhpf4_mode; | 202 | extern const struct soc_enum arizona_lhpf4_mode; |
200 | 203 | ||
201 | extern const struct soc_enum arizona_ng_hold; | 204 | extern const struct soc_enum arizona_ng_hold; |
205 | extern const struct soc_enum arizona_in_hpf_cut_enum; | ||
202 | extern const struct soc_enum arizona_in_dmic_osr[]; | 206 | extern const struct soc_enum arizona_in_dmic_osr[]; |
203 | 207 | ||
204 | extern int arizona_in_ev(struct snd_soc_dapm_widget *w, | 208 | 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/cs42l51.c b/sound/soc/codecs/cs42l51.c index 1e0fa3b5f79a..6e9ea8379a91 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c | |||
@@ -423,21 +423,17 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream, | |||
423 | intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_LJ24); | 423 | intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_LJ24); |
424 | break; | 424 | break; |
425 | case SND_SOC_DAIFMT_RIGHT_J: | 425 | case SND_SOC_DAIFMT_RIGHT_J: |
426 | switch (params_format(params)) { | 426 | switch (params_width(params)) { |
427 | case SNDRV_PCM_FORMAT_S16_LE: | 427 | case 16: |
428 | case SNDRV_PCM_FORMAT_S16_BE: | ||
429 | fmt = CS42L51_DAC_DIF_RJ16; | 428 | fmt = CS42L51_DAC_DIF_RJ16; |
430 | break; | 429 | break; |
431 | case SNDRV_PCM_FORMAT_S18_3LE: | 430 | case 18: |
432 | case SNDRV_PCM_FORMAT_S18_3BE: | ||
433 | fmt = CS42L51_DAC_DIF_RJ18; | 431 | fmt = CS42L51_DAC_DIF_RJ18; |
434 | break; | 432 | break; |
435 | case SNDRV_PCM_FORMAT_S20_3LE: | 433 | case 20: |
436 | case SNDRV_PCM_FORMAT_S20_3BE: | ||
437 | fmt = CS42L51_DAC_DIF_RJ20; | 434 | fmt = CS42L51_DAC_DIF_RJ20; |
438 | break; | 435 | break; |
439 | case SNDRV_PCM_FORMAT_S24_LE: | 436 | case 24: |
440 | case SNDRV_PCM_FORMAT_S24_BE: | ||
441 | fmt = CS42L51_DAC_DIF_RJ24; | 437 | fmt = CS42L51_DAC_DIF_RJ24; |
442 | break; | 438 | break; |
443 | default: | 439 | default: |
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..e62e294a8033 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c | |||
@@ -778,17 +778,17 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, | |||
778 | 778 | ||
779 | dai_cfg1 = 0xFC & snd_soc_read(codec, DA7210_DAI_CFG1); | 779 | dai_cfg1 = 0xFC & snd_soc_read(codec, DA7210_DAI_CFG1); |
780 | 780 | ||
781 | switch (params_format(params)) { | 781 | switch (params_width(params)) { |
782 | case SNDRV_PCM_FORMAT_S16_LE: | 782 | case 16: |
783 | dai_cfg1 |= DA7210_DAI_WORD_S16_LE; | 783 | dai_cfg1 |= DA7210_DAI_WORD_S16_LE; |
784 | break; | 784 | break; |
785 | case SNDRV_PCM_FORMAT_S20_3LE: | 785 | case 20: |
786 | dai_cfg1 |= DA7210_DAI_WORD_S20_3LE; | 786 | dai_cfg1 |= DA7210_DAI_WORD_S20_3LE; |
787 | break; | 787 | break; |
788 | case SNDRV_PCM_FORMAT_S24_LE: | 788 | case 24: |
789 | dai_cfg1 |= DA7210_DAI_WORD_S24_LE; | 789 | dai_cfg1 |= DA7210_DAI_WORD_S24_LE; |
790 | break; | 790 | break; |
791 | case SNDRV_PCM_FORMAT_S32_LE: | 791 | case 32: |
792 | dai_cfg1 |= DA7210_DAI_WORD_S32_LE; | 792 | dai_cfg1 |= DA7210_DAI_WORD_S32_LE; |
793 | break; | 793 | break; |
794 | default: | 794 | default: |
@@ -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/da7213.c b/sound/soc/codecs/da7213.c index 4a6f1daf911f..0c77e7ad7423 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c | |||
@@ -1067,17 +1067,17 @@ static int da7213_hw_params(struct snd_pcm_substream *substream, | |||
1067 | u8 fs; | 1067 | u8 fs; |
1068 | 1068 | ||
1069 | /* Set DAI format */ | 1069 | /* Set DAI format */ |
1070 | switch (params_format(params)) { | 1070 | switch (params_width(params)) { |
1071 | case SNDRV_PCM_FORMAT_S16_LE: | 1071 | case 16: |
1072 | dai_ctrl |= DA7213_DAI_WORD_LENGTH_S16_LE; | 1072 | dai_ctrl |= DA7213_DAI_WORD_LENGTH_S16_LE; |
1073 | break; | 1073 | break; |
1074 | case SNDRV_PCM_FORMAT_S20_3LE: | 1074 | case 20: |
1075 | dai_ctrl |= DA7213_DAI_WORD_LENGTH_S20_LE; | 1075 | dai_ctrl |= DA7213_DAI_WORD_LENGTH_S20_LE; |
1076 | break; | 1076 | break; |
1077 | case SNDRV_PCM_FORMAT_S24_LE: | 1077 | case 24: |
1078 | dai_ctrl |= DA7213_DAI_WORD_LENGTH_S24_LE; | 1078 | dai_ctrl |= DA7213_DAI_WORD_LENGTH_S24_LE; |
1079 | break; | 1079 | break; |
1080 | case SNDRV_PCM_FORMAT_S32_LE: | 1080 | case 32: |
1081 | dai_ctrl |= DA7213_DAI_WORD_LENGTH_S32_LE; | 1081 | dai_ctrl |= DA7213_DAI_WORD_LENGTH_S32_LE; |
1082 | break; | 1082 | break; |
1083 | default: | 1083 | default: |
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index dc0284dc9e6f..f295b6569910 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c | |||
@@ -973,17 +973,17 @@ static int da732x_hw_params(struct snd_pcm_substream *substream, | |||
973 | 973 | ||
974 | reg_aif = dai->driver->base; | 974 | reg_aif = dai->driver->base; |
975 | 975 | ||
976 | switch (params_format(params)) { | 976 | switch (params_width(params)) { |
977 | case SNDRV_PCM_FORMAT_S16_LE: | 977 | case 16: |
978 | aif |= DA732X_AIF_WORD_16; | 978 | aif |= DA732X_AIF_WORD_16; |
979 | break; | 979 | break; |
980 | case SNDRV_PCM_FORMAT_S20_3LE: | 980 | case 20: |
981 | aif |= DA732X_AIF_WORD_20; | 981 | aif |= DA732X_AIF_WORD_20; |
982 | break; | 982 | break; |
983 | case SNDRV_PCM_FORMAT_S24_LE: | 983 | case 24: |
984 | aif |= DA732X_AIF_WORD_24; | 984 | aif |= DA732X_AIF_WORD_24; |
985 | break; | 985 | break; |
986 | case SNDRV_PCM_FORMAT_S32_LE: | 986 | case 32: |
987 | aif |= DA732X_AIF_WORD_32; | 987 | aif |= DA732X_AIF_WORD_32; |
988 | break; | 988 | break; |
989 | default: | 989 | default: |
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index fc9802d1281d..52b79a487ac7 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c | |||
@@ -1058,17 +1058,17 @@ static int da9055_hw_params(struct snd_pcm_substream *substream, | |||
1058 | u8 aif_ctrl, fs; | 1058 | u8 aif_ctrl, fs; |
1059 | u32 sysclk; | 1059 | u32 sysclk; |
1060 | 1060 | ||
1061 | switch (params_format(params)) { | 1061 | switch (params_width(params)) { |
1062 | case SNDRV_PCM_FORMAT_S16_LE: | 1062 | case 16: |
1063 | aif_ctrl = DA9055_AIF_WORD_S16_LE; | 1063 | aif_ctrl = DA9055_AIF_WORD_S16_LE; |
1064 | break; | 1064 | break; |
1065 | case SNDRV_PCM_FORMAT_S20_3LE: | 1065 | case 20: |
1066 | aif_ctrl = DA9055_AIF_WORD_S20_3LE; | 1066 | aif_ctrl = DA9055_AIF_WORD_S20_3LE; |
1067 | break; | 1067 | break; |
1068 | case SNDRV_PCM_FORMAT_S24_LE: | 1068 | case 24: |
1069 | aif_ctrl = DA9055_AIF_WORD_S24_LE; | 1069 | aif_ctrl = DA9055_AIF_WORD_S24_LE; |
1070 | break; | 1070 | break; |
1071 | case SNDRV_PCM_FORMAT_S32_LE: | 1071 | case 32: |
1072 | aif_ctrl = DA9055_AIF_WORD_S32_LE; | 1072 | aif_ctrl = DA9055_AIF_WORD_S32_LE; |
1073 | break; | 1073 | break; |
1074 | default: | 1074 | default: |
diff --git a/sound/soc/codecs/hdmi.c b/sound/soc/codecs/hdmi.c index 68342b121c96..9cb1c7d3e1dc 100644 --- a/sound/soc/codecs/hdmi.c +++ b/sound/soc/codecs/hdmi.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
23 | #include <linux/of_device.h> | ||
23 | 24 | ||
24 | #define DRV_NAME "hdmi-audio-codec" | 25 | #define DRV_NAME "hdmi-audio-codec" |
25 | 26 | ||
@@ -44,7 +45,7 @@ static struct snd_soc_dai_driver hdmi_codec_dai = { | |||
44 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | | 45 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | |
45 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000, | 46 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000, |
46 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 47 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
47 | SNDRV_PCM_FMTBIT_S24_LE, | 48 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, |
48 | }, | 49 | }, |
49 | .capture = { | 50 | .capture = { |
50 | .stream_name = "Capture", | 51 | .stream_name = "Capture", |
@@ -60,6 +61,14 @@ static struct snd_soc_dai_driver hdmi_codec_dai = { | |||
60 | 61 | ||
61 | }; | 62 | }; |
62 | 63 | ||
64 | #ifdef CONFIG_OF | ||
65 | static const struct of_device_id hdmi_audio_codec_ids[] = { | ||
66 | { .compatible = "linux,hdmi-audio", }, | ||
67 | { } | ||
68 | }; | ||
69 | MODULE_DEVICE_TABLE(of, hdmi_audio_codec_ids); | ||
70 | #endif | ||
71 | |||
63 | static struct snd_soc_codec_driver hdmi_codec = { | 72 | static struct snd_soc_codec_driver hdmi_codec = { |
64 | .dapm_widgets = hdmi_widgets, | 73 | .dapm_widgets = hdmi_widgets, |
65 | .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), | 74 | .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), |
@@ -83,6 +92,7 @@ static struct platform_driver hdmi_codec_driver = { | |||
83 | .driver = { | 92 | .driver = { |
84 | .name = DRV_NAME, | 93 | .name = DRV_NAME, |
85 | .owner = THIS_MODULE, | 94 | .owner = THIS_MODULE, |
95 | .of_match_table = of_match_ptr(hdmi_audio_codec_ids), | ||
86 | }, | 96 | }, |
87 | 97 | ||
88 | .probe = hdmi_codec_probe, | 98 | .probe = hdmi_codec_probe, |
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 53b455b8c07a..5839048ec467 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c | |||
@@ -951,11 +951,11 @@ static int isabelle_hw_params(struct snd_pcm_substream *substream, | |||
951 | ISABELLE_FS_RATE_MASK, fs_val); | 951 | ISABELLE_FS_RATE_MASK, fs_val); |
952 | 952 | ||
953 | /* bit size */ | 953 | /* bit size */ |
954 | switch (params_format(params)) { | 954 | switch (params_width(params)) { |
955 | case SNDRV_PCM_FORMAT_S20_3LE: | 955 | case 20: |
956 | aif |= ISABELLE_AIF_LENGTH_20; | 956 | aif |= ISABELLE_AIF_LENGTH_20; |
957 | break; | 957 | break; |
958 | case SNDRV_PCM_FORMAT_S32_LE: | 958 | case 32: |
959 | aif |= ISABELLE_AIF_LENGTH_32; | 959 | aif |= ISABELLE_AIF_LENGTH_32; |
960 | break; | 960 | break; |
961 | default: | 961 | default: |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 53d7dab4e054..ee660e2d3df3 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -1233,12 +1233,12 @@ static int max98088_dai1_hw_params(struct snd_pcm_substream *substream, | |||
1233 | 1233 | ||
1234 | rate = params_rate(params); | 1234 | rate = params_rate(params); |
1235 | 1235 | ||
1236 | switch (params_format(params)) { | 1236 | switch (params_width(params)) { |
1237 | case SNDRV_PCM_FORMAT_S16_LE: | 1237 | case 16: |
1238 | snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, | 1238 | snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, |
1239 | M98088_DAI_WS, 0); | 1239 | M98088_DAI_WS, 0); |
1240 | break; | 1240 | break; |
1241 | case SNDRV_PCM_FORMAT_S24_LE: | 1241 | case 24: |
1242 | snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, | 1242 | snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, |
1243 | M98088_DAI_WS, M98088_DAI_WS); | 1243 | M98088_DAI_WS, M98088_DAI_WS); |
1244 | break; | 1244 | break; |
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 0569a4c3ae00..51f9b3d16b41 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -1840,8 +1840,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, | |||
1840 | 1840 | ||
1841 | max98090->lrclk = params_rate(params); | 1841 | max98090->lrclk = params_rate(params); |
1842 | 1842 | ||
1843 | switch (params_format(params)) { | 1843 | switch (params_width(params)) { |
1844 | case SNDRV_PCM_FORMAT_S16_LE: | 1844 | case 16: |
1845 | snd_soc_update_bits(codec, M98090_REG_INTERFACE_FORMAT, | 1845 | snd_soc_update_bits(codec, M98090_REG_INTERFACE_FORMAT, |
1846 | M98090_WS_MASK, 0); | 1846 | M98090_WS_MASK, 0); |
1847 | break; | 1847 | break; |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 67244315c721..3ba1170ebb53 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
@@ -1213,12 +1213,12 @@ static int max98095_dai1_hw_params(struct snd_pcm_substream *substream, | |||
1213 | 1213 | ||
1214 | rate = params_rate(params); | 1214 | rate = params_rate(params); |
1215 | 1215 | ||
1216 | switch (params_format(params)) { | 1216 | switch (params_width(params)) { |
1217 | case SNDRV_PCM_FORMAT_S16_LE: | 1217 | case 16: |
1218 | snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT, | 1218 | snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT, |
1219 | M98095_DAI_WS, 0); | 1219 | M98095_DAI_WS, 0); |
1220 | break; | 1220 | break; |
1221 | case SNDRV_PCM_FORMAT_S24_LE: | 1221 | case 24: |
1222 | snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT, | 1222 | snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT, |
1223 | M98095_DAI_WS, M98095_DAI_WS); | 1223 | M98095_DAI_WS, M98095_DAI_WS); |
1224 | break; | 1224 | break; |
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index c5dd61785f8d..82757ebf0301 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c | |||
@@ -149,14 +149,14 @@ static int max9850_hw_params(struct snd_pcm_substream *substream, | |||
149 | snd_soc_write(codec, MAX9850_LRCLK_MSB, (lrclk_div >> 8) & 0x7f); | 149 | snd_soc_write(codec, MAX9850_LRCLK_MSB, (lrclk_div >> 8) & 0x7f); |
150 | snd_soc_write(codec, MAX9850_LRCLK_LSB, lrclk_div & 0xff); | 150 | snd_soc_write(codec, MAX9850_LRCLK_LSB, lrclk_div & 0xff); |
151 | 151 | ||
152 | switch (params_format(params)) { | 152 | switch (params_width(params)) { |
153 | case SNDRV_PCM_FORMAT_S16_LE: | 153 | case 16: |
154 | da = 0; | 154 | da = 0; |
155 | break; | 155 | break; |
156 | case SNDRV_PCM_FORMAT_S20_3LE: | 156 | case 20: |
157 | da = 0x2; | 157 | da = 0x2; |
158 | break; | 158 | break; |
159 | case SNDRV_PCM_FORMAT_S24_LE: | 159 | case 24: |
160 | da = 0x3; | 160 | da = 0x3; |
161 | break; | 161 | break; |
162 | default: | 162 | default: |
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index bae60164c7b7..582c2bbd42cb 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
@@ -750,30 +750,26 @@ static struct snd_soc_codec_driver soc_codec_dev_mc13783 = { | |||
750 | .num_dapm_routes = ARRAY_SIZE(mc13783_routes), | 750 | .num_dapm_routes = ARRAY_SIZE(mc13783_routes), |
751 | }; | 751 | }; |
752 | 752 | ||
753 | static int mc13783_codec_probe(struct platform_device *pdev) | 753 | static int __init mc13783_codec_probe(struct platform_device *pdev) |
754 | { | 754 | { |
755 | struct mc13xxx *mc13xxx; | ||
756 | struct mc13783_priv *priv; | 755 | struct mc13783_priv *priv; |
757 | struct mc13xxx_codec_platform_data *pdata = pdev->dev.platform_data; | 756 | struct mc13xxx_codec_platform_data *pdata = pdev->dev.platform_data; |
758 | int ret; | 757 | int ret; |
759 | 758 | ||
760 | mc13xxx = dev_get_drvdata(pdev->dev.parent); | ||
761 | |||
762 | |||
763 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | 759 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
764 | if (priv == NULL) | 760 | if (!priv) |
765 | return -ENOMEM; | 761 | return -ENOMEM; |
766 | 762 | ||
767 | dev_set_drvdata(&pdev->dev, priv); | ||
768 | priv->mc13xxx = mc13xxx; | ||
769 | if (pdata) { | 763 | if (pdata) { |
770 | priv->adc_ssi_port = pdata->adc_ssi_port; | 764 | priv->adc_ssi_port = pdata->adc_ssi_port; |
771 | priv->dac_ssi_port = pdata->dac_ssi_port; | 765 | priv->dac_ssi_port = pdata->dac_ssi_port; |
772 | } else { | 766 | } else { |
773 | priv->adc_ssi_port = MC13783_SSI1_PORT; | 767 | return -ENOSYS; |
774 | priv->dac_ssi_port = MC13783_SSI2_PORT; | ||
775 | } | 768 | } |
776 | 769 | ||
770 | dev_set_drvdata(&pdev->dev, priv); | ||
771 | priv->mc13xxx = dev_get_drvdata(pdev->dev.parent); | ||
772 | |||
777 | if (priv->adc_ssi_port == priv->dac_ssi_port) | 773 | if (priv->adc_ssi_port == priv->dac_ssi_port) |
778 | ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783, | 774 | ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783, |
779 | mc13783_dai_sync, ARRAY_SIZE(mc13783_dai_sync)); | 775 | mc13783_dai_sync, ARRAY_SIZE(mc13783_dai_sync)); |
@@ -781,14 +777,6 @@ static int mc13783_codec_probe(struct platform_device *pdev) | |||
781 | ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783, | 777 | ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783, |
782 | mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async)); | 778 | mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async)); |
783 | 779 | ||
784 | if (ret) | ||
785 | goto err_register_codec; | ||
786 | |||
787 | return 0; | ||
788 | |||
789 | err_register_codec: | ||
790 | dev_err(&pdev->dev, "register codec failed with %d\n", ret); | ||
791 | |||
792 | return ret; | 780 | return ret; |
793 | } | 781 | } |
794 | 782 | ||
@@ -801,14 +789,12 @@ static int mc13783_codec_remove(struct platform_device *pdev) | |||
801 | 789 | ||
802 | static struct platform_driver mc13783_codec_driver = { | 790 | static struct platform_driver mc13783_codec_driver = { |
803 | .driver = { | 791 | .driver = { |
804 | .name = "mc13783-codec", | 792 | .name = "mc13783-codec", |
805 | .owner = THIS_MODULE, | 793 | .owner = THIS_MODULE, |
806 | }, | 794 | }, |
807 | .probe = mc13783_codec_probe, | ||
808 | .remove = mc13783_codec_remove, | 795 | .remove = mc13783_codec_remove, |
809 | }; | 796 | }; |
810 | 797 | module_platform_driver_probe(mc13783_codec_driver, mc13783_codec_probe); | |
811 | module_platform_driver(mc13783_codec_driver); | ||
812 | 798 | ||
813 | MODULE_DESCRIPTION("ASoC MC13783 driver"); | 799 | MODULE_DESCRIPTION("ASoC MC13783 driver"); |
814 | MODULE_AUTHOR("Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>"); | 800 | MODULE_AUTHOR("Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>"); |
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..af76bbd1b24f 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 | ||
@@ -196,7 +194,7 @@ static const struct snd_soc_dapm_route ssm2604_routes[] = { | |||
196 | }; | 194 | }; |
197 | 195 | ||
198 | static const unsigned int ssm2602_rates_12288000[] = { | 196 | static const unsigned int ssm2602_rates_12288000[] = { |
199 | 8000, 32000, 48000, 96000, | 197 | 8000, 16000, 32000, 48000, 96000, |
200 | }; | 198 | }; |
201 | 199 | ||
202 | static struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { | 200 | static struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { |
@@ -233,6 +231,11 @@ static const struct ssm2602_coeff ssm2602_coeff_table[] = { | |||
233 | {18432000, 32000, SSM2602_COEFF_SRATE(0x6, 0x1, 0x0)}, | 231 | {18432000, 32000, SSM2602_COEFF_SRATE(0x6, 0x1, 0x0)}, |
234 | {12000000, 32000, SSM2602_COEFF_SRATE(0x6, 0x0, 0x1)}, | 232 | {12000000, 32000, SSM2602_COEFF_SRATE(0x6, 0x0, 0x1)}, |
235 | 233 | ||
234 | /* 16k */ | ||
235 | {12288000, 16000, SSM2602_COEFF_SRATE(0x5, 0x0, 0x0)}, | ||
236 | {18432000, 16000, SSM2602_COEFF_SRATE(0x5, 0x1, 0x0)}, | ||
237 | {12000000, 16000, SSM2602_COEFF_SRATE(0xa, 0x0, 0x1)}, | ||
238 | |||
236 | /* 8k */ | 239 | /* 8k */ |
237 | {12288000, 8000, SSM2602_COEFF_SRATE(0x3, 0x0, 0x0)}, | 240 | {12288000, 8000, SSM2602_COEFF_SRATE(0x3, 0x0, 0x0)}, |
238 | {18432000, 8000, SSM2602_COEFF_SRATE(0x3, 0x1, 0x0)}, | 241 | {18432000, 8000, SSM2602_COEFF_SRATE(0x3, 0x1, 0x0)}, |
@@ -277,11 +280,6 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
277 | int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params)); | 280 | int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params)); |
278 | unsigned int iface; | 281 | unsigned int iface; |
279 | 282 | ||
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) | 283 | if (srate < 0) |
286 | return srate; | 284 | return srate; |
287 | 285 | ||
@@ -314,33 +312,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
314 | { | 312 | { |
315 | struct snd_soc_codec *codec = dai->codec; | 313 | struct snd_soc_codec *codec = dai->codec; |
316 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 314 | 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 | 315 | ||
345 | if (ssm2602->sysclk_constraints) { | 316 | if (ssm2602->sysclk_constraints) { |
346 | snd_pcm_hw_constraint_list(substream->runtime, 0, | 317 | snd_pcm_hw_constraint_list(substream->runtime, 0, |
@@ -351,19 +322,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
351 | return 0; | 322 | return 0; |
352 | } | 323 | } |
353 | 324 | ||
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) | 325 | static int ssm2602_mute(struct snd_soc_dai *dai, int mute) |
368 | { | 326 | { |
369 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(dai->codec); | 327 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(dai->codec); |
@@ -520,9 +478,10 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | |||
520 | return 0; | 478 | return 0; |
521 | } | 479 | } |
522 | 480 | ||
523 | #define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_32000 |\ | 481 | #define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ |
524 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | 482 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ |
525 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | 483 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ |
484 | SNDRV_PCM_RATE_96000) | ||
526 | 485 | ||
527 | #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 486 | #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
528 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 487 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
@@ -530,7 +489,6 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | |||
530 | static const struct snd_soc_dai_ops ssm2602_dai_ops = { | 489 | static const struct snd_soc_dai_ops ssm2602_dai_ops = { |
531 | .startup = ssm2602_startup, | 490 | .startup = ssm2602_startup, |
532 | .hw_params = ssm2602_hw_params, | 491 | .hw_params = ssm2602_hw_params, |
533 | .shutdown = ssm2602_shutdown, | ||
534 | .digital_mute = ssm2602_mute, | 492 | .digital_mute = ssm2602_mute, |
535 | .set_sysclk = ssm2602_set_dai_sysclk, | 493 | .set_sysclk = ssm2602_set_dai_sysclk, |
536 | .set_fmt = ssm2602_set_dai_fmt, | 494 | .set_fmt = ssm2602_set_dai_fmt, |
@@ -551,6 +509,8 @@ static struct snd_soc_dai_driver ssm2602_dai = { | |||
551 | .rates = SSM2602_RATES, | 509 | .rates = SSM2602_RATES, |
552 | .formats = SSM2602_FORMATS,}, | 510 | .formats = SSM2602_FORMATS,}, |
553 | .ops = &ssm2602_dai_ops, | 511 | .ops = &ssm2602_dai_ops, |
512 | .symmetric_rates = 1, | ||
513 | .symmetric_samplebits = 1, | ||
554 | }; | 514 | }; |
555 | 515 | ||
556 | static int ssm2602_suspend(struct snd_soc_codec *codec) | 516 | static int ssm2602_suspend(struct snd_soc_codec *codec) |
@@ -730,7 +690,7 @@ static struct spi_driver ssm2602_spi_driver = { | |||
730 | }; | 690 | }; |
731 | #endif | 691 | #endif |
732 | 692 | ||
733 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 693 | #if IS_ENABLED(CONFIG_I2C) |
734 | /* | 694 | /* |
735 | * ssm2602 2 wire address is determined by GPIO5 | 695 | * ssm2602 2 wire address is determined by GPIO5 |
736 | * state during powerup. | 696 | * state during powerup. |
@@ -797,7 +757,7 @@ static int __init ssm2602_modinit(void) | |||
797 | return ret; | 757 | return ret; |
798 | #endif | 758 | #endif |
799 | 759 | ||
800 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 760 | #if IS_ENABLED(CONFIG_I2C) |
801 | ret = i2c_add_driver(&ssm2602_i2c_driver); | 761 | ret = i2c_add_driver(&ssm2602_i2c_driver); |
802 | if (ret) | 762 | if (ret) |
803 | return ret; | 763 | return ret; |
@@ -813,7 +773,7 @@ static void __exit ssm2602_exit(void) | |||
813 | spi_unregister_driver(&ssm2602_spi_driver); | 773 | spi_unregister_driver(&ssm2602_spi_driver); |
814 | #endif | 774 | #endif |
815 | 775 | ||
816 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 776 | #if IS_ENABLED(CONFIG_I2C) |
817 | i2c_del_driver(&ssm2602_i2c_driver); | 777 | i2c_del_driver(&ssm2602_i2c_driver); |
818 | #endif | 778 | #endif |
819 | } | 779 | } |
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 18cdcca9014c..385dec16eb8a 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
@@ -267,8 +267,8 @@ static const struct regmap_range_cfg aic32x4_regmap_pages[] = { | |||
267 | .selector_mask = 0xff, | 267 | .selector_mask = 0xff, |
268 | .window_start = 0, | 268 | .window_start = 0, |
269 | .window_len = 128, | 269 | .window_len = 128, |
270 | .range_min = AIC32X4_PAGE1, | 270 | .range_min = 0, |
271 | .range_max = AIC32X4_PAGE1 + 127, | 271 | .range_max = AIC32X4_RMICPGAVOL, |
272 | }, | 272 | }, |
273 | }; | 273 | }; |
274 | 274 | ||
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/twl4030.c b/sound/soc/codecs/twl4030.c index dfc51bb425da..00665ada23e2 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -48,86 +48,6 @@ | |||
48 | 48 | ||
49 | #define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1) | 49 | #define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1) |
50 | 50 | ||
51 | /* | ||
52 | * twl4030 register cache & default register settings | ||
53 | */ | ||
54 | static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { | ||
55 | 0x00, /* this register not used */ | ||
56 | 0x00, /* REG_CODEC_MODE (0x1) */ | ||
57 | 0x00, /* REG_OPTION (0x2) */ | ||
58 | 0x00, /* REG_UNKNOWN (0x3) */ | ||
59 | 0x00, /* REG_MICBIAS_CTL (0x4) */ | ||
60 | 0x00, /* REG_ANAMICL (0x5) */ | ||
61 | 0x00, /* REG_ANAMICR (0x6) */ | ||
62 | 0x00, /* REG_AVADC_CTL (0x7) */ | ||
63 | 0x00, /* REG_ADCMICSEL (0x8) */ | ||
64 | 0x00, /* REG_DIGMIXING (0x9) */ | ||
65 | 0x0f, /* REG_ATXL1PGA (0xA) */ | ||
66 | 0x0f, /* REG_ATXR1PGA (0xB) */ | ||
67 | 0x0f, /* REG_AVTXL2PGA (0xC) */ | ||
68 | 0x0f, /* REG_AVTXR2PGA (0xD) */ | ||
69 | 0x00, /* REG_AUDIO_IF (0xE) */ | ||
70 | 0x00, /* REG_VOICE_IF (0xF) */ | ||
71 | 0x3f, /* REG_ARXR1PGA (0x10) */ | ||
72 | 0x3f, /* REG_ARXL1PGA (0x11) */ | ||
73 | 0x3f, /* REG_ARXR2PGA (0x12) */ | ||
74 | 0x3f, /* REG_ARXL2PGA (0x13) */ | ||
75 | 0x25, /* REG_VRXPGA (0x14) */ | ||
76 | 0x00, /* REG_VSTPGA (0x15) */ | ||
77 | 0x00, /* REG_VRX2ARXPGA (0x16) */ | ||
78 | 0x00, /* REG_AVDAC_CTL (0x17) */ | ||
79 | 0x00, /* REG_ARX2VTXPGA (0x18) */ | ||
80 | 0x32, /* REG_ARXL1_APGA_CTL (0x19) */ | ||
81 | 0x32, /* REG_ARXR1_APGA_CTL (0x1A) */ | ||
82 | 0x32, /* REG_ARXL2_APGA_CTL (0x1B) */ | ||
83 | 0x32, /* REG_ARXR2_APGA_CTL (0x1C) */ | ||
84 | 0x00, /* REG_ATX2ARXPGA (0x1D) */ | ||
85 | 0x00, /* REG_BT_IF (0x1E) */ | ||
86 | 0x55, /* REG_BTPGA (0x1F) */ | ||
87 | 0x00, /* REG_BTSTPGA (0x20) */ | ||
88 | 0x00, /* REG_EAR_CTL (0x21) */ | ||
89 | 0x00, /* REG_HS_SEL (0x22) */ | ||
90 | 0x00, /* REG_HS_GAIN_SET (0x23) */ | ||
91 | 0x00, /* REG_HS_POPN_SET (0x24) */ | ||
92 | 0x00, /* REG_PREDL_CTL (0x25) */ | ||
93 | 0x00, /* REG_PREDR_CTL (0x26) */ | ||
94 | 0x00, /* REG_PRECKL_CTL (0x27) */ | ||
95 | 0x00, /* REG_PRECKR_CTL (0x28) */ | ||
96 | 0x00, /* REG_HFL_CTL (0x29) */ | ||
97 | 0x00, /* REG_HFR_CTL (0x2A) */ | ||
98 | 0x05, /* REG_ALC_CTL (0x2B) */ | ||
99 | 0x00, /* REG_ALC_SET1 (0x2C) */ | ||
100 | 0x00, /* REG_ALC_SET2 (0x2D) */ | ||
101 | 0x00, /* REG_BOOST_CTL (0x2E) */ | ||
102 | 0x00, /* REG_SOFTVOL_CTL (0x2F) */ | ||
103 | 0x13, /* REG_DTMF_FREQSEL (0x30) */ | ||
104 | 0x00, /* REG_DTMF_TONEXT1H (0x31) */ | ||
105 | 0x00, /* REG_DTMF_TONEXT1L (0x32) */ | ||
106 | 0x00, /* REG_DTMF_TONEXT2H (0x33) */ | ||
107 | 0x00, /* REG_DTMF_TONEXT2L (0x34) */ | ||
108 | 0x79, /* REG_DTMF_TONOFF (0x35) */ | ||
109 | 0x11, /* REG_DTMF_WANONOFF (0x36) */ | ||
110 | 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */ | ||
111 | 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */ | ||
112 | 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */ | ||
113 | 0x06, /* REG_APLL_CTL (0x3A) */ | ||
114 | 0x00, /* REG_DTMF_CTL (0x3B) */ | ||
115 | 0x44, /* REG_DTMF_PGA_CTL2 (0x3C) */ | ||
116 | 0x69, /* REG_DTMF_PGA_CTL1 (0x3D) */ | ||
117 | 0x00, /* REG_MISC_SET_1 (0x3E) */ | ||
118 | 0x00, /* REG_PCMBTMUX (0x3F) */ | ||
119 | 0x00, /* not used (0x40) */ | ||
120 | 0x00, /* not used (0x41) */ | ||
121 | 0x00, /* not used (0x42) */ | ||
122 | 0x00, /* REG_RX_PATH_SEL (0x43) */ | ||
123 | 0x32, /* REG_VDL_APGA_CTL (0x44) */ | ||
124 | 0x00, /* REG_VIBRA_CTL (0x45) */ | ||
125 | 0x00, /* REG_VIBRA_SET (0x46) */ | ||
126 | 0x00, /* REG_VIBRA_PWM_SET (0x47) */ | ||
127 | 0x00, /* REG_ANAMIC_GAIN (0x48) */ | ||
128 | 0x00, /* REG_MISC_SET_2 (0x49) */ | ||
129 | }; | ||
130 | |||
131 | /* codec private data */ | 51 | /* codec private data */ |
132 | struct twl4030_priv { | 52 | struct twl4030_priv { |
133 | unsigned int codec_powered; | 53 | unsigned int codec_powered; |
@@ -150,81 +70,108 @@ struct twl4030_priv { | |||
150 | u8 earpiece_enabled; | 70 | u8 earpiece_enabled; |
151 | u8 predrivel_enabled, predriver_enabled; | 71 | u8 predrivel_enabled, predriver_enabled; |
152 | u8 carkitl_enabled, carkitr_enabled; | 72 | u8 carkitl_enabled, carkitr_enabled; |
73 | u8 ctl_cache[TWL4030_REG_PRECKR_CTL - TWL4030_REG_EAR_CTL + 1]; | ||
153 | 74 | ||
154 | struct twl4030_codec_data *pdata; | 75 | struct twl4030_codec_data *pdata; |
155 | }; | 76 | }; |
156 | 77 | ||
157 | /* | 78 | static void tw4030_init_ctl_cache(struct twl4030_priv *twl4030) |
158 | * read twl4030 register cache | ||
159 | */ | ||
160 | static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec, | ||
161 | unsigned int reg) | ||
162 | { | 79 | { |
163 | u8 *cache = codec->reg_cache; | 80 | int i; |
164 | 81 | u8 byte; | |
165 | if (reg >= TWL4030_CACHEREGNUM) | ||
166 | return -EIO; | ||
167 | 82 | ||
168 | return cache[reg]; | 83 | for (i = TWL4030_REG_EAR_CTL; i <= TWL4030_REG_PRECKR_CTL; i++) { |
84 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, i); | ||
85 | twl4030->ctl_cache[i - TWL4030_REG_EAR_CTL] = byte; | ||
86 | } | ||
169 | } | 87 | } |
170 | 88 | ||
171 | /* | 89 | static unsigned int twl4030_read(struct snd_soc_codec *codec, unsigned int reg) |
172 | * write twl4030 register cache | ||
173 | */ | ||
174 | static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec, | ||
175 | u8 reg, u8 value) | ||
176 | { | 90 | { |
177 | u8 *cache = codec->reg_cache; | 91 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
92 | u8 value = 0; | ||
178 | 93 | ||
179 | if (reg >= TWL4030_CACHEREGNUM) | 94 | if (reg >= TWL4030_CACHEREGNUM) |
180 | return; | 95 | return -EIO; |
181 | cache[reg] = value; | 96 | |
97 | switch (reg) { | ||
98 | case TWL4030_REG_EAR_CTL: | ||
99 | case TWL4030_REG_PREDL_CTL: | ||
100 | case TWL4030_REG_PREDR_CTL: | ||
101 | case TWL4030_REG_PRECKL_CTL: | ||
102 | case TWL4030_REG_PRECKR_CTL: | ||
103 | case TWL4030_REG_HS_GAIN_SET: | ||
104 | value = twl4030->ctl_cache[reg - TWL4030_REG_EAR_CTL]; | ||
105 | break; | ||
106 | default: | ||
107 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &value, reg); | ||
108 | break; | ||
109 | } | ||
110 | |||
111 | return value; | ||
182 | } | 112 | } |
183 | 113 | ||
184 | /* | 114 | static bool twl4030_can_write_to_chip(struct twl4030_priv *twl4030, |
185 | * write to the twl4030 register space | 115 | unsigned int reg) |
186 | */ | ||
187 | static int twl4030_write(struct snd_soc_codec *codec, | ||
188 | unsigned int reg, unsigned int value) | ||
189 | { | 116 | { |
190 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 117 | bool write_to_reg = false; |
191 | int write_to_reg = 0; | ||
192 | 118 | ||
193 | twl4030_write_reg_cache(codec, reg, value); | ||
194 | /* Decide if the given register can be written */ | 119 | /* Decide if the given register can be written */ |
195 | switch (reg) { | 120 | switch (reg) { |
196 | case TWL4030_REG_EAR_CTL: | 121 | case TWL4030_REG_EAR_CTL: |
197 | if (twl4030->earpiece_enabled) | 122 | if (twl4030->earpiece_enabled) |
198 | write_to_reg = 1; | 123 | write_to_reg = true; |
199 | break; | 124 | break; |
200 | case TWL4030_REG_PREDL_CTL: | 125 | case TWL4030_REG_PREDL_CTL: |
201 | if (twl4030->predrivel_enabled) | 126 | if (twl4030->predrivel_enabled) |
202 | write_to_reg = 1; | 127 | write_to_reg = true; |
203 | break; | 128 | break; |
204 | case TWL4030_REG_PREDR_CTL: | 129 | case TWL4030_REG_PREDR_CTL: |
205 | if (twl4030->predriver_enabled) | 130 | if (twl4030->predriver_enabled) |
206 | write_to_reg = 1; | 131 | write_to_reg = true; |
207 | break; | 132 | break; |
208 | case TWL4030_REG_PRECKL_CTL: | 133 | case TWL4030_REG_PRECKL_CTL: |
209 | if (twl4030->carkitl_enabled) | 134 | if (twl4030->carkitl_enabled) |
210 | write_to_reg = 1; | 135 | write_to_reg = true; |
211 | break; | 136 | break; |
212 | case TWL4030_REG_PRECKR_CTL: | 137 | case TWL4030_REG_PRECKR_CTL: |
213 | if (twl4030->carkitr_enabled) | 138 | if (twl4030->carkitr_enabled) |
214 | write_to_reg = 1; | 139 | write_to_reg = true; |
215 | break; | 140 | break; |
216 | case TWL4030_REG_HS_GAIN_SET: | 141 | case TWL4030_REG_HS_GAIN_SET: |
217 | if (twl4030->hsl_enabled || twl4030->hsr_enabled) | 142 | if (twl4030->hsl_enabled || twl4030->hsr_enabled) |
218 | write_to_reg = 1; | 143 | write_to_reg = true; |
219 | break; | 144 | break; |
220 | default: | 145 | default: |
221 | /* All other register can be written */ | 146 | /* All other register can be written */ |
222 | write_to_reg = 1; | 147 | write_to_reg = true; |
148 | break; | ||
149 | } | ||
150 | |||
151 | return write_to_reg; | ||
152 | } | ||
153 | |||
154 | static int twl4030_write(struct snd_soc_codec *codec, unsigned int reg, | ||
155 | unsigned int value) | ||
156 | { | ||
157 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | ||
158 | |||
159 | /* Update the ctl cache */ | ||
160 | switch (reg) { | ||
161 | case TWL4030_REG_EAR_CTL: | ||
162 | case TWL4030_REG_PREDL_CTL: | ||
163 | case TWL4030_REG_PREDR_CTL: | ||
164 | case TWL4030_REG_PRECKL_CTL: | ||
165 | case TWL4030_REG_PRECKR_CTL: | ||
166 | case TWL4030_REG_HS_GAIN_SET: | ||
167 | twl4030->ctl_cache[reg - TWL4030_REG_EAR_CTL] = value; | ||
168 | break; | ||
169 | default: | ||
223 | break; | 170 | break; |
224 | } | 171 | } |
225 | if (write_to_reg) | 172 | |
226 | return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | 173 | if (twl4030_can_write_to_chip(twl4030, reg)) |
227 | value, reg); | 174 | return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); |
228 | 175 | ||
229 | return 0; | 176 | return 0; |
230 | } | 177 | } |
@@ -252,46 +199,14 @@ static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) | |||
252 | else | 199 | else |
253 | mode = twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER); | 200 | mode = twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER); |
254 | 201 | ||
255 | if (mode >= 0) { | 202 | if (mode >= 0) |
256 | twl4030_write_reg_cache(codec, TWL4030_REG_CODEC_MODE, mode); | ||
257 | twl4030->codec_powered = enable; | 203 | twl4030->codec_powered = enable; |
258 | } | ||
259 | 204 | ||
260 | /* REVISIT: this delay is present in TI sample drivers */ | 205 | /* REVISIT: this delay is present in TI sample drivers */ |
261 | /* but there seems to be no TRM requirement for it */ | 206 | /* but there seems to be no TRM requirement for it */ |
262 | udelay(10); | 207 | udelay(10); |
263 | } | 208 | } |
264 | 209 | ||
265 | static inline void twl4030_check_defaults(struct snd_soc_codec *codec) | ||
266 | { | ||
267 | int i, difference = 0; | ||
268 | u8 val; | ||
269 | |||
270 | dev_dbg(codec->dev, "Checking TWL audio default configuration\n"); | ||
271 | for (i = 1; i <= TWL4030_REG_MISC_SET_2; i++) { | ||
272 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val, i); | ||
273 | if (val != twl4030_reg[i]) { | ||
274 | difference++; | ||
275 | dev_dbg(codec->dev, | ||
276 | "Reg 0x%02x: chip: 0x%02x driver: 0x%02x\n", | ||
277 | i, val, twl4030_reg[i]); | ||
278 | } | ||
279 | } | ||
280 | dev_dbg(codec->dev, "Found %d non-matching registers. %s\n", | ||
281 | difference, difference ? "Not OK" : "OK"); | ||
282 | } | ||
283 | |||
284 | static inline void twl4030_reset_registers(struct snd_soc_codec *codec) | ||
285 | { | ||
286 | int i; | ||
287 | |||
288 | /* set all audio section registers to reasonable defaults */ | ||
289 | for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) | ||
290 | if (i != TWL4030_REG_APLL_CTL) | ||
291 | twl4030_write(codec, i, twl4030_reg[i]); | ||
292 | |||
293 | } | ||
294 | |||
295 | static void twl4030_setup_pdata_of(struct twl4030_codec_data *pdata, | 210 | static void twl4030_setup_pdata_of(struct twl4030_codec_data *pdata, |
296 | struct device_node *node) | 211 | struct device_node *node) |
297 | { | 212 | { |
@@ -372,27 +287,17 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
372 | } | 287 | } |
373 | } | 288 | } |
374 | 289 | ||
375 | /* Check defaults, if instructed before anything else */ | 290 | /* Initialize the local ctl register cache */ |
376 | if (pdata && pdata->check_defaults) | 291 | tw4030_init_ctl_cache(twl4030); |
377 | twl4030_check_defaults(codec); | ||
378 | |||
379 | /* Reset registers, if no setup data or if instructed to do so */ | ||
380 | if (!pdata || (pdata && pdata->reset_registers)) | ||
381 | twl4030_reset_registers(codec); | ||
382 | |||
383 | /* Refresh APLL_CTL register from HW */ | ||
384 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, | ||
385 | TWL4030_REG_APLL_CTL); | ||
386 | twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, byte); | ||
387 | 292 | ||
388 | /* anti-pop when changing analog gain */ | 293 | /* anti-pop when changing analog gain */ |
389 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); | 294 | reg = twl4030_read(codec, TWL4030_REG_MISC_SET_1); |
390 | twl4030_write(codec, TWL4030_REG_MISC_SET_1, | 295 | twl4030_write(codec, TWL4030_REG_MISC_SET_1, |
391 | reg | TWL4030_SMOOTH_ANAVOL_EN); | 296 | reg | TWL4030_SMOOTH_ANAVOL_EN); |
392 | 297 | ||
393 | twl4030_write(codec, TWL4030_REG_OPTION, | 298 | twl4030_write(codec, TWL4030_REG_OPTION, |
394 | TWL4030_ATXL1_EN | TWL4030_ATXR1_EN | | 299 | TWL4030_ATXL1_EN | TWL4030_ATXR1_EN | |
395 | TWL4030_ARXL2_EN | TWL4030_ARXR2_EN); | 300 | TWL4030_ARXL2_EN | TWL4030_ARXR2_EN); |
396 | 301 | ||
397 | /* REG_ARXR2_APGA_CTL reset according to the TRM: 0dB, DA_EN */ | 302 | /* REG_ARXR2_APGA_CTL reset according to the TRM: 0dB, DA_EN */ |
398 | twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32); | 303 | twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32); |
@@ -403,19 +308,19 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
403 | 308 | ||
404 | twl4030->pdata = pdata; | 309 | twl4030->pdata = pdata; |
405 | 310 | ||
406 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | 311 | reg = twl4030_read(codec, TWL4030_REG_HS_POPN_SET); |
407 | reg &= ~TWL4030_RAMP_DELAY; | 312 | reg &= ~TWL4030_RAMP_DELAY; |
408 | reg |= (pdata->ramp_delay_value << 2); | 313 | reg |= (pdata->ramp_delay_value << 2); |
409 | twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg); | 314 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, reg); |
410 | 315 | ||
411 | /* initiate offset cancellation */ | 316 | /* initiate offset cancellation */ |
412 | twl4030_codec_enable(codec, 1); | 317 | twl4030_codec_enable(codec, 1); |
413 | 318 | ||
414 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); | 319 | reg = twl4030_read(codec, TWL4030_REG_ANAMICL); |
415 | reg &= ~TWL4030_OFFSET_CNCL_SEL; | 320 | reg &= ~TWL4030_OFFSET_CNCL_SEL; |
416 | reg |= pdata->offset_cncl_path; | 321 | reg |= pdata->offset_cncl_path; |
417 | twl4030_write(codec, TWL4030_REG_ANAMICL, | 322 | twl4030_write(codec, TWL4030_REG_ANAMICL, |
418 | reg | TWL4030_CNCL_OFFSET_START); | 323 | reg | TWL4030_CNCL_OFFSET_START); |
419 | 324 | ||
420 | /* | 325 | /* |
421 | * Wait for offset cancellation to complete. | 326 | * Wait for offset cancellation to complete. |
@@ -425,15 +330,14 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
425 | msleep(20); | 330 | msleep(20); |
426 | do { | 331 | do { |
427 | usleep_range(1000, 2000); | 332 | usleep_range(1000, 2000); |
333 | twl_set_regcache_bypass(TWL4030_MODULE_AUDIO_VOICE, true); | ||
428 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, | 334 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, |
429 | TWL4030_REG_ANAMICL); | 335 | TWL4030_REG_ANAMICL); |
336 | twl_set_regcache_bypass(TWL4030_MODULE_AUDIO_VOICE, false); | ||
430 | } while ((i++ < 100) && | 337 | } while ((i++ < 100) && |
431 | ((byte & TWL4030_CNCL_OFFSET_START) == | 338 | ((byte & TWL4030_CNCL_OFFSET_START) == |
432 | TWL4030_CNCL_OFFSET_START)); | 339 | TWL4030_CNCL_OFFSET_START)); |
433 | 340 | ||
434 | /* Make sure that the reg_cache has the same value as the HW */ | ||
435 | twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte); | ||
436 | |||
437 | twl4030_codec_enable(codec, 0); | 341 | twl4030_codec_enable(codec, 0); |
438 | } | 342 | } |
439 | 343 | ||
@@ -453,9 +357,6 @@ static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) | |||
453 | status = twl4030_audio_disable_resource( | 357 | status = twl4030_audio_disable_resource( |
454 | TWL4030_AUDIO_RES_APLL); | 358 | TWL4030_AUDIO_RES_APLL); |
455 | } | 359 | } |
456 | |||
457 | if (status >= 0) | ||
458 | twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status); | ||
459 | } | 360 | } |
460 | 361 | ||
461 | /* Earpiece */ | 362 | /* Earpiece */ |
@@ -671,20 +572,18 @@ static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control = | |||
671 | */ | 572 | */ |
672 | #define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \ | 573 | #define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \ |
673 | static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ | 574 | static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ |
674 | struct snd_kcontrol *kcontrol, int event) \ | 575 | struct snd_kcontrol *kcontrol, int event) \ |
675 | { \ | 576 | { \ |
676 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); \ | 577 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); \ |
677 | \ | 578 | \ |
678 | switch (event) { \ | 579 | switch (event) { \ |
679 | case SND_SOC_DAPM_POST_PMU: \ | 580 | case SND_SOC_DAPM_POST_PMU: \ |
680 | twl4030->pin_name##_enabled = 1; \ | 581 | twl4030->pin_name##_enabled = 1; \ |
681 | twl4030_write(w->codec, reg, \ | 582 | twl4030_write(w->codec, reg, twl4030_read(w->codec, reg)); \ |
682 | twl4030_read_reg_cache(w->codec, reg)); \ | ||
683 | break; \ | 583 | break; \ |
684 | case SND_SOC_DAPM_POST_PMD: \ | 584 | case SND_SOC_DAPM_POST_PMD: \ |
685 | twl4030->pin_name##_enabled = 0; \ | 585 | twl4030->pin_name##_enabled = 0; \ |
686 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ | 586 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, 0, reg); \ |
687 | 0, reg); \ | ||
688 | break; \ | 587 | break; \ |
689 | } \ | 588 | } \ |
690 | return 0; \ | 589 | return 0; \ |
@@ -700,7 +599,7 @@ static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp) | |||
700 | { | 599 | { |
701 | unsigned char hs_ctl; | 600 | unsigned char hs_ctl; |
702 | 601 | ||
703 | hs_ctl = twl4030_read_reg_cache(codec, reg); | 602 | hs_ctl = twl4030_read(codec, reg); |
704 | 603 | ||
705 | if (ramp) { | 604 | if (ramp) { |
706 | /* HF ramp-up */ | 605 | /* HF ramp-up */ |
@@ -727,7 +626,7 @@ static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp) | |||
727 | } | 626 | } |
728 | 627 | ||
729 | static int handsfreelpga_event(struct snd_soc_dapm_widget *w, | 628 | static int handsfreelpga_event(struct snd_soc_dapm_widget *w, |
730 | struct snd_kcontrol *kcontrol, int event) | 629 | struct snd_kcontrol *kcontrol, int event) |
731 | { | 630 | { |
732 | switch (event) { | 631 | switch (event) { |
733 | case SND_SOC_DAPM_POST_PMU: | 632 | case SND_SOC_DAPM_POST_PMU: |
@@ -741,7 +640,7 @@ static int handsfreelpga_event(struct snd_soc_dapm_widget *w, | |||
741 | } | 640 | } |
742 | 641 | ||
743 | static int handsfreerpga_event(struct snd_soc_dapm_widget *w, | 642 | static int handsfreerpga_event(struct snd_soc_dapm_widget *w, |
744 | struct snd_kcontrol *kcontrol, int event) | 643 | struct snd_kcontrol *kcontrol, int event) |
745 | { | 644 | { |
746 | switch (event) { | 645 | switch (event) { |
747 | case SND_SOC_DAPM_POST_PMU: | 646 | case SND_SOC_DAPM_POST_PMU: |
@@ -755,14 +654,14 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w, | |||
755 | } | 654 | } |
756 | 655 | ||
757 | static int vibramux_event(struct snd_soc_dapm_widget *w, | 656 | static int vibramux_event(struct snd_soc_dapm_widget *w, |
758 | struct snd_kcontrol *kcontrol, int event) | 657 | struct snd_kcontrol *kcontrol, int event) |
759 | { | 658 | { |
760 | twl4030_write(w->codec, TWL4030_REG_VIBRA_SET, 0xff); | 659 | twl4030_write(w->codec, TWL4030_REG_VIBRA_SET, 0xff); |
761 | return 0; | 660 | return 0; |
762 | } | 661 | } |
763 | 662 | ||
764 | static int apll_event(struct snd_soc_dapm_widget *w, | 663 | static int apll_event(struct snd_soc_dapm_widget *w, |
765 | struct snd_kcontrol *kcontrol, int event) | 664 | struct snd_kcontrol *kcontrol, int event) |
766 | { | 665 | { |
767 | switch (event) { | 666 | switch (event) { |
768 | case SND_SOC_DAPM_PRE_PMU: | 667 | case SND_SOC_DAPM_PRE_PMU: |
@@ -776,11 +675,11 @@ static int apll_event(struct snd_soc_dapm_widget *w, | |||
776 | } | 675 | } |
777 | 676 | ||
778 | static int aif_event(struct snd_soc_dapm_widget *w, | 677 | static int aif_event(struct snd_soc_dapm_widget *w, |
779 | struct snd_kcontrol *kcontrol, int event) | 678 | struct snd_kcontrol *kcontrol, int event) |
780 | { | 679 | { |
781 | u8 audio_if; | 680 | u8 audio_if; |
782 | 681 | ||
783 | audio_if = twl4030_read_reg_cache(w->codec, TWL4030_REG_AUDIO_IF); | 682 | audio_if = twl4030_read(w->codec, TWL4030_REG_AUDIO_IF); |
784 | switch (event) { | 683 | switch (event) { |
785 | case SND_SOC_DAPM_PRE_PMU: | 684 | case SND_SOC_DAPM_PRE_PMU: |
786 | /* Enable AIF */ | 685 | /* Enable AIF */ |
@@ -788,12 +687,12 @@ static int aif_event(struct snd_soc_dapm_widget *w, | |||
788 | twl4030_apll_enable(w->codec, 1); | 687 | twl4030_apll_enable(w->codec, 1); |
789 | 688 | ||
790 | twl4030_write(w->codec, TWL4030_REG_AUDIO_IF, | 689 | twl4030_write(w->codec, TWL4030_REG_AUDIO_IF, |
791 | audio_if | TWL4030_AIF_EN); | 690 | audio_if | TWL4030_AIF_EN); |
792 | break; | 691 | break; |
793 | case SND_SOC_DAPM_POST_PMD: | 692 | case SND_SOC_DAPM_POST_PMD: |
794 | /* disable the DAI before we stop it's source PLL */ | 693 | /* disable the DAI before we stop it's source PLL */ |
795 | twl4030_write(w->codec, TWL4030_REG_AUDIO_IF, | 694 | twl4030_write(w->codec, TWL4030_REG_AUDIO_IF, |
796 | audio_if & ~TWL4030_AIF_EN); | 695 | audio_if & ~TWL4030_AIF_EN); |
797 | twl4030_apll_enable(w->codec, 0); | 696 | twl4030_apll_enable(w->codec, 0); |
798 | break; | 697 | break; |
799 | } | 698 | } |
@@ -810,8 +709,8 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
810 | 8388608, 16777216, 33554432, 67108864}; | 709 | 8388608, 16777216, 33554432, 67108864}; |
811 | unsigned int delay; | 710 | unsigned int delay; |
812 | 711 | ||
813 | hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET); | 712 | hs_gain = twl4030_read(codec, TWL4030_REG_HS_GAIN_SET); |
814 | hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | 713 | hs_pop = twl4030_read(codec, TWL4030_REG_HS_POPN_SET); |
815 | delay = (ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / | 714 | delay = (ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / |
816 | twl4030->sysclk) + 1; | 715 | twl4030->sysclk) + 1; |
817 | 716 | ||
@@ -831,9 +730,8 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
831 | hs_pop |= TWL4030_VMID_EN; | 730 | hs_pop |= TWL4030_VMID_EN; |
832 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 731 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
833 | /* Actually write to the register */ | 732 | /* Actually write to the register */ |
834 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | 733 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, hs_gain, |
835 | hs_gain, | 734 | TWL4030_REG_HS_GAIN_SET); |
836 | TWL4030_REG_HS_GAIN_SET); | ||
837 | hs_pop |= TWL4030_RAMP_EN; | 735 | hs_pop |= TWL4030_RAMP_EN; |
838 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 736 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
839 | /* Wait ramp delay time + 1, so the VMID can settle */ | 737 | /* Wait ramp delay time + 1, so the VMID can settle */ |
@@ -846,9 +744,8 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
846 | /* Wait ramp delay time + 1, so the VMID can settle */ | 744 | /* Wait ramp delay time + 1, so the VMID can settle */ |
847 | twl4030_wait_ms(delay); | 745 | twl4030_wait_ms(delay); |
848 | /* Bypass the reg_cache to mute the headset */ | 746 | /* Bypass the reg_cache to mute the headset */ |
849 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | 747 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, hs_gain & (~0x0f), |
850 | hs_gain & (~0x0f), | 748 | TWL4030_REG_HS_GAIN_SET); |
851 | TWL4030_REG_HS_GAIN_SET); | ||
852 | 749 | ||
853 | hs_pop &= ~TWL4030_VMID_EN; | 750 | hs_pop &= ~TWL4030_VMID_EN; |
854 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 751 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
@@ -866,7 +763,7 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
866 | } | 763 | } |
867 | 764 | ||
868 | static int headsetlpga_event(struct snd_soc_dapm_widget *w, | 765 | static int headsetlpga_event(struct snd_soc_dapm_widget *w, |
869 | struct snd_kcontrol *kcontrol, int event) | 766 | struct snd_kcontrol *kcontrol, int event) |
870 | { | 767 | { |
871 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); | 768 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); |
872 | 769 | ||
@@ -890,7 +787,7 @@ static int headsetlpga_event(struct snd_soc_dapm_widget *w, | |||
890 | } | 787 | } |
891 | 788 | ||
892 | static int headsetrpga_event(struct snd_soc_dapm_widget *w, | 789 | static int headsetrpga_event(struct snd_soc_dapm_widget *w, |
893 | struct snd_kcontrol *kcontrol, int event) | 790 | struct snd_kcontrol *kcontrol, int event) |
894 | { | 791 | { |
895 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); | 792 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); |
896 | 793 | ||
@@ -914,7 +811,7 @@ static int headsetrpga_event(struct snd_soc_dapm_widget *w, | |||
914 | } | 811 | } |
915 | 812 | ||
916 | static int digimic_event(struct snd_soc_dapm_widget *w, | 813 | static int digimic_event(struct snd_soc_dapm_widget *w, |
917 | struct snd_kcontrol *kcontrol, int event) | 814 | struct snd_kcontrol *kcontrol, int event) |
918 | { | 815 | { |
919 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); | 816 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); |
920 | struct twl4030_codec_data *pdata = twl4030->pdata; | 817 | struct twl4030_codec_data *pdata = twl4030->pdata; |
@@ -935,7 +832,7 @@ static int digimic_event(struct snd_soc_dapm_widget *w, | |||
935 | * Custom volsw and volsw_2r get/put functions to handle these gain bits. | 832 | * Custom volsw and volsw_2r get/put functions to handle these gain bits. |
936 | */ | 833 | */ |
937 | static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol, | 834 | static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol, |
938 | struct snd_ctl_elem_value *ucontrol) | 835 | struct snd_ctl_elem_value *ucontrol) |
939 | { | 836 | { |
940 | struct soc_mixer_control *mc = | 837 | struct soc_mixer_control *mc = |
941 | (struct soc_mixer_control *)kcontrol->private_value; | 838 | (struct soc_mixer_control *)kcontrol->private_value; |
@@ -964,7 +861,7 @@ static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol, | |||
964 | } | 861 | } |
965 | 862 | ||
966 | static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol, | 863 | static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol, |
967 | struct snd_ctl_elem_value *ucontrol) | 864 | struct snd_ctl_elem_value *ucontrol) |
968 | { | 865 | { |
969 | struct soc_mixer_control *mc = | 866 | struct soc_mixer_control *mc = |
970 | (struct soc_mixer_control *)kcontrol->private_value; | 867 | (struct soc_mixer_control *)kcontrol->private_value; |
@@ -993,7 +890,7 @@ static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol, | |||
993 | } | 890 | } |
994 | 891 | ||
995 | static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol, | 892 | static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol, |
996 | struct snd_ctl_elem_value *ucontrol) | 893 | struct snd_ctl_elem_value *ucontrol) |
997 | { | 894 | { |
998 | struct soc_mixer_control *mc = | 895 | struct soc_mixer_control *mc = |
999 | (struct soc_mixer_control *)kcontrol->private_value; | 896 | (struct soc_mixer_control *)kcontrol->private_value; |
@@ -1020,7 +917,7 @@ static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol, | |||
1020 | } | 917 | } |
1021 | 918 | ||
1022 | static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol, | 919 | static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol, |
1023 | struct snd_ctl_elem_value *ucontrol) | 920 | struct snd_ctl_elem_value *ucontrol) |
1024 | { | 921 | { |
1025 | struct soc_mixer_control *mc = | 922 | struct soc_mixer_control *mc = |
1026 | (struct soc_mixer_control *)kcontrol->private_value; | 923 | (struct soc_mixer_control *)kcontrol->private_value; |
@@ -1751,11 +1648,11 @@ static void twl4030_constraints(struct twl4030_priv *twl4030, | |||
1751 | /* In case of 4 channel mode, the RX1 L/R for playback and the TX2 L/R for | 1648 | /* In case of 4 channel mode, the RX1 L/R for playback and the TX2 L/R for |
1752 | * capture has to be enabled/disabled. */ | 1649 | * capture has to be enabled/disabled. */ |
1753 | static void twl4030_tdm_enable(struct snd_soc_codec *codec, int direction, | 1650 | static void twl4030_tdm_enable(struct snd_soc_codec *codec, int direction, |
1754 | int enable) | 1651 | int enable) |
1755 | { | 1652 | { |
1756 | u8 reg, mask; | 1653 | u8 reg, mask; |
1757 | 1654 | ||
1758 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION); | 1655 | reg = twl4030_read(codec, TWL4030_REG_OPTION); |
1759 | 1656 | ||
1760 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) | 1657 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) |
1761 | mask = TWL4030_ARXL1_VRX_EN | TWL4030_ARXR1_EN; | 1658 | mask = TWL4030_ARXL1_VRX_EN | TWL4030_ARXR1_EN; |
@@ -1784,14 +1681,14 @@ static int twl4030_startup(struct snd_pcm_substream *substream, | |||
1784 | if (twl4030->configured) | 1681 | if (twl4030->configured) |
1785 | twl4030_constraints(twl4030, twl4030->master_substream); | 1682 | twl4030_constraints(twl4030, twl4030->master_substream); |
1786 | } else { | 1683 | } else { |
1787 | if (!(twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) & | 1684 | if (!(twl4030_read(codec, TWL4030_REG_CODEC_MODE) & |
1788 | TWL4030_OPTION_1)) { | 1685 | TWL4030_OPTION_1)) { |
1789 | /* In option2 4 channel is not supported, set the | 1686 | /* In option2 4 channel is not supported, set the |
1790 | * constraint for the first stream for channels, the | 1687 | * constraint for the first stream for channels, the |
1791 | * second stream will 'inherit' this cosntraint */ | 1688 | * second stream will 'inherit' this cosntraint */ |
1792 | snd_pcm_hw_constraint_minmax(substream->runtime, | 1689 | snd_pcm_hw_constraint_minmax(substream->runtime, |
1793 | SNDRV_PCM_HW_PARAM_CHANNELS, | 1690 | SNDRV_PCM_HW_PARAM_CHANNELS, |
1794 | 2, 2); | 1691 | 2, 2); |
1795 | } | 1692 | } |
1796 | twl4030->master_substream = substream; | 1693 | twl4030->master_substream = substream; |
1797 | } | 1694 | } |
@@ -1823,8 +1720,8 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream, | |||
1823 | } | 1720 | } |
1824 | 1721 | ||
1825 | static int twl4030_hw_params(struct snd_pcm_substream *substream, | 1722 | static int twl4030_hw_params(struct snd_pcm_substream *substream, |
1826 | struct snd_pcm_hw_params *params, | 1723 | struct snd_pcm_hw_params *params, |
1827 | struct snd_soc_dai *dai) | 1724 | struct snd_soc_dai *dai) |
1828 | { | 1725 | { |
1829 | struct snd_soc_codec *codec = dai->codec; | 1726 | struct snd_soc_codec *codec = dai->codec; |
1830 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1727 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
@@ -1832,8 +1729,8 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, | |||
1832 | 1729 | ||
1833 | /* If the substream has 4 channel, do the necessary setup */ | 1730 | /* If the substream has 4 channel, do the necessary setup */ |
1834 | if (params_channels(params) == 4) { | 1731 | if (params_channels(params) == 4) { |
1835 | format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); | 1732 | format = twl4030_read(codec, TWL4030_REG_AUDIO_IF); |
1836 | mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); | 1733 | mode = twl4030_read(codec, TWL4030_REG_CODEC_MODE); |
1837 | 1734 | ||
1838 | /* Safety check: are we in the correct operating mode and | 1735 | /* Safety check: are we in the correct operating mode and |
1839 | * the interface is in TDM mode? */ | 1736 | * the interface is in TDM mode? */ |
@@ -1849,8 +1746,8 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, | |||
1849 | return 0; | 1746 | return 0; |
1850 | 1747 | ||
1851 | /* bit rate */ | 1748 | /* bit rate */ |
1852 | old_mode = twl4030_read_reg_cache(codec, | 1749 | old_mode = twl4030_read(codec, |
1853 | TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; | 1750 | TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; |
1854 | mode = old_mode & ~TWL4030_APLL_RATE; | 1751 | mode = old_mode & ~TWL4030_APLL_RATE; |
1855 | 1752 | ||
1856 | switch (params_rate(params)) { | 1753 | switch (params_rate(params)) { |
@@ -1891,7 +1788,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, | |||
1891 | } | 1788 | } |
1892 | 1789 | ||
1893 | /* sample size */ | 1790 | /* sample size */ |
1894 | old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); | 1791 | old_format = twl4030_read(codec, TWL4030_REG_AUDIO_IF); |
1895 | format = old_format; | 1792 | format = old_format; |
1896 | format &= ~TWL4030_DATA_WIDTH; | 1793 | format &= ~TWL4030_DATA_WIDTH; |
1897 | switch (params_format(params)) { | 1794 | switch (params_format(params)) { |
@@ -1940,8 +1837,8 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, | |||
1940 | return 0; | 1837 | return 0; |
1941 | } | 1838 | } |
1942 | 1839 | ||
1943 | static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 1840 | static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, |
1944 | int clk_id, unsigned int freq, int dir) | 1841 | unsigned int freq, int dir) |
1945 | { | 1842 | { |
1946 | struct snd_soc_codec *codec = codec_dai->codec; | 1843 | struct snd_soc_codec *codec = codec_dai->codec; |
1947 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1844 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
@@ -1966,15 +1863,14 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
1966 | return 0; | 1863 | return 0; |
1967 | } | 1864 | } |
1968 | 1865 | ||
1969 | static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, | 1866 | static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) |
1970 | unsigned int fmt) | ||
1971 | { | 1867 | { |
1972 | struct snd_soc_codec *codec = codec_dai->codec; | 1868 | struct snd_soc_codec *codec = codec_dai->codec; |
1973 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1869 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
1974 | u8 old_format, format; | 1870 | u8 old_format, format; |
1975 | 1871 | ||
1976 | /* get format */ | 1872 | /* get format */ |
1977 | old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); | 1873 | old_format = twl4030_read(codec, TWL4030_REG_AUDIO_IF); |
1978 | format = old_format; | 1874 | format = old_format; |
1979 | 1875 | ||
1980 | /* set master/slave audio interface */ | 1876 | /* set master/slave audio interface */ |
@@ -2024,7 +1920,7 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
2024 | static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate) | 1920 | static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate) |
2025 | { | 1921 | { |
2026 | struct snd_soc_codec *codec = dai->codec; | 1922 | struct snd_soc_codec *codec = dai->codec; |
2027 | u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); | 1923 | u8 reg = twl4030_read(codec, TWL4030_REG_AUDIO_IF); |
2028 | 1924 | ||
2029 | if (tristate) | 1925 | if (tristate) |
2030 | reg |= TWL4030_AIF_TRI_EN; | 1926 | reg |= TWL4030_AIF_TRI_EN; |
@@ -2037,11 +1933,11 @@ static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate) | |||
2037 | /* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R | 1933 | /* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R |
2038 | * (VTXL, VTXR) for uplink has to be enabled/disabled. */ | 1934 | * (VTXL, VTXR) for uplink has to be enabled/disabled. */ |
2039 | static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction, | 1935 | static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction, |
2040 | int enable) | 1936 | int enable) |
2041 | { | 1937 | { |
2042 | u8 reg, mask; | 1938 | u8 reg, mask; |
2043 | 1939 | ||
2044 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION); | 1940 | reg = twl4030_read(codec, TWL4030_REG_OPTION); |
2045 | 1941 | ||
2046 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) | 1942 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) |
2047 | mask = TWL4030_ARXL1_VRX_EN; | 1943 | mask = TWL4030_ARXL1_VRX_EN; |
@@ -2057,7 +1953,7 @@ static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction, | |||
2057 | } | 1953 | } |
2058 | 1954 | ||
2059 | static int twl4030_voice_startup(struct snd_pcm_substream *substream, | 1955 | static int twl4030_voice_startup(struct snd_pcm_substream *substream, |
2060 | struct snd_soc_dai *dai) | 1956 | struct snd_soc_dai *dai) |
2061 | { | 1957 | { |
2062 | struct snd_soc_codec *codec = dai->codec; | 1958 | struct snd_soc_codec *codec = dai->codec; |
2063 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1959 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
@@ -2076,7 +1972,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream, | |||
2076 | /* If the codec mode is not option2, the voice PCM interface is not | 1972 | /* If the codec mode is not option2, the voice PCM interface is not |
2077 | * available. | 1973 | * available. |
2078 | */ | 1974 | */ |
2079 | mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) | 1975 | mode = twl4030_read(codec, TWL4030_REG_CODEC_MODE) |
2080 | & TWL4030_OPT_MODE; | 1976 | & TWL4030_OPT_MODE; |
2081 | 1977 | ||
2082 | if (mode != TWL4030_OPTION_2) { | 1978 | if (mode != TWL4030_OPTION_2) { |
@@ -2089,7 +1985,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream, | |||
2089 | } | 1985 | } |
2090 | 1986 | ||
2091 | static void twl4030_voice_shutdown(struct snd_pcm_substream *substream, | 1987 | static void twl4030_voice_shutdown(struct snd_pcm_substream *substream, |
2092 | struct snd_soc_dai *dai) | 1988 | struct snd_soc_dai *dai) |
2093 | { | 1989 | { |
2094 | struct snd_soc_codec *codec = dai->codec; | 1990 | struct snd_soc_codec *codec = dai->codec; |
2095 | 1991 | ||
@@ -2098,7 +1994,8 @@ static void twl4030_voice_shutdown(struct snd_pcm_substream *substream, | |||
2098 | } | 1994 | } |
2099 | 1995 | ||
2100 | static int twl4030_voice_hw_params(struct snd_pcm_substream *substream, | 1996 | static int twl4030_voice_hw_params(struct snd_pcm_substream *substream, |
2101 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 1997 | struct snd_pcm_hw_params *params, |
1998 | struct snd_soc_dai *dai) | ||
2102 | { | 1999 | { |
2103 | struct snd_soc_codec *codec = dai->codec; | 2000 | struct snd_soc_codec *codec = dai->codec; |
2104 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 2001 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
@@ -2108,8 +2005,8 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream, | |||
2108 | twl4030_voice_enable(codec, substream->stream, 1); | 2005 | twl4030_voice_enable(codec, substream->stream, 1); |
2109 | 2006 | ||
2110 | /* bit rate */ | 2007 | /* bit rate */ |
2111 | old_mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) | 2008 | old_mode = twl4030_read(codec, |
2112 | & ~(TWL4030_CODECPDZ); | 2009 | TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; |
2113 | mode = old_mode; | 2010 | mode = old_mode; |
2114 | 2011 | ||
2115 | switch (params_rate(params)) { | 2012 | switch (params_rate(params)) { |
@@ -2143,7 +2040,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream, | |||
2143 | } | 2040 | } |
2144 | 2041 | ||
2145 | static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 2042 | static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
2146 | int clk_id, unsigned int freq, int dir) | 2043 | int clk_id, unsigned int freq, int dir) |
2147 | { | 2044 | { |
2148 | struct snd_soc_codec *codec = codec_dai->codec; | 2045 | struct snd_soc_codec *codec = codec_dai->codec; |
2149 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 2046 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
@@ -2164,14 +2061,14 @@ static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
2164 | } | 2061 | } |
2165 | 2062 | ||
2166 | static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, | 2063 | static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, |
2167 | unsigned int fmt) | 2064 | unsigned int fmt) |
2168 | { | 2065 | { |
2169 | struct snd_soc_codec *codec = codec_dai->codec; | 2066 | struct snd_soc_codec *codec = codec_dai->codec; |
2170 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 2067 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
2171 | u8 old_format, format; | 2068 | u8 old_format, format; |
2172 | 2069 | ||
2173 | /* get format */ | 2070 | /* get format */ |
2174 | old_format = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF); | 2071 | old_format = twl4030_read(codec, TWL4030_REG_VOICE_IF); |
2175 | format = old_format; | 2072 | format = old_format; |
2176 | 2073 | ||
2177 | /* set master/slave audio interface */ | 2074 | /* set master/slave audio interface */ |
@@ -2218,7 +2115,7 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
2218 | static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate) | 2115 | static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate) |
2219 | { | 2116 | { |
2220 | struct snd_soc_codec *codec = dai->codec; | 2117 | struct snd_soc_codec *codec = dai->codec; |
2221 | u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF); | 2118 | u8 reg = twl4030_read(codec, TWL4030_REG_VOICE_IF); |
2222 | 2119 | ||
2223 | if (tristate) | 2120 | if (tristate) |
2224 | reg |= TWL4030_VIF_TRI_EN; | 2121 | reg |= TWL4030_VIF_TRI_EN; |
@@ -2310,8 +2207,6 @@ static int twl4030_soc_remove(struct snd_soc_codec *codec) | |||
2310 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 2207 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
2311 | struct twl4030_codec_data *pdata = twl4030->pdata; | 2208 | struct twl4030_codec_data *pdata = twl4030->pdata; |
2312 | 2209 | ||
2313 | /* Reset registers to their chip default before leaving */ | ||
2314 | twl4030_reset_registers(codec); | ||
2315 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2210 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2316 | 2211 | ||
2317 | if (pdata && pdata->hs_extmute && gpio_is_valid(pdata->hs_extmute_gpio)) | 2212 | if (pdata && pdata->hs_extmute && gpio_is_valid(pdata->hs_extmute_gpio)) |
@@ -2323,13 +2218,10 @@ static int twl4030_soc_remove(struct snd_soc_codec *codec) | |||
2323 | static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { | 2218 | static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { |
2324 | .probe = twl4030_soc_probe, | 2219 | .probe = twl4030_soc_probe, |
2325 | .remove = twl4030_soc_remove, | 2220 | .remove = twl4030_soc_remove, |
2326 | .read = twl4030_read_reg_cache, | 2221 | .read = twl4030_read, |
2327 | .write = twl4030_write, | 2222 | .write = twl4030_write, |
2328 | .set_bias_level = twl4030_set_bias_level, | 2223 | .set_bias_level = twl4030_set_bias_level, |
2329 | .idle_bias_off = true, | 2224 | .idle_bias_off = true, |
2330 | .reg_cache_size = sizeof(twl4030_reg), | ||
2331 | .reg_word_size = sizeof(u8), | ||
2332 | .reg_cache_default = twl4030_reg, | ||
2333 | 2225 | ||
2334 | .controls = twl4030_snd_controls, | 2226 | .controls = twl4030_snd_controls, |
2335 | .num_controls = ARRAY_SIZE(twl4030_snd_controls), | 2227 | .num_controls = ARRAY_SIZE(twl4030_snd_controls), |
@@ -2342,7 +2234,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { | |||
2342 | static int twl4030_codec_probe(struct platform_device *pdev) | 2234 | static int twl4030_codec_probe(struct platform_device *pdev) |
2343 | { | 2235 | { |
2344 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030, | 2236 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030, |
2345 | twl4030_dai, ARRAY_SIZE(twl4030_dai)); | 2237 | twl4030_dai, ARRAY_SIZE(twl4030_dai)); |
2346 | } | 2238 | } |
2347 | 2239 | ||
2348 | static int twl4030_codec_remove(struct platform_device *pdev) | 2240 | static int twl4030_codec_remove(struct platform_device *pdev) |
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 0ab2dc296474..d862f76b59f9 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,6 +313,13 @@ 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 | ||
316 | SOC_SINGLE("HPOUT1 SC Protect Switch", ARIZONA_HP1_SHORT_CIRCUIT_CTRL, | ||
317 | ARIZONA_HP1_SC_ENA_SHIFT, 1, 0), | ||
318 | SOC_SINGLE("HPOUT2 SC Protect Switch", ARIZONA_HP2_SHORT_CIRCUIT_CTRL, | ||
319 | ARIZONA_HP2_SC_ENA_SHIFT, 1, 0), | ||
320 | SOC_SINGLE("HPOUT3 SC Protect Switch", ARIZONA_HP3_SHORT_CIRCUIT_CTRL, | ||
321 | ARIZONA_HP3_SC_ENA_SHIFT, 1, 0), | ||
322 | |||
251 | SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, | 323 | SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, |
252 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), | 324 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), |
253 | SOC_DOUBLE_R("HPOUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, | 325 | SOC_DOUBLE_R("HPOUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, |
@@ -285,6 +357,13 @@ SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | |||
285 | SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT, | 357 | SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT, |
286 | ARIZONA_SPK2R_MUTE_SHIFT, 1, 1), | 358 | ARIZONA_SPK2R_MUTE_SHIFT, 1, 1), |
287 | 359 | ||
360 | SOC_DOUBLE("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE, | ||
361 | ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0), | ||
362 | SOC_DOUBLE("HPOUT2 DRE Switch", ARIZONA_DRE_ENABLE, | ||
363 | ARIZONA_DRE2L_ENA_SHIFT, ARIZONA_DRE2R_ENA_SHIFT, 1, 0), | ||
364 | SOC_DOUBLE("HPOUT3 DRE Switch", ARIZONA_DRE_ENABLE, | ||
365 | ARIZONA_DRE3L_ENA_SHIFT, ARIZONA_DRE3R_ENA_SHIFT, 1, 0), | ||
366 | |||
288 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), | 367 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), |
289 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), | 368 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), |
290 | 369 | ||
@@ -318,6 +397,10 @@ ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE), | |||
318 | 397 | ||
319 | ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE), | 398 | ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE), |
320 | ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), | 399 | ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), |
400 | ARIZONA_MIXER_CONTROLS("AIF2TX3", ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE), | ||
401 | ARIZONA_MIXER_CONTROLS("AIF2TX4", ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE), | ||
402 | ARIZONA_MIXER_CONTROLS("AIF2TX5", ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE), | ||
403 | ARIZONA_MIXER_CONTROLS("AIF2TX6", ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE), | ||
321 | 404 | ||
322 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), | 405 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), |
323 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), | 406 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), |
@@ -347,6 +430,22 @@ ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); | |||
347 | ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE); | 430 | ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE); |
348 | ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE); | 431 | ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE); |
349 | 432 | ||
433 | ARIZONA_MIXER_ENUMS(DSP1L, ARIZONA_DSP1LMIX_INPUT_1_SOURCE); | ||
434 | ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE); | ||
435 | ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE); | ||
436 | |||
437 | ARIZONA_MIXER_ENUMS(DSP2L, ARIZONA_DSP2LMIX_INPUT_1_SOURCE); | ||
438 | ARIZONA_MIXER_ENUMS(DSP2R, ARIZONA_DSP2RMIX_INPUT_1_SOURCE); | ||
439 | ARIZONA_DSP_AUX_ENUMS(DSP2, ARIZONA_DSP2AUX1MIX_INPUT_1_SOURCE); | ||
440 | |||
441 | ARIZONA_MIXER_ENUMS(DSP3L, ARIZONA_DSP3LMIX_INPUT_1_SOURCE); | ||
442 | ARIZONA_MIXER_ENUMS(DSP3R, ARIZONA_DSP3RMIX_INPUT_1_SOURCE); | ||
443 | ARIZONA_DSP_AUX_ENUMS(DSP3, ARIZONA_DSP3AUX1MIX_INPUT_1_SOURCE); | ||
444 | |||
445 | ARIZONA_MIXER_ENUMS(DSP4L, ARIZONA_DSP4LMIX_INPUT_1_SOURCE); | ||
446 | ARIZONA_MIXER_ENUMS(DSP4R, ARIZONA_DSP4RMIX_INPUT_1_SOURCE); | ||
447 | ARIZONA_DSP_AUX_ENUMS(DSP4, ARIZONA_DSP4AUX1MIX_INPUT_1_SOURCE); | ||
448 | |||
350 | ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE); | 449 | ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE); |
351 | ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE); | 450 | ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE); |
352 | 451 | ||
@@ -377,6 +476,10 @@ ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE); | |||
377 | 476 | ||
378 | ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE); | 477 | ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE); |
379 | ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | 478 | ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); |
479 | ARIZONA_MIXER_ENUMS(AIF2TX3, ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE); | ||
480 | ARIZONA_MIXER_ENUMS(AIF2TX4, ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE); | ||
481 | ARIZONA_MIXER_ENUMS(AIF2TX5, ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE); | ||
482 | ARIZONA_MIXER_ENUMS(AIF2TX6, ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE); | ||
380 | 483 | ||
381 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | 484 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); |
382 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | 485 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); |
@@ -395,6 +498,36 @@ ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | |||
395 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 498 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
396 | ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | 499 | ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); |
397 | 500 | ||
501 | ARIZONA_MUX_ENUMS(ISRC1INT1, ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE); | ||
502 | ARIZONA_MUX_ENUMS(ISRC1INT2, ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE); | ||
503 | ARIZONA_MUX_ENUMS(ISRC1INT3, ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE); | ||
504 | ARIZONA_MUX_ENUMS(ISRC1INT4, ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE); | ||
505 | |||
506 | ARIZONA_MUX_ENUMS(ISRC1DEC1, ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE); | ||
507 | ARIZONA_MUX_ENUMS(ISRC1DEC2, ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE); | ||
508 | ARIZONA_MUX_ENUMS(ISRC1DEC3, ARIZONA_ISRC1DEC3MIX_INPUT_1_SOURCE); | ||
509 | ARIZONA_MUX_ENUMS(ISRC1DEC4, ARIZONA_ISRC1DEC4MIX_INPUT_1_SOURCE); | ||
510 | |||
511 | ARIZONA_MUX_ENUMS(ISRC2INT1, ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE); | ||
512 | ARIZONA_MUX_ENUMS(ISRC2INT2, ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE); | ||
513 | ARIZONA_MUX_ENUMS(ISRC2INT3, ARIZONA_ISRC2INT3MIX_INPUT_1_SOURCE); | ||
514 | ARIZONA_MUX_ENUMS(ISRC2INT4, ARIZONA_ISRC2INT4MIX_INPUT_1_SOURCE); | ||
515 | |||
516 | ARIZONA_MUX_ENUMS(ISRC2DEC1, ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE); | ||
517 | ARIZONA_MUX_ENUMS(ISRC2DEC2, ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE); | ||
518 | ARIZONA_MUX_ENUMS(ISRC2DEC3, ARIZONA_ISRC2DEC3MIX_INPUT_1_SOURCE); | ||
519 | ARIZONA_MUX_ENUMS(ISRC2DEC4, ARIZONA_ISRC2DEC4MIX_INPUT_1_SOURCE); | ||
520 | |||
521 | ARIZONA_MUX_ENUMS(ISRC3INT1, ARIZONA_ISRC3INT1MIX_INPUT_1_SOURCE); | ||
522 | ARIZONA_MUX_ENUMS(ISRC3INT2, ARIZONA_ISRC3INT2MIX_INPUT_1_SOURCE); | ||
523 | ARIZONA_MUX_ENUMS(ISRC3INT3, ARIZONA_ISRC3INT3MIX_INPUT_1_SOURCE); | ||
524 | ARIZONA_MUX_ENUMS(ISRC3INT4, ARIZONA_ISRC3INT4MIX_INPUT_1_SOURCE); | ||
525 | |||
526 | ARIZONA_MUX_ENUMS(ISRC3DEC1, ARIZONA_ISRC3DEC1MIX_INPUT_1_SOURCE); | ||
527 | ARIZONA_MUX_ENUMS(ISRC3DEC2, ARIZONA_ISRC3DEC2MIX_INPUT_1_SOURCE); | ||
528 | ARIZONA_MUX_ENUMS(ISRC3DEC3, ARIZONA_ISRC3DEC3MIX_INPUT_1_SOURCE); | ||
529 | ARIZONA_MUX_ENUMS(ISRC3DEC4, ARIZONA_ISRC3DEC4MIX_INPUT_1_SOURCE); | ||
530 | |||
398 | static const char *wm5110_aec_loopback_texts[] = { | 531 | static const char *wm5110_aec_loopback_texts[] = { |
399 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", | 532 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", |
400 | "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", "SPKDAT2L", "SPKDAT2R", | 533 | "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", "SPKDAT2L", "SPKDAT2R", |
@@ -535,6 +668,65 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, | |||
535 | SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, | 668 | SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, |
536 | NULL, 0), | 669 | NULL, 0), |
537 | 670 | ||
671 | WM_ADSP2("DSP1", 0), | ||
672 | WM_ADSP2("DSP2", 1), | ||
673 | WM_ADSP2("DSP3", 2), | ||
674 | WM_ADSP2("DSP4", 3), | ||
675 | |||
676 | SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3, | ||
677 | ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0), | ||
678 | SND_SOC_DAPM_PGA("ISRC1INT2", ARIZONA_ISRC_1_CTRL_3, | ||
679 | ARIZONA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0), | ||
680 | SND_SOC_DAPM_PGA("ISRC1INT3", ARIZONA_ISRC_1_CTRL_3, | ||
681 | ARIZONA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0), | ||
682 | SND_SOC_DAPM_PGA("ISRC1INT4", ARIZONA_ISRC_1_CTRL_3, | ||
683 | ARIZONA_ISRC1_INT3_ENA_SHIFT, 0, NULL, 0), | ||
684 | |||
685 | SND_SOC_DAPM_PGA("ISRC1DEC1", ARIZONA_ISRC_1_CTRL_3, | ||
686 | ARIZONA_ISRC1_DEC0_ENA_SHIFT, 0, NULL, 0), | ||
687 | SND_SOC_DAPM_PGA("ISRC1DEC2", ARIZONA_ISRC_1_CTRL_3, | ||
688 | ARIZONA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
689 | SND_SOC_DAPM_PGA("ISRC1DEC3", ARIZONA_ISRC_1_CTRL_3, | ||
690 | ARIZONA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0), | ||
691 | SND_SOC_DAPM_PGA("ISRC1DEC4", ARIZONA_ISRC_1_CTRL_3, | ||
692 | ARIZONA_ISRC1_DEC3_ENA_SHIFT, 0, NULL, 0), | ||
693 | |||
694 | SND_SOC_DAPM_PGA("ISRC2INT1", ARIZONA_ISRC_2_CTRL_3, | ||
695 | ARIZONA_ISRC2_INT0_ENA_SHIFT, 0, NULL, 0), | ||
696 | SND_SOC_DAPM_PGA("ISRC2INT2", ARIZONA_ISRC_2_CTRL_3, | ||
697 | ARIZONA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0), | ||
698 | SND_SOC_DAPM_PGA("ISRC2INT3", ARIZONA_ISRC_2_CTRL_3, | ||
699 | ARIZONA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0), | ||
700 | SND_SOC_DAPM_PGA("ISRC2INT4", ARIZONA_ISRC_2_CTRL_3, | ||
701 | ARIZONA_ISRC2_INT3_ENA_SHIFT, 0, NULL, 0), | ||
702 | |||
703 | SND_SOC_DAPM_PGA("ISRC2DEC1", ARIZONA_ISRC_2_CTRL_3, | ||
704 | ARIZONA_ISRC2_DEC0_ENA_SHIFT, 0, NULL, 0), | ||
705 | SND_SOC_DAPM_PGA("ISRC2DEC2", ARIZONA_ISRC_2_CTRL_3, | ||
706 | ARIZONA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
707 | SND_SOC_DAPM_PGA("ISRC2DEC3", ARIZONA_ISRC_2_CTRL_3, | ||
708 | ARIZONA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0), | ||
709 | SND_SOC_DAPM_PGA("ISRC2DEC4", ARIZONA_ISRC_2_CTRL_3, | ||
710 | ARIZONA_ISRC2_DEC3_ENA_SHIFT, 0, NULL, 0), | ||
711 | |||
712 | SND_SOC_DAPM_PGA("ISRC3INT1", ARIZONA_ISRC_3_CTRL_3, | ||
713 | ARIZONA_ISRC3_INT0_ENA_SHIFT, 0, NULL, 0), | ||
714 | SND_SOC_DAPM_PGA("ISRC3INT2", ARIZONA_ISRC_3_CTRL_3, | ||
715 | ARIZONA_ISRC3_INT1_ENA_SHIFT, 0, NULL, 0), | ||
716 | SND_SOC_DAPM_PGA("ISRC3INT3", ARIZONA_ISRC_3_CTRL_3, | ||
717 | ARIZONA_ISRC3_INT2_ENA_SHIFT, 0, NULL, 0), | ||
718 | SND_SOC_DAPM_PGA("ISRC3INT4", ARIZONA_ISRC_3_CTRL_3, | ||
719 | ARIZONA_ISRC3_INT3_ENA_SHIFT, 0, NULL, 0), | ||
720 | |||
721 | SND_SOC_DAPM_PGA("ISRC3DEC1", ARIZONA_ISRC_3_CTRL_3, | ||
722 | ARIZONA_ISRC3_DEC0_ENA_SHIFT, 0, NULL, 0), | ||
723 | SND_SOC_DAPM_PGA("ISRC3DEC2", ARIZONA_ISRC_3_CTRL_3, | ||
724 | ARIZONA_ISRC3_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
725 | SND_SOC_DAPM_PGA("ISRC3DEC3", ARIZONA_ISRC_3_CTRL_3, | ||
726 | ARIZONA_ISRC3_DEC2_ENA_SHIFT, 0, NULL, 0), | ||
727 | SND_SOC_DAPM_PGA("ISRC3DEC4", ARIZONA_ISRC_3_CTRL_3, | ||
728 | ARIZONA_ISRC3_DEC3_ENA_SHIFT, 0, NULL, 0), | ||
729 | |||
538 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | 730 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, |
539 | ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0, | 731 | ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0, |
540 | &wm5110_aec_loopback_mux), | 732 | &wm5110_aec_loopback_mux), |
@@ -577,11 +769,27 @@ SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, | |||
577 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), | 769 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), |
578 | SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, | 770 | SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, |
579 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), | 771 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), |
772 | SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, | ||
773 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX3_ENA_SHIFT, 0), | ||
774 | SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, | ||
775 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX4_ENA_SHIFT, 0), | ||
776 | SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, | ||
777 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX5_ENA_SHIFT, 0), | ||
778 | SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, | ||
779 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX6_ENA_SHIFT, 0), | ||
580 | 780 | ||
581 | SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, | 781 | SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, |
582 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), | 782 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), |
583 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, | 783 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, |
584 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), | 784 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), |
785 | SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, | ||
786 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX3_ENA_SHIFT, 0), | ||
787 | SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, | ||
788 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX4_ENA_SHIFT, 0), | ||
789 | SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, | ||
790 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX5_ENA_SHIFT, 0), | ||
791 | SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, | ||
792 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX6_ENA_SHIFT, 0), | ||
585 | 793 | ||
586 | SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, | 794 | SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, |
587 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | 795 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, |
@@ -719,6 +927,10 @@ ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), | |||
719 | 927 | ||
720 | ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), | 928 | ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), |
721 | ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | 929 | ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), |
930 | ARIZONA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"), | ||
931 | ARIZONA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"), | ||
932 | ARIZONA_MIXER_WIDGETS(AIF2TX5, "AIF2TX5"), | ||
933 | ARIZONA_MIXER_WIDGETS(AIF2TX6, "AIF2TX6"), | ||
722 | 934 | ||
723 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | 935 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), |
724 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | 936 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), |
@@ -737,6 +949,41 @@ ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), | |||
737 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), | 949 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), |
738 | ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"), | 950 | ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"), |
739 | 951 | ||
952 | ARIZONA_DSP_WIDGETS(DSP1, "DSP1"), | ||
953 | ARIZONA_DSP_WIDGETS(DSP2, "DSP2"), | ||
954 | ARIZONA_DSP_WIDGETS(DSP3, "DSP3"), | ||
955 | ARIZONA_DSP_WIDGETS(DSP4, "DSP4"), | ||
956 | |||
957 | ARIZONA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), | ||
958 | ARIZONA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), | ||
959 | ARIZONA_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"), | ||
960 | ARIZONA_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"), | ||
961 | |||
962 | ARIZONA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), | ||
963 | ARIZONA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), | ||
964 | ARIZONA_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"), | ||
965 | ARIZONA_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"), | ||
966 | |||
967 | ARIZONA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), | ||
968 | ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), | ||
969 | ARIZONA_MUX_WIDGETS(ISRC2DEC3, "ISRC2DEC3"), | ||
970 | ARIZONA_MUX_WIDGETS(ISRC2DEC4, "ISRC2DEC4"), | ||
971 | |||
972 | ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), | ||
973 | ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), | ||
974 | ARIZONA_MUX_WIDGETS(ISRC2INT3, "ISRC2INT3"), | ||
975 | ARIZONA_MUX_WIDGETS(ISRC2INT4, "ISRC2INT4"), | ||
976 | |||
977 | ARIZONA_MUX_WIDGETS(ISRC3DEC1, "ISRC3DEC1"), | ||
978 | ARIZONA_MUX_WIDGETS(ISRC3DEC2, "ISRC3DEC2"), | ||
979 | ARIZONA_MUX_WIDGETS(ISRC3DEC3, "ISRC3DEC3"), | ||
980 | ARIZONA_MUX_WIDGETS(ISRC3DEC4, "ISRC3DEC4"), | ||
981 | |||
982 | ARIZONA_MUX_WIDGETS(ISRC3INT1, "ISRC3INT1"), | ||
983 | ARIZONA_MUX_WIDGETS(ISRC3INT2, "ISRC3INT2"), | ||
984 | ARIZONA_MUX_WIDGETS(ISRC3INT3, "ISRC3INT3"), | ||
985 | ARIZONA_MUX_WIDGETS(ISRC3INT4, "ISRC3INT4"), | ||
986 | |||
740 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), | 987 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), |
741 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | 988 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), |
742 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), | 989 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), |
@@ -780,6 +1027,10 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"), | |||
780 | { name, "AIF1RX8", "AIF1RX8" }, \ | 1027 | { name, "AIF1RX8", "AIF1RX8" }, \ |
781 | { name, "AIF2RX1", "AIF2RX1" }, \ | 1028 | { name, "AIF2RX1", "AIF2RX1" }, \ |
782 | { name, "AIF2RX2", "AIF2RX2" }, \ | 1029 | { name, "AIF2RX2", "AIF2RX2" }, \ |
1030 | { name, "AIF2RX3", "AIF2RX3" }, \ | ||
1031 | { name, "AIF2RX4", "AIF2RX4" }, \ | ||
1032 | { name, "AIF2RX5", "AIF2RX5" }, \ | ||
1033 | { name, "AIF2RX6", "AIF2RX6" }, \ | ||
783 | { name, "AIF3RX1", "AIF3RX1" }, \ | 1034 | { name, "AIF3RX1", "AIF3RX1" }, \ |
784 | { name, "AIF3RX2", "AIF3RX2" }, \ | 1035 | { name, "AIF3RX2", "AIF3RX2" }, \ |
785 | { name, "SLIMRX1", "SLIMRX1" }, \ | 1036 | { name, "SLIMRX1", "SLIMRX1" }, \ |
@@ -805,7 +1056,55 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"), | |||
805 | { name, "ASRC1L", "ASRC1L" }, \ | 1056 | { name, "ASRC1L", "ASRC1L" }, \ |
806 | { name, "ASRC1R", "ASRC1R" }, \ | 1057 | { name, "ASRC1R", "ASRC1R" }, \ |
807 | { name, "ASRC2L", "ASRC2L" }, \ | 1058 | { name, "ASRC2L", "ASRC2L" }, \ |
808 | { name, "ASRC2R", "ASRC2R" } | 1059 | { name, "ASRC2R", "ASRC2R" }, \ |
1060 | { name, "ISRC1DEC1", "ISRC1DEC1" }, \ | ||
1061 | { name, "ISRC1DEC2", "ISRC1DEC2" }, \ | ||
1062 | { name, "ISRC1DEC3", "ISRC1DEC3" }, \ | ||
1063 | { name, "ISRC1DEC4", "ISRC1DEC4" }, \ | ||
1064 | { name, "ISRC1INT1", "ISRC1INT1" }, \ | ||
1065 | { name, "ISRC1INT2", "ISRC1INT2" }, \ | ||
1066 | { name, "ISRC1INT3", "ISRC1INT3" }, \ | ||
1067 | { name, "ISRC1INT4", "ISRC1INT4" }, \ | ||
1068 | { name, "ISRC2DEC1", "ISRC2DEC1" }, \ | ||
1069 | { name, "ISRC2DEC2", "ISRC2DEC2" }, \ | ||
1070 | { name, "ISRC2DEC3", "ISRC2DEC3" }, \ | ||
1071 | { name, "ISRC2DEC4", "ISRC2DEC4" }, \ | ||
1072 | { name, "ISRC2INT1", "ISRC2INT1" }, \ | ||
1073 | { name, "ISRC2INT2", "ISRC2INT2" }, \ | ||
1074 | { name, "ISRC2INT3", "ISRC2INT3" }, \ | ||
1075 | { name, "ISRC2INT4", "ISRC2INT4" }, \ | ||
1076 | { name, "ISRC3DEC1", "ISRC3DEC1" }, \ | ||
1077 | { name, "ISRC3DEC2", "ISRC3DEC2" }, \ | ||
1078 | { name, "ISRC3DEC3", "ISRC3DEC3" }, \ | ||
1079 | { name, "ISRC3DEC4", "ISRC3DEC4" }, \ | ||
1080 | { name, "ISRC3INT1", "ISRC3INT1" }, \ | ||
1081 | { name, "ISRC3INT2", "ISRC3INT2" }, \ | ||
1082 | { name, "ISRC3INT3", "ISRC3INT3" }, \ | ||
1083 | { name, "ISRC3INT4", "ISRC3INT4" }, \ | ||
1084 | { name, "DSP1.1", "DSP1" }, \ | ||
1085 | { name, "DSP1.2", "DSP1" }, \ | ||
1086 | { name, "DSP1.3", "DSP1" }, \ | ||
1087 | { name, "DSP1.4", "DSP1" }, \ | ||
1088 | { name, "DSP1.5", "DSP1" }, \ | ||
1089 | { name, "DSP1.6", "DSP1" }, \ | ||
1090 | { name, "DSP2.1", "DSP2" }, \ | ||
1091 | { name, "DSP2.2", "DSP2" }, \ | ||
1092 | { name, "DSP2.3", "DSP2" }, \ | ||
1093 | { name, "DSP2.4", "DSP2" }, \ | ||
1094 | { name, "DSP2.5", "DSP2" }, \ | ||
1095 | { name, "DSP2.6", "DSP2" }, \ | ||
1096 | { name, "DSP3.1", "DSP3" }, \ | ||
1097 | { name, "DSP3.2", "DSP3" }, \ | ||
1098 | { name, "DSP3.3", "DSP3" }, \ | ||
1099 | { name, "DSP3.4", "DSP3" }, \ | ||
1100 | { name, "DSP3.5", "DSP3" }, \ | ||
1101 | { name, "DSP3.6", "DSP3" }, \ | ||
1102 | { name, "DSP4.1", "DSP4" }, \ | ||
1103 | { name, "DSP4.2", "DSP4" }, \ | ||
1104 | { name, "DSP4.3", "DSP4" }, \ | ||
1105 | { name, "DSP4.4", "DSP4" }, \ | ||
1106 | { name, "DSP4.5", "DSP4" }, \ | ||
1107 | { name, "DSP4.6", "DSP4" } | ||
809 | 1108 | ||
810 | static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | 1109 | static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { |
811 | { "AIF2 Capture", NULL, "DBVDD2" }, | 1110 | { "AIF2 Capture", NULL, "DBVDD2" }, |
@@ -877,9 +1176,17 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
877 | 1176 | ||
878 | { "AIF2 Capture", NULL, "AIF2TX1" }, | 1177 | { "AIF2 Capture", NULL, "AIF2TX1" }, |
879 | { "AIF2 Capture", NULL, "AIF2TX2" }, | 1178 | { "AIF2 Capture", NULL, "AIF2TX2" }, |
1179 | { "AIF2 Capture", NULL, "AIF2TX3" }, | ||
1180 | { "AIF2 Capture", NULL, "AIF2TX4" }, | ||
1181 | { "AIF2 Capture", NULL, "AIF2TX5" }, | ||
1182 | { "AIF2 Capture", NULL, "AIF2TX6" }, | ||
880 | 1183 | ||
881 | { "AIF2RX1", NULL, "AIF2 Playback" }, | 1184 | { "AIF2RX1", NULL, "AIF2 Playback" }, |
882 | { "AIF2RX2", NULL, "AIF2 Playback" }, | 1185 | { "AIF2RX2", NULL, "AIF2 Playback" }, |
1186 | { "AIF2RX3", NULL, "AIF2 Playback" }, | ||
1187 | { "AIF2RX4", NULL, "AIF2 Playback" }, | ||
1188 | { "AIF2RX5", NULL, "AIF2 Playback" }, | ||
1189 | { "AIF2RX6", NULL, "AIF2 Playback" }, | ||
883 | 1190 | ||
884 | { "AIF3 Capture", NULL, "AIF3TX1" }, | 1191 | { "AIF3 Capture", NULL, "AIF3TX1" }, |
885 | { "AIF3 Capture", NULL, "AIF3TX2" }, | 1192 | { "AIF3 Capture", NULL, "AIF3TX2" }, |
@@ -963,6 +1270,10 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
963 | 1270 | ||
964 | ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), | 1271 | ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), |
965 | ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), | 1272 | ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), |
1273 | ARIZONA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"), | ||
1274 | ARIZONA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"), | ||
1275 | ARIZONA_MIXER_ROUTES("AIF2TX5", "AIF2TX5"), | ||
1276 | ARIZONA_MIXER_ROUTES("AIF2TX6", "AIF2TX6"), | ||
966 | 1277 | ||
967 | ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), | 1278 | ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), |
968 | ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), | 1279 | ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), |
@@ -999,6 +1310,41 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
999 | ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"), | 1310 | ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"), |
1000 | ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"), | 1311 | ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"), |
1001 | 1312 | ||
1313 | ARIZONA_DSP_ROUTES("DSP1"), | ||
1314 | ARIZONA_DSP_ROUTES("DSP2"), | ||
1315 | ARIZONA_DSP_ROUTES("DSP3"), | ||
1316 | ARIZONA_DSP_ROUTES("DSP4"), | ||
1317 | |||
1318 | ARIZONA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), | ||
1319 | ARIZONA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), | ||
1320 | ARIZONA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"), | ||
1321 | ARIZONA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"), | ||
1322 | |||
1323 | ARIZONA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), | ||
1324 | ARIZONA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), | ||
1325 | ARIZONA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"), | ||
1326 | ARIZONA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"), | ||
1327 | |||
1328 | ARIZONA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), | ||
1329 | ARIZONA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), | ||
1330 | ARIZONA_MUX_ROUTES("ISRC2INT3", "ISRC2INT3"), | ||
1331 | ARIZONA_MUX_ROUTES("ISRC2INT4", "ISRC2INT4"), | ||
1332 | |||
1333 | ARIZONA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), | ||
1334 | ARIZONA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), | ||
1335 | ARIZONA_MUX_ROUTES("ISRC2DEC3", "ISRC2DEC3"), | ||
1336 | ARIZONA_MUX_ROUTES("ISRC2DEC4", "ISRC2DEC4"), | ||
1337 | |||
1338 | ARIZONA_MUX_ROUTES("ISRC3INT1", "ISRC3INT1"), | ||
1339 | ARIZONA_MUX_ROUTES("ISRC3INT2", "ISRC3INT2"), | ||
1340 | ARIZONA_MUX_ROUTES("ISRC3INT3", "ISRC3INT3"), | ||
1341 | ARIZONA_MUX_ROUTES("ISRC3INT4", "ISRC3INT4"), | ||
1342 | |||
1343 | ARIZONA_MUX_ROUTES("ISRC3DEC1", "ISRC3DEC1"), | ||
1344 | ARIZONA_MUX_ROUTES("ISRC3DEC2", "ISRC3DEC2"), | ||
1345 | ARIZONA_MUX_ROUTES("ISRC3DEC3", "ISRC3DEC3"), | ||
1346 | ARIZONA_MUX_ROUTES("ISRC3DEC4", "ISRC3DEC4"), | ||
1347 | |||
1002 | { "AEC Loopback", "HPOUT1L", "OUT1L" }, | 1348 | { "AEC Loopback", "HPOUT1L", "OUT1L" }, |
1003 | { "AEC Loopback", "HPOUT1R", "OUT1R" }, | 1349 | { "AEC Loopback", "HPOUT1R", "OUT1R" }, |
1004 | { "HPOUT1L", NULL, "OUT1L" }, | 1350 | { "HPOUT1L", NULL, "OUT1L" }, |
@@ -1095,14 +1441,14 @@ static struct snd_soc_dai_driver wm5110_dai[] = { | |||
1095 | .playback = { | 1441 | .playback = { |
1096 | .stream_name = "AIF2 Playback", | 1442 | .stream_name = "AIF2 Playback", |
1097 | .channels_min = 1, | 1443 | .channels_min = 1, |
1098 | .channels_max = 2, | 1444 | .channels_max = 6, |
1099 | .rates = WM5110_RATES, | 1445 | .rates = WM5110_RATES, |
1100 | .formats = WM5110_FORMATS, | 1446 | .formats = WM5110_FORMATS, |
1101 | }, | 1447 | }, |
1102 | .capture = { | 1448 | .capture = { |
1103 | .stream_name = "AIF2 Capture", | 1449 | .stream_name = "AIF2 Capture", |
1104 | .channels_min = 1, | 1450 | .channels_min = 1, |
1105 | .channels_max = 2, | 1451 | .channels_max = 6, |
1106 | .rates = WM5110_RATES, | 1452 | .rates = WM5110_RATES, |
1107 | .formats = WM5110_FORMATS, | 1453 | .formats = WM5110_FORMATS, |
1108 | }, | 1454 | }, |
@@ -1204,6 +1550,10 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) | |||
1204 | arizona_init_spk(codec); | 1550 | arizona_init_spk(codec); |
1205 | arizona_init_gpio(codec); | 1551 | arizona_init_gpio(codec); |
1206 | 1552 | ||
1553 | ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8); | ||
1554 | if (ret != 0) | ||
1555 | return ret; | ||
1556 | |||
1207 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); | 1557 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); |
1208 | 1558 | ||
1209 | priv->core.arizona->dapm = &codec->dapm; | 1559 | priv->core.arizona->dapm = &codec->dapm; |
@@ -1258,7 +1608,7 @@ static int wm5110_probe(struct platform_device *pdev) | |||
1258 | { | 1608 | { |
1259 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | 1609 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); |
1260 | struct wm5110_priv *wm5110; | 1610 | struct wm5110_priv *wm5110; |
1261 | int i; | 1611 | int i, ret; |
1262 | 1612 | ||
1263 | wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv), | 1613 | wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv), |
1264 | GFP_KERNEL); | 1614 | GFP_KERNEL); |
@@ -1269,6 +1619,24 @@ static int wm5110_probe(struct platform_device *pdev) | |||
1269 | wm5110->core.arizona = arizona; | 1619 | wm5110->core.arizona = arizona; |
1270 | wm5110->core.num_inputs = 8; | 1620 | wm5110->core.num_inputs = 8; |
1271 | 1621 | ||
1622 | for (i = 0; i < WM5110_NUM_ADSP; i++) { | ||
1623 | wm5110->core.adsp[i].part = "wm5110"; | ||
1624 | wm5110->core.adsp[i].num = i + 1; | ||
1625 | wm5110->core.adsp[i].type = WMFW_ADSP2; | ||
1626 | wm5110->core.adsp[i].dev = arizona->dev; | ||
1627 | wm5110->core.adsp[i].regmap = arizona->regmap; | ||
1628 | |||
1629 | wm5110->core.adsp[i].base = ARIZONA_DSP1_CONTROL_1 | ||
1630 | + (0x100 * i); | ||
1631 | wm5110->core.adsp[i].mem = wm5110_dsp_regions[i]; | ||
1632 | wm5110->core.adsp[i].num_mems | ||
1633 | = ARRAY_SIZE(wm5110_dsp1_regions); | ||
1634 | |||
1635 | ret = wm_adsp2_init(&wm5110->core.adsp[i], false); | ||
1636 | if (ret != 0) | ||
1637 | return ret; | ||
1638 | } | ||
1639 | |||
1272 | for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) | 1640 | for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) |
1273 | wm5110->fll[i].vco_mult = 3; | 1641 | wm5110->fll[i].vco_mult = 3; |
1274 | 1642 | ||
@@ -1279,6 +1647,12 @@ static int wm5110_probe(struct platform_device *pdev) | |||
1279 | ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, | 1647 | ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, |
1280 | &wm5110->fll[1]); | 1648 | &wm5110->fll[1]); |
1281 | 1649 | ||
1650 | /* SR2 fixed at 8kHz, SR3 fixed at 16kHz */ | ||
1651 | regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_2, | ||
1652 | ARIZONA_SAMPLE_RATE_2_MASK, 0x11); | ||
1653 | regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_3, | ||
1654 | ARIZONA_SAMPLE_RATE_3_MASK, 0x12); | ||
1655 | |||
1282 | for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++) | 1656 | for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++) |
1283 | arizona_init_dai(&wm5110->core, i); | 1657 | arizona_init_dai(&wm5110->core, i); |
1284 | 1658 | ||
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 bc7472c968e3..029720366ff8 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -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/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 0f17ed3e29f4..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; |
@@ -3121,7 +3121,7 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
3121 | } | 3121 | } |
3122 | EXPORT_SYMBOL_GPL(wm8962_mic_detect); | 3122 | EXPORT_SYMBOL_GPL(wm8962_mic_detect); |
3123 | 3123 | ||
3124 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 3124 | #if IS_ENABLED(CONFIG_INPUT) |
3125 | static int beep_rates[] = { | 3125 | static int beep_rates[] = { |
3126 | 500, 1000, 2000, 4000, | 3126 | 500, 1000, 2000, 4000, |
3127 | }; | 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 4f05fb88bddf..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; |
@@ -1260,7 +1225,7 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, | |||
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); |
1262 | 1227 | ||
1263 | codec->cache_sync = 1; | 1228 | regcache_mark_dirty(wm8990->regmap); |
1264 | break; | 1229 | break; |
1265 | } | 1230 | } |
1266 | 1231 | ||
@@ -1329,7 +1294,7 @@ static int wm8990_probe(struct snd_soc_codec *codec) | |||
1329 | { | 1294 | { |
1330 | int ret; | 1295 | int ret; |
1331 | 1296 | ||
1332 | 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); |
1333 | if (ret < 0) { | 1298 | if (ret < 0) { |
1334 | 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); |
1335 | return ret; | 1300 | return ret; |
@@ -1352,10 +1317,6 @@ static int wm8990_probe(struct snd_soc_codec *codec) | |||
1352 | snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1317 | snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1353 | snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1318 | snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1354 | 1319 | ||
1355 | snd_soc_add_codec_controls(codec, wm8990_snd_controls, | ||
1356 | ARRAY_SIZE(wm8990_snd_controls)); | ||
1357 | wm8990_add_widgets(codec); | ||
1358 | |||
1359 | return 0; | 1320 | return 0; |
1360 | } | 1321 | } |
1361 | 1322 | ||
@@ -1372,13 +1333,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { | |||
1372 | .suspend = wm8990_suspend, | 1333 | .suspend = wm8990_suspend, |
1373 | .resume = wm8990_resume, | 1334 | .resume = wm8990_resume, |
1374 | .set_bias_level = wm8990_set_bias_level, | 1335 | .set_bias_level = wm8990_set_bias_level, |
1375 | .reg_cache_size = ARRAY_SIZE(wm8990_reg), | 1336 | .controls = wm8990_snd_controls, |
1376 | .reg_word_size = sizeof(u16), | 1337 | .num_controls = ARRAY_SIZE(wm8990_snd_controls), |
1377 | .reg_cache_default = wm8990_reg, | 1338 | .dapm_widgets = wm8990_dapm_widgets, |
1378 | .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, | ||
1379 | }; | 1353 | }; |
1380 | 1354 | ||
1381 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1382 | static int wm8990_i2c_probe(struct i2c_client *i2c, | 1355 | static int wm8990_i2c_probe(struct i2c_client *i2c, |
1383 | const struct i2c_device_id *id) | 1356 | const struct i2c_device_id *id) |
1384 | { | 1357 | { |
@@ -1420,29 +1393,8 @@ static struct i2c_driver wm8990_i2c_driver = { | |||
1420 | .remove = wm8990_i2c_remove, | 1393 | .remove = wm8990_i2c_remove, |
1421 | .id_table = wm8990_i2c_id, | 1394 | .id_table = wm8990_i2c_id, |
1422 | }; | 1395 | }; |
1423 | #endif | ||
1424 | 1396 | ||
1425 | static int __init wm8990_modinit(void) | 1397 | module_i2c_driver(wm8990_i2c_driver); |
1426 | { | ||
1427 | int ret = 0; | ||
1428 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1429 | ret = i2c_add_driver(&wm8990_i2c_driver); | ||
1430 | if (ret != 0) { | ||
1431 | printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n", | ||
1432 | ret); | ||
1433 | } | ||
1434 | #endif | ||
1435 | return ret; | ||
1436 | } | ||
1437 | module_init(wm8990_modinit); | ||
1438 | |||
1439 | static void __exit wm8990_exit(void) | ||
1440 | { | ||
1441 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1442 | i2c_del_driver(&wm8990_i2c_driver); | ||
1443 | #endif | ||
1444 | } | ||
1445 | module_exit(wm8990_exit); | ||
1446 | 1398 | ||
1447 | MODULE_DESCRIPTION("ASoC WM8990 driver"); | 1399 | MODULE_DESCRIPTION("ASoC WM8990 driver"); |
1448 | 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 4fbcab63e61f..444626fcab40 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,8 +1469,8 @@ 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 | ||
@@ -1492,112 +1493,153 @@ static int wm_adsp2_ena(struct wm_adsp *dsp) | |||
1492 | } | 1493 | } |
1493 | 1494 | ||
1494 | adsp_dbg(dsp, "RAM ready after %d polls\n", count); | 1495 | adsp_dbg(dsp, "RAM ready after %d polls\n", count); |
1495 | adsp_info(dsp, "RAM ready after %d polls\n", count); | ||
1496 | 1496 | ||
1497 | return 0; | 1497 | return 0; |
1498 | } | 1498 | } |
1499 | 1499 | ||
1500 | int wm_adsp2_event(struct snd_soc_dapm_widget *w, | 1500 | static void wm_adsp2_boot_work(struct work_struct *work) |
1501 | struct snd_kcontrol *kcontrol, int event) | ||
1502 | { | 1501 | { |
1503 | struct snd_soc_codec *codec = w->codec; | 1502 | struct wm_adsp *dsp = container_of(work, |
1504 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | 1503 | struct wm_adsp, |
1505 | struct wm_adsp *dsp = &dsps[w->shift]; | 1504 | boot_work); |
1506 | struct wm_adsp_alg_region *alg_region; | ||
1507 | struct wm_coeff_ctl *ctl; | ||
1508 | unsigned int val; | ||
1509 | int ret; | 1505 | int ret; |
1506 | unsigned int val; | ||
1510 | 1507 | ||
1511 | dsp->card = codec->card; | 1508 | /* |
1509 | * For simplicity set the DSP clock rate to be the | ||
1510 | * SYSCLK rate rather than making it configurable. | ||
1511 | */ | ||
1512 | ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); | ||
1513 | if (ret != 0) { | ||
1514 | adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret); | ||
1515 | return; | ||
1516 | } | ||
1517 | val = (val & ARIZONA_SYSCLK_FREQ_MASK) | ||
1518 | >> ARIZONA_SYSCLK_FREQ_SHIFT; | ||
1512 | 1519 | ||
1513 | switch (event) { | 1520 | ret = regmap_update_bits_async(dsp->regmap, |
1514 | case SND_SOC_DAPM_POST_PMU: | 1521 | dsp->base + ADSP2_CLOCKING, |
1515 | /* | 1522 | ADSP2_CLK_SEL_MASK, val); |
1516 | * For simplicity set the DSP clock rate to be the | 1523 | if (ret != 0) { |
1517 | * SYSCLK rate rather than making it configurable. | 1524 | adsp_err(dsp, "Failed to set clock rate: %d\n", ret); |
1518 | */ | 1525 | return; |
1519 | ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); | 1526 | } |
1520 | if (ret != 0) { | ||
1521 | adsp_err(dsp, "Failed to read SYSCLK state: %d\n", | ||
1522 | ret); | ||
1523 | return ret; | ||
1524 | } | ||
1525 | val = (val & ARIZONA_SYSCLK_FREQ_MASK) | ||
1526 | >> ARIZONA_SYSCLK_FREQ_SHIFT; | ||
1527 | 1527 | ||
1528 | ret = regmap_update_bits(dsp->regmap, | 1528 | if (dsp->dvfs) { |
1529 | dsp->base + ADSP2_CLOCKING, | 1529 | ret = regmap_read(dsp->regmap, |
1530 | ADSP2_CLK_SEL_MASK, val); | 1530 | dsp->base + ADSP2_CLOCKING, &val); |
1531 | if (ret != 0) { | 1531 | if (ret != 0) { |
1532 | adsp_err(dsp, "Failed to set clock rate: %d\n", | 1532 | dev_err(dsp->dev, "Failed to read clocking: %d\n", ret); |
1533 | ret); | 1533 | return; |
1534 | return ret; | ||
1535 | } | 1534 | } |
1536 | 1535 | ||
1537 | if (dsp->dvfs) { | 1536 | if ((val & ADSP2_CLK_SEL_MASK) >= 3) { |
1538 | ret = regmap_read(dsp->regmap, | 1537 | ret = regulator_enable(dsp->dvfs); |
1539 | dsp->base + ADSP2_CLOCKING, &val); | ||
1540 | if (ret != 0) { | 1538 | if (ret != 0) { |
1541 | dev_err(dsp->dev, | 1539 | dev_err(dsp->dev, |
1542 | "Failed to read clocking: %d\n", ret); | 1540 | "Failed to enable supply: %d\n", |
1543 | return ret; | 1541 | ret); |
1542 | return; | ||
1544 | } | 1543 | } |
1545 | 1544 | ||
1546 | if ((val & ADSP2_CLK_SEL_MASK) >= 3) { | 1545 | ret = regulator_set_voltage(dsp->dvfs, |
1547 | ret = regulator_enable(dsp->dvfs); | 1546 | 1800000, |
1548 | if (ret != 0) { | 1547 | 1800000); |
1549 | dev_err(dsp->dev, | 1548 | if (ret != 0) { |
1550 | "Failed to enable supply: %d\n", | 1549 | dev_err(dsp->dev, |
1551 | ret); | 1550 | "Failed to raise supply: %d\n", |
1552 | return ret; | 1551 | ret); |
1553 | } | 1552 | return; |
1554 | |||
1555 | ret = regulator_set_voltage(dsp->dvfs, | ||
1556 | 1800000, | ||
1557 | 1800000); | ||
1558 | if (ret != 0) { | ||
1559 | dev_err(dsp->dev, | ||
1560 | "Failed to raise supply: %d\n", | ||
1561 | ret); | ||
1562 | return ret; | ||
1563 | } | ||
1564 | } | 1553 | } |
1565 | } | 1554 | } |
1555 | } | ||
1566 | 1556 | ||
1567 | ret = wm_adsp2_ena(dsp); | 1557 | ret = wm_adsp2_ena(dsp); |
1568 | if (ret != 0) | 1558 | if (ret != 0) |
1569 | return ret; | 1559 | return; |
1570 | 1560 | ||
1571 | ret = wm_adsp_load(dsp); | 1561 | ret = wm_adsp_load(dsp); |
1572 | if (ret != 0) | 1562 | if (ret != 0) |
1573 | goto err; | 1563 | goto err; |
1574 | 1564 | ||
1575 | ret = wm_adsp_setup_algs(dsp); | 1565 | ret = wm_adsp_setup_algs(dsp); |
1576 | if (ret != 0) | 1566 | if (ret != 0) |
1577 | goto err; | 1567 | goto err; |
1578 | 1568 | ||
1579 | ret = wm_adsp_load_coeff(dsp); | 1569 | ret = wm_adsp_load_coeff(dsp); |
1580 | if (ret != 0) | 1570 | if (ret != 0) |
1581 | goto err; | 1571 | goto err; |
1582 | 1572 | ||
1583 | /* Initialize caches for enabled and unset controls */ | 1573 | /* Initialize caches for enabled and unset controls */ |
1584 | ret = wm_coeff_init_control_caches(dsp); | 1574 | ret = wm_coeff_init_control_caches(dsp); |
1585 | if (ret != 0) | 1575 | if (ret != 0) |
1586 | goto err; | 1576 | goto err; |
1587 | 1577 | ||
1588 | /* Sync set controls */ | 1578 | /* Sync set controls */ |
1589 | ret = wm_coeff_sync_controls(dsp); | 1579 | ret = wm_coeff_sync_controls(dsp); |
1590 | if (ret != 0) | 1580 | if (ret != 0) |
1591 | goto err; | 1581 | goto err; |
1582 | |||
1583 | ret = regmap_update_bits_async(dsp->regmap, | ||
1584 | dsp->base + ADSP2_CONTROL, | ||
1585 | ADSP2_CORE_ENA, | ||
1586 | ADSP2_CORE_ENA); | ||
1587 | if (ret != 0) | ||
1588 | goto err; | ||
1589 | |||
1590 | dsp->running = true; | ||
1591 | |||
1592 | return; | ||
1593 | |||
1594 | err: | ||
1595 | regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, | ||
1596 | ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); | ||
1597 | } | ||
1598 | |||
1599 | int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, | ||
1600 | struct snd_kcontrol *kcontrol, int event) | ||
1601 | { | ||
1602 | struct snd_soc_codec *codec = w->codec; | ||
1603 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | ||
1604 | struct wm_adsp *dsp = &dsps[w->shift]; | ||
1605 | |||
1606 | dsp->card = codec->card; | ||
1607 | |||
1608 | switch (event) { | ||
1609 | case SND_SOC_DAPM_PRE_PMU: | ||
1610 | queue_work(system_unbound_wq, &dsp->boot_work); | ||
1611 | break; | ||
1612 | default: | ||
1613 | break; | ||
1614 | }; | ||
1615 | |||
1616 | return 0; | ||
1617 | } | ||
1618 | EXPORT_SYMBOL_GPL(wm_adsp2_early_event); | ||
1619 | |||
1620 | int wm_adsp2_event(struct snd_soc_dapm_widget *w, | ||
1621 | struct snd_kcontrol *kcontrol, int event) | ||
1622 | { | ||
1623 | struct snd_soc_codec *codec = w->codec; | ||
1624 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | ||
1625 | struct wm_adsp *dsp = &dsps[w->shift]; | ||
1626 | struct wm_adsp_alg_region *alg_region; | ||
1627 | struct wm_coeff_ctl *ctl; | ||
1628 | int ret; | ||
1629 | |||
1630 | switch (event) { | ||
1631 | case SND_SOC_DAPM_POST_PMU: | ||
1632 | flush_work(&dsp->boot_work); | ||
1633 | |||
1634 | if (!dsp->running) | ||
1635 | return -EIO; | ||
1592 | 1636 | ||
1593 | ret = regmap_update_bits(dsp->regmap, | 1637 | ret = regmap_update_bits(dsp->regmap, |
1594 | dsp->base + ADSP2_CONTROL, | 1638 | dsp->base + ADSP2_CONTROL, |
1595 | ADSP2_CORE_ENA | ADSP2_START, | 1639 | ADSP2_START, |
1596 | ADSP2_CORE_ENA | ADSP2_START); | 1640 | ADSP2_START); |
1597 | if (ret != 0) | 1641 | if (ret != 0) |
1598 | goto err; | 1642 | goto err; |
1599 | |||
1600 | dsp->running = true; | ||
1601 | break; | 1643 | break; |
1602 | 1644 | ||
1603 | case SND_SOC_DAPM_PRE_PMD: | 1645 | case SND_SOC_DAPM_PRE_PMD: |
@@ -1668,6 +1710,7 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) | |||
1668 | 1710 | ||
1669 | INIT_LIST_HEAD(&adsp->alg_regions); | 1711 | INIT_LIST_HEAD(&adsp->alg_regions); |
1670 | INIT_LIST_HEAD(&adsp->ctl_list); | 1712 | INIT_LIST_HEAD(&adsp->ctl_list); |
1713 | INIT_WORK(&adsp->boot_work, wm_adsp2_boot_work); | ||
1671 | 1714 | ||
1672 | if (dvfs) { | 1715 | if (dvfs) { |
1673 | adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); | 1716 | adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); |
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index d018dea6254d..a4f6b64deb61 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h | |||
@@ -59,6 +59,8 @@ struct wm_adsp { | |||
59 | struct regulator *dvfs; | 59 | struct regulator *dvfs; |
60 | 60 | ||
61 | struct list_head ctl_list; | 61 | struct list_head ctl_list; |
62 | |||
63 | struct work_struct boot_work; | ||
62 | }; | 64 | }; |
63 | 65 | ||
64 | #define WM_ADSP1(wname, num) \ | 66 | #define WM_ADSP1(wname, num) \ |
@@ -66,8 +68,12 @@ struct wm_adsp { | |||
66 | wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) | 68 | wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) |
67 | 69 | ||
68 | #define WM_ADSP2(wname, num) \ | 70 | #define WM_ADSP2(wname, num) \ |
69 | SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ | 71 | { .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \ |
70 | wm_adsp2_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) | 72 | .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_early_event, \ |
73 | .event_flags = SND_SOC_DAPM_PRE_PMU }, \ | ||
74 | { .id = snd_soc_dapm_out_drv, .name = wname, \ | ||
75 | .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \ | ||
76 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } | ||
71 | 77 | ||
72 | extern const struct snd_kcontrol_new wm_adsp1_fw_controls[]; | 78 | extern const struct snd_kcontrol_new wm_adsp1_fw_controls[]; |
73 | extern const struct snd_kcontrol_new wm_adsp2_fw_controls[]; | 79 | extern const struct snd_kcontrol_new wm_adsp2_fw_controls[]; |
@@ -76,6 +82,8 @@ int wm_adsp1_init(struct wm_adsp *adsp); | |||
76 | int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs); | 82 | int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs); |
77 | int wm_adsp1_event(struct snd_soc_dapm_widget *w, | 83 | int wm_adsp1_event(struct snd_soc_dapm_widget *w, |
78 | struct snd_kcontrol *kcontrol, int event); | 84 | struct snd_kcontrol *kcontrol, int event); |
85 | int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, | ||
86 | struct snd_kcontrol *kcontrol, int event); | ||
79 | int wm_adsp2_event(struct snd_soc_dapm_widget *w, | 87 | int wm_adsp2_event(struct snd_soc_dapm_widget *w, |
80 | struct snd_kcontrol *kcontrol, int event); | 88 | struct snd_kcontrol *kcontrol, int event); |
81 | 89 | ||
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..324988dea4bd 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -1,9 +1,16 @@ | |||
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 | ||
4 | config SND_SOC_FSL_SPDIF | 8 | config SND_SOC_FSL_SPDIF |
5 | tristate | 9 | tristate |
6 | 10 | ||
11 | config SND_SOC_FSL_ESAI | ||
12 | tristate | ||
13 | |||
7 | config SND_SOC_FSL_UTILS | 14 | config SND_SOC_FSL_UTILS |
8 | tristate | 15 | tristate |
9 | 16 | ||
@@ -197,7 +204,6 @@ config SND_SOC_IMX_SPDIF | |||
197 | tristate "SoC Audio support for i.MX boards with S/PDIF" | 204 | tristate "SoC Audio support for i.MX boards with S/PDIF" |
198 | select SND_SOC_IMX_PCM_DMA | 205 | select SND_SOC_IMX_PCM_DMA |
199 | select SND_SOC_FSL_SPDIF | 206 | select SND_SOC_FSL_SPDIF |
200 | select SND_SOC_SPDIF | ||
201 | select REGMAP_MMIO | 207 | select REGMAP_MMIO |
202 | help | 208 | help |
203 | SoC Audio support for i.MX boards with S/PDIF | 209 | SoC Audio support for i.MX boards with S/PDIF |
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 8db705b0fdf9..b12ad4b9b4da 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
@@ -10,13 +10,17 @@ 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 |
17 | snd-soc-fsl-esai-objs := fsl_esai.o | ||
16 | snd-soc-fsl-utils-objs := fsl_utils.o | 18 | snd-soc-fsl-utils-objs := fsl_utils.o |
17 | snd-soc-fsl-dma-objs := fsl_dma.o | 19 | snd-soc-fsl-dma-objs := fsl_dma.o |
20 | obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o | ||
18 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o | 21 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o |
19 | obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o | 22 | obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o |
23 | obj-$(CONFIG_SND_SOC_FSL_ESAI) += snd-soc-fsl-esai.o | ||
20 | obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o | 24 | obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o |
21 | obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o | 25 | obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o |
22 | 26 | ||
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index fb9bb9eb5ca3..6bb0ea59284f 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
@@ -55,10 +55,6 @@ | |||
55 | SNDRV_PCM_FMTBIT_S32_BE | \ | 55 | SNDRV_PCM_FMTBIT_S32_BE | \ |
56 | SNDRV_PCM_FMTBIT_U32_LE | \ | 56 | SNDRV_PCM_FMTBIT_U32_LE | \ |
57 | SNDRV_PCM_FMTBIT_U32_BE) | 57 | SNDRV_PCM_FMTBIT_U32_BE) |
58 | |||
59 | #define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ | ||
60 | SNDRV_PCM_RATE_CONTINUOUS) | ||
61 | |||
62 | struct dma_object { | 58 | struct dma_object { |
63 | struct snd_soc_platform_driver dai; | 59 | struct snd_soc_platform_driver dai; |
64 | dma_addr_t ssi_stx_phys; | 60 | dma_addr_t ssi_stx_phys; |
@@ -140,9 +136,6 @@ static const struct snd_pcm_hardware fsl_dma_hardware = { | |||
140 | SNDRV_PCM_INFO_JOINT_DUPLEX | | 136 | SNDRV_PCM_INFO_JOINT_DUPLEX | |
141 | SNDRV_PCM_INFO_PAUSE, | 137 | SNDRV_PCM_INFO_PAUSE, |
142 | .formats = FSLDMA_PCM_FORMATS, | 138 | .formats = FSLDMA_PCM_FORMATS, |
143 | .rates = FSLDMA_PCM_RATES, | ||
144 | .rate_min = 5512, | ||
145 | .rate_max = 192000, | ||
146 | .period_bytes_min = 512, /* A reasonable limit */ | 139 | .period_bytes_min = 512, /* A reasonable limit */ |
147 | .period_bytes_max = (u32) -1, | 140 | .period_bytes_max = (u32) -1, |
148 | .periods_min = NUM_DMA_LINKS, | 141 | .periods_min = NUM_DMA_LINKS, |
@@ -852,7 +845,7 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm) | |||
852 | } | 845 | } |
853 | 846 | ||
854 | /** | 847 | /** |
855 | * find_ssi_node -- returns the SSI node that points to his DMA channel node | 848 | * find_ssi_node -- returns the SSI node that points to its DMA channel node |
856 | * | 849 | * |
857 | * Although this DMA driver attempts to operate independently of the other | 850 | * Although this DMA driver attempts to operate independently of the other |
858 | * devices, it still needs to determine some information about the SSI device | 851 | * devices, it still needs to determine some information about the SSI device |
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c new file mode 100644 index 000000000000..d0c72ed261e7 --- /dev/null +++ b/sound/soc/fsl/fsl_esai.c | |||
@@ -0,0 +1,815 @@ | |||
1 | /* | ||
2 | * Freescale ESAI ALSA SoC Digital Audio Interface (DAI) driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | #include <linux/clk.h> | ||
12 | #include <linux/dmaengine.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/of_irq.h> | ||
15 | #include <linux/of_platform.h> | ||
16 | #include <sound/dmaengine_pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | |||
19 | #include "fsl_esai.h" | ||
20 | #include "imx-pcm.h" | ||
21 | |||
22 | #define FSL_ESAI_RATES SNDRV_PCM_RATE_8000_192000 | ||
23 | #define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ | ||
24 | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
25 | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
26 | SNDRV_PCM_FMTBIT_S24_LE) | ||
27 | |||
28 | /** | ||
29 | * fsl_esai: ESAI private data | ||
30 | * | ||
31 | * @dma_params_rx: DMA parameters for receive channel | ||
32 | * @dma_params_tx: DMA parameters for transmit channel | ||
33 | * @pdev: platform device pointer | ||
34 | * @regmap: regmap handler | ||
35 | * @coreclk: clock source to access register | ||
36 | * @extalclk: esai clock source to derive HCK, SCK and FS | ||
37 | * @fsysclk: system clock source to derive HCK, SCK and FS | ||
38 | * @fifo_depth: depth of tx/rx FIFO | ||
39 | * @slot_width: width of each DAI slot | ||
40 | * @hck_rate: clock rate of desired HCKx clock | ||
41 | * @sck_div: if using PSR/PM dividers for SCKx clock | ||
42 | * @slave_mode: if fully using DAI slave mode | ||
43 | * @synchronous: if using tx/rx synchronous mode | ||
44 | * @name: driver name | ||
45 | */ | ||
46 | struct fsl_esai { | ||
47 | struct snd_dmaengine_dai_dma_data dma_params_rx; | ||
48 | struct snd_dmaengine_dai_dma_data dma_params_tx; | ||
49 | struct platform_device *pdev; | ||
50 | struct regmap *regmap; | ||
51 | struct clk *coreclk; | ||
52 | struct clk *extalclk; | ||
53 | struct clk *fsysclk; | ||
54 | u32 fifo_depth; | ||
55 | u32 slot_width; | ||
56 | u32 hck_rate[2]; | ||
57 | bool sck_div[2]; | ||
58 | bool slave_mode; | ||
59 | bool synchronous; | ||
60 | char name[32]; | ||
61 | }; | ||
62 | |||
63 | static irqreturn_t esai_isr(int irq, void *devid) | ||
64 | { | ||
65 | struct fsl_esai *esai_priv = (struct fsl_esai *)devid; | ||
66 | struct platform_device *pdev = esai_priv->pdev; | ||
67 | u32 esr; | ||
68 | |||
69 | regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr); | ||
70 | |||
71 | if (esr & ESAI_ESR_TINIT_MASK) | ||
72 | dev_dbg(&pdev->dev, "isr: Transmition Initialized\n"); | ||
73 | |||
74 | if (esr & ESAI_ESR_RFF_MASK) | ||
75 | dev_warn(&pdev->dev, "isr: Receiving overrun\n"); | ||
76 | |||
77 | if (esr & ESAI_ESR_TFE_MASK) | ||
78 | dev_warn(&pdev->dev, "isr: Transmition underrun\n"); | ||
79 | |||
80 | if (esr & ESAI_ESR_TLS_MASK) | ||
81 | dev_dbg(&pdev->dev, "isr: Just transmitted the last slot\n"); | ||
82 | |||
83 | if (esr & ESAI_ESR_TDE_MASK) | ||
84 | dev_dbg(&pdev->dev, "isr: Transmition data exception\n"); | ||
85 | |||
86 | if (esr & ESAI_ESR_TED_MASK) | ||
87 | dev_dbg(&pdev->dev, "isr: Transmitting even slots\n"); | ||
88 | |||
89 | if (esr & ESAI_ESR_TD_MASK) | ||
90 | dev_dbg(&pdev->dev, "isr: Transmitting data\n"); | ||
91 | |||
92 | if (esr & ESAI_ESR_RLS_MASK) | ||
93 | dev_dbg(&pdev->dev, "isr: Just received the last slot\n"); | ||
94 | |||
95 | if (esr & ESAI_ESR_RDE_MASK) | ||
96 | dev_dbg(&pdev->dev, "isr: Receiving data exception\n"); | ||
97 | |||
98 | if (esr & ESAI_ESR_RED_MASK) | ||
99 | dev_dbg(&pdev->dev, "isr: Receiving even slots\n"); | ||
100 | |||
101 | if (esr & ESAI_ESR_RD_MASK) | ||
102 | dev_dbg(&pdev->dev, "isr: Receiving data\n"); | ||
103 | |||
104 | return IRQ_HANDLED; | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * This function is used to calculate the divisors of psr, pm, fp and it is | ||
109 | * supposed to be called in set_dai_sysclk() and set_bclk(). | ||
110 | * | ||
111 | * @ratio: desired overall ratio for the paticipating dividers | ||
112 | * @usefp: for HCK setting, there is no need to set fp divider | ||
113 | * @fp: bypass other dividers by setting fp directly if fp != 0 | ||
114 | * @tx: current setting is for playback or capture | ||
115 | */ | ||
116 | static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio, | ||
117 | bool usefp, u32 fp) | ||
118 | { | ||
119 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | ||
120 | u32 psr, pm = 999, maxfp, prod, sub, savesub, i, j; | ||
121 | |||
122 | maxfp = usefp ? 16 : 1; | ||
123 | |||
124 | if (usefp && fp) | ||
125 | goto out_fp; | ||
126 | |||
127 | if (ratio > 2 * 8 * 256 * maxfp || ratio < 2) { | ||
128 | dev_err(dai->dev, "the ratio is out of range (2 ~ %d)\n", | ||
129 | 2 * 8 * 256 * maxfp); | ||
130 | return -EINVAL; | ||
131 | } else if (ratio % 2) { | ||
132 | dev_err(dai->dev, "the raio must be even if using upper divider\n"); | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | |||
136 | ratio /= 2; | ||
137 | |||
138 | psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8; | ||
139 | |||
140 | /* Set the max fluctuation -- 0.1% of the max devisor */ | ||
141 | savesub = (psr ? 1 : 8) * 256 * maxfp / 1000; | ||
142 | |||
143 | /* Find the best value for PM */ | ||
144 | for (i = 1; i <= 256; i++) { | ||
145 | for (j = 1; j <= maxfp; j++) { | ||
146 | /* PSR (1 or 8) * PM (1 ~ 256) * FP (1 ~ 16) */ | ||
147 | prod = (psr ? 1 : 8) * i * j; | ||
148 | |||
149 | if (prod == ratio) | ||
150 | sub = 0; | ||
151 | else if (prod / ratio == 1) | ||
152 | sub = prod - ratio; | ||
153 | else if (ratio / prod == 1) | ||
154 | sub = ratio - prod; | ||
155 | else | ||
156 | continue; | ||
157 | |||
158 | /* Calculate the fraction */ | ||
159 | sub = sub * 1000 / ratio; | ||
160 | if (sub < savesub) { | ||
161 | savesub = sub; | ||
162 | pm = i; | ||
163 | fp = j; | ||
164 | } | ||
165 | |||
166 | /* We are lucky */ | ||
167 | if (savesub == 0) | ||
168 | goto out; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | if (pm == 999) { | ||
173 | dev_err(dai->dev, "failed to calculate proper divisors\n"); | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
177 | out: | ||
178 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx), | ||
179 | ESAI_xCCR_xPSR_MASK | ESAI_xCCR_xPM_MASK, | ||
180 | psr | ESAI_xCCR_xPM(pm)); | ||
181 | |||
182 | out_fp: | ||
183 | /* Bypass fp if not being required */ | ||
184 | if (maxfp <= 1) | ||
185 | return 0; | ||
186 | |||
187 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx), | ||
188 | ESAI_xCCR_xFP_MASK, ESAI_xCCR_xFP(fp)); | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * This function mainly configures the clock frequency of MCLK (HCKT/HCKR) | ||
195 | * | ||
196 | * @Parameters: | ||
197 | * clk_id: The clock source of HCKT/HCKR | ||
198 | * (Input from outside; output from inside, FSYS or EXTAL) | ||
199 | * freq: The required clock rate of HCKT/HCKR | ||
200 | * dir: The clock direction of HCKT/HCKR | ||
201 | * | ||
202 | * Note: If the direction is input, we do not care about clk_id. | ||
203 | */ | ||
204 | static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
205 | unsigned int freq, int dir) | ||
206 | { | ||
207 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | ||
208 | struct clk *clksrc = esai_priv->extalclk; | ||
209 | bool tx = clk_id <= ESAI_HCKT_EXTAL; | ||
210 | bool in = dir == SND_SOC_CLOCK_IN; | ||
211 | u32 ret, ratio, ecr = 0; | ||
212 | unsigned long clk_rate; | ||
213 | |||
214 | /* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */ | ||
215 | esai_priv->sck_div[tx] = true; | ||
216 | |||
217 | /* Set the direction of HCKT/HCKR pins */ | ||
218 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx), | ||
219 | ESAI_xCCR_xHCKD, in ? 0 : ESAI_xCCR_xHCKD); | ||
220 | |||
221 | if (in) | ||
222 | goto out; | ||
223 | |||
224 | switch (clk_id) { | ||
225 | case ESAI_HCKT_FSYS: | ||
226 | case ESAI_HCKR_FSYS: | ||
227 | clksrc = esai_priv->fsysclk; | ||
228 | break; | ||
229 | case ESAI_HCKT_EXTAL: | ||
230 | ecr |= ESAI_ECR_ETI; | ||
231 | case ESAI_HCKR_EXTAL: | ||
232 | ecr |= ESAI_ECR_ERI; | ||
233 | break; | ||
234 | default: | ||
235 | return -EINVAL; | ||
236 | } | ||
237 | |||
238 | if (IS_ERR(clksrc)) { | ||
239 | dev_err(dai->dev, "no assigned %s clock\n", | ||
240 | clk_id % 2 ? "extal" : "fsys"); | ||
241 | return PTR_ERR(clksrc); | ||
242 | } | ||
243 | clk_rate = clk_get_rate(clksrc); | ||
244 | |||
245 | ratio = clk_rate / freq; | ||
246 | if (ratio * freq > clk_rate) | ||
247 | ret = ratio * freq - clk_rate; | ||
248 | else if (ratio * freq < clk_rate) | ||
249 | ret = clk_rate - ratio * freq; | ||
250 | else | ||
251 | ret = 0; | ||
252 | |||
253 | /* Block if clock source can not be divided into the required rate */ | ||
254 | if (ret != 0 && clk_rate / ret < 1000) { | ||
255 | dev_err(dai->dev, "failed to derive required HCK%c rate\n", | ||
256 | tx ? 'T' : 'R'); | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
260 | if (ratio == 1) { | ||
261 | /* Bypass all the dividers if not being needed */ | ||
262 | ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO; | ||
263 | goto out; | ||
264 | } | ||
265 | |||
266 | ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0); | ||
267 | if (ret) | ||
268 | return ret; | ||
269 | |||
270 | esai_priv->sck_div[tx] = false; | ||
271 | |||
272 | out: | ||
273 | esai_priv->hck_rate[tx] = freq; | ||
274 | |||
275 | regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, | ||
276 | tx ? ESAI_ECR_ETI | ESAI_ECR_ETO : | ||
277 | ESAI_ECR_ERI | ESAI_ECR_ERO, ecr); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | /** | ||
283 | * This function configures the related dividers according to the bclk rate | ||
284 | */ | ||
285 | static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) | ||
286 | { | ||
287 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | ||
288 | u32 hck_rate = esai_priv->hck_rate[tx]; | ||
289 | u32 sub, ratio = hck_rate / freq; | ||
290 | |||
291 | /* Don't apply for fully slave mode*/ | ||
292 | if (esai_priv->slave_mode) | ||
293 | return 0; | ||
294 | |||
295 | if (ratio * freq > hck_rate) | ||
296 | sub = ratio * freq - hck_rate; | ||
297 | else if (ratio * freq < hck_rate) | ||
298 | sub = hck_rate - ratio * freq; | ||
299 | else | ||
300 | sub = 0; | ||
301 | |||
302 | /* Block if clock source can not be divided into the required rate */ | ||
303 | if (sub != 0 && hck_rate / sub < 1000) { | ||
304 | dev_err(dai->dev, "failed to derive required SCK%c rate\n", | ||
305 | tx ? 'T' : 'R'); | ||
306 | return -EINVAL; | ||
307 | } | ||
308 | |||
309 | if (esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) { | ||
310 | dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n"); | ||
311 | return -EINVAL; | ||
312 | } | ||
313 | |||
314 | return fsl_esai_divisor_cal(dai, tx, ratio, true, | ||
315 | esai_priv->sck_div[tx] ? 0 : ratio); | ||
316 | } | ||
317 | |||
318 | static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, | ||
319 | u32 rx_mask, int slots, int slot_width) | ||
320 | { | ||
321 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | ||
322 | |||
323 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, | ||
324 | ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots)); | ||
325 | |||
326 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA, | ||
327 | ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask)); | ||
328 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB, | ||
329 | ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(tx_mask)); | ||
330 | |||
331 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, | ||
332 | ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots)); | ||
333 | |||
334 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA, | ||
335 | ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask)); | ||
336 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB, | ||
337 | ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(rx_mask)); | ||
338 | |||
339 | esai_priv->slot_width = slot_width; | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
345 | { | ||
346 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | ||
347 | u32 xcr = 0, xccr = 0, mask; | ||
348 | |||
349 | /* DAI mode */ | ||
350 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
351 | case SND_SOC_DAIFMT_I2S: | ||
352 | /* Data on rising edge of bclk, frame low, 1clk before data */ | ||
353 | xcr |= ESAI_xCR_xFSR; | ||
354 | xccr |= ESAI_xCCR_xFSP | ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP; | ||
355 | break; | ||
356 | case SND_SOC_DAIFMT_LEFT_J: | ||
357 | /* Data on rising edge of bclk, frame high */ | ||
358 | xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP; | ||
359 | break; | ||
360 | case SND_SOC_DAIFMT_RIGHT_J: | ||
361 | /* Data on rising edge of bclk, frame high, right aligned */ | ||
362 | xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCR_xWA; | ||
363 | break; | ||
364 | case SND_SOC_DAIFMT_DSP_A: | ||
365 | /* Data on rising edge of bclk, frame high, 1clk before data */ | ||
366 | xcr |= ESAI_xCR_xFSL | ESAI_xCR_xFSR; | ||
367 | xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP; | ||
368 | break; | ||
369 | case SND_SOC_DAIFMT_DSP_B: | ||
370 | /* Data on rising edge of bclk, frame high */ | ||
371 | xcr |= ESAI_xCR_xFSL; | ||
372 | xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP; | ||
373 | break; | ||
374 | default: | ||
375 | return -EINVAL; | ||
376 | } | ||
377 | |||
378 | /* DAI clock inversion */ | ||
379 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
380 | case SND_SOC_DAIFMT_NB_NF: | ||
381 | /* Nothing to do for both normal cases */ | ||
382 | break; | ||
383 | case SND_SOC_DAIFMT_IB_NF: | ||
384 | /* Invert bit clock */ | ||
385 | xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP; | ||
386 | break; | ||
387 | case SND_SOC_DAIFMT_NB_IF: | ||
388 | /* Invert frame clock */ | ||
389 | xccr ^= ESAI_xCCR_xFSP; | ||
390 | break; | ||
391 | case SND_SOC_DAIFMT_IB_IF: | ||
392 | /* Invert both clocks */ | ||
393 | xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP; | ||
394 | break; | ||
395 | default: | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | |||
399 | esai_priv->slave_mode = false; | ||
400 | |||
401 | /* DAI clock master masks */ | ||
402 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
403 | case SND_SOC_DAIFMT_CBM_CFM: | ||
404 | esai_priv->slave_mode = true; | ||
405 | break; | ||
406 | case SND_SOC_DAIFMT_CBS_CFM: | ||
407 | xccr |= ESAI_xCCR_xCKD; | ||
408 | break; | ||
409 | case SND_SOC_DAIFMT_CBM_CFS: | ||
410 | xccr |= ESAI_xCCR_xFSD; | ||
411 | break; | ||
412 | case SND_SOC_DAIFMT_CBS_CFS: | ||
413 | xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD; | ||
414 | break; | ||
415 | default: | ||
416 | return -EINVAL; | ||
417 | } | ||
418 | |||
419 | mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR; | ||
420 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, xcr); | ||
421 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, mask, xcr); | ||
422 | |||
423 | mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP | | ||
424 | ESAI_xCCR_xFSD | ESAI_xCCR_xCKD | ESAI_xCR_xWA; | ||
425 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, mask, xccr); | ||
426 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, mask, xccr); | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static int fsl_esai_startup(struct snd_pcm_substream *substream, | ||
432 | struct snd_soc_dai *dai) | ||
433 | { | ||
434 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | ||
435 | |||
436 | /* | ||
437 | * Some platforms might use the same bit to gate all three or two of | ||
438 | * clocks, so keep all clocks open/close at the same time for safety | ||
439 | */ | ||
440 | clk_prepare_enable(esai_priv->coreclk); | ||
441 | if (!IS_ERR(esai_priv->extalclk)) | ||
442 | clk_prepare_enable(esai_priv->extalclk); | ||
443 | if (!IS_ERR(esai_priv->fsysclk)) | ||
444 | clk_prepare_enable(esai_priv->fsysclk); | ||
445 | |||
446 | if (!dai->active) { | ||
447 | /* Reset Port C */ | ||
448 | regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, | ||
449 | ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO)); | ||
450 | regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, | ||
451 | ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO)); | ||
452 | |||
453 | /* Set synchronous mode */ | ||
454 | regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR, | ||
455 | ESAI_SAICR_SYNC, esai_priv->synchronous ? | ||
456 | ESAI_SAICR_SYNC : 0); | ||
457 | |||
458 | /* Set a default slot number -- 2 */ | ||
459 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, | ||
460 | ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2)); | ||
461 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, | ||
462 | ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2)); | ||
463 | } | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static int fsl_esai_hw_params(struct snd_pcm_substream *substream, | ||
469 | struct snd_pcm_hw_params *params, | ||
470 | struct snd_soc_dai *dai) | ||
471 | { | ||
472 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | ||
473 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
474 | u32 width = snd_pcm_format_width(params_format(params)); | ||
475 | u32 channels = params_channels(params); | ||
476 | u32 bclk, mask, val, ret; | ||
477 | |||
478 | bclk = params_rate(params) * esai_priv->slot_width * 2; | ||
479 | |||
480 | ret = fsl_esai_set_bclk(dai, tx, bclk); | ||
481 | if (ret) | ||
482 | return ret; | ||
483 | |||
484 | /* Use Normal mode to support monaural audio */ | ||
485 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), | ||
486 | ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ? | ||
487 | ESAI_xCR_xMOD_NETWORK : 0); | ||
488 | |||
489 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), | ||
490 | ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR); | ||
491 | |||
492 | mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK | | ||
493 | (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK); | ||
494 | val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) | | ||
495 | (tx ? ESAI_xFCR_TE(channels) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(channels)); | ||
496 | |||
497 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val); | ||
498 | |||
499 | mask = ESAI_xCR_xSWS_MASK | (tx ? ESAI_xCR_PADC : 0); | ||
500 | val = ESAI_xCR_xSWS(esai_priv->slot_width, width) | (tx ? ESAI_xCR_PADC : 0); | ||
501 | |||
502 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val); | ||
503 | |||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | static void fsl_esai_shutdown(struct snd_pcm_substream *substream, | ||
508 | struct snd_soc_dai *dai) | ||
509 | { | ||
510 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | ||
511 | |||
512 | if (!IS_ERR(esai_priv->fsysclk)) | ||
513 | clk_disable_unprepare(esai_priv->fsysclk); | ||
514 | if (!IS_ERR(esai_priv->extalclk)) | ||
515 | clk_disable_unprepare(esai_priv->extalclk); | ||
516 | clk_disable_unprepare(esai_priv->coreclk); | ||
517 | } | ||
518 | |||
519 | static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, | ||
520 | struct snd_soc_dai *dai) | ||
521 | { | ||
522 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | ||
523 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
524 | u8 i, channels = substream->runtime->channels; | ||
525 | |||
526 | switch (cmd) { | ||
527 | case SNDRV_PCM_TRIGGER_START: | ||
528 | case SNDRV_PCM_TRIGGER_RESUME: | ||
529 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
530 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), | ||
531 | ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN); | ||
532 | |||
533 | /* Write initial words reqiured by ESAI as normal procedure */ | ||
534 | for (i = 0; tx && i < channels; i++) | ||
535 | regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0); | ||
536 | |||
537 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), | ||
538 | tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, | ||
539 | tx ? ESAI_xCR_TE(channels) : ESAI_xCR_RE(channels)); | ||
540 | break; | ||
541 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
542 | case SNDRV_PCM_TRIGGER_STOP: | ||
543 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
544 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), | ||
545 | tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); | ||
546 | |||
547 | /* Disable and reset FIFO */ | ||
548 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), | ||
549 | ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR); | ||
550 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), | ||
551 | ESAI_xFCR_xFR, 0); | ||
552 | break; | ||
553 | default: | ||
554 | return -EINVAL; | ||
555 | } | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | static struct snd_soc_dai_ops fsl_esai_dai_ops = { | ||
561 | .startup = fsl_esai_startup, | ||
562 | .shutdown = fsl_esai_shutdown, | ||
563 | .trigger = fsl_esai_trigger, | ||
564 | .hw_params = fsl_esai_hw_params, | ||
565 | .set_sysclk = fsl_esai_set_dai_sysclk, | ||
566 | .set_fmt = fsl_esai_set_dai_fmt, | ||
567 | .set_tdm_slot = fsl_esai_set_dai_tdm_slot, | ||
568 | }; | ||
569 | |||
570 | static int fsl_esai_dai_probe(struct snd_soc_dai *dai) | ||
571 | { | ||
572 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | ||
573 | |||
574 | snd_soc_dai_init_dma_data(dai, &esai_priv->dma_params_tx, | ||
575 | &esai_priv->dma_params_rx); | ||
576 | |||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | static struct snd_soc_dai_driver fsl_esai_dai = { | ||
581 | .probe = fsl_esai_dai_probe, | ||
582 | .playback = { | ||
583 | .channels_min = 1, | ||
584 | .channels_max = 12, | ||
585 | .rates = FSL_ESAI_RATES, | ||
586 | .formats = FSL_ESAI_FORMATS, | ||
587 | }, | ||
588 | .capture = { | ||
589 | .channels_min = 1, | ||
590 | .channels_max = 8, | ||
591 | .rates = FSL_ESAI_RATES, | ||
592 | .formats = FSL_ESAI_FORMATS, | ||
593 | }, | ||
594 | .ops = &fsl_esai_dai_ops, | ||
595 | }; | ||
596 | |||
597 | static const struct snd_soc_component_driver fsl_esai_component = { | ||
598 | .name = "fsl-esai", | ||
599 | }; | ||
600 | |||
601 | static bool fsl_esai_readable_reg(struct device *dev, unsigned int reg) | ||
602 | { | ||
603 | switch (reg) { | ||
604 | case REG_ESAI_ERDR: | ||
605 | case REG_ESAI_ECR: | ||
606 | case REG_ESAI_ESR: | ||
607 | case REG_ESAI_TFCR: | ||
608 | case REG_ESAI_TFSR: | ||
609 | case REG_ESAI_RFCR: | ||
610 | case REG_ESAI_RFSR: | ||
611 | case REG_ESAI_RX0: | ||
612 | case REG_ESAI_RX1: | ||
613 | case REG_ESAI_RX2: | ||
614 | case REG_ESAI_RX3: | ||
615 | case REG_ESAI_SAISR: | ||
616 | case REG_ESAI_SAICR: | ||
617 | case REG_ESAI_TCR: | ||
618 | case REG_ESAI_TCCR: | ||
619 | case REG_ESAI_RCR: | ||
620 | case REG_ESAI_RCCR: | ||
621 | case REG_ESAI_TSMA: | ||
622 | case REG_ESAI_TSMB: | ||
623 | case REG_ESAI_RSMA: | ||
624 | case REG_ESAI_RSMB: | ||
625 | case REG_ESAI_PRRC: | ||
626 | case REG_ESAI_PCRC: | ||
627 | return true; | ||
628 | default: | ||
629 | return false; | ||
630 | } | ||
631 | } | ||
632 | |||
633 | static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg) | ||
634 | { | ||
635 | switch (reg) { | ||
636 | case REG_ESAI_ETDR: | ||
637 | case REG_ESAI_ECR: | ||
638 | case REG_ESAI_TFCR: | ||
639 | case REG_ESAI_RFCR: | ||
640 | case REG_ESAI_TX0: | ||
641 | case REG_ESAI_TX1: | ||
642 | case REG_ESAI_TX2: | ||
643 | case REG_ESAI_TX3: | ||
644 | case REG_ESAI_TX4: | ||
645 | case REG_ESAI_TX5: | ||
646 | case REG_ESAI_TSR: | ||
647 | case REG_ESAI_SAICR: | ||
648 | case REG_ESAI_TCR: | ||
649 | case REG_ESAI_TCCR: | ||
650 | case REG_ESAI_RCR: | ||
651 | case REG_ESAI_RCCR: | ||
652 | case REG_ESAI_TSMA: | ||
653 | case REG_ESAI_TSMB: | ||
654 | case REG_ESAI_RSMA: | ||
655 | case REG_ESAI_RSMB: | ||
656 | case REG_ESAI_PRRC: | ||
657 | case REG_ESAI_PCRC: | ||
658 | return true; | ||
659 | default: | ||
660 | return false; | ||
661 | } | ||
662 | } | ||
663 | |||
664 | static const struct regmap_config fsl_esai_regmap_config = { | ||
665 | .reg_bits = 32, | ||
666 | .reg_stride = 4, | ||
667 | .val_bits = 32, | ||
668 | |||
669 | .max_register = REG_ESAI_PCRC, | ||
670 | .readable_reg = fsl_esai_readable_reg, | ||
671 | .writeable_reg = fsl_esai_writeable_reg, | ||
672 | }; | ||
673 | |||
674 | static int fsl_esai_probe(struct platform_device *pdev) | ||
675 | { | ||
676 | struct device_node *np = pdev->dev.of_node; | ||
677 | struct fsl_esai *esai_priv; | ||
678 | struct resource *res; | ||
679 | const uint32_t *iprop; | ||
680 | void __iomem *regs; | ||
681 | int irq, ret; | ||
682 | |||
683 | esai_priv = devm_kzalloc(&pdev->dev, sizeof(*esai_priv), GFP_KERNEL); | ||
684 | if (!esai_priv) | ||
685 | return -ENOMEM; | ||
686 | |||
687 | esai_priv->pdev = pdev; | ||
688 | strcpy(esai_priv->name, np->name); | ||
689 | |||
690 | /* Get the addresses and IRQ */ | ||
691 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
692 | regs = devm_ioremap_resource(&pdev->dev, res); | ||
693 | if (IS_ERR(regs)) | ||
694 | return PTR_ERR(regs); | ||
695 | |||
696 | esai_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, | ||
697 | "core", regs, &fsl_esai_regmap_config); | ||
698 | if (IS_ERR(esai_priv->regmap)) { | ||
699 | dev_err(&pdev->dev, "failed to init regmap: %ld\n", | ||
700 | PTR_ERR(esai_priv->regmap)); | ||
701 | return PTR_ERR(esai_priv->regmap); | ||
702 | } | ||
703 | |||
704 | esai_priv->coreclk = devm_clk_get(&pdev->dev, "core"); | ||
705 | if (IS_ERR(esai_priv->coreclk)) { | ||
706 | dev_err(&pdev->dev, "failed to get core clock: %ld\n", | ||
707 | PTR_ERR(esai_priv->coreclk)); | ||
708 | return PTR_ERR(esai_priv->coreclk); | ||
709 | } | ||
710 | |||
711 | esai_priv->extalclk = devm_clk_get(&pdev->dev, "extal"); | ||
712 | if (IS_ERR(esai_priv->extalclk)) | ||
713 | dev_warn(&pdev->dev, "failed to get extal clock: %ld\n", | ||
714 | PTR_ERR(esai_priv->extalclk)); | ||
715 | |||
716 | esai_priv->fsysclk = devm_clk_get(&pdev->dev, "fsys"); | ||
717 | if (IS_ERR(esai_priv->fsysclk)) | ||
718 | dev_warn(&pdev->dev, "failed to get fsys clock: %ld\n", | ||
719 | PTR_ERR(esai_priv->fsysclk)); | ||
720 | |||
721 | irq = platform_get_irq(pdev, 0); | ||
722 | if (irq < 0) { | ||
723 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | ||
724 | return irq; | ||
725 | } | ||
726 | |||
727 | ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0, | ||
728 | esai_priv->name, esai_priv); | ||
729 | if (ret) { | ||
730 | dev_err(&pdev->dev, "failed to claim irq %u\n", irq); | ||
731 | return ret; | ||
732 | } | ||
733 | |||
734 | /* Set a default slot size */ | ||
735 | esai_priv->slot_width = 32; | ||
736 | |||
737 | /* Set a default master/slave state */ | ||
738 | esai_priv->slave_mode = true; | ||
739 | |||
740 | /* Determine the FIFO depth */ | ||
741 | iprop = of_get_property(np, "fsl,fifo-depth", NULL); | ||
742 | if (iprop) | ||
743 | esai_priv->fifo_depth = be32_to_cpup(iprop); | ||
744 | else | ||
745 | esai_priv->fifo_depth = 64; | ||
746 | |||
747 | esai_priv->dma_params_tx.maxburst = 16; | ||
748 | esai_priv->dma_params_rx.maxburst = 16; | ||
749 | esai_priv->dma_params_tx.addr = res->start + REG_ESAI_ETDR; | ||
750 | esai_priv->dma_params_rx.addr = res->start + REG_ESAI_ERDR; | ||
751 | |||
752 | esai_priv->synchronous = | ||
753 | of_property_read_bool(np, "fsl,esai-synchronous"); | ||
754 | |||
755 | /* Implement full symmetry for synchronous mode */ | ||
756 | if (esai_priv->synchronous) { | ||
757 | fsl_esai_dai.symmetric_rates = 1; | ||
758 | fsl_esai_dai.symmetric_channels = 1; | ||
759 | fsl_esai_dai.symmetric_samplebits = 1; | ||
760 | } | ||
761 | |||
762 | dev_set_drvdata(&pdev->dev, esai_priv); | ||
763 | |||
764 | /* Reset ESAI unit */ | ||
765 | ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST); | ||
766 | if (ret) { | ||
767 | dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret); | ||
768 | return ret; | ||
769 | } | ||
770 | |||
771 | /* | ||
772 | * We need to enable ESAI so as to access some of its registers. | ||
773 | * Otherwise, we would fail to dump regmap from user space. | ||
774 | */ | ||
775 | ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN); | ||
776 | if (ret) { | ||
777 | dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret); | ||
778 | return ret; | ||
779 | } | ||
780 | |||
781 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component, | ||
782 | &fsl_esai_dai, 1); | ||
783 | if (ret) { | ||
784 | dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); | ||
785 | return ret; | ||
786 | } | ||
787 | |||
788 | ret = imx_pcm_dma_init(pdev); | ||
789 | if (ret) | ||
790 | dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret); | ||
791 | |||
792 | return ret; | ||
793 | } | ||
794 | |||
795 | static const struct of_device_id fsl_esai_dt_ids[] = { | ||
796 | { .compatible = "fsl,imx35-esai", }, | ||
797 | {} | ||
798 | }; | ||
799 | MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); | ||
800 | |||
801 | static struct platform_driver fsl_esai_driver = { | ||
802 | .probe = fsl_esai_probe, | ||
803 | .driver = { | ||
804 | .name = "fsl-esai-dai", | ||
805 | .owner = THIS_MODULE, | ||
806 | .of_match_table = fsl_esai_dt_ids, | ||
807 | }, | ||
808 | }; | ||
809 | |||
810 | module_platform_driver(fsl_esai_driver); | ||
811 | |||
812 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
813 | MODULE_DESCRIPTION("Freescale ESAI CPU DAI driver"); | ||
814 | MODULE_LICENSE("GPL v2"); | ||
815 | MODULE_ALIAS("platform:fsl-esai-dai"); | ||
diff --git a/sound/soc/fsl/fsl_esai.h b/sound/soc/fsl/fsl_esai.h new file mode 100644 index 000000000000..9c9f957fcae1 --- /dev/null +++ b/sound/soc/fsl/fsl_esai.h | |||
@@ -0,0 +1,354 @@ | |||
1 | /* | ||
2 | * fsl_esai.h - ALSA ESAI interface for the Freescale i.MX SoC | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Nicolin Chen <Guangyu.Chen@freescale.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of any | ||
10 | * kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #ifndef _FSL_ESAI_DAI_H | ||
14 | #define _FSL_ESAI_DAI_H | ||
15 | |||
16 | /* ESAI Register Map */ | ||
17 | #define REG_ESAI_ETDR 0x00 | ||
18 | #define REG_ESAI_ERDR 0x04 | ||
19 | #define REG_ESAI_ECR 0x08 | ||
20 | #define REG_ESAI_ESR 0x0C | ||
21 | #define REG_ESAI_TFCR 0x10 | ||
22 | #define REG_ESAI_TFSR 0x14 | ||
23 | #define REG_ESAI_RFCR 0x18 | ||
24 | #define REG_ESAI_RFSR 0x1C | ||
25 | #define REG_ESAI_xFCR(tx) (tx ? REG_ESAI_TFCR : REG_ESAI_RFCR) | ||
26 | #define REG_ESAI_xFSR(tx) (tx ? REG_ESAI_TFSR : REG_ESAI_RFSR) | ||
27 | #define REG_ESAI_TX0 0x80 | ||
28 | #define REG_ESAI_TX1 0x84 | ||
29 | #define REG_ESAI_TX2 0x88 | ||
30 | #define REG_ESAI_TX3 0x8C | ||
31 | #define REG_ESAI_TX4 0x90 | ||
32 | #define REG_ESAI_TX5 0x94 | ||
33 | #define REG_ESAI_TSR 0x98 | ||
34 | #define REG_ESAI_RX0 0xA0 | ||
35 | #define REG_ESAI_RX1 0xA4 | ||
36 | #define REG_ESAI_RX2 0xA8 | ||
37 | #define REG_ESAI_RX3 0xAC | ||
38 | #define REG_ESAI_SAISR 0xCC | ||
39 | #define REG_ESAI_SAICR 0xD0 | ||
40 | #define REG_ESAI_TCR 0xD4 | ||
41 | #define REG_ESAI_TCCR 0xD8 | ||
42 | #define REG_ESAI_RCR 0xDC | ||
43 | #define REG_ESAI_RCCR 0xE0 | ||
44 | #define REG_ESAI_xCR(tx) (tx ? REG_ESAI_TCR : REG_ESAI_RCR) | ||
45 | #define REG_ESAI_xCCR(tx) (tx ? REG_ESAI_TCCR : REG_ESAI_RCCR) | ||
46 | #define REG_ESAI_TSMA 0xE4 | ||
47 | #define REG_ESAI_TSMB 0xE8 | ||
48 | #define REG_ESAI_RSMA 0xEC | ||
49 | #define REG_ESAI_RSMB 0xF0 | ||
50 | #define REG_ESAI_xSMA(tx) (tx ? REG_ESAI_TSMA : REG_ESAI_RSMA) | ||
51 | #define REG_ESAI_xSMB(tx) (tx ? REG_ESAI_TSMB : REG_ESAI_RSMB) | ||
52 | #define REG_ESAI_PRRC 0xF8 | ||
53 | #define REG_ESAI_PCRC 0xFC | ||
54 | |||
55 | /* ESAI Control Register -- REG_ESAI_ECR 0x8 */ | ||
56 | #define ESAI_ECR_ETI_SHIFT 19 | ||
57 | #define ESAI_ECR_ETI_MASK (1 << ESAI_ECR_ETI_SHIFT) | ||
58 | #define ESAI_ECR_ETI (1 << ESAI_ECR_ETI_SHIFT) | ||
59 | #define ESAI_ECR_ETO_SHIFT 18 | ||
60 | #define ESAI_ECR_ETO_MASK (1 << ESAI_ECR_ETO_SHIFT) | ||
61 | #define ESAI_ECR_ETO (1 << ESAI_ECR_ETO_SHIFT) | ||
62 | #define ESAI_ECR_ERI_SHIFT 17 | ||
63 | #define ESAI_ECR_ERI_MASK (1 << ESAI_ECR_ERI_SHIFT) | ||
64 | #define ESAI_ECR_ERI (1 << ESAI_ECR_ERI_SHIFT) | ||
65 | #define ESAI_ECR_ERO_SHIFT 16 | ||
66 | #define ESAI_ECR_ERO_MASK (1 << ESAI_ECR_ERO_SHIFT) | ||
67 | #define ESAI_ECR_ERO (1 << ESAI_ECR_ERO_SHIFT) | ||
68 | #define ESAI_ECR_ERST_SHIFT 1 | ||
69 | #define ESAI_ECR_ERST_MASK (1 << ESAI_ECR_ERST_SHIFT) | ||
70 | #define ESAI_ECR_ERST (1 << ESAI_ECR_ERST_SHIFT) | ||
71 | #define ESAI_ECR_ESAIEN_SHIFT 0 | ||
72 | #define ESAI_ECR_ESAIEN_MASK (1 << ESAI_ECR_ESAIEN_SHIFT) | ||
73 | #define ESAI_ECR_ESAIEN (1 << ESAI_ECR_ESAIEN_SHIFT) | ||
74 | |||
75 | /* ESAI Status Register -- REG_ESAI_ESR 0xC */ | ||
76 | #define ESAI_ESR_TINIT_SHIFT 10 | ||
77 | #define ESAI_ESR_TINIT_MASK (1 << ESAI_ESR_TINIT_SHIFT) | ||
78 | #define ESAI_ESR_TINIT (1 << ESAI_ESR_TINIT_SHIFT) | ||
79 | #define ESAI_ESR_RFF_SHIFT 9 | ||
80 | #define ESAI_ESR_RFF_MASK (1 << ESAI_ESR_RFF_SHIFT) | ||
81 | #define ESAI_ESR_RFF (1 << ESAI_ESR_RFF_SHIFT) | ||
82 | #define ESAI_ESR_TFE_SHIFT 8 | ||
83 | #define ESAI_ESR_TFE_MASK (1 << ESAI_ESR_TFE_SHIFT) | ||
84 | #define ESAI_ESR_TFE (1 << ESAI_ESR_TFE_SHIFT) | ||
85 | #define ESAI_ESR_TLS_SHIFT 7 | ||
86 | #define ESAI_ESR_TLS_MASK (1 << ESAI_ESR_TLS_SHIFT) | ||
87 | #define ESAI_ESR_TLS (1 << ESAI_ESR_TLS_SHIFT) | ||
88 | #define ESAI_ESR_TDE_SHIFT 6 | ||
89 | #define ESAI_ESR_TDE_MASK (1 << ESAI_ESR_TDE_SHIFT) | ||
90 | #define ESAI_ESR_TDE (1 << ESAI_ESR_TDE_SHIFT) | ||
91 | #define ESAI_ESR_TED_SHIFT 5 | ||
92 | #define ESAI_ESR_TED_MASK (1 << ESAI_ESR_TED_SHIFT) | ||
93 | #define ESAI_ESR_TED (1 << ESAI_ESR_TED_SHIFT) | ||
94 | #define ESAI_ESR_TD_SHIFT 4 | ||
95 | #define ESAI_ESR_TD_MASK (1 << ESAI_ESR_TD_SHIFT) | ||
96 | #define ESAI_ESR_TD (1 << ESAI_ESR_TD_SHIFT) | ||
97 | #define ESAI_ESR_RLS_SHIFT 3 | ||
98 | #define ESAI_ESR_RLS_MASK (1 << ESAI_ESR_RLS_SHIFT) | ||
99 | #define ESAI_ESR_RLS (1 << ESAI_ESR_RLS_SHIFT) | ||
100 | #define ESAI_ESR_RDE_SHIFT 2 | ||
101 | #define ESAI_ESR_RDE_MASK (1 << ESAI_ESR_RDE_SHIFT) | ||
102 | #define ESAI_ESR_RDE (1 << ESAI_ESR_RDE_SHIFT) | ||
103 | #define ESAI_ESR_RED_SHIFT 1 | ||
104 | #define ESAI_ESR_RED_MASK (1 << ESAI_ESR_RED_SHIFT) | ||
105 | #define ESAI_ESR_RED (1 << ESAI_ESR_RED_SHIFT) | ||
106 | #define ESAI_ESR_RD_SHIFT 0 | ||
107 | #define ESAI_ESR_RD_MASK (1 << ESAI_ESR_RD_SHIFT) | ||
108 | #define ESAI_ESR_RD (1 << ESAI_ESR_RD_SHIFT) | ||
109 | |||
110 | /* | ||
111 | * Transmit FIFO Configuration Register -- REG_ESAI_TFCR 0x10 | ||
112 | * Receive FIFO Configuration Register -- REG_ESAI_RFCR 0x18 | ||
113 | */ | ||
114 | #define ESAI_xFCR_TIEN_SHIFT 19 | ||
115 | #define ESAI_xFCR_TIEN_MASK (1 << ESAI_xFCR_TIEN_SHIFT) | ||
116 | #define ESAI_xFCR_TIEN (1 << ESAI_xFCR_TIEN_SHIFT) | ||
117 | #define ESAI_xFCR_REXT_SHIFT 19 | ||
118 | #define ESAI_xFCR_REXT_MASK (1 << ESAI_xFCR_REXT_SHIFT) | ||
119 | #define ESAI_xFCR_REXT (1 << ESAI_xFCR_REXT_SHIFT) | ||
120 | #define ESAI_xFCR_xWA_SHIFT 16 | ||
121 | #define ESAI_xFCR_xWA_WIDTH 3 | ||
122 | #define ESAI_xFCR_xWA_MASK (((1 << ESAI_xFCR_xWA_WIDTH) - 1) << ESAI_xFCR_xWA_SHIFT) | ||
123 | #define ESAI_xFCR_xWA(v) (((8 - ((v) >> 2)) << ESAI_xFCR_xWA_SHIFT) & ESAI_xFCR_xWA_MASK) | ||
124 | #define ESAI_xFCR_xFWM_SHIFT 8 | ||
125 | #define ESAI_xFCR_xFWM_WIDTH 8 | ||
126 | #define ESAI_xFCR_xFWM_MASK (((1 << ESAI_xFCR_xFWM_WIDTH) - 1) << ESAI_xFCR_xFWM_SHIFT) | ||
127 | #define ESAI_xFCR_xFWM(v) ((((v) - 1) << ESAI_xFCR_xFWM_SHIFT) & ESAI_xFCR_xFWM_MASK) | ||
128 | #define ESAI_xFCR_xE_SHIFT 2 | ||
129 | #define ESAI_xFCR_TE_WIDTH 6 | ||
130 | #define ESAI_xFCR_RE_WIDTH 4 | ||
131 | #define ESAI_xFCR_TE_MASK (((1 << ESAI_xFCR_TE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT) | ||
132 | #define ESAI_xFCR_RE_MASK (((1 << ESAI_xFCR_RE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT) | ||
133 | #define ESAI_xFCR_TE(x) ((ESAI_xFCR_TE_MASK >> (ESAI_xFCR_TE_WIDTH - ((x + 1) >> 1))) & ESAI_xFCR_TE_MASK) | ||
134 | #define ESAI_xFCR_RE(x) ((ESAI_xFCR_RE_MASK >> (ESAI_xFCR_RE_WIDTH - ((x + 1) >> 1))) & ESAI_xFCR_RE_MASK) | ||
135 | #define ESAI_xFCR_xFR_SHIFT 1 | ||
136 | #define ESAI_xFCR_xFR_MASK (1 << ESAI_xFCR_xFR_SHIFT) | ||
137 | #define ESAI_xFCR_xFR (1 << ESAI_xFCR_xFR_SHIFT) | ||
138 | #define ESAI_xFCR_xFEN_SHIFT 0 | ||
139 | #define ESAI_xFCR_xFEN_MASK (1 << ESAI_xFCR_xFEN_SHIFT) | ||
140 | #define ESAI_xFCR_xFEN (1 << ESAI_xFCR_xFEN_SHIFT) | ||
141 | |||
142 | /* | ||
143 | * Transmit FIFO Status Register -- REG_ESAI_TFSR 0x14 | ||
144 | * Receive FIFO Status Register --REG_ESAI_RFSR 0x1C | ||
145 | */ | ||
146 | #define ESAI_xFSR_NTFO_SHIFT 12 | ||
147 | #define ESAI_xFSR_NRFI_SHIFT 12 | ||
148 | #define ESAI_xFSR_NTFI_SHIFT 8 | ||
149 | #define ESAI_xFSR_NRFO_SHIFT 8 | ||
150 | #define ESAI_xFSR_NTFx_WIDTH 3 | ||
151 | #define ESAI_xFSR_NRFx_WIDTH 2 | ||
152 | #define ESAI_xFSR_NTFO_MASK (((1 << ESAI_xFSR_NTFx_WIDTH) - 1) << ESAI_xFSR_NTFO_SHIFT) | ||
153 | #define ESAI_xFSR_NTFI_MASK (((1 << ESAI_xFSR_NTFx_WIDTH) - 1) << ESAI_xFSR_NTFI_SHIFT) | ||
154 | #define ESAI_xFSR_NRFO_MASK (((1 << ESAI_xFSR_NRFx_WIDTH) - 1) << ESAI_xFSR_NRFO_SHIFT) | ||
155 | #define ESAI_xFSR_NRFI_MASK (((1 << ESAI_xFSR_NRFx_WIDTH) - 1) << ESAI_xFSR_NRFI_SHIFT) | ||
156 | #define ESAI_xFSR_xFCNT_SHIFT 0 | ||
157 | #define ESAI_xFSR_xFCNT_WIDTH 8 | ||
158 | #define ESAI_xFSR_xFCNT_MASK (((1 << ESAI_xFSR_xFCNT_WIDTH) - 1) << ESAI_xFSR_xFCNT_SHIFT) | ||
159 | |||
160 | /* ESAI Transmit Slot Register -- REG_ESAI_TSR 0x98 */ | ||
161 | #define ESAI_TSR_SHIFT 0 | ||
162 | #define ESAI_TSR_WIDTH 24 | ||
163 | #define ESAI_TSR_MASK (((1 << ESAI_TSR_WIDTH) - 1) << ESAI_TSR_SHIFT) | ||
164 | |||
165 | /* Serial Audio Interface Status Register -- REG_ESAI_SAISR 0xCC */ | ||
166 | #define ESAI_SAISR_TODFE_SHIFT 17 | ||
167 | #define ESAI_SAISR_TODFE_MASK (1 << ESAI_SAISR_TODFE_SHIFT) | ||
168 | #define ESAI_SAISR_TODFE (1 << ESAI_SAISR_TODFE_SHIFT) | ||
169 | #define ESAI_SAISR_TEDE_SHIFT 16 | ||
170 | #define ESAI_SAISR_TEDE_MASK (1 << ESAI_SAISR_TEDE_SHIFT) | ||
171 | #define ESAI_SAISR_TEDE (1 << ESAI_SAISR_TEDE_SHIFT) | ||
172 | #define ESAI_SAISR_TDE_SHIFT 15 | ||
173 | #define ESAI_SAISR_TDE_MASK (1 << ESAI_SAISR_TDE_SHIFT) | ||
174 | #define ESAI_SAISR_TDE (1 << ESAI_SAISR_TDE_SHIFT) | ||
175 | #define ESAI_SAISR_TUE_SHIFT 14 | ||
176 | #define ESAI_SAISR_TUE_MASK (1 << ESAI_SAISR_TUE_SHIFT) | ||
177 | #define ESAI_SAISR_TUE (1 << ESAI_SAISR_TUE_SHIFT) | ||
178 | #define ESAI_SAISR_TFS_SHIFT 13 | ||
179 | #define ESAI_SAISR_TFS_MASK (1 << ESAI_SAISR_TFS_SHIFT) | ||
180 | #define ESAI_SAISR_TFS (1 << ESAI_SAISR_TFS_SHIFT) | ||
181 | #define ESAI_SAISR_RODF_SHIFT 10 | ||
182 | #define ESAI_SAISR_RODF_MASK (1 << ESAI_SAISR_RODF_SHIFT) | ||
183 | #define ESAI_SAISR_RODF (1 << ESAI_SAISR_RODF_SHIFT) | ||
184 | #define ESAI_SAISR_REDF_SHIFT 9 | ||
185 | #define ESAI_SAISR_REDF_MASK (1 << ESAI_SAISR_REDF_SHIFT) | ||
186 | #define ESAI_SAISR_REDF (1 << ESAI_SAISR_REDF_SHIFT) | ||
187 | #define ESAI_SAISR_RDF_SHIFT 8 | ||
188 | #define ESAI_SAISR_RDF_MASK (1 << ESAI_SAISR_RDF_SHIFT) | ||
189 | #define ESAI_SAISR_RDF (1 << ESAI_SAISR_RDF_SHIFT) | ||
190 | #define ESAI_SAISR_ROE_SHIFT 7 | ||
191 | #define ESAI_SAISR_ROE_MASK (1 << ESAI_SAISR_ROE_SHIFT) | ||
192 | #define ESAI_SAISR_ROE (1 << ESAI_SAISR_ROE_SHIFT) | ||
193 | #define ESAI_SAISR_RFS_SHIFT 6 | ||
194 | #define ESAI_SAISR_RFS_MASK (1 << ESAI_SAISR_RFS_SHIFT) | ||
195 | #define ESAI_SAISR_RFS (1 << ESAI_SAISR_RFS_SHIFT) | ||
196 | #define ESAI_SAISR_IF2_SHIFT 2 | ||
197 | #define ESAI_SAISR_IF2_MASK (1 << ESAI_SAISR_IF2_SHIFT) | ||
198 | #define ESAI_SAISR_IF2 (1 << ESAI_SAISR_IF2_SHIFT) | ||
199 | #define ESAI_SAISR_IF1_SHIFT 1 | ||
200 | #define ESAI_SAISR_IF1_MASK (1 << ESAI_SAISR_IF1_SHIFT) | ||
201 | #define ESAI_SAISR_IF1 (1 << ESAI_SAISR_IF1_SHIFT) | ||
202 | #define ESAI_SAISR_IF0_SHIFT 0 | ||
203 | #define ESAI_SAISR_IF0_MASK (1 << ESAI_SAISR_IF0_SHIFT) | ||
204 | #define ESAI_SAISR_IF0 (1 << ESAI_SAISR_IF0_SHIFT) | ||
205 | |||
206 | /* Serial Audio Interface Control Register -- REG_ESAI_SAICR 0xD0 */ | ||
207 | #define ESAI_SAICR_ALC_SHIFT 8 | ||
208 | #define ESAI_SAICR_ALC_MASK (1 << ESAI_SAICR_ALC_SHIFT) | ||
209 | #define ESAI_SAICR_ALC (1 << ESAI_SAICR_ALC_SHIFT) | ||
210 | #define ESAI_SAICR_TEBE_SHIFT 7 | ||
211 | #define ESAI_SAICR_TEBE_MASK (1 << ESAI_SAICR_TEBE_SHIFT) | ||
212 | #define ESAI_SAICR_TEBE (1 << ESAI_SAICR_TEBE_SHIFT) | ||
213 | #define ESAI_SAICR_SYNC_SHIFT 6 | ||
214 | #define ESAI_SAICR_SYNC_MASK (1 << ESAI_SAICR_SYNC_SHIFT) | ||
215 | #define ESAI_SAICR_SYNC (1 << ESAI_SAICR_SYNC_SHIFT) | ||
216 | #define ESAI_SAICR_OF2_SHIFT 2 | ||
217 | #define ESAI_SAICR_OF2_MASK (1 << ESAI_SAICR_OF2_SHIFT) | ||
218 | #define ESAI_SAICR_OF2 (1 << ESAI_SAICR_OF2_SHIFT) | ||
219 | #define ESAI_SAICR_OF1_SHIFT 1 | ||
220 | #define ESAI_SAICR_OF1_MASK (1 << ESAI_SAICR_OF1_SHIFT) | ||
221 | #define ESAI_SAICR_OF1 (1 << ESAI_SAICR_OF1_SHIFT) | ||
222 | #define ESAI_SAICR_OF0_SHIFT 0 | ||
223 | #define ESAI_SAICR_OF0_MASK (1 << ESAI_SAICR_OF0_SHIFT) | ||
224 | #define ESAI_SAICR_OF0 (1 << ESAI_SAICR_OF0_SHIFT) | ||
225 | |||
226 | /* | ||
227 | * Transmit Control Register -- REG_ESAI_TCR 0xD4 | ||
228 | * Receive Control Register -- REG_ESAI_RCR 0xDC | ||
229 | */ | ||
230 | #define ESAI_xCR_xLIE_SHIFT 23 | ||
231 | #define ESAI_xCR_xLIE_MASK (1 << ESAI_xCR_xLIE_SHIFT) | ||
232 | #define ESAI_xCR_xLIE (1 << ESAI_xCR_xLIE_SHIFT) | ||
233 | #define ESAI_xCR_xIE_SHIFT 22 | ||
234 | #define ESAI_xCR_xIE_MASK (1 << ESAI_xCR_xIE_SHIFT) | ||
235 | #define ESAI_xCR_xIE (1 << ESAI_xCR_xIE_SHIFT) | ||
236 | #define ESAI_xCR_xEDIE_SHIFT 21 | ||
237 | #define ESAI_xCR_xEDIE_MASK (1 << ESAI_xCR_xEDIE_SHIFT) | ||
238 | #define ESAI_xCR_xEDIE (1 << ESAI_xCR_xEDIE_SHIFT) | ||
239 | #define ESAI_xCR_xEIE_SHIFT 20 | ||
240 | #define ESAI_xCR_xEIE_MASK (1 << ESAI_xCR_xEIE_SHIFT) | ||
241 | #define ESAI_xCR_xEIE (1 << ESAI_xCR_xEIE_SHIFT) | ||
242 | #define ESAI_xCR_xPR_SHIFT 19 | ||
243 | #define ESAI_xCR_xPR_MASK (1 << ESAI_xCR_xPR_SHIFT) | ||
244 | #define ESAI_xCR_xPR (1 << ESAI_xCR_xPR_SHIFT) | ||
245 | #define ESAI_xCR_PADC_SHIFT 17 | ||
246 | #define ESAI_xCR_PADC_MASK (1 << ESAI_xCR_PADC_SHIFT) | ||
247 | #define ESAI_xCR_PADC (1 << ESAI_xCR_PADC_SHIFT) | ||
248 | #define ESAI_xCR_xFSR_SHIFT 16 | ||
249 | #define ESAI_xCR_xFSR_MASK (1 << ESAI_xCR_xFSR_SHIFT) | ||
250 | #define ESAI_xCR_xFSR (1 << ESAI_xCR_xFSR_SHIFT) | ||
251 | #define ESAI_xCR_xFSL_SHIFT 15 | ||
252 | #define ESAI_xCR_xFSL_MASK (1 << ESAI_xCR_xFSL_SHIFT) | ||
253 | #define ESAI_xCR_xFSL (1 << ESAI_xCR_xFSL_SHIFT) | ||
254 | #define ESAI_xCR_xSWS_SHIFT 10 | ||
255 | #define ESAI_xCR_xSWS_WIDTH 5 | ||
256 | #define ESAI_xCR_xSWS_MASK (((1 << ESAI_xCR_xSWS_WIDTH) - 1) << ESAI_xCR_xSWS_SHIFT) | ||
257 | #define ESAI_xCR_xSWS(s, w) ((w < 24 ? (s - w + ((w - 8) >> 2)) : (s < 32 ? 0x1e : 0x1f)) << ESAI_xCR_xSWS_SHIFT) | ||
258 | #define ESAI_xCR_xMOD_SHIFT 8 | ||
259 | #define ESAI_xCR_xMOD_WIDTH 2 | ||
260 | #define ESAI_xCR_xMOD_MASK (((1 << ESAI_xCR_xMOD_WIDTH) - 1) << ESAI_xCR_xMOD_SHIFT) | ||
261 | #define ESAI_xCR_xMOD_ONDEMAND (0x1 << ESAI_xCR_xMOD_SHIFT) | ||
262 | #define ESAI_xCR_xMOD_NETWORK (0x1 << ESAI_xCR_xMOD_SHIFT) | ||
263 | #define ESAI_xCR_xMOD_AC97 (0x3 << ESAI_xCR_xMOD_SHIFT) | ||
264 | #define ESAI_xCR_xWA_SHIFT 7 | ||
265 | #define ESAI_xCR_xWA_MASK (1 << ESAI_xCR_xWA_SHIFT) | ||
266 | #define ESAI_xCR_xWA (1 << ESAI_xCR_xWA_SHIFT) | ||
267 | #define ESAI_xCR_xSHFD_SHIFT 6 | ||
268 | #define ESAI_xCR_xSHFD_MASK (1 << ESAI_xCR_xSHFD_SHIFT) | ||
269 | #define ESAI_xCR_xSHFD (1 << ESAI_xCR_xSHFD_SHIFT) | ||
270 | #define ESAI_xCR_xE_SHIFT 0 | ||
271 | #define ESAI_xCR_TE_WIDTH 6 | ||
272 | #define ESAI_xCR_RE_WIDTH 4 | ||
273 | #define ESAI_xCR_TE_MASK (((1 << ESAI_xCR_TE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT) | ||
274 | #define ESAI_xCR_RE_MASK (((1 << ESAI_xCR_RE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT) | ||
275 | #define ESAI_xCR_TE(x) ((ESAI_xCR_TE_MASK >> (ESAI_xCR_TE_WIDTH - ((x + 1) >> 1))) & ESAI_xCR_TE_MASK) | ||
276 | #define ESAI_xCR_RE(x) ((ESAI_xCR_RE_MASK >> (ESAI_xCR_RE_WIDTH - ((x + 1) >> 1))) & ESAI_xCR_RE_MASK) | ||
277 | |||
278 | /* | ||
279 | * Transmit Clock Control Register -- REG_ESAI_TCCR 0xD8 | ||
280 | * Receive Clock Control Register -- REG_ESAI_RCCR 0xE0 | ||
281 | */ | ||
282 | #define ESAI_xCCR_xHCKD_SHIFT 23 | ||
283 | #define ESAI_xCCR_xHCKD_MASK (1 << ESAI_xCCR_xHCKD_SHIFT) | ||
284 | #define ESAI_xCCR_xHCKD (1 << ESAI_xCCR_xHCKD_SHIFT) | ||
285 | #define ESAI_xCCR_xFSD_SHIFT 22 | ||
286 | #define ESAI_xCCR_xFSD_MASK (1 << ESAI_xCCR_xFSD_SHIFT) | ||
287 | #define ESAI_xCCR_xFSD (1 << ESAI_xCCR_xFSD_SHIFT) | ||
288 | #define ESAI_xCCR_xCKD_SHIFT 21 | ||
289 | #define ESAI_xCCR_xCKD_MASK (1 << ESAI_xCCR_xCKD_SHIFT) | ||
290 | #define ESAI_xCCR_xCKD (1 << ESAI_xCCR_xCKD_SHIFT) | ||
291 | #define ESAI_xCCR_xHCKP_SHIFT 20 | ||
292 | #define ESAI_xCCR_xHCKP_MASK (1 << ESAI_xCCR_xHCKP_SHIFT) | ||
293 | #define ESAI_xCCR_xHCKP (1 << ESAI_xCCR_xHCKP_SHIFT) | ||
294 | #define ESAI_xCCR_xFSP_SHIFT 19 | ||
295 | #define ESAI_xCCR_xFSP_MASK (1 << ESAI_xCCR_xFSP_SHIFT) | ||
296 | #define ESAI_xCCR_xFSP (1 << ESAI_xCCR_xFSP_SHIFT) | ||
297 | #define ESAI_xCCR_xCKP_SHIFT 18 | ||
298 | #define ESAI_xCCR_xCKP_MASK (1 << ESAI_xCCR_xCKP_SHIFT) | ||
299 | #define ESAI_xCCR_xCKP (1 << ESAI_xCCR_xCKP_SHIFT) | ||
300 | #define ESAI_xCCR_xFP_SHIFT 14 | ||
301 | #define ESAI_xCCR_xFP_WIDTH 4 | ||
302 | #define ESAI_xCCR_xFP_MASK (((1 << ESAI_xCCR_xFP_WIDTH) - 1) << ESAI_xCCR_xFP_SHIFT) | ||
303 | #define ESAI_xCCR_xFP(v) ((((v) - 1) << ESAI_xCCR_xFP_SHIFT) & ESAI_xCCR_xFP_MASK) | ||
304 | #define ESAI_xCCR_xDC_SHIFT 9 | ||
305 | #define ESAI_xCCR_xDC_WIDTH 4 | ||
306 | #define ESAI_xCCR_xDC_MASK (((1 << ESAI_xCCR_xDC_WIDTH) - 1) << ESAI_xCCR_xDC_SHIFT) | ||
307 | #define ESAI_xCCR_xDC(v) ((((v) - 1) << ESAI_xCCR_xDC_SHIFT) & ESAI_xCCR_xDC_MASK) | ||
308 | #define ESAI_xCCR_xPSR_SHIFT 8 | ||
309 | #define ESAI_xCCR_xPSR_MASK (1 << ESAI_xCCR_xPSR_SHIFT) | ||
310 | #define ESAI_xCCR_xPSR_BYPASS (1 << ESAI_xCCR_xPSR_SHIFT) | ||
311 | #define ESAI_xCCR_xPSR_DIV8 (0 << ESAI_xCCR_xPSR_SHIFT) | ||
312 | #define ESAI_xCCR_xPM_SHIFT 0 | ||
313 | #define ESAI_xCCR_xPM_WIDTH 8 | ||
314 | #define ESAI_xCCR_xPM_MASK (((1 << ESAI_xCCR_xPM_WIDTH) - 1) << ESAI_xCCR_xPM_SHIFT) | ||
315 | #define ESAI_xCCR_xPM(v) ((((v) - 1) << ESAI_xCCR_xPM_SHIFT) & ESAI_xCCR_xPM_MASK) | ||
316 | |||
317 | /* Transmit Slot Mask Register A/B -- REG_ESAI_TSMA/B 0xE4 ~ 0xF0 */ | ||
318 | #define ESAI_xSMA_xS_SHIFT 0 | ||
319 | #define ESAI_xSMA_xS_WIDTH 16 | ||
320 | #define ESAI_xSMA_xS_MASK (((1 << ESAI_xSMA_xS_WIDTH) - 1) << ESAI_xSMA_xS_SHIFT) | ||
321 | #define ESAI_xSMA_xS(v) ((v) & ESAI_xSMA_xS_MASK) | ||
322 | #define ESAI_xSMB_xS_SHIFT 0 | ||
323 | #define ESAI_xSMB_xS_WIDTH 16 | ||
324 | #define ESAI_xSMB_xS_MASK (((1 << ESAI_xSMB_xS_WIDTH) - 1) << ESAI_xSMB_xS_SHIFT) | ||
325 | #define ESAI_xSMB_xS(v) (((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMA_xS_MASK) | ||
326 | |||
327 | /* Port C Direction Register -- REG_ESAI_PRRC 0xF8 */ | ||
328 | #define ESAI_PRRC_PDC_SHIFT 0 | ||
329 | #define ESAI_PRRC_PDC_WIDTH 12 | ||
330 | #define ESAI_PRRC_PDC_MASK (((1 << ESAI_PRRC_PDC_WIDTH) - 1) << ESAI_PRRC_PDC_SHIFT) | ||
331 | #define ESAI_PRRC_PDC(v) ((v) & ESAI_PRRC_PDC_MASK) | ||
332 | |||
333 | /* Port C Control Register -- REG_ESAI_PCRC 0xFC */ | ||
334 | #define ESAI_PCRC_PC_SHIFT 0 | ||
335 | #define ESAI_PCRC_PC_WIDTH 12 | ||
336 | #define ESAI_PCRC_PC_MASK (((1 << ESAI_PCRC_PC_WIDTH) - 1) << ESAI_PCRC_PC_SHIFT) | ||
337 | #define ESAI_PCRC_PC(v) ((v) & ESAI_PCRC_PC_MASK) | ||
338 | |||
339 | #define ESAI_GPIO 0xfff | ||
340 | |||
341 | /* ESAI clock source */ | ||
342 | #define ESAI_HCKT_FSYS 0 | ||
343 | #define ESAI_HCKT_EXTAL 1 | ||
344 | #define ESAI_HCKR_FSYS 2 | ||
345 | #define ESAI_HCKR_EXTAL 3 | ||
346 | |||
347 | /* ESAI clock divider */ | ||
348 | #define ESAI_TX_DIV_PSR 0 | ||
349 | #define ESAI_TX_DIV_PM 1 | ||
350 | #define ESAI_TX_DIV_FP 2 | ||
351 | #define ESAI_RX_DIV_PSR 3 | ||
352 | #define ESAI_RX_DIV_PM 4 | ||
353 | #define ESAI_RX_DIV_FP 5 | ||
354 | #endif /* _FSL_ESAI_DAI_H */ | ||
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c new file mode 100644 index 000000000000..cdd3fa830704 --- /dev/null +++ b/sound/soc/fsl/fsl_sai.c | |||
@@ -0,0 +1,459 @@ | |||
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 | val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK; | ||
66 | |||
67 | switch (clk_id) { | ||
68 | case FSL_SAI_CLK_BUS: | ||
69 | val_cr2 |= FSL_SAI_CR2_MSEL_BUS; | ||
70 | break; | ||
71 | case FSL_SAI_CLK_MAST1: | ||
72 | val_cr2 |= FSL_SAI_CR2_MSEL_MCLK1; | ||
73 | break; | ||
74 | case FSL_SAI_CLK_MAST2: | ||
75 | val_cr2 |= FSL_SAI_CR2_MSEL_MCLK2; | ||
76 | break; | ||
77 | case FSL_SAI_CLK_MAST3: | ||
78 | val_cr2 |= FSL_SAI_CR2_MSEL_MCLK3; | ||
79 | break; | ||
80 | default: | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | |||
84 | sai_writel(sai, val_cr2, sai->base + reg_cr2); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | ||
90 | int clk_id, unsigned int freq, int dir) | ||
91 | { | ||
92 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
93 | int ret; | ||
94 | |||
95 | if (dir == SND_SOC_CLOCK_IN) | ||
96 | return 0; | ||
97 | |||
98 | ret = clk_prepare_enable(sai->clk); | ||
99 | if (ret) | ||
100 | return ret; | ||
101 | |||
102 | ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, | ||
103 | FSL_FMT_TRANSMITTER); | ||
104 | if (ret) { | ||
105 | dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret); | ||
106 | goto err_clk; | ||
107 | } | ||
108 | |||
109 | ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, | ||
110 | FSL_FMT_RECEIVER); | ||
111 | if (ret) { | ||
112 | dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret); | ||
113 | goto err_clk; | ||
114 | } | ||
115 | |||
116 | err_clk: | ||
117 | clk_disable_unprepare(sai->clk); | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, | ||
123 | unsigned int fmt, int fsl_dir) | ||
124 | { | ||
125 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
126 | u32 val_cr2, val_cr4, reg_cr2, reg_cr4; | ||
127 | |||
128 | if (fsl_dir == FSL_FMT_TRANSMITTER) { | ||
129 | reg_cr2 = FSL_SAI_TCR2; | ||
130 | reg_cr4 = FSL_SAI_TCR4; | ||
131 | } else { | ||
132 | reg_cr2 = FSL_SAI_RCR2; | ||
133 | reg_cr4 = FSL_SAI_RCR4; | ||
134 | } | ||
135 | |||
136 | val_cr2 = sai_readl(sai, sai->base + reg_cr2); | ||
137 | val_cr4 = sai_readl(sai, sai->base + reg_cr4); | ||
138 | |||
139 | if (sai->big_endian_data) | ||
140 | val_cr4 &= ~FSL_SAI_CR4_MF; | ||
141 | else | ||
142 | val_cr4 |= FSL_SAI_CR4_MF; | ||
143 | |||
144 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
145 | case SND_SOC_DAIFMT_I2S: | ||
146 | val_cr4 |= FSL_SAI_CR4_FSE; | ||
147 | break; | ||
148 | default: | ||
149 | return -EINVAL; | ||
150 | } | ||
151 | |||
152 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
153 | case SND_SOC_DAIFMT_IB_IF: | ||
154 | val_cr4 |= FSL_SAI_CR4_FSP; | ||
155 | val_cr2 &= ~FSL_SAI_CR2_BCP; | ||
156 | break; | ||
157 | case SND_SOC_DAIFMT_IB_NF: | ||
158 | val_cr4 &= ~FSL_SAI_CR4_FSP; | ||
159 | val_cr2 &= ~FSL_SAI_CR2_BCP; | ||
160 | break; | ||
161 | case SND_SOC_DAIFMT_NB_IF: | ||
162 | val_cr4 |= FSL_SAI_CR4_FSP; | ||
163 | val_cr2 |= FSL_SAI_CR2_BCP; | ||
164 | break; | ||
165 | case SND_SOC_DAIFMT_NB_NF: | ||
166 | val_cr4 &= ~FSL_SAI_CR4_FSP; | ||
167 | val_cr2 |= FSL_SAI_CR2_BCP; | ||
168 | break; | ||
169 | default: | ||
170 | return -EINVAL; | ||
171 | } | ||
172 | |||
173 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
174 | case SND_SOC_DAIFMT_CBS_CFS: | ||
175 | val_cr2 |= FSL_SAI_CR2_BCD_MSTR; | ||
176 | val_cr4 |= FSL_SAI_CR4_FSD_MSTR; | ||
177 | break; | ||
178 | case SND_SOC_DAIFMT_CBM_CFM: | ||
179 | val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR; | ||
180 | val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR; | ||
181 | break; | ||
182 | default: | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | |||
186 | sai_writel(sai, val_cr2, sai->base + reg_cr2); | ||
187 | sai_writel(sai, val_cr4, sai->base + reg_cr4); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | ||
193 | { | ||
194 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
195 | int ret; | ||
196 | |||
197 | ret = clk_prepare_enable(sai->clk); | ||
198 | if (ret) | ||
199 | return ret; | ||
200 | |||
201 | ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER); | ||
202 | if (ret) { | ||
203 | dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret); | ||
204 | goto err_clk; | ||
205 | } | ||
206 | |||
207 | ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER); | ||
208 | if (ret) { | ||
209 | dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret); | ||
210 | goto err_clk; | ||
211 | } | ||
212 | |||
213 | err_clk: | ||
214 | clk_disable_unprepare(sai->clk); | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | static int fsl_sai_hw_params(struct snd_pcm_substream *substream, | ||
220 | struct snd_pcm_hw_params *params, | ||
221 | struct snd_soc_dai *cpu_dai) | ||
222 | { | ||
223 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
224 | u32 val_cr4, val_cr5, val_mr, reg_cr4, reg_cr5, reg_mr; | ||
225 | unsigned int channels = params_channels(params); | ||
226 | u32 word_width = snd_pcm_format_width(params_format(params)); | ||
227 | |||
228 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
229 | reg_cr4 = FSL_SAI_TCR4; | ||
230 | reg_cr5 = FSL_SAI_TCR5; | ||
231 | reg_mr = FSL_SAI_TMR; | ||
232 | } else { | ||
233 | reg_cr4 = FSL_SAI_RCR4; | ||
234 | reg_cr5 = FSL_SAI_RCR5; | ||
235 | reg_mr = FSL_SAI_RMR; | ||
236 | } | ||
237 | |||
238 | val_cr4 = sai_readl(sai, sai->base + reg_cr4); | ||
239 | val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK; | ||
240 | val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK; | ||
241 | |||
242 | val_cr5 = sai_readl(sai, sai->base + reg_cr5); | ||
243 | val_cr5 &= ~FSL_SAI_CR5_WNW_MASK; | ||
244 | val_cr5 &= ~FSL_SAI_CR5_W0W_MASK; | ||
245 | val_cr5 &= ~FSL_SAI_CR5_FBT_MASK; | ||
246 | |||
247 | val_cr4 |= FSL_SAI_CR4_SYWD(word_width); | ||
248 | val_cr5 |= FSL_SAI_CR5_WNW(word_width); | ||
249 | val_cr5 |= FSL_SAI_CR5_W0W(word_width); | ||
250 | |||
251 | val_cr5 &= ~FSL_SAI_CR5_FBT_MASK; | ||
252 | if (sai->big_endian_data) | ||
253 | val_cr5 |= FSL_SAI_CR5_FBT(0); | ||
254 | else | ||
255 | val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1); | ||
256 | |||
257 | val_cr4 |= FSL_SAI_CR4_FRSZ(channels); | ||
258 | val_mr = ~0UL - ((1 << channels) - 1); | ||
259 | |||
260 | sai_writel(sai, val_cr4, sai->base + reg_cr4); | ||
261 | sai_writel(sai, val_cr5, sai->base + reg_cr5); | ||
262 | sai_writel(sai, val_mr, sai->base + reg_mr); | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | ||
268 | struct snd_soc_dai *cpu_dai) | ||
269 | { | ||
270 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
271 | u32 tcsr, rcsr, val_cr2, val_cr3, reg_cr3; | ||
272 | |||
273 | val_cr2 = sai_readl(sai, sai->base + FSL_SAI_TCR2); | ||
274 | val_cr2 &= ~FSL_SAI_CR2_SYNC; | ||
275 | sai_writel(sai, val_cr2, sai->base + FSL_SAI_TCR2); | ||
276 | |||
277 | val_cr2 = sai_readl(sai, sai->base + FSL_SAI_RCR2); | ||
278 | val_cr2 |= FSL_SAI_CR2_SYNC; | ||
279 | sai_writel(sai, val_cr2, sai->base + FSL_SAI_RCR2); | ||
280 | |||
281 | tcsr = sai_readl(sai, sai->base + FSL_SAI_TCSR); | ||
282 | rcsr = sai_readl(sai, sai->base + FSL_SAI_RCSR); | ||
283 | |||
284 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
285 | tcsr |= FSL_SAI_CSR_FRDE; | ||
286 | rcsr &= ~FSL_SAI_CSR_FRDE; | ||
287 | reg_cr3 = FSL_SAI_TCR3; | ||
288 | } else { | ||
289 | rcsr |= FSL_SAI_CSR_FRDE; | ||
290 | tcsr &= ~FSL_SAI_CSR_FRDE; | ||
291 | reg_cr3 = FSL_SAI_RCR3; | ||
292 | } | ||
293 | |||
294 | val_cr3 = sai_readl(sai, sai->base + reg_cr3); | ||
295 | |||
296 | switch (cmd) { | ||
297 | case SNDRV_PCM_TRIGGER_START: | ||
298 | case SNDRV_PCM_TRIGGER_RESUME: | ||
299 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
300 | tcsr |= FSL_SAI_CSR_TERE; | ||
301 | rcsr |= FSL_SAI_CSR_TERE; | ||
302 | val_cr3 |= FSL_SAI_CR3_TRCE; | ||
303 | |||
304 | sai_writel(sai, val_cr3, sai->base + reg_cr3); | ||
305 | sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); | ||
306 | sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); | ||
307 | break; | ||
308 | |||
309 | case SNDRV_PCM_TRIGGER_STOP: | ||
310 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
311 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
312 | if (!(cpu_dai->playback_active || cpu_dai->capture_active)) { | ||
313 | tcsr &= ~FSL_SAI_CSR_TERE; | ||
314 | rcsr &= ~FSL_SAI_CSR_TERE; | ||
315 | } | ||
316 | |||
317 | val_cr3 &= ~FSL_SAI_CR3_TRCE; | ||
318 | |||
319 | sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); | ||
320 | sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); | ||
321 | sai_writel(sai, val_cr3, sai->base + reg_cr3); | ||
322 | break; | ||
323 | default: | ||
324 | return -EINVAL; | ||
325 | } | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static int fsl_sai_startup(struct snd_pcm_substream *substream, | ||
331 | struct snd_soc_dai *cpu_dai) | ||
332 | { | ||
333 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
334 | |||
335 | return clk_prepare_enable(sai->clk); | ||
336 | } | ||
337 | |||
338 | static void fsl_sai_shutdown(struct snd_pcm_substream *substream, | ||
339 | struct snd_soc_dai *cpu_dai) | ||
340 | { | ||
341 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
342 | |||
343 | clk_disable_unprepare(sai->clk); | ||
344 | } | ||
345 | |||
346 | static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { | ||
347 | .set_sysclk = fsl_sai_set_dai_sysclk, | ||
348 | .set_fmt = fsl_sai_set_dai_fmt, | ||
349 | .hw_params = fsl_sai_hw_params, | ||
350 | .trigger = fsl_sai_trigger, | ||
351 | .startup = fsl_sai_startup, | ||
352 | .shutdown = fsl_sai_shutdown, | ||
353 | }; | ||
354 | |||
355 | static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) | ||
356 | { | ||
357 | struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); | ||
358 | int ret; | ||
359 | |||
360 | ret = clk_prepare_enable(sai->clk); | ||
361 | if (ret) | ||
362 | return ret; | ||
363 | |||
364 | sai_writel(sai, 0x0, sai->base + FSL_SAI_RCSR); | ||
365 | sai_writel(sai, 0x0, sai->base + FSL_SAI_TCSR); | ||
366 | sai_writel(sai, FSL_SAI_MAXBURST_TX * 2, sai->base + FSL_SAI_TCR1); | ||
367 | sai_writel(sai, FSL_SAI_MAXBURST_RX - 1, sai->base + FSL_SAI_RCR1); | ||
368 | |||
369 | clk_disable_unprepare(sai->clk); | ||
370 | |||
371 | snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, | ||
372 | &sai->dma_params_rx); | ||
373 | |||
374 | snd_soc_dai_set_drvdata(cpu_dai, sai); | ||
375 | |||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static struct snd_soc_dai_driver fsl_sai_dai = { | ||
380 | .probe = fsl_sai_dai_probe, | ||
381 | .playback = { | ||
382 | .channels_min = 1, | ||
383 | .channels_max = 2, | ||
384 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
385 | .formats = FSL_SAI_FORMATS, | ||
386 | }, | ||
387 | .capture = { | ||
388 | .channels_min = 1, | ||
389 | .channels_max = 2, | ||
390 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
391 | .formats = FSL_SAI_FORMATS, | ||
392 | }, | ||
393 | .ops = &fsl_sai_pcm_dai_ops, | ||
394 | }; | ||
395 | |||
396 | static const struct snd_soc_component_driver fsl_component = { | ||
397 | .name = "fsl-sai", | ||
398 | }; | ||
399 | |||
400 | static int fsl_sai_probe(struct platform_device *pdev) | ||
401 | { | ||
402 | struct device_node *np = pdev->dev.of_node; | ||
403 | struct fsl_sai *sai; | ||
404 | struct resource *res; | ||
405 | int ret; | ||
406 | |||
407 | sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); | ||
408 | if (!sai) | ||
409 | return -ENOMEM; | ||
410 | |||
411 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
412 | sai->base = devm_ioremap_resource(&pdev->dev, res); | ||
413 | if (IS_ERR(sai->base)) | ||
414 | return PTR_ERR(sai->base); | ||
415 | |||
416 | sai->clk = devm_clk_get(&pdev->dev, "sai"); | ||
417 | if (IS_ERR(sai->clk)) { | ||
418 | dev_err(&pdev->dev, "Cannot get SAI's clock\n"); | ||
419 | return PTR_ERR(sai->clk); | ||
420 | } | ||
421 | |||
422 | sai->dma_params_rx.addr = res->start + FSL_SAI_RDR; | ||
423 | sai->dma_params_tx.addr = res->start + FSL_SAI_TDR; | ||
424 | sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; | ||
425 | sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; | ||
426 | |||
427 | sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs"); | ||
428 | sai->big_endian_data = of_property_read_bool(np, "big-endian-data"); | ||
429 | |||
430 | platform_set_drvdata(pdev, sai); | ||
431 | |||
432 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, | ||
433 | &fsl_sai_dai, 1); | ||
434 | if (ret) | ||
435 | return ret; | ||
436 | |||
437 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, | ||
438 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE); | ||
439 | } | ||
440 | |||
441 | static const struct of_device_id fsl_sai_ids[] = { | ||
442 | { .compatible = "fsl,vf610-sai", }, | ||
443 | { /* sentinel */ } | ||
444 | }; | ||
445 | |||
446 | static struct platform_driver fsl_sai_driver = { | ||
447 | .probe = fsl_sai_probe, | ||
448 | .driver = { | ||
449 | .name = "fsl-sai", | ||
450 | .owner = THIS_MODULE, | ||
451 | .of_match_table = fsl_sai_ids, | ||
452 | }, | ||
453 | }; | ||
454 | module_platform_driver(fsl_sai_driver); | ||
455 | |||
456 | MODULE_DESCRIPTION("Freescale Soc SAI Interface"); | ||
457 | MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>"); | ||
458 | MODULE_ALIAS("platform:fsl-sai"); | ||
459 | 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..f9090b167ad7 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -35,9 +35,11 @@ | |||
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
37 | #include <linux/clk.h> | 37 | #include <linux/clk.h> |
38 | #include <linux/debugfs.h> | ||
38 | #include <linux/device.h> | 39 | #include <linux/device.h> |
39 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
40 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | #include <linux/spinlock.h> | ||
41 | #include <linux/of_address.h> | 43 | #include <linux/of_address.h> |
42 | #include <linux/of_irq.h> | 44 | #include <linux/of_irq.h> |
43 | #include <linux/of_platform.h> | 45 | #include <linux/of_platform.h> |
@@ -79,8 +81,7 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set) | |||
79 | * ALSA that we support all rates and let the codec driver decide what rates | 81 | * ALSA that we support all rates and let the codec driver decide what rates |
80 | * are really supported. | 82 | * are really supported. |
81 | */ | 83 | */ |
82 | #define FSLSSI_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ | 84 | #define FSLSSI_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS |
83 | SNDRV_PCM_RATE_CONTINUOUS) | ||
84 | 85 | ||
85 | /** | 86 | /** |
86 | * FSLSSI_I2S_FORMATS: audio formats supported by the SSI | 87 | * FSLSSI_I2S_FORMATS: audio formats supported by the SSI |
@@ -106,12 +107,33 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set) | |||
106 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE) | 107 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE) |
107 | #endif | 108 | #endif |
108 | 109 | ||
109 | /* SIER bitflag of interrupts to enable */ | 110 | #define FSLSSI_SIER_DBG_RX_FLAGS (CCSR_SSI_SIER_RFF0_EN | \ |
110 | #define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \ | 111 | CCSR_SSI_SIER_RLS_EN | CCSR_SSI_SIER_RFS_EN | \ |
111 | CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \ | 112 | CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_RFRC_EN) |
112 | CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \ | 113 | #define FSLSSI_SIER_DBG_TX_FLAGS (CCSR_SSI_SIER_TFE0_EN | \ |
113 | CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \ | 114 | CCSR_SSI_SIER_TLS_EN | CCSR_SSI_SIER_TFS_EN | \ |
114 | CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN) | 115 | CCSR_SSI_SIER_TUE0_EN | CCSR_SSI_SIER_TFRC_EN) |
116 | #define FSLSSI_SISR_MASK (FSLSSI_SIER_DBG_RX_FLAGS | FSLSSI_SIER_DBG_TX_FLAGS) | ||
117 | |||
118 | |||
119 | enum fsl_ssi_type { | ||
120 | FSL_SSI_MCP8610, | ||
121 | FSL_SSI_MX21, | ||
122 | FSL_SSI_MX35, | ||
123 | FSL_SSI_MX51, | ||
124 | }; | ||
125 | |||
126 | struct fsl_ssi_reg_val { | ||
127 | u32 sier; | ||
128 | u32 srcr; | ||
129 | u32 stcr; | ||
130 | u32 scr; | ||
131 | }; | ||
132 | |||
133 | struct fsl_ssi_rxtx_reg_val { | ||
134 | struct fsl_ssi_reg_val rx; | ||
135 | struct fsl_ssi_reg_val tx; | ||
136 | }; | ||
115 | 137 | ||
116 | /** | 138 | /** |
117 | * fsl_ssi_private: per-SSI private data | 139 | * fsl_ssi_private: per-SSI private data |
@@ -119,8 +141,6 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set) | |||
119 | * @ssi: pointer to the SSI's registers | 141 | * @ssi: pointer to the SSI's registers |
120 | * @ssi_phys: physical address of the SSI registers | 142 | * @ssi_phys: physical address of the SSI registers |
121 | * @irq: IRQ of this SSI | 143 | * @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 | 144 | * @playback: the number of playback streams opened |
125 | * @capture: the number of capture streams opened | 145 | * @capture: the number of capture streams opened |
126 | * @cpu_dai: the CPU DAI for this device | 146 | * @cpu_dai: the CPU DAI for this device |
@@ -132,23 +152,29 @@ struct fsl_ssi_private { | |||
132 | struct ccsr_ssi __iomem *ssi; | 152 | struct ccsr_ssi __iomem *ssi; |
133 | dma_addr_t ssi_phys; | 153 | dma_addr_t ssi_phys; |
134 | unsigned int irq; | 154 | unsigned int irq; |
135 | struct snd_pcm_substream *first_stream; | ||
136 | struct snd_pcm_substream *second_stream; | ||
137 | unsigned int fifo_depth; | 155 | unsigned int fifo_depth; |
138 | struct snd_soc_dai_driver cpu_dai_drv; | 156 | struct snd_soc_dai_driver cpu_dai_drv; |
139 | struct device_attribute dev_attr; | ||
140 | struct platform_device *pdev; | 157 | struct platform_device *pdev; |
141 | 158 | ||
159 | enum fsl_ssi_type hw_type; | ||
142 | bool new_binding; | 160 | bool new_binding; |
143 | bool ssi_on_imx; | 161 | bool ssi_on_imx; |
144 | bool imx_ac97; | 162 | bool imx_ac97; |
145 | bool use_dma; | 163 | bool use_dma; |
164 | bool baudclk_locked; | ||
165 | bool irq_stats; | ||
166 | bool offline_config; | ||
167 | u8 i2s_mode; | ||
168 | spinlock_t baudclk_lock; | ||
169 | struct clk *baudclk; | ||
146 | struct clk *clk; | 170 | struct clk *clk; |
147 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 171 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
148 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 172 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
149 | struct imx_dma_data filter_data_tx; | 173 | struct imx_dma_data filter_data_tx; |
150 | struct imx_dma_data filter_data_rx; | 174 | struct imx_dma_data filter_data_rx; |
151 | struct imx_pcm_fiq_params fiq_params; | 175 | struct imx_pcm_fiq_params fiq_params; |
176 | /* Register values for rx/tx configuration */ | ||
177 | struct fsl_ssi_rxtx_reg_val rxtx_reg_val; | ||
152 | 178 | ||
153 | struct { | 179 | struct { |
154 | unsigned int rfrc; | 180 | unsigned int rfrc; |
@@ -173,10 +199,21 @@ struct fsl_ssi_private { | |||
173 | unsigned int tfe1; | 199 | unsigned int tfe1; |
174 | unsigned int tfe0; | 200 | unsigned int tfe0; |
175 | } stats; | 201 | } stats; |
202 | struct dentry *dbg_dir; | ||
203 | struct dentry *dbg_stats; | ||
176 | 204 | ||
177 | char name[1]; | 205 | char name[1]; |
178 | }; | 206 | }; |
179 | 207 | ||
208 | static const struct of_device_id fsl_ssi_ids[] = { | ||
209 | { .compatible = "fsl,mpc8610-ssi", .data = (void *) FSL_SSI_MCP8610}, | ||
210 | { .compatible = "fsl,imx51-ssi", .data = (void *) FSL_SSI_MX51}, | ||
211 | { .compatible = "fsl,imx35-ssi", .data = (void *) FSL_SSI_MX35}, | ||
212 | { .compatible = "fsl,imx21-ssi", .data = (void *) FSL_SSI_MX21}, | ||
213 | {} | ||
214 | }; | ||
215 | MODULE_DEVICE_TABLE(of, fsl_ssi_ids); | ||
216 | |||
180 | /** | 217 | /** |
181 | * fsl_ssi_isr: SSI interrupt handler | 218 | * fsl_ssi_isr: SSI interrupt handler |
182 | * | 219 | * |
@@ -195,23 +232,40 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
195 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 232 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
196 | irqreturn_t ret = IRQ_NONE; | 233 | irqreturn_t ret = IRQ_NONE; |
197 | __be32 sisr; | 234 | __be32 sisr; |
198 | __be32 sisr2 = 0; | 235 | __be32 sisr2; |
236 | __be32 sisr_write_mask = 0; | ||
237 | |||
238 | switch (ssi_private->hw_type) { | ||
239 | case FSL_SSI_MX21: | ||
240 | sisr_write_mask = 0; | ||
241 | break; | ||
242 | |||
243 | case FSL_SSI_MCP8610: | ||
244 | case FSL_SSI_MX35: | ||
245 | sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC | | ||
246 | CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 | | ||
247 | CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1; | ||
248 | break; | ||
249 | |||
250 | case FSL_SSI_MX51: | ||
251 | sisr_write_mask = CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 | | ||
252 | CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1; | ||
253 | break; | ||
254 | } | ||
199 | 255 | ||
200 | /* We got an interrupt, so read the status register to see what we | 256 | /* We got an interrupt, so read the status register to see what we |
201 | were interrupted for. We mask it with the Interrupt Enable register | 257 | were interrupted for. We mask it with the Interrupt Enable register |
202 | so that we only check for events that we're interested in. | 258 | so that we only check for events that we're interested in. |
203 | */ | 259 | */ |
204 | sisr = read_ssi(&ssi->sisr) & SIER_FLAGS; | 260 | sisr = read_ssi(&ssi->sisr) & FSLSSI_SISR_MASK; |
205 | 261 | ||
206 | if (sisr & CCSR_SSI_SISR_RFRC) { | 262 | if (sisr & CCSR_SSI_SISR_RFRC) { |
207 | ssi_private->stats.rfrc++; | 263 | ssi_private->stats.rfrc++; |
208 | sisr2 |= CCSR_SSI_SISR_RFRC; | ||
209 | ret = IRQ_HANDLED; | 264 | ret = IRQ_HANDLED; |
210 | } | 265 | } |
211 | 266 | ||
212 | if (sisr & CCSR_SSI_SISR_TFRC) { | 267 | if (sisr & CCSR_SSI_SISR_TFRC) { |
213 | ssi_private->stats.tfrc++; | 268 | ssi_private->stats.tfrc++; |
214 | sisr2 |= CCSR_SSI_SISR_TFRC; | ||
215 | ret = IRQ_HANDLED; | 269 | ret = IRQ_HANDLED; |
216 | } | 270 | } |
217 | 271 | ||
@@ -252,25 +306,21 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
252 | 306 | ||
253 | if (sisr & CCSR_SSI_SISR_ROE1) { | 307 | if (sisr & CCSR_SSI_SISR_ROE1) { |
254 | ssi_private->stats.roe1++; | 308 | ssi_private->stats.roe1++; |
255 | sisr2 |= CCSR_SSI_SISR_ROE1; | ||
256 | ret = IRQ_HANDLED; | 309 | ret = IRQ_HANDLED; |
257 | } | 310 | } |
258 | 311 | ||
259 | if (sisr & CCSR_SSI_SISR_ROE0) { | 312 | if (sisr & CCSR_SSI_SISR_ROE0) { |
260 | ssi_private->stats.roe0++; | 313 | ssi_private->stats.roe0++; |
261 | sisr2 |= CCSR_SSI_SISR_ROE0; | ||
262 | ret = IRQ_HANDLED; | 314 | ret = IRQ_HANDLED; |
263 | } | 315 | } |
264 | 316 | ||
265 | if (sisr & CCSR_SSI_SISR_TUE1) { | 317 | if (sisr & CCSR_SSI_SISR_TUE1) { |
266 | ssi_private->stats.tue1++; | 318 | ssi_private->stats.tue1++; |
267 | sisr2 |= CCSR_SSI_SISR_TUE1; | ||
268 | ret = IRQ_HANDLED; | 319 | ret = IRQ_HANDLED; |
269 | } | 320 | } |
270 | 321 | ||
271 | if (sisr & CCSR_SSI_SISR_TUE0) { | 322 | if (sisr & CCSR_SSI_SISR_TUE0) { |
272 | ssi_private->stats.tue0++; | 323 | ssi_private->stats.tue0++; |
273 | sisr2 |= CCSR_SSI_SISR_TUE0; | ||
274 | ret = IRQ_HANDLED; | 324 | ret = IRQ_HANDLED; |
275 | } | 325 | } |
276 | 326 | ||
@@ -314,6 +364,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
314 | ret = IRQ_HANDLED; | 364 | ret = IRQ_HANDLED; |
315 | } | 365 | } |
316 | 366 | ||
367 | sisr2 = sisr & sisr_write_mask; | ||
317 | /* Clear the bits that we set */ | 368 | /* Clear the bits that we set */ |
318 | if (sisr2) | 369 | if (sisr2) |
319 | write_ssi(sisr2, &ssi->sisr); | 370 | write_ssi(sisr2, &ssi->sisr); |
@@ -321,17 +372,287 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
321 | return ret; | 372 | return ret; |
322 | } | 373 | } |
323 | 374 | ||
375 | #if IS_ENABLED(CONFIG_DEBUG_FS) | ||
376 | /* Show the statistics of a flag only if its interrupt is enabled. The | ||
377 | * compiler will optimze this code to a no-op if the interrupt is not | ||
378 | * enabled. | ||
379 | */ | ||
380 | #define SIER_SHOW(flag, name) \ | ||
381 | do { \ | ||
382 | if (FSLSSI_SISR_MASK & CCSR_SSI_SIER_##flag) \ | ||
383 | seq_printf(s, #name "=%u\n", ssi_private->stats.name); \ | ||
384 | } while (0) | ||
385 | |||
386 | |||
387 | /** | ||
388 | * fsl_sysfs_ssi_show: display SSI statistics | ||
389 | * | ||
390 | * Display the statistics for the current SSI device. To avoid confusion, | ||
391 | * we only show those counts that are enabled. | ||
392 | */ | ||
393 | static int fsl_ssi_stats_show(struct seq_file *s, void *unused) | ||
394 | { | ||
395 | struct fsl_ssi_private *ssi_private = s->private; | ||
396 | |||
397 | SIER_SHOW(RFRC_EN, rfrc); | ||
398 | SIER_SHOW(TFRC_EN, tfrc); | ||
399 | SIER_SHOW(CMDAU_EN, cmdau); | ||
400 | SIER_SHOW(CMDDU_EN, cmddu); | ||
401 | SIER_SHOW(RXT_EN, rxt); | ||
402 | SIER_SHOW(RDR1_EN, rdr1); | ||
403 | SIER_SHOW(RDR0_EN, rdr0); | ||
404 | SIER_SHOW(TDE1_EN, tde1); | ||
405 | SIER_SHOW(TDE0_EN, tde0); | ||
406 | SIER_SHOW(ROE1_EN, roe1); | ||
407 | SIER_SHOW(ROE0_EN, roe0); | ||
408 | SIER_SHOW(TUE1_EN, tue1); | ||
409 | SIER_SHOW(TUE0_EN, tue0); | ||
410 | SIER_SHOW(TFS_EN, tfs); | ||
411 | SIER_SHOW(RFS_EN, rfs); | ||
412 | SIER_SHOW(TLS_EN, tls); | ||
413 | SIER_SHOW(RLS_EN, rls); | ||
414 | SIER_SHOW(RFF1_EN, rff1); | ||
415 | SIER_SHOW(RFF0_EN, rff0); | ||
416 | SIER_SHOW(TFE1_EN, tfe1); | ||
417 | SIER_SHOW(TFE0_EN, tfe0); | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int fsl_ssi_stats_open(struct inode *inode, struct file *file) | ||
423 | { | ||
424 | return single_open(file, fsl_ssi_stats_show, inode->i_private); | ||
425 | } | ||
426 | |||
427 | static const struct file_operations fsl_ssi_stats_ops = { | ||
428 | .open = fsl_ssi_stats_open, | ||
429 | .read = seq_read, | ||
430 | .llseek = seq_lseek, | ||
431 | .release = single_release, | ||
432 | }; | ||
433 | |||
434 | static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private, | ||
435 | struct device *dev) | ||
436 | { | ||
437 | ssi_private->dbg_dir = debugfs_create_dir(dev_name(dev), NULL); | ||
438 | if (!ssi_private->dbg_dir) | ||
439 | return -ENOMEM; | ||
440 | |||
441 | ssi_private->dbg_stats = debugfs_create_file("stats", S_IRUGO, | ||
442 | ssi_private->dbg_dir, ssi_private, &fsl_ssi_stats_ops); | ||
443 | if (!ssi_private->dbg_stats) { | ||
444 | debugfs_remove(ssi_private->dbg_dir); | ||
445 | return -ENOMEM; | ||
446 | } | ||
447 | |||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private) | ||
452 | { | ||
453 | debugfs_remove(ssi_private->dbg_stats); | ||
454 | debugfs_remove(ssi_private->dbg_dir); | ||
455 | } | ||
456 | |||
457 | #else | ||
458 | |||
459 | static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private, | ||
460 | struct device *dev) | ||
461 | { | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private) | ||
466 | { | ||
467 | } | ||
468 | |||
469 | #endif /* IS_ENABLED(CONFIG_DEBUG_FS) */ | ||
470 | |||
471 | /* | ||
472 | * Enable/Disable all rx/tx config flags at once. | ||
473 | */ | ||
474 | static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private, | ||
475 | bool enable) | ||
476 | { | ||
477 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
478 | struct fsl_ssi_rxtx_reg_val *vals = &ssi_private->rxtx_reg_val; | ||
479 | |||
480 | if (enable) { | ||
481 | write_ssi_mask(&ssi->sier, 0, vals->rx.sier | vals->tx.sier); | ||
482 | write_ssi_mask(&ssi->srcr, 0, vals->rx.srcr | vals->tx.srcr); | ||
483 | write_ssi_mask(&ssi->stcr, 0, vals->rx.stcr | vals->tx.stcr); | ||
484 | } else { | ||
485 | write_ssi_mask(&ssi->srcr, vals->rx.srcr | vals->tx.srcr, 0); | ||
486 | write_ssi_mask(&ssi->stcr, vals->rx.stcr | vals->tx.stcr, 0); | ||
487 | write_ssi_mask(&ssi->sier, vals->rx.sier | vals->tx.sier, 0); | ||
488 | } | ||
489 | } | ||
490 | |||
491 | /* | ||
492 | * Enable/Disable a ssi configuration. You have to pass either | ||
493 | * ssi_private->rxtx_reg_val.rx or tx as vals parameter. | ||
494 | */ | ||
495 | static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable, | ||
496 | struct fsl_ssi_reg_val *vals) | ||
497 | { | ||
498 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
499 | struct fsl_ssi_reg_val *avals; | ||
500 | u32 scr_val = read_ssi(&ssi->scr); | ||
501 | int nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) + | ||
502 | !!(scr_val & CCSR_SSI_SCR_RE); | ||
503 | |||
504 | /* Find the other direction values rx or tx which we do not want to | ||
505 | * modify */ | ||
506 | if (&ssi_private->rxtx_reg_val.rx == vals) | ||
507 | avals = &ssi_private->rxtx_reg_val.tx; | ||
508 | else | ||
509 | avals = &ssi_private->rxtx_reg_val.rx; | ||
510 | |||
511 | /* If vals should be disabled, start with disabling the unit */ | ||
512 | if (!enable) { | ||
513 | u32 scr = vals->scr & (vals->scr ^ avals->scr); | ||
514 | write_ssi_mask(&ssi->scr, scr, 0); | ||
515 | } | ||
516 | |||
517 | /* | ||
518 | * We are running on a SoC which does not support online SSI | ||
519 | * reconfiguration, so we have to enable all necessary flags at once | ||
520 | * even if we do not use them later (capture and playback configuration) | ||
521 | */ | ||
522 | if (ssi_private->offline_config) { | ||
523 | if ((enable && !nr_active_streams) || | ||
524 | (!enable && nr_active_streams == 1)) | ||
525 | fsl_ssi_rxtx_config(ssi_private, enable); | ||
526 | |||
527 | goto config_done; | ||
528 | } | ||
529 | |||
530 | /* | ||
531 | * Configure single direction units while the SSI unit is running | ||
532 | * (online configuration) | ||
533 | */ | ||
534 | if (enable) { | ||
535 | write_ssi_mask(&ssi->sier, 0, vals->sier); | ||
536 | write_ssi_mask(&ssi->srcr, 0, vals->srcr); | ||
537 | write_ssi_mask(&ssi->stcr, 0, vals->stcr); | ||
538 | } else { | ||
539 | u32 sier; | ||
540 | u32 srcr; | ||
541 | u32 stcr; | ||
542 | |||
543 | /* | ||
544 | * Disabling the necessary flags for one of rx/tx while the | ||
545 | * other stream is active is a little bit more difficult. We | ||
546 | * have to disable only those flags that differ between both | ||
547 | * streams (rx XOR tx) and that are set in the stream that is | ||
548 | * disabled now. Otherwise we could alter flags of the other | ||
549 | * stream | ||
550 | */ | ||
551 | |||
552 | /* These assignments are simply vals without bits set in avals*/ | ||
553 | sier = vals->sier & (vals->sier ^ avals->sier); | ||
554 | srcr = vals->srcr & (vals->srcr ^ avals->srcr); | ||
555 | stcr = vals->stcr & (vals->stcr ^ avals->stcr); | ||
556 | |||
557 | write_ssi_mask(&ssi->srcr, srcr, 0); | ||
558 | write_ssi_mask(&ssi->stcr, stcr, 0); | ||
559 | write_ssi_mask(&ssi->sier, sier, 0); | ||
560 | } | ||
561 | |||
562 | config_done: | ||
563 | /* Enabling of subunits is done after configuration */ | ||
564 | if (enable) | ||
565 | write_ssi_mask(&ssi->scr, 0, vals->scr); | ||
566 | } | ||
567 | |||
568 | |||
569 | static void fsl_ssi_rx_config(struct fsl_ssi_private *ssi_private, bool enable) | ||
570 | { | ||
571 | fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.rx); | ||
572 | } | ||
573 | |||
574 | static void fsl_ssi_tx_config(struct fsl_ssi_private *ssi_private, bool enable) | ||
575 | { | ||
576 | fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.tx); | ||
577 | } | ||
578 | |||
579 | /* | ||
580 | * Setup rx/tx register values used to enable/disable the streams. These will | ||
581 | * be used later in fsl_ssi_config to setup the streams without the need to | ||
582 | * check for all different SSI modes. | ||
583 | */ | ||
584 | static void fsl_ssi_setup_reg_vals(struct fsl_ssi_private *ssi_private) | ||
585 | { | ||
586 | struct fsl_ssi_rxtx_reg_val *reg = &ssi_private->rxtx_reg_val; | ||
587 | |||
588 | reg->rx.sier = CCSR_SSI_SIER_RFF0_EN; | ||
589 | reg->rx.srcr = CCSR_SSI_SRCR_RFEN0; | ||
590 | reg->rx.scr = 0; | ||
591 | reg->tx.sier = CCSR_SSI_SIER_TFE0_EN; | ||
592 | reg->tx.stcr = CCSR_SSI_STCR_TFEN0; | ||
593 | reg->tx.scr = 0; | ||
594 | |||
595 | if (!ssi_private->imx_ac97) { | ||
596 | reg->rx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE; | ||
597 | reg->rx.sier |= CCSR_SSI_SIER_RFF0_EN; | ||
598 | reg->tx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE; | ||
599 | reg->tx.sier |= CCSR_SSI_SIER_TFE0_EN; | ||
600 | } | ||
601 | |||
602 | if (ssi_private->use_dma) { | ||
603 | reg->rx.sier |= CCSR_SSI_SIER_RDMAE; | ||
604 | reg->tx.sier |= CCSR_SSI_SIER_TDMAE; | ||
605 | } else { | ||
606 | reg->rx.sier |= CCSR_SSI_SIER_RIE; | ||
607 | reg->tx.sier |= CCSR_SSI_SIER_TIE; | ||
608 | } | ||
609 | |||
610 | reg->rx.sier |= FSLSSI_SIER_DBG_RX_FLAGS; | ||
611 | reg->tx.sier |= FSLSSI_SIER_DBG_TX_FLAGS; | ||
612 | } | ||
613 | |||
614 | static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) | ||
615 | { | ||
616 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
617 | |||
618 | /* | ||
619 | * Setup the clock control register | ||
620 | */ | ||
621 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
622 | &ssi->stccr); | ||
623 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
624 | &ssi->srccr); | ||
625 | |||
626 | /* | ||
627 | * Enable AC97 mode and startup the SSI | ||
628 | */ | ||
629 | write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV, | ||
630 | &ssi->sacnt); | ||
631 | write_ssi(0xff, &ssi->saccdis); | ||
632 | write_ssi(0x300, &ssi->saccen); | ||
633 | |||
634 | /* | ||
635 | * Enable SSI, Transmit and Receive. AC97 has to communicate with the | ||
636 | * codec before a stream is started. | ||
637 | */ | ||
638 | write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN | | ||
639 | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE); | ||
640 | |||
641 | write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor); | ||
642 | } | ||
643 | |||
324 | static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) | 644 | static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) |
325 | { | 645 | { |
326 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 646 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
327 | u8 i2s_mode; | ||
328 | u8 wm; | 647 | u8 wm; |
329 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; | 648 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; |
330 | 649 | ||
650 | fsl_ssi_setup_reg_vals(ssi_private); | ||
651 | |||
331 | if (ssi_private->imx_ac97) | 652 | if (ssi_private->imx_ac97) |
332 | i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; | 653 | ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; |
333 | else | 654 | else |
334 | i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; | 655 | ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; |
335 | 656 | ||
336 | /* | 657 | /* |
337 | * Section 16.5 of the MPC8610 reference manual says that the SSI needs | 658 | * Section 16.5 of the MPC8610 reference manual says that the SSI needs |
@@ -348,16 +669,15 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) | |||
348 | write_ssi_mask(&ssi->scr, | 669 | write_ssi_mask(&ssi->scr, |
349 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, | 670 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, |
350 | CCSR_SSI_SCR_TFR_CLK_DIS | | 671 | CCSR_SSI_SCR_TFR_CLK_DIS | |
351 | i2s_mode | | 672 | ssi_private->i2s_mode | |
352 | (synchronous ? CCSR_SSI_SCR_SYN : 0)); | 673 | (synchronous ? CCSR_SSI_SCR_SYN : 0)); |
353 | 674 | ||
354 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | | 675 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFSI | |
355 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | | 676 | CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP, &ssi->stcr); |
356 | CCSR_SSI_STCR_TSCKP, &ssi->stcr); | 677 | |
678 | write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFSI | | ||
679 | CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); | ||
357 | 680 | ||
358 | write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | | ||
359 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | | ||
360 | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); | ||
361 | /* | 681 | /* |
362 | * The DC and PM bits are only used if the SSI is the clock master. | 682 | * The DC and PM bits are only used if the SSI is the clock master. |
363 | */ | 683 | */ |
@@ -387,30 +707,18 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) | |||
387 | * because it is also running without an active substream. Normally SSI | 707 | * because it is also running without an active substream. Normally SSI |
388 | * is only enabled when there is a substream. | 708 | * is only enabled when there is a substream. |
389 | */ | 709 | */ |
390 | if (ssi_private->imx_ac97) { | 710 | if (ssi_private->imx_ac97) |
391 | /* | 711 | 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 | 712 | ||
413 | write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor); | 713 | /* |
714 | * Set a default slot number so that there is no need for those common | ||
715 | * cases like I2S mode to call the extra set_tdm_slot() any more. | ||
716 | */ | ||
717 | if (!ssi_private->imx_ac97) { | ||
718 | write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK, | ||
719 | CCSR_SSI_SxCCR_DC(2)); | ||
720 | write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK, | ||
721 | CCSR_SSI_SxCCR_DC(2)); | ||
414 | } | 722 | } |
415 | 723 | ||
416 | return 0; | 724 | return 0; |
@@ -431,53 +739,17 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
431 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 739 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
432 | struct fsl_ssi_private *ssi_private = | 740 | struct fsl_ssi_private *ssi_private = |
433 | snd_soc_dai_get_drvdata(rtd->cpu_dai); | 741 | snd_soc_dai_get_drvdata(rtd->cpu_dai); |
434 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; | 742 | unsigned long flags; |
435 | 743 | ||
436 | /* | 744 | /* 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 | 745 | * Second, fsl_ssi_setup was already called by ac97_init earlier if |
438 | * and initialize the SSI registers. | 746 | * the driver is in ac97 mode. |
439 | */ | 747 | */ |
440 | if (!ssi_private->first_stream) { | 748 | if (!dai->active && !ssi_private->imx_ac97) { |
441 | ssi_private->first_stream = substream; | 749 | fsl_ssi_setup(ssi_private); |
442 | 750 | spin_lock_irqsave(&ssi_private->baudclk_lock, flags); | |
443 | /* | 751 | ssi_private->baudclk_locked = false; |
444 | * fsl_ssi_setup was already called by ac97_init earlier if | 752 | 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 | } | 753 | } |
482 | 754 | ||
483 | return 0; | 755 | return 0; |
@@ -501,6 +773,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | |||
501 | { | 773 | { |
502 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); | 774 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); |
503 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 775 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
776 | unsigned int channels = params_channels(hw_params); | ||
504 | unsigned int sample_size = | 777 | unsigned int sample_size = |
505 | snd_pcm_format_width(params_format(hw_params)); | 778 | snd_pcm_format_width(params_format(hw_params)); |
506 | u32 wl = CCSR_SSI_SxCCR_WL(sample_size); | 779 | u32 wl = CCSR_SSI_SxCCR_WL(sample_size); |
@@ -530,6 +803,248 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | |||
530 | else | 803 | else |
531 | write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); | 804 | write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); |
532 | 805 | ||
806 | if (!ssi_private->imx_ac97) | ||
807 | write_ssi_mask(&ssi->scr, | ||
808 | CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK, | ||
809 | channels == 1 ? 0 : ssi_private->i2s_mode); | ||
810 | |||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | /** | ||
815 | * fsl_ssi_set_dai_fmt - configure Digital Audio Interface Format. | ||
816 | */ | ||
817 | static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | ||
818 | { | ||
819 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); | ||
820 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
821 | u32 strcr = 0, stcr, srcr, scr, mask; | ||
822 | |||
823 | scr = read_ssi(&ssi->scr) & ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK); | ||
824 | scr |= CCSR_SSI_SCR_NET; | ||
825 | |||
826 | mask = CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR | | ||
827 | CCSR_SSI_STCR_TSCKP | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TFSL | | ||
828 | CCSR_SSI_STCR_TEFS; | ||
829 | stcr = read_ssi(&ssi->stcr) & ~mask; | ||
830 | srcr = read_ssi(&ssi->srcr) & ~mask; | ||
831 | |||
832 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
833 | case SND_SOC_DAIFMT_I2S: | ||
834 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
835 | case SND_SOC_DAIFMT_CBS_CFS: | ||
836 | ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_MASTER; | ||
837 | break; | ||
838 | case SND_SOC_DAIFMT_CBM_CFM: | ||
839 | ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; | ||
840 | break; | ||
841 | default: | ||
842 | return -EINVAL; | ||
843 | } | ||
844 | scr |= ssi_private->i2s_mode; | ||
845 | |||
846 | /* Data on rising edge of bclk, frame low, 1clk before data */ | ||
847 | strcr |= CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TSCKP | | ||
848 | CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS; | ||
849 | break; | ||
850 | case SND_SOC_DAIFMT_LEFT_J: | ||
851 | /* Data on rising edge of bclk, frame high */ | ||
852 | strcr |= CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TSCKP; | ||
853 | break; | ||
854 | case SND_SOC_DAIFMT_DSP_A: | ||
855 | /* Data on rising edge of bclk, frame high, 1clk before data */ | ||
856 | strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP | | ||
857 | CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS; | ||
858 | break; | ||
859 | case SND_SOC_DAIFMT_DSP_B: | ||
860 | /* Data on rising edge of bclk, frame high */ | ||
861 | strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP | | ||
862 | CCSR_SSI_STCR_TXBIT0; | ||
863 | break; | ||
864 | default: | ||
865 | return -EINVAL; | ||
866 | } | ||
867 | |||
868 | /* DAI clock inversion */ | ||
869 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
870 | case SND_SOC_DAIFMT_NB_NF: | ||
871 | /* Nothing to do for both normal cases */ | ||
872 | break; | ||
873 | case SND_SOC_DAIFMT_IB_NF: | ||
874 | /* Invert bit clock */ | ||
875 | strcr ^= CCSR_SSI_STCR_TSCKP; | ||
876 | break; | ||
877 | case SND_SOC_DAIFMT_NB_IF: | ||
878 | /* Invert frame clock */ | ||
879 | strcr ^= CCSR_SSI_STCR_TFSI; | ||
880 | break; | ||
881 | case SND_SOC_DAIFMT_IB_IF: | ||
882 | /* Invert both clocks */ | ||
883 | strcr ^= CCSR_SSI_STCR_TSCKP; | ||
884 | strcr ^= CCSR_SSI_STCR_TFSI; | ||
885 | break; | ||
886 | default: | ||
887 | return -EINVAL; | ||
888 | } | ||
889 | |||
890 | /* DAI clock master masks */ | ||
891 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
892 | case SND_SOC_DAIFMT_CBS_CFS: | ||
893 | strcr |= CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR; | ||
894 | scr |= CCSR_SSI_SCR_SYS_CLK_EN; | ||
895 | break; | ||
896 | case SND_SOC_DAIFMT_CBM_CFM: | ||
897 | scr &= ~CCSR_SSI_SCR_SYS_CLK_EN; | ||
898 | break; | ||
899 | default: | ||
900 | return -EINVAL; | ||
901 | } | ||
902 | |||
903 | stcr |= strcr; | ||
904 | srcr |= strcr; | ||
905 | |||
906 | if (ssi_private->cpu_dai_drv.symmetric_rates) { | ||
907 | /* Need to clear RXDIR when using SYNC mode */ | ||
908 | srcr &= ~CCSR_SSI_SRCR_RXDIR; | ||
909 | scr |= CCSR_SSI_SCR_SYN; | ||
910 | } | ||
911 | |||
912 | write_ssi(stcr, &ssi->stcr); | ||
913 | write_ssi(srcr, &ssi->srcr); | ||
914 | write_ssi(scr, &ssi->scr); | ||
915 | |||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | /** | ||
920 | * fsl_ssi_set_dai_sysclk - configure Digital Audio Interface bit clock | ||
921 | * | ||
922 | * Note: This function can be only called when using SSI as DAI master | ||
923 | * | ||
924 | * Quick instruction for parameters: | ||
925 | * freq: Output BCLK frequency = samplerate * 32 (fixed) * channels | ||
926 | * dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK. | ||
927 | */ | ||
928 | static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | ||
929 | int clk_id, unsigned int freq, int dir) | ||
930 | { | ||
931 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); | ||
932 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
933 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret; | ||
934 | u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i; | ||
935 | unsigned long flags, clkrate, baudrate, tmprate; | ||
936 | u64 sub, savesub = 100000; | ||
937 | |||
938 | /* Don't apply it to any non-baudclk circumstance */ | ||
939 | if (IS_ERR(ssi_private->baudclk)) | ||
940 | return -EINVAL; | ||
941 | |||
942 | /* It should be already enough to divide clock by setting pm alone */ | ||
943 | psr = 0; | ||
944 | div2 = 0; | ||
945 | |||
946 | factor = (div2 + 1) * (7 * psr + 1) * 2; | ||
947 | |||
948 | for (i = 0; i < 255; i++) { | ||
949 | /* The bclk rate must be smaller than 1/5 sysclk rate */ | ||
950 | if (factor * (i + 1) < 5) | ||
951 | continue; | ||
952 | |||
953 | tmprate = freq * factor * (i + 2); | ||
954 | clkrate = clk_round_rate(ssi_private->baudclk, tmprate); | ||
955 | |||
956 | do_div(clkrate, factor); | ||
957 | afreq = (u32)clkrate / (i + 1); | ||
958 | |||
959 | if (freq == afreq) | ||
960 | sub = 0; | ||
961 | else if (freq / afreq == 1) | ||
962 | sub = freq - afreq; | ||
963 | else if (afreq / freq == 1) | ||
964 | sub = afreq - freq; | ||
965 | else | ||
966 | continue; | ||
967 | |||
968 | /* Calculate the fraction */ | ||
969 | sub *= 100000; | ||
970 | do_div(sub, freq); | ||
971 | |||
972 | if (sub < savesub) { | ||
973 | baudrate = tmprate; | ||
974 | savesub = sub; | ||
975 | pm = i; | ||
976 | } | ||
977 | |||
978 | /* We are lucky */ | ||
979 | if (savesub == 0) | ||
980 | break; | ||
981 | } | ||
982 | |||
983 | /* No proper pm found if it is still remaining the initial value */ | ||
984 | if (pm == 999) { | ||
985 | dev_err(cpu_dai->dev, "failed to handle the required sysclk\n"); | ||
986 | return -EINVAL; | ||
987 | } | ||
988 | |||
989 | stccr = CCSR_SSI_SxCCR_PM(pm + 1) | (div2 ? CCSR_SSI_SxCCR_DIV2 : 0) | | ||
990 | (psr ? CCSR_SSI_SxCCR_PSR : 0); | ||
991 | mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 | CCSR_SSI_SxCCR_PSR; | ||
992 | |||
993 | if (dir == SND_SOC_CLOCK_OUT || synchronous) | ||
994 | write_ssi_mask(&ssi->stccr, mask, stccr); | ||
995 | else | ||
996 | write_ssi_mask(&ssi->srccr, mask, stccr); | ||
997 | |||
998 | spin_lock_irqsave(&ssi_private->baudclk_lock, flags); | ||
999 | if (!ssi_private->baudclk_locked) { | ||
1000 | ret = clk_set_rate(ssi_private->baudclk, baudrate); | ||
1001 | if (ret) { | ||
1002 | spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); | ||
1003 | dev_err(cpu_dai->dev, "failed to set baudclk rate\n"); | ||
1004 | return -EINVAL; | ||
1005 | } | ||
1006 | ssi_private->baudclk_locked = true; | ||
1007 | } | ||
1008 | spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); | ||
1009 | |||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | /** | ||
1014 | * fsl_ssi_set_dai_tdm_slot - set TDM slot number | ||
1015 | * | ||
1016 | * Note: This function can be only called when using SSI as DAI master | ||
1017 | */ | ||
1018 | static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask, | ||
1019 | u32 rx_mask, int slots, int slot_width) | ||
1020 | { | ||
1021 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); | ||
1022 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
1023 | u32 val; | ||
1024 | |||
1025 | /* The slot number should be >= 2 if using Network mode or I2S mode */ | ||
1026 | val = read_ssi(&ssi->scr) & (CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET); | ||
1027 | if (val && slots < 2) { | ||
1028 | dev_err(cpu_dai->dev, "slot number should be >= 2 in I2S or NET\n"); | ||
1029 | return -EINVAL; | ||
1030 | } | ||
1031 | |||
1032 | write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK, | ||
1033 | CCSR_SSI_SxCCR_DC(slots)); | ||
1034 | write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK, | ||
1035 | CCSR_SSI_SxCCR_DC(slots)); | ||
1036 | |||
1037 | /* The register SxMSKs needs SSI to provide essential clock due to | ||
1038 | * hardware design. So we here temporarily enable SSI to set them. | ||
1039 | */ | ||
1040 | val = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN; | ||
1041 | write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN); | ||
1042 | |||
1043 | write_ssi(tx_mask, &ssi->stmsk); | ||
1044 | write_ssi(rx_mask, &ssi->srmsk); | ||
1045 | |||
1046 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, val); | ||
1047 | |||
533 | return 0; | 1048 | return 0; |
534 | } | 1049 | } |
535 | 1050 | ||
@@ -548,77 +1063,46 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
548 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1063 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
549 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 1064 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
550 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 1065 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
551 | unsigned int sier_bits; | 1066 | unsigned long flags; |
552 | |||
553 | /* | ||
554 | * Enable only the interrupts and DMA requests | ||
555 | * that are needed for the channel. As the fiq | ||
556 | * is polling for this bits, we have to ensure | ||
557 | * that this are aligned with the preallocated | ||
558 | * buffers | ||
559 | */ | ||
560 | |||
561 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
562 | if (ssi_private->use_dma) | ||
563 | sier_bits = SIER_FLAGS; | ||
564 | else | ||
565 | sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN; | ||
566 | } else { | ||
567 | if (ssi_private->use_dma) | ||
568 | sier_bits = SIER_FLAGS; | ||
569 | else | ||
570 | sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN; | ||
571 | } | ||
572 | 1067 | ||
573 | switch (cmd) { | 1068 | switch (cmd) { |
574 | case SNDRV_PCM_TRIGGER_START: | 1069 | case SNDRV_PCM_TRIGGER_START: |
575 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 1070 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
576 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1071 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
577 | write_ssi_mask(&ssi->scr, 0, | 1072 | fsl_ssi_tx_config(ssi_private, true); |
578 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); | ||
579 | else | 1073 | else |
580 | write_ssi_mask(&ssi->scr, 0, | 1074 | fsl_ssi_rx_config(ssi_private, true); |
581 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); | ||
582 | break; | 1075 | break; |
583 | 1076 | ||
584 | case SNDRV_PCM_TRIGGER_STOP: | 1077 | case SNDRV_PCM_TRIGGER_STOP: |
585 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 1078 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
586 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1079 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
587 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0); | 1080 | fsl_ssi_tx_config(ssi_private, false); |
588 | else | 1081 | else |
589 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); | 1082 | fsl_ssi_rx_config(ssi_private, false); |
590 | 1083 | ||
591 | if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & | 1084 | if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & |
592 | (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) | 1085 | (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) { |
593 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | 1086 | spin_lock_irqsave(&ssi_private->baudclk_lock, flags); |
1087 | ssi_private->baudclk_locked = false; | ||
1088 | spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); | ||
1089 | } | ||
594 | break; | 1090 | break; |
595 | 1091 | ||
596 | default: | 1092 | default: |
597 | return -EINVAL; | 1093 | return -EINVAL; |
598 | } | 1094 | } |
599 | 1095 | ||
600 | write_ssi(sier_bits, &ssi->sier); | 1096 | if (ssi_private->imx_ac97) { |
1097 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
1098 | write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor); | ||
1099 | else | ||
1100 | write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor); | ||
1101 | } | ||
601 | 1102 | ||
602 | return 0; | 1103 | return 0; |
603 | } | 1104 | } |
604 | 1105 | ||
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) | 1106 | static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) |
623 | { | 1107 | { |
624 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); | 1108 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); |
@@ -634,7 +1118,9 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) | |||
634 | static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { | 1118 | static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { |
635 | .startup = fsl_ssi_startup, | 1119 | .startup = fsl_ssi_startup, |
636 | .hw_params = fsl_ssi_hw_params, | 1120 | .hw_params = fsl_ssi_hw_params, |
637 | .shutdown = fsl_ssi_shutdown, | 1121 | .set_fmt = fsl_ssi_set_dai_fmt, |
1122 | .set_sysclk = fsl_ssi_set_dai_sysclk, | ||
1123 | .set_tdm_slot = fsl_ssi_set_dai_tdm_slot, | ||
638 | .trigger = fsl_ssi_trigger, | 1124 | .trigger = fsl_ssi_trigger, |
639 | }; | 1125 | }; |
640 | 1126 | ||
@@ -642,14 +1128,13 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { | |||
642 | static struct snd_soc_dai_driver fsl_ssi_dai_template = { | 1128 | static struct snd_soc_dai_driver fsl_ssi_dai_template = { |
643 | .probe = fsl_ssi_dai_probe, | 1129 | .probe = fsl_ssi_dai_probe, |
644 | .playback = { | 1130 | .playback = { |
645 | /* The SSI does not support monaural audio. */ | 1131 | .channels_min = 1, |
646 | .channels_min = 2, | ||
647 | .channels_max = 2, | 1132 | .channels_max = 2, |
648 | .rates = FSLSSI_I2S_RATES, | 1133 | .rates = FSLSSI_I2S_RATES, |
649 | .formats = FSLSSI_I2S_FORMATS, | 1134 | .formats = FSLSSI_I2S_FORMATS, |
650 | }, | 1135 | }, |
651 | .capture = { | 1136 | .capture = { |
652 | .channels_min = 2, | 1137 | .channels_min = 1, |
653 | .channels_max = 2, | 1138 | .channels_max = 2, |
654 | .rates = FSLSSI_I2S_RATES, | 1139 | .rates = FSLSSI_I2S_RATES, |
655 | .formats = FSLSSI_I2S_FORMATS, | 1140 | .formats = FSLSSI_I2S_FORMATS, |
@@ -661,59 +1146,6 @@ static const struct snd_soc_component_driver fsl_ssi_component = { | |||
661 | .name = "fsl-ssi", | 1146 | .name = "fsl-ssi", |
662 | }; | 1147 | }; |
663 | 1148 | ||
664 | /** | ||
665 | * fsl_ssi_ac97_trigger: start and stop the AC97 receive/transmit. | ||
666 | * | ||
667 | * This function is called by ALSA to start, stop, pause, and resume the | ||
668 | * transfer of data. | ||
669 | */ | ||
670 | static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | ||
671 | struct snd_soc_dai *dai) | ||
672 | { | ||
673 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
674 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata( | ||
675 | rtd->cpu_dai); | ||
676 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
677 | |||
678 | switch (cmd) { | ||
679 | case SNDRV_PCM_TRIGGER_START: | ||
680 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
681 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
682 | write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_TIE | | ||
683 | CCSR_SSI_SIER_TFE0_EN); | ||
684 | else | ||
685 | write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_RIE | | ||
686 | CCSR_SSI_SIER_RFF0_EN); | ||
687 | break; | ||
688 | |||
689 | case SNDRV_PCM_TRIGGER_STOP: | ||
690 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
691 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
692 | write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_TIE | | ||
693 | CCSR_SSI_SIER_TFE0_EN, 0); | ||
694 | else | ||
695 | write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RIE | | ||
696 | CCSR_SSI_SIER_RFF0_EN, 0); | ||
697 | break; | ||
698 | |||
699 | default: | ||
700 | return -EINVAL; | ||
701 | } | ||
702 | |||
703 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
704 | write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor); | ||
705 | else | ||
706 | write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor); | ||
707 | |||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { | ||
712 | .startup = fsl_ssi_startup, | ||
713 | .shutdown = fsl_ssi_shutdown, | ||
714 | .trigger = fsl_ssi_ac97_trigger, | ||
715 | }; | ||
716 | |||
717 | static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { | 1149 | static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { |
718 | .ac97_control = 1, | 1150 | .ac97_control = 1, |
719 | .playback = { | 1151 | .playback = { |
@@ -730,7 +1162,7 @@ static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { | |||
730 | .rates = SNDRV_PCM_RATE_48000, | 1162 | .rates = SNDRV_PCM_RATE_48000, |
731 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 1163 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
732 | }, | 1164 | }, |
733 | .ops = &fsl_ssi_ac97_dai_ops, | 1165 | .ops = &fsl_ssi_dai_ops, |
734 | }; | 1166 | }; |
735 | 1167 | ||
736 | 1168 | ||
@@ -788,56 +1220,6 @@ static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = { | |||
788 | .write = fsl_ssi_ac97_write, | 1220 | .write = fsl_ssi_ac97_write, |
789 | }; | 1221 | }; |
790 | 1222 | ||
791 | /* Show the statistics of a flag only if its interrupt is enabled. The | ||
792 | * compiler will optimze this code to a no-op if the interrupt is not | ||
793 | * enabled. | ||
794 | */ | ||
795 | #define SIER_SHOW(flag, name) \ | ||
796 | do { \ | ||
797 | if (SIER_FLAGS & CCSR_SSI_SIER_##flag) \ | ||
798 | length += sprintf(buf + length, #name "=%u\n", \ | ||
799 | ssi_private->stats.name); \ | ||
800 | } while (0) | ||
801 | |||
802 | |||
803 | /** | ||
804 | * fsl_sysfs_ssi_show: display SSI statistics | ||
805 | * | ||
806 | * Display the statistics for the current SSI device. To avoid confusion, | ||
807 | * we only show those counts that are enabled. | ||
808 | */ | ||
809 | static ssize_t fsl_sysfs_ssi_show(struct device *dev, | ||
810 | struct device_attribute *attr, char *buf) | ||
811 | { | ||
812 | struct fsl_ssi_private *ssi_private = | ||
813 | container_of(attr, struct fsl_ssi_private, dev_attr); | ||
814 | ssize_t length = 0; | ||
815 | |||
816 | SIER_SHOW(RFRC_EN, rfrc); | ||
817 | SIER_SHOW(TFRC_EN, tfrc); | ||
818 | SIER_SHOW(CMDAU_EN, cmdau); | ||
819 | SIER_SHOW(CMDDU_EN, cmddu); | ||
820 | SIER_SHOW(RXT_EN, rxt); | ||
821 | SIER_SHOW(RDR1_EN, rdr1); | ||
822 | SIER_SHOW(RDR0_EN, rdr0); | ||
823 | SIER_SHOW(TDE1_EN, tde1); | ||
824 | SIER_SHOW(TDE0_EN, tde0); | ||
825 | SIER_SHOW(ROE1_EN, roe1); | ||
826 | SIER_SHOW(ROE0_EN, roe0); | ||
827 | SIER_SHOW(TUE1_EN, tue1); | ||
828 | SIER_SHOW(TUE0_EN, tue0); | ||
829 | SIER_SHOW(TFS_EN, tfs); | ||
830 | SIER_SHOW(RFS_EN, rfs); | ||
831 | SIER_SHOW(TLS_EN, tls); | ||
832 | SIER_SHOW(RLS_EN, rls); | ||
833 | SIER_SHOW(RFF1_EN, rff1); | ||
834 | SIER_SHOW(RFF0_EN, rff0); | ||
835 | SIER_SHOW(TFE1_EN, tfe1); | ||
836 | SIER_SHOW(TFE0_EN, tfe0); | ||
837 | |||
838 | return length; | ||
839 | } | ||
840 | |||
841 | /** | 1223 | /** |
842 | * Make every character in a string lower-case | 1224 | * Make every character in a string lower-case |
843 | */ | 1225 | */ |
@@ -859,6 +1241,8 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
859 | int ret = 0; | 1241 | int ret = 0; |
860 | struct device_attribute *dev_attr = NULL; | 1242 | struct device_attribute *dev_attr = NULL; |
861 | struct device_node *np = pdev->dev.of_node; | 1243 | struct device_node *np = pdev->dev.of_node; |
1244 | const struct of_device_id *of_id; | ||
1245 | enum fsl_ssi_type hw_type; | ||
862 | const char *p, *sprop; | 1246 | const char *p, *sprop; |
863 | const uint32_t *iprop; | 1247 | const uint32_t *iprop; |
864 | struct resource res; | 1248 | struct resource res; |
@@ -873,6 +1257,11 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
873 | if (!of_device_is_available(np)) | 1257 | if (!of_device_is_available(np)) |
874 | return -ENODEV; | 1258 | return -ENODEV; |
875 | 1259 | ||
1260 | of_id = of_match_device(fsl_ssi_ids, &pdev->dev); | ||
1261 | if (!of_id) | ||
1262 | return -EINVAL; | ||
1263 | hw_type = (enum fsl_ssi_type) of_id->data; | ||
1264 | |||
876 | /* We only support the SSI in "I2S Slave" mode */ | 1265 | /* We only support the SSI in "I2S Slave" mode */ |
877 | sprop = of_get_property(np, "fsl,mode", NULL); | 1266 | sprop = of_get_property(np, "fsl,mode", NULL); |
878 | if (!sprop) { | 1267 | if (!sprop) { |
@@ -899,6 +1288,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
899 | 1288 | ||
900 | ssi_private->use_dma = !of_property_read_bool(np, | 1289 | ssi_private->use_dma = !of_property_read_bool(np, |
901 | "fsl,fiq-stream-filter"); | 1290 | "fsl,fiq-stream-filter"); |
1291 | ssi_private->hw_type = hw_type; | ||
902 | 1292 | ||
903 | if (ac97) { | 1293 | if (ac97) { |
904 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai, | 1294 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai, |
@@ -935,8 +1325,11 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
935 | } | 1325 | } |
936 | 1326 | ||
937 | /* Are the RX and the TX clocks locked? */ | 1327 | /* Are the RX and the TX clocks locked? */ |
938 | if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) | 1328 | if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) { |
939 | ssi_private->cpu_dai_drv.symmetric_rates = 1; | 1329 | ssi_private->cpu_dai_drv.symmetric_rates = 1; |
1330 | ssi_private->cpu_dai_drv.symmetric_channels = 1; | ||
1331 | ssi_private->cpu_dai_drv.symmetric_samplebits = 1; | ||
1332 | } | ||
940 | 1333 | ||
941 | /* Determine the FIFO depth. */ | 1334 | /* Determine the FIFO depth. */ |
942 | iprop = of_get_property(np, "fsl,fifo-depth", NULL); | 1335 | iprop = of_get_property(np, "fsl,fifo-depth", NULL); |
@@ -946,7 +1339,37 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
946 | /* Older 8610 DTs didn't have the fifo-depth property */ | 1339 | /* Older 8610 DTs didn't have the fifo-depth property */ |
947 | ssi_private->fifo_depth = 8; | 1340 | ssi_private->fifo_depth = 8; |
948 | 1341 | ||
949 | if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) { | 1342 | ssi_private->baudclk_locked = false; |
1343 | spin_lock_init(&ssi_private->baudclk_lock); | ||
1344 | |||
1345 | /* | ||
1346 | * imx51 and later SoCs have a slightly different IP that allows the | ||
1347 | * SSI configuration while the SSI unit is running. | ||
1348 | * | ||
1349 | * More important, it is necessary on those SoCs to configure the | ||
1350 | * sperate TX/RX DMA bits just before starting the stream | ||
1351 | * (fsl_ssi_trigger). The SDMA unit has to be configured before fsl_ssi | ||
1352 | * sends any DMA requests to the SDMA unit, otherwise it is not defined | ||
1353 | * how the SDMA unit handles the DMA request. | ||
1354 | * | ||
1355 | * SDMA units are present on devices starting at imx35 but the imx35 | ||
1356 | * reference manual states that the DMA bits should not be changed | ||
1357 | * while the SSI unit is running (SSIEN). So we support the necessary | ||
1358 | * online configuration of fsl-ssi starting at imx51. | ||
1359 | */ | ||
1360 | switch (hw_type) { | ||
1361 | case FSL_SSI_MCP8610: | ||
1362 | case FSL_SSI_MX21: | ||
1363 | case FSL_SSI_MX35: | ||
1364 | ssi_private->offline_config = true; | ||
1365 | break; | ||
1366 | case FSL_SSI_MX51: | ||
1367 | ssi_private->offline_config = false; | ||
1368 | break; | ||
1369 | } | ||
1370 | |||
1371 | if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51 || | ||
1372 | hw_type == FSL_SSI_MX35) { | ||
950 | u32 dma_events[2]; | 1373 | u32 dma_events[2]; |
951 | ssi_private->ssi_on_imx = true; | 1374 | ssi_private->ssi_on_imx = true; |
952 | 1375 | ||
@@ -963,6 +1386,16 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
963 | goto error_irqmap; | 1386 | goto error_irqmap; |
964 | } | 1387 | } |
965 | 1388 | ||
1389 | /* For those SLAVE implementations, we ingore non-baudclk cases | ||
1390 | * and, instead, abandon MASTER mode that needs baud clock. | ||
1391 | */ | ||
1392 | ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud"); | ||
1393 | if (IS_ERR(ssi_private->baudclk)) | ||
1394 | dev_warn(&pdev->dev, "could not get baud clock: %ld\n", | ||
1395 | PTR_ERR(ssi_private->baudclk)); | ||
1396 | else | ||
1397 | clk_prepare_enable(ssi_private->baudclk); | ||
1398 | |||
966 | /* | 1399 | /* |
967 | * We have burstsize be "fifo_depth - 2" to match the SSI | 1400 | * We have burstsize be "fifo_depth - 2" to match the SSI |
968 | * watermark setting in fsl_ssi_startup(). | 1401 | * watermark setting in fsl_ssi_startup(). |
@@ -1001,32 +1434,25 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1001 | dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); | 1434 | dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); |
1002 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, | 1435 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, |
1003 | dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); | 1436 | dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); |
1004 | } else if (ssi_private->use_dma) { | 1437 | } |
1438 | |||
1439 | /* | ||
1440 | * Enable interrupts only for MCP8610 and MX51. The other MXs have | ||
1441 | * different writeable interrupt status registers. | ||
1442 | */ | ||
1443 | if (ssi_private->use_dma) { | ||
1005 | /* The 'name' should not have any slashes in it. */ | 1444 | /* The 'name' should not have any slashes in it. */ |
1006 | ret = devm_request_irq(&pdev->dev, ssi_private->irq, | 1445 | ret = devm_request_irq(&pdev->dev, ssi_private->irq, |
1007 | fsl_ssi_isr, 0, ssi_private->name, | 1446 | fsl_ssi_isr, 0, ssi_private->name, |
1008 | ssi_private); | 1447 | ssi_private); |
1448 | ssi_private->irq_stats = true; | ||
1009 | if (ret < 0) { | 1449 | if (ret < 0) { |
1010 | dev_err(&pdev->dev, "could not claim irq %u\n", | 1450 | dev_err(&pdev->dev, "could not claim irq %u\n", |
1011 | ssi_private->irq); | 1451 | ssi_private->irq); |
1012 | goto error_irqmap; | 1452 | goto error_clk; |
1013 | } | 1453 | } |
1014 | } | 1454 | } |
1015 | 1455 | ||
1016 | /* Initialize the the device_attribute structure */ | ||
1017 | dev_attr = &ssi_private->dev_attr; | ||
1018 | sysfs_attr_init(&dev_attr->attr); | ||
1019 | dev_attr->attr.name = "statistics"; | ||
1020 | dev_attr->attr.mode = S_IRUGO; | ||
1021 | dev_attr->show = fsl_sysfs_ssi_show; | ||
1022 | |||
1023 | ret = device_create_file(&pdev->dev, dev_attr); | ||
1024 | if (ret) { | ||
1025 | dev_err(&pdev->dev, "could not create sysfs %s file\n", | ||
1026 | ssi_private->dev_attr.attr.name); | ||
1027 | goto error_clk; | ||
1028 | } | ||
1029 | |||
1030 | /* Register with ASoC */ | 1456 | /* Register with ASoC */ |
1031 | dev_set_drvdata(&pdev->dev, ssi_private); | 1457 | dev_set_drvdata(&pdev->dev, ssi_private); |
1032 | 1458 | ||
@@ -1037,6 +1463,10 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1037 | goto error_dev; | 1463 | goto error_dev; |
1038 | } | 1464 | } |
1039 | 1465 | ||
1466 | ret = fsl_ssi_debugfs_create(ssi_private, &pdev->dev); | ||
1467 | if (ret) | ||
1468 | goto error_dbgfs; | ||
1469 | |||
1040 | if (ssi_private->ssi_on_imx) { | 1470 | if (ssi_private->ssi_on_imx) { |
1041 | if (!ssi_private->use_dma) { | 1471 | if (!ssi_private->use_dma) { |
1042 | 1472 | ||
@@ -1056,11 +1486,11 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1056 | 1486 | ||
1057 | ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params); | 1487 | ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params); |
1058 | if (ret) | 1488 | if (ret) |
1059 | goto error_dev; | 1489 | goto error_pcm; |
1060 | } else { | 1490 | } else { |
1061 | ret = imx_pcm_dma_init(pdev); | 1491 | ret = imx_pcm_dma_init(pdev); |
1062 | if (ret) | 1492 | if (ret) |
1063 | goto error_dev; | 1493 | goto error_pcm; |
1064 | } | 1494 | } |
1065 | } | 1495 | } |
1066 | 1496 | ||
@@ -1102,19 +1532,28 @@ done: | |||
1102 | return 0; | 1532 | return 0; |
1103 | 1533 | ||
1104 | error_dai: | 1534 | error_dai: |
1105 | if (ssi_private->ssi_on_imx) | 1535 | if (ssi_private->ssi_on_imx && !ssi_private->use_dma) |
1106 | imx_pcm_dma_exit(pdev); | 1536 | imx_pcm_fiq_exit(pdev); |
1537 | |||
1538 | error_pcm: | ||
1539 | fsl_ssi_debugfs_remove(ssi_private); | ||
1540 | |||
1541 | error_dbgfs: | ||
1107 | snd_soc_unregister_component(&pdev->dev); | 1542 | snd_soc_unregister_component(&pdev->dev); |
1108 | 1543 | ||
1109 | error_dev: | 1544 | error_dev: |
1110 | device_remove_file(&pdev->dev, dev_attr); | 1545 | device_remove_file(&pdev->dev, dev_attr); |
1111 | 1546 | ||
1112 | error_clk: | 1547 | error_clk: |
1113 | if (ssi_private->ssi_on_imx) | 1548 | if (ssi_private->ssi_on_imx) { |
1549 | if (!IS_ERR(ssi_private->baudclk)) | ||
1550 | clk_disable_unprepare(ssi_private->baudclk); | ||
1114 | clk_disable_unprepare(ssi_private->clk); | 1551 | clk_disable_unprepare(ssi_private->clk); |
1552 | } | ||
1115 | 1553 | ||
1116 | error_irqmap: | 1554 | error_irqmap: |
1117 | irq_dispose_mapping(ssi_private->irq); | 1555 | if (ssi_private->irq_stats) |
1556 | irq_dispose_mapping(ssi_private->irq); | ||
1118 | 1557 | ||
1119 | return ret; | 1558 | return ret; |
1120 | } | 1559 | } |
@@ -1123,26 +1562,22 @@ static int fsl_ssi_remove(struct platform_device *pdev) | |||
1123 | { | 1562 | { |
1124 | struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev); | 1563 | struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev); |
1125 | 1564 | ||
1565 | fsl_ssi_debugfs_remove(ssi_private); | ||
1566 | |||
1126 | if (!ssi_private->new_binding) | 1567 | if (!ssi_private->new_binding) |
1127 | platform_device_unregister(ssi_private->pdev); | 1568 | 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); | 1569 | snd_soc_unregister_component(&pdev->dev); |
1131 | device_remove_file(&pdev->dev, &ssi_private->dev_attr); | 1570 | if (ssi_private->ssi_on_imx) { |
1132 | if (ssi_private->ssi_on_imx) | 1571 | if (!IS_ERR(ssi_private->baudclk)) |
1572 | clk_disable_unprepare(ssi_private->baudclk); | ||
1133 | clk_disable_unprepare(ssi_private->clk); | 1573 | clk_disable_unprepare(ssi_private->clk); |
1134 | irq_dispose_mapping(ssi_private->irq); | 1574 | } |
1575 | if (ssi_private->irq_stats) | ||
1576 | irq_dispose_mapping(ssi_private->irq); | ||
1135 | 1577 | ||
1136 | return 0; | 1578 | return 0; |
1137 | } | 1579 | } |
1138 | 1580 | ||
1139 | static const struct of_device_id fsl_ssi_ids[] = { | ||
1140 | { .compatible = "fsl,mpc8610-ssi", }, | ||
1141 | { .compatible = "fsl,imx21-ssi", }, | ||
1142 | {} | ||
1143 | }; | ||
1144 | MODULE_DEVICE_TABLE(of, fsl_ssi_ids); | ||
1145 | |||
1146 | static struct platform_driver fsl_ssi_driver = { | 1581 | static struct platform_driver fsl_ssi_driver = { |
1147 | .driver = { | 1582 | .driver = { |
1148 | .name = "fsl-ssi-dai", | 1583 | .name = "fsl-ssi-dai", |
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..2585ae44e634 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c | |||
@@ -41,9 +41,6 @@ static const struct snd_pcm_hardware imx_pcm_hardware = { | |||
41 | SNDRV_PCM_INFO_PAUSE | | 41 | SNDRV_PCM_INFO_PAUSE | |
42 | SNDRV_PCM_INFO_RESUME, | 42 | SNDRV_PCM_INFO_RESUME, |
43 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 43 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
44 | .rate_min = 8000, | ||
45 | .channels_min = 2, | ||
46 | .channels_max = 2, | ||
47 | .buffer_bytes_max = IMX_SSI_DMABUF_SIZE, | 44 | .buffer_bytes_max = IMX_SSI_DMABUF_SIZE, |
48 | .period_bytes_min = 128, | 45 | .period_bytes_min = 128, |
49 | .period_bytes_max = 65535, /* Limited by SDMA engine */ | 46 | .period_bytes_max = 65535, /* Limited by SDMA engine */ |
@@ -61,16 +58,11 @@ static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = { | |||
61 | 58 | ||
62 | int imx_pcm_dma_init(struct platform_device *pdev) | 59 | int imx_pcm_dma_init(struct platform_device *pdev) |
63 | { | 60 | { |
64 | return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config, | 61 | return devm_snd_dmaengine_pcm_register(&pdev->dev, |
62 | &imx_dmaengine_pcm_config, | ||
65 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | 63 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | |
66 | SND_DMAENGINE_PCM_FLAG_COMPAT); | 64 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
67 | } | 65 | } |
68 | EXPORT_SYMBOL_GPL(imx_pcm_dma_init); | 66 | EXPORT_SYMBOL_GPL(imx_pcm_dma_init); |
69 | 67 | ||
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"); | 68 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index c75d43bb2e92..6553202dd48c 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c | |||
@@ -162,9 +162,6 @@ static struct snd_pcm_hardware snd_imx_hardware = { | |||
162 | SNDRV_PCM_INFO_PAUSE | | 162 | SNDRV_PCM_INFO_PAUSE | |
163 | SNDRV_PCM_INFO_RESUME, | 163 | SNDRV_PCM_INFO_RESUME, |
164 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 164 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
165 | .rate_min = 8000, | ||
166 | .channels_min = 2, | ||
167 | .channels_max = 2, | ||
168 | .buffer_bytes_max = IMX_SSI_DMABUF_SIZE, | 165 | .buffer_bytes_max = IMX_SSI_DMABUF_SIZE, |
169 | .period_bytes_min = 128, | 166 | .period_bytes_min = 128, |
170 | .period_bytes_max = 16 * 1024, | 167 | .period_bytes_max = 16 * 1024, |
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/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 71bf2f248cd4..f2b5d756b1f3 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c | |||
@@ -200,10 +200,6 @@ static const struct snd_pcm_hardware psc_dma_hardware = { | |||
200 | SNDRV_PCM_INFO_BATCH, | 200 | SNDRV_PCM_INFO_BATCH, |
201 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | | 201 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | |
202 | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE, | 202 | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE, |
203 | .rate_min = 8000, | ||
204 | .rate_max = 48000, | ||
205 | .channels_min = 1, | ||
206 | .channels_max = 2, | ||
207 | .period_bytes_max = 1024 * 1024, | 203 | .period_bytes_max = 1024 * 1024, |
208 | .period_bytes_min = 32, | 204 | .period_bytes_min = 32, |
209 | .periods_min = 2, | 205 | .periods_min = 2, |
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index f4efaadb80a2..5d07e8a74a21 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c | |||
@@ -26,8 +26,7 @@ | |||
26 | * ALSA that we support all rates and let the codec driver decide what rates | 26 | * ALSA that we support all rates and let the codec driver decide what rates |
27 | * are really supported. | 27 | * are really supported. |
28 | */ | 28 | */ |
29 | #define PSC_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ | 29 | #define PSC_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS |
30 | SNDRV_PCM_RATE_CONTINUOUS) | ||
31 | 30 | ||
32 | /** | 31 | /** |
33 | * PSC_I2S_FORMATS: audio formats supported by the PSC I2S mode | 32 | * PSC_I2S_FORMATS: audio formats supported by the PSC I2S mode |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index b2fbb7075a6c..2a1b1b5b5221 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -8,14 +8,13 @@ | |||
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/platform_device.h> | ||
13 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/of.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/string.h> | ||
14 | #include <sound/simple_card.h> | 16 | #include <sound/simple_card.h> |
15 | 17 | ||
16 | #define asoc_simple_get_card_info(p) \ | ||
17 | container_of(p->dai_link, struct asoc_simple_card_info, snd_link) | ||
18 | |||
19 | static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, | 18 | static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, |
20 | struct asoc_simple_dai *set, | 19 | struct asoc_simple_dai *set, |
21 | unsigned int daifmt) | 20 | unsigned int daifmt) |
@@ -24,7 +23,7 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, | |||
24 | 23 | ||
25 | daifmt |= set->fmt; | 24 | daifmt |= set->fmt; |
26 | 25 | ||
27 | if (!ret && daifmt) | 26 | if (daifmt) |
28 | ret = snd_soc_dai_set_fmt(dai, daifmt); | 27 | ret = snd_soc_dai_set_fmt(dai, daifmt); |
29 | 28 | ||
30 | if (ret == -ENOTSUPP) { | 29 | if (ret == -ENOTSUPP) { |
@@ -40,7 +39,8 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, | |||
40 | 39 | ||
41 | static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | 40 | static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) |
42 | { | 41 | { |
43 | struct asoc_simple_card_info *info = asoc_simple_get_card_info(rtd); | 42 | struct asoc_simple_card_info *info = |
43 | snd_soc_card_get_drvdata(rtd->card); | ||
44 | struct snd_soc_dai *codec = rtd->codec_dai; | 44 | struct snd_soc_dai *codec = rtd->codec_dai; |
45 | struct snd_soc_dai *cpu = rtd->cpu_dai; | 45 | struct snd_soc_dai *cpu = rtd->cpu_dai; |
46 | unsigned int daifmt = info->daifmt; | 46 | unsigned int daifmt = info->daifmt; |
@@ -57,22 +57,182 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
57 | return 0; | 57 | return 0; |
58 | } | 58 | } |
59 | 59 | ||
60 | static int | ||
61 | asoc_simple_card_sub_parse_of(struct device_node *np, | ||
62 | struct asoc_simple_dai *dai, | ||
63 | struct device_node **node) | ||
64 | { | ||
65 | struct clk *clk; | ||
66 | int ret; | ||
67 | |||
68 | /* | ||
69 | * get node via "sound-dai = <&phandle port>" | ||
70 | * it will be used as xxx_of_node on soc_bind_dai_link() | ||
71 | */ | ||
72 | *node = of_parse_phandle(np, "sound-dai", 0); | ||
73 | if (!*node) | ||
74 | return -ENODEV; | ||
75 | |||
76 | /* get dai->name */ | ||
77 | ret = snd_soc_of_get_dai_name(np, &dai->name); | ||
78 | if (ret < 0) | ||
79 | goto parse_error; | ||
80 | |||
81 | /* | ||
82 | * bitclock-inversion, frame-inversion | ||
83 | * bitclock-master, frame-master | ||
84 | * and specific "format" if it has | ||
85 | */ | ||
86 | dai->fmt = snd_soc_of_parse_daifmt(np, NULL); | ||
87 | |||
88 | /* | ||
89 | * dai->sysclk come from | ||
90 | * "clocks = <&xxx>" (if system has common clock) | ||
91 | * or "system-clock-frequency = <xxx>" | ||
92 | * or device's module clock. | ||
93 | */ | ||
94 | if (of_property_read_bool(np, "clocks")) { | ||
95 | clk = of_clk_get(np, 0); | ||
96 | if (IS_ERR(clk)) { | ||
97 | ret = PTR_ERR(clk); | ||
98 | goto parse_error; | ||
99 | } | ||
100 | |||
101 | dai->sysclk = clk_get_rate(clk); | ||
102 | } else if (of_property_read_bool(np, "system-clock-frequency")) { | ||
103 | of_property_read_u32(np, | ||
104 | "system-clock-frequency", | ||
105 | &dai->sysclk); | ||
106 | } else { | ||
107 | clk = of_clk_get(*node, 0); | ||
108 | if (!IS_ERR(clk)) | ||
109 | dai->sysclk = clk_get_rate(clk); | ||
110 | } | ||
111 | |||
112 | ret = 0; | ||
113 | |||
114 | parse_error: | ||
115 | of_node_put(*node); | ||
116 | |||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | static int asoc_simple_card_parse_of(struct device_node *node, | ||
121 | struct asoc_simple_card_info *info, | ||
122 | struct device *dev, | ||
123 | struct device_node **of_cpu, | ||
124 | struct device_node **of_codec, | ||
125 | struct device_node **of_platform) | ||
126 | { | ||
127 | struct device_node *np; | ||
128 | char *name; | ||
129 | int ret; | ||
130 | |||
131 | /* get CPU/CODEC common format via simple-audio-card,format */ | ||
132 | info->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & | ||
133 | (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); | ||
134 | |||
135 | /* DAPM routes */ | ||
136 | if (of_property_read_bool(node, "simple-audio-card,routing")) { | ||
137 | ret = snd_soc_of_parse_audio_routing(&info->snd_card, | ||
138 | "simple-audio-card,routing"); | ||
139 | if (ret) | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | /* CPU sub-node */ | ||
144 | ret = -EINVAL; | ||
145 | np = of_get_child_by_name(node, "simple-audio-card,cpu"); | ||
146 | if (np) | ||
147 | ret = asoc_simple_card_sub_parse_of(np, | ||
148 | &info->cpu_dai, | ||
149 | of_cpu); | ||
150 | if (ret < 0) | ||
151 | return ret; | ||
152 | |||
153 | /* CODEC sub-node */ | ||
154 | ret = -EINVAL; | ||
155 | np = of_get_child_by_name(node, "simple-audio-card,codec"); | ||
156 | if (np) | ||
157 | ret = asoc_simple_card_sub_parse_of(np, | ||
158 | &info->codec_dai, | ||
159 | of_codec); | ||
160 | if (ret < 0) | ||
161 | return ret; | ||
162 | |||
163 | if (!info->cpu_dai.name || !info->codec_dai.name) | ||
164 | return -EINVAL; | ||
165 | |||
166 | /* card name is created from CPU/CODEC dai name */ | ||
167 | name = devm_kzalloc(dev, | ||
168 | strlen(info->cpu_dai.name) + | ||
169 | strlen(info->codec_dai.name) + 2, | ||
170 | GFP_KERNEL); | ||
171 | sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); | ||
172 | info->name = info->card = name; | ||
173 | |||
174 | /* simple-card assumes platform == cpu */ | ||
175 | *of_platform = *of_cpu; | ||
176 | |||
177 | dev_dbg(dev, "card-name : %s\n", info->card); | ||
178 | dev_dbg(dev, "platform : %04x\n", info->daifmt); | ||
179 | dev_dbg(dev, "cpu : %s / %04x / %d\n", | ||
180 | info->cpu_dai.name, | ||
181 | info->cpu_dai.fmt, | ||
182 | info->cpu_dai.sysclk); | ||
183 | dev_dbg(dev, "codec : %s / %04x / %d\n", | ||
184 | info->codec_dai.name, | ||
185 | info->codec_dai.fmt, | ||
186 | info->codec_dai.sysclk); | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
60 | static int asoc_simple_card_probe(struct platform_device *pdev) | 191 | static int asoc_simple_card_probe(struct platform_device *pdev) |
61 | { | 192 | { |
62 | struct asoc_simple_card_info *cinfo = pdev->dev.platform_data; | 193 | struct asoc_simple_card_info *cinfo; |
194 | struct device_node *np = pdev->dev.of_node; | ||
195 | struct device_node *of_cpu, *of_codec, *of_platform; | ||
63 | struct device *dev = &pdev->dev; | 196 | struct device *dev = &pdev->dev; |
197 | int ret; | ||
64 | 198 | ||
65 | if (!cinfo) { | 199 | cinfo = NULL; |
66 | dev_err(dev, "no info for asoc-simple-card\n"); | 200 | of_cpu = NULL; |
67 | return -EINVAL; | 201 | of_codec = NULL; |
202 | of_platform = NULL; | ||
203 | |||
204 | cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL); | ||
205 | if (!cinfo) | ||
206 | return -ENOMEM; | ||
207 | |||
208 | if (np && of_device_is_available(np)) { | ||
209 | cinfo->snd_card.dev = dev; | ||
210 | |||
211 | ret = asoc_simple_card_parse_of(np, cinfo, dev, | ||
212 | &of_cpu, | ||
213 | &of_codec, | ||
214 | &of_platform); | ||
215 | if (ret < 0) { | ||
216 | if (ret != -EPROBE_DEFER) | ||
217 | dev_err(dev, "parse error %d\n", ret); | ||
218 | return ret; | ||
219 | } | ||
220 | } else { | ||
221 | if (!dev->platform_data) { | ||
222 | dev_err(dev, "no info for asoc-simple-card\n"); | ||
223 | return -EINVAL; | ||
224 | } | ||
225 | |||
226 | memcpy(cinfo, dev->platform_data, sizeof(*cinfo)); | ||
227 | cinfo->snd_card.dev = dev; | ||
68 | } | 228 | } |
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,25 @@ 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 | snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); |
101 | } | ||
102 | 263 | ||
103 | static int asoc_simple_card_remove(struct platform_device *pdev) | 264 | return devm_snd_soc_register_card(&pdev->dev, &cinfo->snd_card); |
104 | { | ||
105 | struct asoc_simple_card_info *cinfo = pdev->dev.platform_data; | ||
106 | |||
107 | return snd_soc_unregister_card(&cinfo->snd_card); | ||
108 | } | 265 | } |
109 | 266 | ||
267 | static const struct of_device_id asoc_simple_of_match[] = { | ||
268 | { .compatible = "simple-audio-card", }, | ||
269 | {}, | ||
270 | }; | ||
271 | MODULE_DEVICE_TABLE(of, asoc_simple_of_match); | ||
272 | |||
110 | static struct platform_driver asoc_simple_card = { | 273 | static struct platform_driver asoc_simple_card = { |
111 | .driver = { | 274 | .driver = { |
112 | .name = "asoc-simple-card", | 275 | .name = "asoc-simple-card", |
113 | .owner = THIS_MODULE, | 276 | .owner = THIS_MODULE, |
277 | .of_match_table = asoc_simple_of_match, | ||
114 | }, | 278 | }, |
115 | .probe = asoc_simple_card_probe, | 279 | .probe = asoc_simple_card_probe, |
116 | .remove = asoc_simple_card_remove, | ||
117 | }; | 280 | }; |
118 | 281 | ||
119 | module_platform_driver(asoc_simple_card); | 282 | 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..f465a8180863 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/intel/sst_platform.c | |||
@@ -89,16 +89,6 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = { | |||
89 | SNDRV_PCM_INFO_MMAP_VALID | | 89 | SNDRV_PCM_INFO_MMAP_VALID | |
90 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 90 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
91 | SNDRV_PCM_INFO_SYNC_START), | 91 | SNDRV_PCM_INFO_SYNC_START), |
92 | .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 | | ||
93 | SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 | | ||
94 | SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32), | ||
95 | .rates = (SNDRV_PCM_RATE_8000| | ||
96 | SNDRV_PCM_RATE_44100 | | ||
97 | SNDRV_PCM_RATE_48000), | ||
98 | .rate_min = SST_MIN_RATE, | ||
99 | .rate_max = SST_MAX_RATE, | ||
100 | .channels_min = SST_MIN_CHANNEL, | ||
101 | .channels_max = SST_MAX_CHANNEL, | ||
102 | .buffer_bytes_max = SST_MAX_BUFFER, | 92 | .buffer_bytes_max = SST_MAX_BUFFER, |
103 | .period_bytes_min = SST_MIN_PERIOD_BYTES, | 93 | .period_bytes_min = SST_MIN_PERIOD_BYTES, |
104 | .period_bytes_max = SST_MAX_PERIOD_BYTES, | 94 | .period_bytes_max = SST_MAX_PERIOD_BYTES, |
diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/intel/sst_platform.h index cacc9066ec52..bee64fb7d2ef 100644 --- a/sound/soc/mid-x86/sst_platform.h +++ b/sound/soc/intel/sst_platform.h | |||
@@ -33,10 +33,6 @@ | |||
33 | #define SST_STEREO 2 | 33 | #define SST_STEREO 2 |
34 | #define SST_MAX_CAP 5 | 34 | #define SST_MAX_CAP 5 |
35 | 35 | ||
36 | #define SST_MIN_RATE 8000 | ||
37 | #define SST_MAX_RATE 48000 | ||
38 | #define SST_MIN_CHANNEL 1 | ||
39 | #define SST_MAX_CHANNEL 5 | ||
40 | #define SST_MAX_BUFFER (800*1024) | 36 | #define SST_MAX_BUFFER (800*1024) |
41 | #define SST_MIN_BUFFER (800*1024) | 37 | #define SST_MIN_BUFFER (800*1024) |
42 | #define SST_MIN_PERIOD_BYTES 32 | 38 | #define SST_MIN_PERIOD_BYTES 32 |
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-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index 4af1936cf0f4..aac22fccdcdc 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c | |||
@@ -21,16 +21,6 @@ | |||
21 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
22 | #include "kirkwood.h" | 22 | #include "kirkwood.h" |
23 | 23 | ||
24 | #define KIRKWOOD_RATES \ | ||
25 | (SNDRV_PCM_RATE_8000_192000 | \ | ||
26 | SNDRV_PCM_RATE_CONTINUOUS | \ | ||
27 | SNDRV_PCM_RATE_KNOT) | ||
28 | |||
29 | #define KIRKWOOD_FORMATS \ | ||
30 | (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
31 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
32 | SNDRV_PCM_FMTBIT_S32_LE) | ||
33 | |||
34 | static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs) | 24 | static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs) |
35 | { | 25 | { |
36 | struct snd_soc_pcm_runtime *soc_runtime = subs->private_data; | 26 | struct snd_soc_pcm_runtime *soc_runtime = subs->private_data; |
@@ -43,12 +33,6 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = { | |||
43 | SNDRV_PCM_INFO_MMAP_VALID | | 33 | SNDRV_PCM_INFO_MMAP_VALID | |
44 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 34 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
45 | SNDRV_PCM_INFO_PAUSE), | 35 | SNDRV_PCM_INFO_PAUSE), |
46 | .formats = KIRKWOOD_FORMATS, | ||
47 | .rates = KIRKWOOD_RATES, | ||
48 | .rate_min = 8000, | ||
49 | .rate_max = 384000, | ||
50 | .channels_min = 1, | ||
51 | .channels_max = 8, | ||
52 | .buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES, | 36 | .buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES, |
53 | .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, | 37 | .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, |
54 | .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES, | 38 | .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES, |
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index b16abbbf7764..a371b4f91c53 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c | |||
@@ -36,11 +36,6 @@ static const struct snd_pcm_hardware snd_mxs_hardware = { | |||
36 | SNDRV_PCM_INFO_RESUME | | 36 | SNDRV_PCM_INFO_RESUME | |
37 | SNDRV_PCM_INFO_INTERLEAVED | | 37 | SNDRV_PCM_INFO_INTERLEAVED | |
38 | SNDRV_PCM_INFO_HALF_DUPLEX, | 38 | SNDRV_PCM_INFO_HALF_DUPLEX, |
39 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
40 | SNDRV_PCM_FMTBIT_S20_3LE | | ||
41 | SNDRV_PCM_FMTBIT_S24_LE, | ||
42 | .channels_min = 2, | ||
43 | .channels_max = 2, | ||
44 | .period_bytes_min = 32, | 39 | .period_bytes_min = 32, |
45 | .period_bytes_max = 8192, | 40 | .period_bytes_max = 8192, |
46 | .periods_min = 1, | 41 | .periods_min = 1, |
@@ -56,16 +51,9 @@ static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = { | |||
56 | 51 | ||
57 | int mxs_pcm_platform_register(struct device *dev) | 52 | int mxs_pcm_platform_register(struct device *dev) |
58 | { | 53 | { |
59 | return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config, | 54 | return devm_snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config, |
60 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | ||
61 | SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX); | 55 | SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX); |
62 | } | 56 | } |
63 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); | 57 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); |
64 | 58 | ||
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"); | 59 | 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/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c index f588ee45b4fd..f434ed79d1b6 100644 --- a/sound/soc/nuc900/nuc900-pcm.c +++ b/sound/soc/nuc900/nuc900-pcm.c | |||
@@ -32,9 +32,6 @@ static const struct snd_pcm_hardware nuc900_pcm_hardware = { | |||
32 | SNDRV_PCM_INFO_MMAP_VALID | | 32 | SNDRV_PCM_INFO_MMAP_VALID | |
33 | SNDRV_PCM_INFO_PAUSE | | 33 | SNDRV_PCM_INFO_PAUSE | |
34 | SNDRV_PCM_INFO_RESUME, | 34 | SNDRV_PCM_INFO_RESUME, |
35 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
36 | .channels_min = 1, | ||
37 | .channels_max = 2, | ||
38 | .buffer_bytes_max = 4*1024, | 35 | .buffer_bytes_max = 4*1024, |
39 | .period_bytes_min = 1*1024, | 36 | .period_bytes_min = 1*1024, |
40 | .period_bytes_max = 4*1024, | 37 | .period_bytes_max = 4*1024, |
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/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-i2s.c b/sound/soc/s6000/s6000-i2s.c index 73bb99f0109a..7eba7979b9af 100644 --- a/sound/soc/s6000/s6000-i2s.c +++ b/sound/soc/s6000/s6000-i2s.c | |||
@@ -405,8 +405,7 @@ static int s6000_i2s_dai_probe(struct snd_soc_dai *dai) | |||
405 | return 0; | 405 | return 0; |
406 | } | 406 | } |
407 | 407 | ||
408 | #define S6000_I2S_RATES (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_5512 | \ | 408 | #define S6000_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS |
409 | SNDRV_PCM_RATE_8000_192000) | ||
410 | #define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | 409 | #define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) |
411 | 410 | ||
412 | static const struct snd_soc_dai_ops s6000_i2s_dai_ops = { | 411 | static const struct snd_soc_dai_ops s6000_i2s_dai_ops = { |
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..750ce5808d9f --- /dev/null +++ b/sound/soc/samsung/dmaengine.c | |||
@@ -0,0 +1,83 @@ | |||
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_COMPAT); | ||
72 | } | ||
73 | EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); | ||
74 | |||
75 | void samsung_asoc_dma_platform_unregister(struct device *dev) | ||
76 | { | ||
77 | return snd_dmaengine_pcm_unregister(dev); | ||
78 | } | ||
79 | EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_unregister); | ||
80 | |||
81 | MODULE_AUTHOR("Mark Brown <broonie@linaro.org>"); | ||
82 | MODULE_DESCRIPTION("Samsung dmaengine ASoC driver"); | ||
83 | 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/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index 1a8b03e4b41b..c85f8eb66c97 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c | |||
@@ -89,29 +89,12 @@ struct camelot_pcm { | |||
89 | #define DMABRG_PREALLOC_BUFFER 32 * 1024 | 89 | #define DMABRG_PREALLOC_BUFFER 32 * 1024 |
90 | #define DMABRG_PREALLOC_BUFFER_MAX 32 * 1024 | 90 | #define DMABRG_PREALLOC_BUFFER_MAX 32 * 1024 |
91 | 91 | ||
92 | /* support everything the SSI supports */ | ||
93 | #define DMABRG_RATES \ | ||
94 | SNDRV_PCM_RATE_8000_192000 | ||
95 | |||
96 | #define DMABRG_FMTS \ | ||
97 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \ | ||
98 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \ | ||
99 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \ | ||
100 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \ | ||
101 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE) | ||
102 | |||
103 | static struct snd_pcm_hardware camelot_pcm_hardware = { | 92 | static struct snd_pcm_hardware camelot_pcm_hardware = { |
104 | .info = (SNDRV_PCM_INFO_MMAP | | 93 | .info = (SNDRV_PCM_INFO_MMAP | |
105 | SNDRV_PCM_INFO_INTERLEAVED | | 94 | SNDRV_PCM_INFO_INTERLEAVED | |
106 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 95 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
107 | SNDRV_PCM_INFO_MMAP_VALID | | 96 | SNDRV_PCM_INFO_MMAP_VALID | |
108 | SNDRV_PCM_INFO_BATCH), | 97 | SNDRV_PCM_INFO_BATCH), |
109 | .formats = DMABRG_FMTS, | ||
110 | .rates = DMABRG_RATES, | ||
111 | .rate_min = 8000, | ||
112 | .rate_max = 192000, | ||
113 | .channels_min = 2, | ||
114 | .channels_max = 8, /* max of the SSI */ | ||
115 | .buffer_bytes_max = DMABRG_PERIOD_MAX, | 98 | .buffer_bytes_max = DMABRG_PERIOD_MAX, |
116 | .period_bytes_min = DMABRG_PERIOD_MIN, | 99 | .period_bytes_min = DMABRG_PERIOD_MIN, |
117 | .period_bytes_max = DMABRG_PERIOD_MAX / 2, | 100 | .period_bytes_max = DMABRG_PERIOD_MAX / 2, |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index b33ca7cd085b..1967f44e7cd4 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; |
@@ -1777,12 +1787,6 @@ static struct snd_pcm_hardware fsi_pcm_hardware = { | |||
1777 | SNDRV_PCM_INFO_MMAP | | 1787 | SNDRV_PCM_INFO_MMAP | |
1778 | SNDRV_PCM_INFO_MMAP_VALID | | 1788 | SNDRV_PCM_INFO_MMAP_VALID | |
1779 | SNDRV_PCM_INFO_PAUSE, | 1789 | SNDRV_PCM_INFO_PAUSE, |
1780 | .formats = FSI_FMTS, | ||
1781 | .rates = FSI_RATES, | ||
1782 | .rate_min = 8000, | ||
1783 | .rate_max = 192000, | ||
1784 | .channels_min = 2, | ||
1785 | .channels_max = 2, | ||
1786 | .buffer_bytes_max = 64 * 1024, | 1790 | .buffer_bytes_max = 64 * 1024, |
1787 | .period_bytes_min = 32, | 1791 | .period_bytes_min = 32, |
1788 | .period_bytes_max = 8192, | 1792 | .period_bytes_max = 8192, |
@@ -1960,7 +1964,7 @@ static void fsi_handler_init(struct fsi_priv *fsi, | |||
1960 | fsi->capture.priv = fsi; | 1964 | fsi->capture.priv = fsi; |
1961 | 1965 | ||
1962 | if (info->tx_id) { | 1966 | if (info->tx_id) { |
1963 | fsi->playback.slave.shdma_slave.slave_id = info->tx_id; | 1967 | fsi->playback.dma_id = info->tx_id; |
1964 | fsi->playback.handler = &fsi_dma_push_handler; | 1968 | fsi->playback.handler = &fsi_dma_push_handler; |
1965 | } | 1969 | } |
1966 | } | 1970 | } |
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/core.c b/sound/soc/sh/rcar/core.c index b3653d37f75f..743de5e3b1e1 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -628,12 +628,6 @@ static struct snd_pcm_hardware rsnd_pcm_hardware = { | |||
628 | SNDRV_PCM_INFO_MMAP | | 628 | SNDRV_PCM_INFO_MMAP | |
629 | SNDRV_PCM_INFO_MMAP_VALID | | 629 | SNDRV_PCM_INFO_MMAP_VALID | |
630 | SNDRV_PCM_INFO_PAUSE, | 630 | SNDRV_PCM_INFO_PAUSE, |
631 | .formats = RSND_FMTS, | ||
632 | .rates = RSND_RATES, | ||
633 | .rate_min = 8000, | ||
634 | .rate_max = 192000, | ||
635 | .channels_min = 2, | ||
636 | .channels_max = 2, | ||
637 | .buffer_bytes_max = 64 * 1024, | 631 | .buffer_bytes_max = 64 * 1024, |
638 | .period_bytes_min = 32, | 632 | .period_bytes_min = 32, |
639 | .period_bytes_max = 8192, | 633 | .period_bytes_max = 8192, |
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-compress.c b/sound/soc/soc-compress.c index 53c9ecdd119f..5e9690c85d8f 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <sound/compress_driver.h> | 24 | #include <sound/compress_driver.h> |
25 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
26 | #include <sound/initval.h> | 26 | #include <sound/initval.h> |
27 | #include <sound/soc-dpcm.h> | ||
27 | 28 | ||
28 | static int soc_compr_open(struct snd_compr_stream *cstream) | 29 | static int soc_compr_open(struct snd_compr_stream *cstream) |
29 | { | 30 | { |
@@ -75,6 +76,98 @@ out: | |||
75 | return ret; | 76 | return ret; |
76 | } | 77 | } |
77 | 78 | ||
79 | static int soc_compr_open_fe(struct snd_compr_stream *cstream) | ||
80 | { | ||
81 | struct snd_soc_pcm_runtime *fe = cstream->private_data; | ||
82 | struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; | ||
83 | struct snd_soc_platform *platform = fe->platform; | ||
84 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; | ||
85 | struct snd_soc_dai *codec_dai = fe->codec_dai; | ||
86 | struct snd_soc_dpcm *dpcm; | ||
87 | struct snd_soc_dapm_widget_list *list; | ||
88 | int stream; | ||
89 | int ret = 0; | ||
90 | |||
91 | if (cstream->direction == SND_COMPRESS_PLAYBACK) | ||
92 | stream = SNDRV_PCM_STREAM_PLAYBACK; | ||
93 | else | ||
94 | stream = SNDRV_PCM_STREAM_CAPTURE; | ||
95 | |||
96 | mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); | ||
97 | |||
98 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { | ||
99 | ret = platform->driver->compr_ops->open(cstream); | ||
100 | if (ret < 0) { | ||
101 | pr_err("compress asoc: can't open platform %s\n", platform->name); | ||
102 | goto out; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) { | ||
107 | ret = fe->dai_link->compr_ops->startup(cstream); | ||
108 | if (ret < 0) { | ||
109 | pr_err("compress asoc: %s startup failed\n", fe->dai_link->name); | ||
110 | goto machine_err; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | fe->dpcm[stream].runtime = fe_substream->runtime; | ||
115 | |||
116 | if (dpcm_path_get(fe, stream, &list) <= 0) { | ||
117 | dev_dbg(fe->dev, "ASoC: %s no valid %s route\n", | ||
118 | fe->dai_link->name, stream ? "capture" : "playback"); | ||
119 | } | ||
120 | |||
121 | /* calculate valid and active FE <-> BE dpcms */ | ||
122 | dpcm_process_paths(fe, stream, &list, 1); | ||
123 | |||
124 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; | ||
125 | |||
126 | ret = dpcm_be_dai_startup(fe, stream); | ||
127 | if (ret < 0) { | ||
128 | /* clean up all links */ | ||
129 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) | ||
130 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; | ||
131 | |||
132 | dpcm_be_disconnect(fe, stream); | ||
133 | fe->dpcm[stream].runtime = NULL; | ||
134 | goto fe_err; | ||
135 | } | ||
136 | |||
137 | dpcm_clear_pending_state(fe, stream); | ||
138 | dpcm_path_put(&list); | ||
139 | |||
140 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; | ||
141 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | ||
142 | |||
143 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | ||
144 | cpu_dai->playback_active++; | ||
145 | codec_dai->playback_active++; | ||
146 | } else { | ||
147 | cpu_dai->capture_active++; | ||
148 | codec_dai->capture_active++; | ||
149 | } | ||
150 | |||
151 | cpu_dai->active++; | ||
152 | codec_dai->active++; | ||
153 | fe->codec->active++; | ||
154 | |||
155 | mutex_unlock(&fe->card->mutex); | ||
156 | |||
157 | return 0; | ||
158 | |||
159 | fe_err: | ||
160 | if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown) | ||
161 | fe->dai_link->compr_ops->shutdown(cstream); | ||
162 | machine_err: | ||
163 | if (platform->driver->compr_ops && platform->driver->compr_ops->free) | ||
164 | platform->driver->compr_ops->free(cstream); | ||
165 | out: | ||
166 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | ||
167 | mutex_unlock(&fe->card->mutex); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
78 | /* | 171 | /* |
79 | * Power down the audio subsystem pmdown_time msecs after close is called. | 172 | * Power down the audio subsystem pmdown_time msecs after close is called. |
80 | * This is to ensure there are no pops or clicks in between any music tracks | 173 | * This is to ensure there are no pops or clicks in between any music tracks |
@@ -164,6 +257,65 @@ static int soc_compr_free(struct snd_compr_stream *cstream) | |||
164 | return 0; | 257 | return 0; |
165 | } | 258 | } |
166 | 259 | ||
260 | static int soc_compr_free_fe(struct snd_compr_stream *cstream) | ||
261 | { | ||
262 | struct snd_soc_pcm_runtime *fe = cstream->private_data; | ||
263 | struct snd_soc_platform *platform = fe->platform; | ||
264 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; | ||
265 | struct snd_soc_dai *codec_dai = fe->codec_dai; | ||
266 | struct snd_soc_dpcm *dpcm; | ||
267 | int stream, ret; | ||
268 | |||
269 | mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); | ||
270 | |||
271 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | ||
272 | stream = SNDRV_PCM_STREAM_PLAYBACK; | ||
273 | cpu_dai->playback_active--; | ||
274 | codec_dai->playback_active--; | ||
275 | } else { | ||
276 | stream = SNDRV_PCM_STREAM_CAPTURE; | ||
277 | cpu_dai->capture_active--; | ||
278 | codec_dai->capture_active--; | ||
279 | } | ||
280 | |||
281 | cpu_dai->active--; | ||
282 | codec_dai->active--; | ||
283 | fe->codec->active--; | ||
284 | |||
285 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; | ||
286 | |||
287 | ret = dpcm_be_dai_hw_free(fe, stream); | ||
288 | if (ret < 0) | ||
289 | dev_err(fe->dev, "compressed hw_free failed %d\n", ret); | ||
290 | |||
291 | ret = dpcm_be_dai_shutdown(fe, stream); | ||
292 | |||
293 | /* mark FE's links ready to prune */ | ||
294 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) | ||
295 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; | ||
296 | |||
297 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
298 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); | ||
299 | else | ||
300 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); | ||
301 | |||
302 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; | ||
303 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | ||
304 | |||
305 | dpcm_be_disconnect(fe, stream); | ||
306 | |||
307 | fe->dpcm[stream].runtime = NULL; | ||
308 | |||
309 | if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown) | ||
310 | fe->dai_link->compr_ops->shutdown(cstream); | ||
311 | |||
312 | if (platform->driver->compr_ops && platform->driver->compr_ops->free) | ||
313 | platform->driver->compr_ops->free(cstream); | ||
314 | |||
315 | mutex_unlock(&fe->card->mutex); | ||
316 | return 0; | ||
317 | } | ||
318 | |||
167 | static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) | 319 | static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) |
168 | { | 320 | { |
169 | 321 | ||
@@ -194,6 +346,59 @@ out: | |||
194 | return ret; | 346 | return ret; |
195 | } | 347 | } |
196 | 348 | ||
349 | static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) | ||
350 | { | ||
351 | struct snd_soc_pcm_runtime *fe = cstream->private_data; | ||
352 | struct snd_soc_platform *platform = fe->platform; | ||
353 | int ret = 0, stream; | ||
354 | |||
355 | if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN || | ||
356 | cmd == SND_COMPR_TRIGGER_DRAIN) { | ||
357 | |||
358 | if (platform->driver->compr_ops && | ||
359 | platform->driver->compr_ops->trigger) | ||
360 | return platform->driver->compr_ops->trigger(cstream, cmd); | ||
361 | } | ||
362 | |||
363 | if (cstream->direction == SND_COMPRESS_PLAYBACK) | ||
364 | stream = SNDRV_PCM_STREAM_PLAYBACK; | ||
365 | else | ||
366 | stream = SNDRV_PCM_STREAM_CAPTURE; | ||
367 | |||
368 | |||
369 | mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); | ||
370 | |||
371 | if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) { | ||
372 | ret = platform->driver->compr_ops->trigger(cstream, cmd); | ||
373 | if (ret < 0) | ||
374 | goto out; | ||
375 | } | ||
376 | |||
377 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; | ||
378 | |||
379 | ret = dpcm_be_dai_trigger(fe, stream, cmd); | ||
380 | |||
381 | switch (cmd) { | ||
382 | case SNDRV_PCM_TRIGGER_START: | ||
383 | case SNDRV_PCM_TRIGGER_RESUME: | ||
384 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
385 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START; | ||
386 | break; | ||
387 | case SNDRV_PCM_TRIGGER_STOP: | ||
388 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
389 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; | ||
390 | break; | ||
391 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
392 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED; | ||
393 | break; | ||
394 | } | ||
395 | |||
396 | out: | ||
397 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | ||
398 | mutex_unlock(&fe->card->mutex); | ||
399 | return ret; | ||
400 | } | ||
401 | |||
197 | static int soc_compr_set_params(struct snd_compr_stream *cstream, | 402 | static int soc_compr_set_params(struct snd_compr_stream *cstream, |
198 | struct snd_compr_params *params) | 403 | struct snd_compr_params *params) |
199 | { | 404 | { |
@@ -241,6 +446,64 @@ err: | |||
241 | return ret; | 446 | return ret; |
242 | } | 447 | } |
243 | 448 | ||
449 | static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, | ||
450 | struct snd_compr_params *params) | ||
451 | { | ||
452 | struct snd_soc_pcm_runtime *fe = cstream->private_data; | ||
453 | struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; | ||
454 | struct snd_soc_platform *platform = fe->platform; | ||
455 | int ret = 0, stream; | ||
456 | |||
457 | if (cstream->direction == SND_COMPRESS_PLAYBACK) | ||
458 | stream = SNDRV_PCM_STREAM_PLAYBACK; | ||
459 | else | ||
460 | stream = SNDRV_PCM_STREAM_CAPTURE; | ||
461 | |||
462 | mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); | ||
463 | |||
464 | if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) { | ||
465 | ret = platform->driver->compr_ops->set_params(cstream, params); | ||
466 | if (ret < 0) | ||
467 | goto out; | ||
468 | } | ||
469 | |||
470 | if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) { | ||
471 | ret = fe->dai_link->compr_ops->set_params(cstream); | ||
472 | if (ret < 0) | ||
473 | goto out; | ||
474 | } | ||
475 | |||
476 | /* | ||
477 | * Create an empty hw_params for the BE as the machine driver must | ||
478 | * fix this up to match DSP decoder and ASRC configuration. | ||
479 | * I.e. machine driver fixup for compressed BE is mandatory. | ||
480 | */ | ||
481 | memset(&fe->dpcm[fe_substream->stream].hw_params, 0, | ||
482 | sizeof(struct snd_pcm_hw_params)); | ||
483 | |||
484 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; | ||
485 | |||
486 | ret = dpcm_be_dai_hw_params(fe, stream); | ||
487 | if (ret < 0) | ||
488 | goto out; | ||
489 | |||
490 | ret = dpcm_be_dai_prepare(fe, stream); | ||
491 | if (ret < 0) | ||
492 | goto out; | ||
493 | |||
494 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
495 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); | ||
496 | else | ||
497 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); | ||
498 | |||
499 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; | ||
500 | |||
501 | out: | ||
502 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | ||
503 | mutex_unlock(&fe->card->mutex); | ||
504 | return ret; | ||
505 | } | ||
506 | |||
244 | static int soc_compr_get_params(struct snd_compr_stream *cstream, | 507 | static int soc_compr_get_params(struct snd_compr_stream *cstream, |
245 | struct snd_codec *params) | 508 | struct snd_codec *params) |
246 | { | 509 | { |
@@ -360,6 +623,7 @@ static int soc_compr_get_metadata(struct snd_compr_stream *cstream, | |||
360 | 623 | ||
361 | return ret; | 624 | return ret; |
362 | } | 625 | } |
626 | |||
363 | /* ASoC Compress operations */ | 627 | /* ASoC Compress operations */ |
364 | static struct snd_compr_ops soc_compr_ops = { | 628 | static struct snd_compr_ops soc_compr_ops = { |
365 | .open = soc_compr_open, | 629 | .open = soc_compr_open, |
@@ -375,6 +639,21 @@ static struct snd_compr_ops soc_compr_ops = { | |||
375 | .get_codec_caps = soc_compr_get_codec_caps | 639 | .get_codec_caps = soc_compr_get_codec_caps |
376 | }; | 640 | }; |
377 | 641 | ||
642 | /* ASoC Dynamic Compress operations */ | ||
643 | static struct snd_compr_ops soc_compr_dyn_ops = { | ||
644 | .open = soc_compr_open_fe, | ||
645 | .free = soc_compr_free_fe, | ||
646 | .set_params = soc_compr_set_params_fe, | ||
647 | .get_params = soc_compr_get_params, | ||
648 | .set_metadata = soc_compr_set_metadata, | ||
649 | .get_metadata = soc_compr_get_metadata, | ||
650 | .trigger = soc_compr_trigger_fe, | ||
651 | .pointer = soc_compr_pointer, | ||
652 | .ack = soc_compr_ack, | ||
653 | .get_caps = soc_compr_get_caps, | ||
654 | .get_codec_caps = soc_compr_get_codec_caps | ||
655 | }; | ||
656 | |||
378 | /* create a new compress */ | 657 | /* create a new compress */ |
379 | int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) | 658 | int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) |
380 | { | 659 | { |
@@ -383,6 +662,7 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) | |||
383 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 662 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
384 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 663 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
385 | struct snd_compr *compr; | 664 | struct snd_compr *compr; |
665 | struct snd_pcm *be_pcm; | ||
386 | char new_name[64]; | 666 | char new_name[64]; |
387 | int ret = 0, direction = 0; | 667 | int ret = 0, direction = 0; |
388 | 668 | ||
@@ -410,7 +690,26 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) | |||
410 | ret = -ENOMEM; | 690 | ret = -ENOMEM; |
411 | goto compr_err; | 691 | goto compr_err; |
412 | } | 692 | } |
413 | memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); | 693 | |
694 | if (rtd->dai_link->dynamic) { | ||
695 | snprintf(new_name, sizeof(new_name), "(%s)", | ||
696 | rtd->dai_link->stream_name); | ||
697 | |||
698 | ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, | ||
699 | 1, 0, &be_pcm); | ||
700 | if (ret < 0) { | ||
701 | dev_err(rtd->card->dev, "ASoC: can't create compressed for %s\n", | ||
702 | rtd->dai_link->name); | ||
703 | goto compr_err; | ||
704 | } | ||
705 | |||
706 | rtd->pcm = be_pcm; | ||
707 | rtd->fe_compr = 1; | ||
708 | be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; | ||
709 | be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; | ||
710 | memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); | ||
711 | } else | ||
712 | memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); | ||
414 | 713 | ||
415 | /* Add copy callback for not memory mapped DSPs */ | 714 | /* Add copy callback for not memory mapped DSPs */ |
416 | if (platform->driver->compr_ops && platform->driver->compr_ops->copy) | 715 | if (platform->driver->compr_ops && platform->driver->compr_ops->copy) |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a66783e13a9c..fe1df50805a3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -1728,6 +1728,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1728 | } | 1728 | } |
1729 | 1729 | ||
1730 | snd_soc_dapm_link_dai_widgets(card); | 1730 | snd_soc_dapm_link_dai_widgets(card); |
1731 | snd_soc_dapm_connect_dai_link_widgets(card); | ||
1731 | 1732 | ||
1732 | if (card->controls) | 1733 | if (card->controls) |
1733 | snd_soc_add_card_controls(card, card->controls, card->num_controls); | 1734 | snd_soc_add_card_controls(card, card->controls, card->num_controls); |
@@ -3484,7 +3485,7 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
3484 | return dai->codec->driver->set_sysclk(dai->codec, clk_id, 0, | 3485 | return dai->codec->driver->set_sysclk(dai->codec, clk_id, 0, |
3485 | freq, dir); | 3486 | freq, dir); |
3486 | else | 3487 | else |
3487 | return -EINVAL; | 3488 | return -ENOTSUPP; |
3488 | } | 3489 | } |
3489 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); | 3490 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); |
3490 | 3491 | ||
@@ -3505,7 +3506,7 @@ int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
3505 | return codec->driver->set_sysclk(codec, clk_id, source, | 3506 | return codec->driver->set_sysclk(codec, clk_id, source, |
3506 | freq, dir); | 3507 | freq, dir); |
3507 | else | 3508 | else |
3508 | return -EINVAL; | 3509 | return -ENOTSUPP; |
3509 | } | 3510 | } |
3510 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_sysclk); | 3511 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_sysclk); |
3511 | 3512 | ||
@@ -4617,10 +4618,14 @@ int snd_soc_of_get_dai_name(struct device_node *of_node, | |||
4617 | 4618 | ||
4618 | if (id < 0 || id >= pos->num_dai) { | 4619 | if (id < 0 || id >= pos->num_dai) { |
4619 | ret = -EINVAL; | 4620 | ret = -EINVAL; |
4620 | } else { | 4621 | break; |
4621 | *dai_name = pos->dai_drv[id].name; | ||
4622 | ret = 0; | ||
4623 | } | 4622 | } |
4623 | |||
4624 | ret = 0; | ||
4625 | |||
4626 | *dai_name = pos->dai_drv[id].name; | ||
4627 | if (!*dai_name) | ||
4628 | *dai_name = pos->name; | ||
4624 | } | 4629 | } |
4625 | 4630 | ||
4626 | break; | 4631 | break; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dcade130157f..dc8ff13187f7 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -371,12 +371,16 @@ static void dapm_reset(struct snd_soc_card *card) | |||
371 | } | 371 | } |
372 | } | 372 | } |
373 | 373 | ||
374 | static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg) | 374 | static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg, |
375 | unsigned int *value) | ||
375 | { | 376 | { |
376 | if (w->codec) | 377 | if (w->codec) { |
377 | return snd_soc_read(w->codec, reg); | 378 | *value = snd_soc_read(w->codec, reg); |
378 | else if (w->platform) | 379 | return 0; |
379 | return snd_soc_platform_read(w->platform, reg); | 380 | } else if (w->platform) { |
381 | *value = snd_soc_platform_read(w->platform, reg); | ||
382 | return 0; | ||
383 | } | ||
380 | 384 | ||
381 | dev_err(w->dapm->dev, "ASoC: no valid widget read method\n"); | 385 | dev_err(w->dapm->dev, "ASoC: no valid widget read method\n"); |
382 | return -1; | 386 | return -1; |
@@ -430,13 +434,12 @@ static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w, | |||
430 | return ret; | 434 | return ret; |
431 | } else { | 435 | } else { |
432 | soc_widget_lock(w); | 436 | soc_widget_lock(w); |
433 | ret = soc_widget_read(w, reg); | 437 | ret = soc_widget_read(w, reg, &old); |
434 | if (ret < 0) { | 438 | if (ret < 0) { |
435 | soc_widget_unlock(w); | 439 | soc_widget_unlock(w); |
436 | return ret; | 440 | return ret; |
437 | } | 441 | } |
438 | 442 | ||
439 | old = ret; | ||
440 | new = (old & ~mask) | (value & mask); | 443 | new = (old & ~mask) | (value & mask); |
441 | change = old != new; | 444 | change = old != new; |
442 | if (change) { | 445 | if (change) { |
@@ -513,7 +516,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
513 | unsigned int invert = mc->invert; | 516 | unsigned int invert = mc->invert; |
514 | 517 | ||
515 | if (reg != SND_SOC_NOPM) { | 518 | if (reg != SND_SOC_NOPM) { |
516 | val = soc_widget_read(w, reg); | 519 | soc_widget_read(w, reg, &val); |
517 | val = (val >> shift) & mask; | 520 | val = (val >> shift) & mask; |
518 | if (invert) | 521 | if (invert) |
519 | val = max - val; | 522 | val = max - val; |
@@ -529,7 +532,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
529 | w->kcontrol_news[i].private_value; | 532 | w->kcontrol_news[i].private_value; |
530 | int val, item; | 533 | int val, item; |
531 | 534 | ||
532 | val = soc_widget_read(w, e->reg); | 535 | soc_widget_read(w, e->reg, &val); |
533 | item = (val >> e->shift_l) & e->mask; | 536 | item = (val >> e->shift_l) & e->mask; |
534 | 537 | ||
535 | if (item < e->max && !strcmp(p->name, e->texts[item])) | 538 | if (item < e->max && !strcmp(p->name, e->texts[item])) |
@@ -558,7 +561,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
558 | w->kcontrol_news[i].private_value; | 561 | w->kcontrol_news[i].private_value; |
559 | int val, item; | 562 | int val, item; |
560 | 563 | ||
561 | val = soc_widget_read(w, e->reg); | 564 | soc_widget_read(w, e->reg, &val); |
562 | val = (val >> e->shift_l) & e->mask; | 565 | val = (val >> e->shift_l) & e->mask; |
563 | for (item = 0; item < e->max; item++) { | 566 | for (item = 0; item < e->max; item++) { |
564 | if (val == e->values[item]) | 567 | if (val == e->values[item]) |
@@ -2473,7 +2476,8 @@ err: | |||
2473 | } | 2476 | } |
2474 | 2477 | ||
2475 | static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | 2478 | static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, |
2476 | const struct snd_soc_dapm_route *route) | 2479 | const struct snd_soc_dapm_route *route, |
2480 | unsigned int is_prefixed) | ||
2477 | { | 2481 | { |
2478 | struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; | 2482 | struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; |
2479 | struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL; | 2483 | struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL; |
@@ -2483,7 +2487,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
2483 | char prefixed_source[80]; | 2487 | char prefixed_source[80]; |
2484 | int ret; | 2488 | int ret; |
2485 | 2489 | ||
2486 | if (dapm->codec && dapm->codec->name_prefix) { | 2490 | if (dapm->codec && dapm->codec->name_prefix && !is_prefixed) { |
2487 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", | 2491 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", |
2488 | dapm->codec->name_prefix, route->sink); | 2492 | dapm->codec->name_prefix, route->sink); |
2489 | sink = prefixed_sink; | 2493 | sink = prefixed_sink; |
@@ -2611,7 +2615,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, | |||
2611 | 2615 | ||
2612 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); | 2616 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); |
2613 | for (i = 0; i < num; i++) { | 2617 | for (i = 0; i < num; i++) { |
2614 | r = snd_soc_dapm_add_route(dapm, route); | 2618 | r = snd_soc_dapm_add_route(dapm, route, false); |
2615 | if (r < 0) { | 2619 | if (r < 0) { |
2616 | dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n", | 2620 | dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n", |
2617 | route->source, | 2621 | route->source, |
@@ -2782,7 +2786,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) | |||
2782 | 2786 | ||
2783 | /* Read the initial power state from the device */ | 2787 | /* Read the initial power state from the device */ |
2784 | if (w->reg >= 0) { | 2788 | if (w->reg >= 0) { |
2785 | val = soc_widget_read(w, w->reg) >> w->shift; | 2789 | soc_widget_read(w, w->reg, &val); |
2790 | val = val >> w->shift; | ||
2786 | val &= w->mask; | 2791 | val &= w->mask; |
2787 | if (val == w->on_val) | 2792 | if (val == w->on_val) |
2788 | w->power = 1; | 2793 | w->power = 1; |
@@ -2868,6 +2873,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2868 | unsigned int val; | 2873 | unsigned int val; |
2869 | int connect, change; | 2874 | int connect, change; |
2870 | struct snd_soc_dapm_update update; | 2875 | struct snd_soc_dapm_update update; |
2876 | int ret = 0; | ||
2871 | 2877 | ||
2872 | if (snd_soc_volsw_is_stereo(mc)) | 2878 | if (snd_soc_volsw_is_stereo(mc)) |
2873 | dev_warn(codec->dapm.dev, | 2879 | dev_warn(codec->dapm.dev, |
@@ -2901,12 +2907,16 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2901 | card->update = &update; | 2907 | card->update = &update; |
2902 | } | 2908 | } |
2903 | 2909 | ||
2904 | soc_dapm_mixer_update_power(card, kcontrol, connect); | 2910 | ret = soc_dapm_mixer_update_power(card, kcontrol, connect); |
2905 | 2911 | ||
2906 | card->update = NULL; | 2912 | card->update = NULL; |
2907 | } | 2913 | } |
2908 | 2914 | ||
2909 | mutex_unlock(&card->dapm_mutex); | 2915 | mutex_unlock(&card->dapm_mutex); |
2916 | |||
2917 | if (ret > 0) | ||
2918 | soc_dpcm_runtime_update(card); | ||
2919 | |||
2910 | return change; | 2920 | return change; |
2911 | } | 2921 | } |
2912 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | 2922 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); |
@@ -2955,6 +2965,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2955 | unsigned int val, mux, change; | 2965 | unsigned int val, mux, change; |
2956 | unsigned int mask; | 2966 | unsigned int mask; |
2957 | struct snd_soc_dapm_update update; | 2967 | struct snd_soc_dapm_update update; |
2968 | int ret = 0; | ||
2958 | 2969 | ||
2959 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2970 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
2960 | return -EINVAL; | 2971 | return -EINVAL; |
@@ -2978,12 +2989,16 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2978 | update.val = val; | 2989 | update.val = val; |
2979 | card->update = &update; | 2990 | card->update = &update; |
2980 | 2991 | ||
2981 | soc_dapm_mux_update_power(card, kcontrol, mux, e); | 2992 | ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); |
2982 | 2993 | ||
2983 | card->update = NULL; | 2994 | card->update = NULL; |
2984 | } | 2995 | } |
2985 | 2996 | ||
2986 | mutex_unlock(&card->dapm_mutex); | 2997 | mutex_unlock(&card->dapm_mutex); |
2998 | |||
2999 | if (ret > 0) | ||
3000 | soc_dpcm_runtime_update(card); | ||
3001 | |||
2987 | return change; | 3002 | return change; |
2988 | } | 3003 | } |
2989 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); | 3004 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); |
@@ -3019,6 +3034,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, | |||
3019 | struct soc_enum *e = | 3034 | struct soc_enum *e = |
3020 | (struct soc_enum *)kcontrol->private_value; | 3035 | (struct soc_enum *)kcontrol->private_value; |
3021 | int change; | 3036 | int change; |
3037 | int ret = 0; | ||
3022 | 3038 | ||
3023 | if (ucontrol->value.enumerated.item[0] >= e->max) | 3039 | if (ucontrol->value.enumerated.item[0] >= e->max) |
3024 | return -EINVAL; | 3040 | return -EINVAL; |
@@ -3028,9 +3044,13 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, | |||
3028 | value = ucontrol->value.enumerated.item[0]; | 3044 | value = ucontrol->value.enumerated.item[0]; |
3029 | change = dapm_kcontrol_set_value(kcontrol, value); | 3045 | change = dapm_kcontrol_set_value(kcontrol, value); |
3030 | if (change) | 3046 | if (change) |
3031 | soc_dapm_mux_update_power(card, kcontrol, value, e); | 3047 | ret = soc_dapm_mux_update_power(card, kcontrol, value, e); |
3032 | 3048 | ||
3033 | mutex_unlock(&card->dapm_mutex); | 3049 | mutex_unlock(&card->dapm_mutex); |
3050 | |||
3051 | if (ret > 0) | ||
3052 | soc_dpcm_runtime_update(card); | ||
3053 | |||
3034 | return change; | 3054 | return change; |
3035 | } | 3055 | } |
3036 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); | 3056 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); |
@@ -3097,6 +3117,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
3097 | unsigned int val, mux, change; | 3117 | unsigned int val, mux, change; |
3098 | unsigned int mask; | 3118 | unsigned int mask; |
3099 | struct snd_soc_dapm_update update; | 3119 | struct snd_soc_dapm_update update; |
3120 | int ret = 0; | ||
3100 | 3121 | ||
3101 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 3122 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
3102 | return -EINVAL; | 3123 | return -EINVAL; |
@@ -3120,12 +3141,16 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
3120 | update.val = val; | 3141 | update.val = val; |
3121 | card->update = &update; | 3142 | card->update = &update; |
3122 | 3143 | ||
3123 | soc_dapm_mux_update_power(card, kcontrol, mux, e); | 3144 | ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); |
3124 | 3145 | ||
3125 | card->update = NULL; | 3146 | card->update = NULL; |
3126 | } | 3147 | } |
3127 | 3148 | ||
3128 | mutex_unlock(&card->dapm_mutex); | 3149 | mutex_unlock(&card->dapm_mutex); |
3150 | |||
3151 | if (ret > 0) | ||
3152 | soc_dpcm_runtime_update(card); | ||
3153 | |||
3129 | return change; | 3154 | return change; |
3130 | } | 3155 | } |
3131 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); | 3156 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); |
@@ -3614,6 +3639,55 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) | |||
3614 | return 0; | 3639 | return 0; |
3615 | } | 3640 | } |
3616 | 3641 | ||
3642 | void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) | ||
3643 | { | ||
3644 | struct snd_soc_pcm_runtime *rtd = card->rtd; | ||
3645 | struct snd_soc_dai *cpu_dai, *codec_dai; | ||
3646 | struct snd_soc_dapm_route r; | ||
3647 | int i; | ||
3648 | |||
3649 | memset(&r, 0, sizeof(r)); | ||
3650 | |||
3651 | /* for each BE DAI link... */ | ||
3652 | for (i = 0; i < card->num_rtd; i++) { | ||
3653 | rtd = &card->rtd[i]; | ||
3654 | cpu_dai = rtd->cpu_dai; | ||
3655 | codec_dai = rtd->codec_dai; | ||
3656 | |||
3657 | /* dynamic FE links have no fixed DAI mapping */ | ||
3658 | if (rtd->dai_link->dynamic) | ||
3659 | continue; | ||
3660 | |||
3661 | /* there is no point in connecting BE DAI links with dummies */ | ||
3662 | if (snd_soc_dai_is_dummy(codec_dai) || | ||
3663 | snd_soc_dai_is_dummy(cpu_dai)) | ||
3664 | continue; | ||
3665 | |||
3666 | /* connect BE DAI playback if widgets are valid */ | ||
3667 | if (codec_dai->playback_widget && cpu_dai->playback_widget) { | ||
3668 | r.source = cpu_dai->playback_widget->name; | ||
3669 | r.sink = codec_dai->playback_widget->name; | ||
3670 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", | ||
3671 | cpu_dai->codec->name, r.source, | ||
3672 | codec_dai->platform->name, r.sink); | ||
3673 | |||
3674 | snd_soc_dapm_add_route(&card->dapm, &r, true); | ||
3675 | } | ||
3676 | |||
3677 | /* connect BE DAI capture if widgets are valid */ | ||
3678 | if (codec_dai->capture_widget && cpu_dai->capture_widget) { | ||
3679 | r.source = codec_dai->capture_widget->name; | ||
3680 | r.sink = cpu_dai->capture_widget->name; | ||
3681 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", | ||
3682 | codec_dai->codec->name, r.source, | ||
3683 | cpu_dai->platform->name, r.sink); | ||
3684 | |||
3685 | snd_soc_dapm_add_route(&card->dapm, &r, true); | ||
3686 | } | ||
3687 | |||
3688 | } | ||
3689 | } | ||
3690 | |||
3617 | static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, | 3691 | static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, |
3618 | int event) | 3692 | int event) |
3619 | { | 3693 | { |
diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c index 3449c1e909ae..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 | { |
@@ -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 41949af3baae..5bace124ef43 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -137,10 +137,15 @@ 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) |
143 | hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; | 146 | hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; |
147 | if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) | ||
148 | hw.info |= SNDRV_PCM_INFO_BATCH; | ||
144 | } | 149 | } |
145 | 150 | ||
146 | return snd_soc_set_runtime_hwparams(substream, &hw); | 151 | return snd_soc_set_runtime_hwparams(substream, &hw); |
@@ -171,17 +176,35 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel( | |||
171 | { | 176 | { |
172 | struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); | 177 | struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); |
173 | struct snd_dmaengine_dai_dma_data *dma_data; | 178 | struct snd_dmaengine_dai_dma_data *dma_data; |
179 | dma_filter_fn fn = NULL; | ||
174 | 180 | ||
175 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 181 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
176 | 182 | ||
177 | if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0]) | 183 | if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0]) |
178 | return pcm->chan[0]; | 184 | return pcm->chan[0]; |
179 | 185 | ||
180 | if (pcm->config->compat_request_channel) | 186 | if (pcm->config && pcm->config->compat_request_channel) |
181 | return pcm->config->compat_request_channel(rtd, substream); | 187 | return pcm->config->compat_request_channel(rtd, substream); |
182 | 188 | ||
183 | return snd_dmaengine_pcm_request_channel(pcm->config->compat_filter_fn, | 189 | if (pcm->config) |
184 | dma_data->filter_data); | 190 | fn = pcm->config->compat_filter_fn; |
191 | |||
192 | return snd_dmaengine_pcm_request_channel(fn, dma_data->filter_data); | ||
193 | } | ||
194 | |||
195 | static bool dmaengine_pcm_can_report_residue(struct dma_chan *chan) | ||
196 | { | ||
197 | struct dma_slave_caps dma_caps; | ||
198 | int ret; | ||
199 | |||
200 | ret = dma_get_slave_caps(chan, &dma_caps); | ||
201 | if (ret != 0) | ||
202 | return true; | ||
203 | |||
204 | if (dma_caps.residue_granularity == DMA_RESIDUE_GRANULARITY_DESCRIPTOR) | ||
205 | return false; | ||
206 | |||
207 | return true; | ||
185 | } | 208 | } |
186 | 209 | ||
187 | static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) | 210 | static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) |
@@ -236,6 +259,16 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
236 | max_buffer_size); | 259 | max_buffer_size); |
237 | if (ret) | 260 | if (ret) |
238 | goto err_free; | 261 | goto err_free; |
262 | |||
263 | /* | ||
264 | * This will only return false if we know for sure that at least | ||
265 | * one channel does not support residue reporting. If the DMA | ||
266 | * driver does not implement the slave_caps API we rely having | ||
267 | * the NO_RESIDUE flag set manually in case residue reporting is | ||
268 | * not supported. | ||
269 | */ | ||
270 | if (!dmaengine_pcm_can_report_residue(pcm->chan[i])) | ||
271 | pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE; | ||
239 | } | 272 | } |
240 | 273 | ||
241 | return 0; | 274 | return 0; |
@@ -245,6 +278,18 @@ err_free: | |||
245 | return ret; | 278 | return ret; |
246 | } | 279 | } |
247 | 280 | ||
281 | static snd_pcm_uframes_t dmaengine_pcm_pointer( | ||
282 | struct snd_pcm_substream *substream) | ||
283 | { | ||
284 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
285 | struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); | ||
286 | |||
287 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) | ||
288 | return snd_dmaengine_pcm_pointer_no_residue(substream); | ||
289 | else | ||
290 | return snd_dmaengine_pcm_pointer(substream); | ||
291 | } | ||
292 | |||
248 | static const struct snd_pcm_ops dmaengine_pcm_ops = { | 293 | static const struct snd_pcm_ops dmaengine_pcm_ops = { |
249 | .open = dmaengine_pcm_open, | 294 | .open = dmaengine_pcm_open, |
250 | .close = snd_dmaengine_pcm_close, | 295 | .close = snd_dmaengine_pcm_close, |
@@ -252,7 +297,7 @@ static const struct snd_pcm_ops dmaengine_pcm_ops = { | |||
252 | .hw_params = dmaengine_pcm_hw_params, | 297 | .hw_params = dmaengine_pcm_hw_params, |
253 | .hw_free = snd_pcm_lib_free_pages, | 298 | .hw_free = snd_pcm_lib_free_pages, |
254 | .trigger = snd_dmaengine_pcm_trigger, | 299 | .trigger = snd_dmaengine_pcm_trigger, |
255 | .pointer = snd_dmaengine_pcm_pointer, | 300 | .pointer = dmaengine_pcm_pointer, |
256 | }; | 301 | }; |
257 | 302 | ||
258 | static const struct snd_soc_platform_driver dmaengine_pcm_platform = { | 303 | static const struct snd_soc_platform_driver dmaengine_pcm_platform = { |
@@ -262,47 +307,59 @@ static const struct snd_soc_platform_driver dmaengine_pcm_platform = { | |||
262 | .probe_order = SND_SOC_COMP_ORDER_LATE, | 307 | .probe_order = SND_SOC_COMP_ORDER_LATE, |
263 | }; | 308 | }; |
264 | 309 | ||
265 | static const struct snd_pcm_ops dmaengine_no_residue_pcm_ops = { | ||
266 | .open = dmaengine_pcm_open, | ||
267 | .close = snd_dmaengine_pcm_close, | ||
268 | .ioctl = snd_pcm_lib_ioctl, | ||
269 | .hw_params = dmaengine_pcm_hw_params, | ||
270 | .hw_free = snd_pcm_lib_free_pages, | ||
271 | .trigger = snd_dmaengine_pcm_trigger, | ||
272 | .pointer = snd_dmaengine_pcm_pointer_no_residue, | ||
273 | }; | ||
274 | |||
275 | static const struct snd_soc_platform_driver dmaengine_no_residue_pcm_platform = { | ||
276 | .ops = &dmaengine_no_residue_pcm_ops, | ||
277 | .pcm_new = dmaengine_pcm_new, | ||
278 | .pcm_free = dmaengine_pcm_free, | ||
279 | .probe_order = SND_SOC_COMP_ORDER_LATE, | ||
280 | }; | ||
281 | |||
282 | static const char * const dmaengine_pcm_dma_channel_names[] = { | 310 | static const char * const dmaengine_pcm_dma_channel_names[] = { |
283 | [SNDRV_PCM_STREAM_PLAYBACK] = "tx", | 311 | [SNDRV_PCM_STREAM_PLAYBACK] = "tx", |
284 | [SNDRV_PCM_STREAM_CAPTURE] = "rx", | 312 | [SNDRV_PCM_STREAM_CAPTURE] = "rx", |
285 | }; | 313 | }; |
286 | 314 | ||
287 | static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, | 315 | static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, |
288 | struct device *dev) | 316 | struct device *dev, const struct snd_dmaengine_pcm_config *config) |
289 | { | 317 | { |
290 | unsigned int i; | 318 | unsigned int i; |
319 | const char *name; | ||
320 | struct dma_chan *chan; | ||
291 | 321 | ||
292 | if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT | | 322 | if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT | |
293 | SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) || | 323 | SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) || |
294 | !dev->of_node) | 324 | !dev->of_node) |
295 | return; | 325 | return 0; |
326 | |||
327 | if (config && config->dma_dev) { | ||
328 | /* | ||
329 | * If this warning is seen, it probably means that your Linux | ||
330 | * device structure does not match your HW device structure. | ||
331 | * It would be best to refactor the Linux device structure to | ||
332 | * correctly match the HW structure. | ||
333 | */ | ||
334 | dev_warn(dev, "DMA channels sourced from device %s", | ||
335 | dev_name(config->dma_dev)); | ||
336 | dev = config->dma_dev; | ||
337 | } | ||
296 | 338 | ||
297 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) { | 339 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; |
298 | pcm->chan[0] = dma_request_slave_channel(dev, "rx-tx"); | 340 | i++) { |
299 | pcm->chan[1] = pcm->chan[0]; | 341 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) |
300 | } else { | 342 | name = "rx-tx"; |
301 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { | 343 | else |
302 | pcm->chan[i] = dma_request_slave_channel(dev, | 344 | name = dmaengine_pcm_dma_channel_names[i]; |
303 | dmaengine_pcm_dma_channel_names[i]); | 345 | if (config && config->chan_names[i]) |
346 | name = config->chan_names[i]; | ||
347 | chan = dma_request_slave_channel_reason(dev, name); | ||
348 | if (IS_ERR(chan)) { | ||
349 | if (PTR_ERR(chan) == -EPROBE_DEFER) | ||
350 | return -EPROBE_DEFER; | ||
351 | pcm->chan[i] = NULL; | ||
352 | } else { | ||
353 | pcm->chan[i] = chan; | ||
304 | } | 354 | } |
355 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
356 | break; | ||
305 | } | 357 | } |
358 | |||
359 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
360 | pcm->chan[1] = pcm->chan[0]; | ||
361 | |||
362 | return 0; | ||
306 | } | 363 | } |
307 | 364 | ||
308 | static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) | 365 | static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) |
@@ -338,14 +395,12 @@ int snd_dmaengine_pcm_register(struct device *dev, | |||
338 | pcm->config = config; | 395 | pcm->config = config; |
339 | pcm->flags = flags; | 396 | pcm->flags = flags; |
340 | 397 | ||
341 | dmaengine_pcm_request_chan_of(pcm, dev); | 398 | ret = dmaengine_pcm_request_chan_of(pcm, dev, config); |
399 | if (ret) | ||
400 | goto err_free_dma; | ||
342 | 401 | ||
343 | if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) | 402 | ret = snd_soc_add_platform(dev, &pcm->platform, |
344 | ret = snd_soc_add_platform(dev, &pcm->platform, | 403 | &dmaengine_pcm_platform); |
345 | &dmaengine_no_residue_pcm_platform); | ||
346 | else | ||
347 | ret = snd_soc_add_platform(dev, &pcm->platform, | ||
348 | &dmaengine_pcm_platform); | ||
349 | if (ret) | 404 | if (ret) |
350 | goto err_free_dma; | 405 | goto err_free_dma; |
351 | 406 | ||
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 891b9a9bcbf8..47e1ce771e65 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -58,7 +58,7 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, | |||
58 | EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams); | 58 | EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams); |
59 | 59 | ||
60 | /* DPCM stream event, send event to FE and all active BEs. */ | 60 | /* DPCM stream event, send event to FE and all active BEs. */ |
61 | static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, | 61 | int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, |
62 | int event) | 62 | int event) |
63 | { | 63 | { |
64 | struct snd_soc_dpcm *dpcm; | 64 | struct snd_soc_dpcm *dpcm; |
@@ -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); | ||
90 | 91 | ||
91 | /* This can happen if multiple streams are starting simultaneously - | 92 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, |
92 | * the second can need to get its constraints before the first has | 93 | SNDRV_PCM_HW_PARAM_RATE, |
93 | * picked a rate. Complain and allow the application to carry on. | 94 | soc_dai->rate, soc_dai->rate); |
94 | */ | 95 | if (ret < 0) { |
95 | if (!soc_dai->rate) { | 96 | dev_err(soc_dai->dev, |
96 | dev_warn(soc_dai->dev, | 97 | "ASoC: Unable to apply rate constraint: %d\n", |
97 | "ASoC: Not enforcing symmetric_rates due to race\n"); | 98 | ret); |
98 | return 0; | 99 | return ret; |
100 | } | ||
99 | } | 101 | } |
100 | 102 | ||
101 | dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", soc_dai->rate); | 103 | if (soc_dai->channels && (soc_dai->driver->symmetric_channels || |
104 | rtd->dai_link->symmetric_channels)) { | ||
105 | dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n", | ||
106 | soc_dai->channels); | ||
102 | 107 | ||
103 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, | 108 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, |
104 | SNDRV_PCM_HW_PARAM_RATE, | 109 | SNDRV_PCM_HW_PARAM_CHANNELS, |
105 | soc_dai->rate, soc_dai->rate); | 110 | soc_dai->channels, |
106 | if (ret < 0) { | 111 | soc_dai->channels); |
107 | dev_err(soc_dai->dev, | 112 | if (ret < 0) { |
108 | "ASoC: Unable to apply rate symmetry constraint: %d\n", | 113 | dev_err(soc_dai->dev, |
109 | ret); | 114 | "ASoC: Unable to apply channel symmetry constraint: %d\n", |
110 | return ret; | 115 | ret); |
116 | return ret; | ||
117 | } | ||
118 | } | ||
119 | |||
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); | ||
124 | |||
125 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, | ||
126 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | ||
127 | soc_dai->sample_bits, | ||
128 | soc_dai->sample_bits); | ||
129 | if (ret < 0) { | ||
130 | dev_err(soc_dai->dev, | ||
131 | "ASoC: Unable to apply sample bits symmetry constraint: %d\n", | ||
132 | ret); | ||
133 | return ret; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | return 0; | ||
138 | } | ||
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; | ||
111 | } | 178 | } |
112 | 179 | ||
113 | return 0; | 180 | return 0; |
114 | } | 181 | } |
115 | 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 |
@@ -158,14 +240,15 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime, | |||
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, |
160 | cpu_stream->channels_max); | 242 | cpu_stream->channels_max); |
161 | hw->formats = codec_stream->formats & cpu_stream->formats; | 243 | if (hw->formats) |
162 | hw->rates = codec_stream->rates & cpu_stream->rates; | 244 | hw->formats &= codec_stream->formats & cpu_stream->formats; |
163 | if (codec_stream->rates | 245 | else |
164 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | 246 | hw->formats = codec_stream->formats & cpu_stream->formats; |
165 | hw->rates |= cpu_stream->rates; | 247 | hw->rates = snd_pcm_rate_mask_intersect(codec_stream->rates, |
166 | if (cpu_stream->rates | 248 | cpu_stream->rates); |
167 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | 249 | |
168 | hw->rates |= codec_stream->rates; | 250 | hw->rate_min = 0; |
251 | hw->rate_max = UINT_MAX; | ||
169 | 252 | ||
170 | snd_pcm_limit_hw_rates(runtime); | 253 | snd_pcm_limit_hw_rates(runtime); |
171 | 254 | ||
@@ -249,6 +332,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
249 | &cpu_dai_drv->capture); | 332 | &cpu_dai_drv->capture); |
250 | } | 333 | } |
251 | 334 | ||
335 | if (soc_pcm_has_symmetry(substream)) | ||
336 | runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; | ||
337 | |||
252 | ret = -EINVAL; | 338 | ret = -EINVAL; |
253 | if (!runtime->hw.rates) { | 339 | if (!runtime->hw.rates) { |
254 | printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n", | 340 | printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n", |
@@ -396,11 +482,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
396 | if (!codec_dai->active) | 482 | if (!codec_dai->active) |
397 | codec_dai->rate = 0; | 483 | codec_dai->rate = 0; |
398 | 484 | ||
399 | /* Muting the DAC suppresses artifacts caused during digital | ||
400 | * shutdown, for example from stopping clocks. | ||
401 | */ | ||
402 | snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); | ||
403 | |||
404 | if (cpu_dai->driver->ops->shutdown) | 485 | if (cpu_dai->driver->ops->shutdown) |
405 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | 486 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
406 | 487 | ||
@@ -531,6 +612,10 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
531 | 612 | ||
532 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 613 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
533 | 614 | ||
615 | ret = soc_pcm_params_symmetry(substream, params); | ||
616 | if (ret) | ||
617 | goto out; | ||
618 | |||
534 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { | 619 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { |
535 | ret = rtd->dai_link->ops->hw_params(substream, params); | 620 | ret = rtd->dai_link->ops->hw_params(substream, params); |
536 | if (ret < 0) { | 621 | if (ret < 0) { |
@@ -567,9 +652,16 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
567 | } | 652 | } |
568 | } | 653 | } |
569 | 654 | ||
570 | /* store the rate for each DAIs */ | 655 | /* store the parameters for each DAIs */ |
571 | cpu_dai->rate = params_rate(params); | 656 | cpu_dai->rate = params_rate(params); |
657 | cpu_dai->channels = params_channels(params); | ||
658 | cpu_dai->sample_bits = | ||
659 | snd_pcm_format_physical_width(params_format(params)); | ||
660 | |||
572 | codec_dai->rate = params_rate(params); | 661 | codec_dai->rate = params_rate(params); |
662 | codec_dai->channels = params_channels(params); | ||
663 | codec_dai->sample_bits = | ||
664 | snd_pcm_format_physical_width(params_format(params)); | ||
573 | 665 | ||
574 | out: | 666 | out: |
575 | mutex_unlock(&rtd->pcm_mutex); | 667 | mutex_unlock(&rtd->pcm_mutex); |
@@ -604,6 +696,19 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
604 | 696 | ||
605 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 697 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
606 | 698 | ||
699 | /* clear the corresponding DAIs parameters when going to be inactive */ | ||
700 | if (cpu_dai->active == 1) { | ||
701 | cpu_dai->rate = 0; | ||
702 | cpu_dai->channels = 0; | ||
703 | cpu_dai->sample_bits = 0; | ||
704 | } | ||
705 | |||
706 | if (codec_dai->active == 1) { | ||
707 | codec_dai->rate = 0; | ||
708 | codec_dai->channels = 0; | ||
709 | codec_dai->sample_bits = 0; | ||
710 | } | ||
711 | |||
607 | /* apply codec digital mute */ | 712 | /* apply codec digital mute */ |
608 | if ((playback && codec_dai->playback_active == 1) || | 713 | if ((playback && codec_dai->playback_active == 1) || |
609 | (!playback && codec_dai->capture_active == 1)) | 714 | (!playback && codec_dai->capture_active == 1)) |
@@ -672,7 +777,7 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, | |||
672 | return ret; | 777 | return ret; |
673 | } | 778 | } |
674 | 779 | ||
675 | if (platform->driver->ops && platform->driver->bespoke_trigger) { | 780 | if (platform->driver->bespoke_trigger) { |
676 | ret = platform->driver->bespoke_trigger(substream, cmd); | 781 | ret = platform->driver->bespoke_trigger(substream, cmd); |
677 | if (ret < 0) | 782 | if (ret < 0) |
678 | return ret; | 783 | return ret; |
@@ -780,7 +885,7 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe, | |||
780 | } | 885 | } |
781 | 886 | ||
782 | /* disconnect a BE and FE */ | 887 | /* disconnect a BE and FE */ |
783 | static void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) | 888 | void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) |
784 | { | 889 | { |
785 | struct snd_soc_dpcm *dpcm, *d; | 890 | struct snd_soc_dpcm *dpcm, *d; |
786 | 891 | ||
@@ -876,7 +981,7 @@ static int widget_in_list(struct snd_soc_dapm_widget_list *list, | |||
876 | return 0; | 981 | return 0; |
877 | } | 982 | } |
878 | 983 | ||
879 | static int dpcm_path_get(struct snd_soc_pcm_runtime *fe, | 984 | int dpcm_path_get(struct snd_soc_pcm_runtime *fe, |
880 | int stream, struct snd_soc_dapm_widget_list **list_) | 985 | int stream, struct snd_soc_dapm_widget_list **list_) |
881 | { | 986 | { |
882 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; | 987 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; |
@@ -898,11 +1003,6 @@ static int dpcm_path_get(struct snd_soc_pcm_runtime *fe, | |||
898 | return paths; | 1003 | return paths; |
899 | } | 1004 | } |
900 | 1005 | ||
901 | static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list) | ||
902 | { | ||
903 | kfree(*list); | ||
904 | } | ||
905 | |||
906 | static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, | 1006 | static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, |
907 | struct snd_soc_dapm_widget_list **list_) | 1007 | struct snd_soc_dapm_widget_list **list_) |
908 | { | 1008 | { |
@@ -972,7 +1072,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, | |||
972 | continue; | 1072 | continue; |
973 | 1073 | ||
974 | /* don't connect if FE is not running */ | 1074 | /* don't connect if FE is not running */ |
975 | if (!fe->dpcm[stream].runtime) | 1075 | if (!fe->dpcm[stream].runtime && !fe->fe_compr) |
976 | continue; | 1076 | continue; |
977 | 1077 | ||
978 | /* newly connected FE and BE */ | 1078 | /* newly connected FE and BE */ |
@@ -997,7 +1097,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, | |||
997 | * Find the corresponding BE DAIs that source or sink audio to this | 1097 | * Find the corresponding BE DAIs that source or sink audio to this |
998 | * FE substream. | 1098 | * FE substream. |
999 | */ | 1099 | */ |
1000 | static int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, | 1100 | int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, |
1001 | int stream, struct snd_soc_dapm_widget_list **list, int new) | 1101 | int stream, struct snd_soc_dapm_widget_list **list, int new) |
1002 | { | 1102 | { |
1003 | if (new) | 1103 | if (new) |
@@ -1006,7 +1106,7 @@ static int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, | |||
1006 | return dpcm_prune_paths(fe, stream, list); | 1106 | return dpcm_prune_paths(fe, stream, list); |
1007 | } | 1107 | } |
1008 | 1108 | ||
1009 | static void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream) | 1109 | void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream) |
1010 | { | 1110 | { |
1011 | struct snd_soc_dpcm *dpcm; | 1111 | struct snd_soc_dpcm *dpcm; |
1012 | 1112 | ||
@@ -1044,7 +1144,7 @@ static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe, | |||
1044 | } | 1144 | } |
1045 | } | 1145 | } |
1046 | 1146 | ||
1047 | static int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) | 1147 | int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) |
1048 | { | 1148 | { |
1049 | struct snd_soc_dpcm *dpcm; | 1149 | struct snd_soc_dpcm *dpcm; |
1050 | int err, count = 0; | 1150 | int err, count = 0; |
@@ -1131,6 +1231,20 @@ unwind: | |||
1131 | return err; | 1231 | return err; |
1132 | } | 1232 | } |
1133 | 1233 | ||
1234 | static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, | ||
1235 | struct snd_soc_pcm_stream *stream) | ||
1236 | { | ||
1237 | runtime->hw.rate_min = stream->rate_min; | ||
1238 | runtime->hw.rate_max = stream->rate_max; | ||
1239 | runtime->hw.channels_min = stream->channels_min; | ||
1240 | runtime->hw.channels_max = stream->channels_max; | ||
1241 | if (runtime->hw.formats) | ||
1242 | runtime->hw.formats &= stream->formats; | ||
1243 | else | ||
1244 | runtime->hw.formats = stream->formats; | ||
1245 | runtime->hw.rates = stream->rates; | ||
1246 | } | ||
1247 | |||
1134 | static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) | 1248 | static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) |
1135 | { | 1249 | { |
1136 | struct snd_pcm_runtime *runtime = substream->runtime; | 1250 | struct snd_pcm_runtime *runtime = substream->runtime; |
@@ -1138,21 +1252,10 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) | |||
1138 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1252 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1139 | struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; | 1253 | struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; |
1140 | 1254 | ||
1141 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 1255 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1142 | runtime->hw.rate_min = cpu_dai_drv->playback.rate_min; | 1256 | dpcm_init_runtime_hw(runtime, &cpu_dai_drv->playback); |
1143 | runtime->hw.rate_max = cpu_dai_drv->playback.rate_max; | 1257 | else |
1144 | runtime->hw.channels_min = cpu_dai_drv->playback.channels_min; | 1258 | dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture); |
1145 | runtime->hw.channels_max = cpu_dai_drv->playback.channels_max; | ||
1146 | runtime->hw.formats &= cpu_dai_drv->playback.formats; | ||
1147 | runtime->hw.rates = cpu_dai_drv->playback.rates; | ||
1148 | } else { | ||
1149 | runtime->hw.rate_min = cpu_dai_drv->capture.rate_min; | ||
1150 | runtime->hw.rate_max = cpu_dai_drv->capture.rate_max; | ||
1151 | runtime->hw.channels_min = cpu_dai_drv->capture.channels_min; | ||
1152 | runtime->hw.channels_max = cpu_dai_drv->capture.channels_max; | ||
1153 | runtime->hw.formats &= cpu_dai_drv->capture.formats; | ||
1154 | runtime->hw.rates = cpu_dai_drv->capture.rates; | ||
1155 | } | ||
1156 | } | 1259 | } |
1157 | 1260 | ||
1158 | static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) | 1261 | static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) |
@@ -1193,7 +1296,7 @@ be_err: | |||
1193 | return ret; | 1296 | return ret; |
1194 | } | 1297 | } |
1195 | 1298 | ||
1196 | static int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream) | 1299 | int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream) |
1197 | { | 1300 | { |
1198 | struct snd_soc_dpcm *dpcm; | 1301 | struct snd_soc_dpcm *dpcm; |
1199 | 1302 | ||
@@ -1254,7 +1357,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) | |||
1254 | return 0; | 1357 | return 0; |
1255 | } | 1358 | } |
1256 | 1359 | ||
1257 | static int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) | 1360 | int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) |
1258 | { | 1361 | { |
1259 | struct snd_soc_dpcm *dpcm; | 1362 | struct snd_soc_dpcm *dpcm; |
1260 | 1363 | ||
@@ -1319,7 +1422,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) | |||
1319 | return 0; | 1422 | return 0; |
1320 | } | 1423 | } |
1321 | 1424 | ||
1322 | static int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) | 1425 | int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) |
1323 | { | 1426 | { |
1324 | struct snd_soc_dpcm *dpcm; | 1427 | struct snd_soc_dpcm *dpcm; |
1325 | int ret; | 1428 | int ret; |
@@ -1449,7 +1552,7 @@ static int dpcm_do_trigger(struct snd_soc_dpcm *dpcm, | |||
1449 | return ret; | 1552 | return ret; |
1450 | } | 1553 | } |
1451 | 1554 | ||
1452 | static int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, | 1555 | int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, |
1453 | int cmd) | 1556 | int cmd) |
1454 | { | 1557 | { |
1455 | struct snd_soc_dpcm *dpcm; | 1558 | struct snd_soc_dpcm *dpcm; |
@@ -1617,7 +1720,7 @@ out: | |||
1617 | return ret; | 1720 | return ret; |
1618 | } | 1721 | } |
1619 | 1722 | ||
1620 | static int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) | 1723 | int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) |
1621 | { | 1724 | { |
1622 | struct snd_soc_dpcm *dpcm; | 1725 | struct snd_soc_dpcm *dpcm; |
1623 | int ret = 0; | 1726 | int ret = 0; |
@@ -2033,10 +2136,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2033 | int ret = 0, playback = 0, capture = 0; | 2136 | int ret = 0, playback = 0, capture = 0; |
2034 | 2137 | ||
2035 | if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) { | 2138 | if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) { |
2036 | if (cpu_dai->driver->playback.channels_min) | 2139 | playback = rtd->dai_link->dpcm_playback; |
2037 | playback = 1; | 2140 | capture = rtd->dai_link->dpcm_capture; |
2038 | if (cpu_dai->driver->capture.channels_min) | ||
2039 | capture = 1; | ||
2040 | } else { | 2141 | } else { |
2041 | if (codec_dai->driver->playback.channels_min && | 2142 | if (codec_dai->driver->playback.channels_min && |
2042 | cpu_dai->driver->playback.channels_min) | 2143 | cpu_dai->driver->playback.channels_min) |
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 5e633659c1b3..7f22ca35a413 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, |
@@ -123,6 +119,13 @@ static struct snd_soc_dai_driver dummy_dai = { | |||
123 | }, | 119 | }, |
124 | }; | 120 | }; |
125 | 121 | ||
122 | int snd_soc_dai_is_dummy(struct snd_soc_dai *dai) | ||
123 | { | ||
124 | if (dai->driver == &dummy_dai) | ||
125 | return 1; | ||
126 | return 0; | ||
127 | } | ||
128 | |||
126 | static int snd_soc_dummy_probe(struct platform_device *pdev) | 129 | static int snd_soc_dummy_probe(struct platform_device *pdev) |
127 | { | 130 | { |
128 | int ret; | 131 | int ret; |
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/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, |
diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 178d1bad6259..b3b66aa98dce 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c | |||
@@ -91,6 +91,8 @@ static int mop500_of_probe(struct platform_device *pdev, | |||
91 | for (i = 0; i < 2; i++) { | 91 | for (i = 0; i < 2; i++) { |
92 | mop500_dai_links[i].cpu_of_node = msp_np[i]; | 92 | mop500_dai_links[i].cpu_of_node = msp_np[i]; |
93 | mop500_dai_links[i].cpu_dai_name = NULL; | 93 | mop500_dai_links[i].cpu_dai_name = NULL; |
94 | mop500_dai_links[i].platform_of_node = msp_np[i]; | ||
95 | mop500_dai_links[i].platform_name = NULL; | ||
94 | mop500_dai_links[i].codec_of_node = codec_np; | 96 | mop500_dai_links[i].codec_of_node = codec_np; |
95 | mop500_dai_links[i].codec_name = NULL; | 97 | mop500_dai_links[i].codec_name = NULL; |
96 | } | 98 | } |
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index c6fb5cce980e..5f4807b2c007 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c | |||
@@ -17,12 +17,14 @@ | |||
17 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
20 | #include <linux/of.h> | ||
20 | #include <linux/regulator/consumer.h> | 21 | #include <linux/regulator/consumer.h> |
21 | #include <linux/mfd/dbx500-prcmu.h> | 22 | #include <linux/mfd/dbx500-prcmu.h> |
22 | #include <linux/platform_data/asoc-ux500-msp.h> | 23 | #include <linux/platform_data/asoc-ux500-msp.h> |
23 | 24 | ||
24 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
25 | #include <sound/soc-dai.h> | 26 | #include <sound/soc-dai.h> |
27 | #include <sound/dmaengine_pcm.h> | ||
26 | 28 | ||
27 | #include "ux500_msp_i2s.h" | 29 | #include "ux500_msp_i2s.h" |
28 | #include "ux500_msp_dai.h" | 30 | #include "ux500_msp_dai.h" |
@@ -654,16 +656,52 @@ static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream, | |||
654 | return ret; | 656 | return ret; |
655 | } | 657 | } |
656 | 658 | ||
659 | static int ux500_msp_dai_of_probe(struct snd_soc_dai *dai) | ||
660 | { | ||
661 | struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev); | ||
662 | struct snd_dmaengine_dai_dma_data *playback_dma_data; | ||
663 | struct snd_dmaengine_dai_dma_data *capture_dma_data; | ||
664 | |||
665 | playback_dma_data = devm_kzalloc(dai->dev, | ||
666 | sizeof(*playback_dma_data), | ||
667 | GFP_KERNEL); | ||
668 | if (!playback_dma_data) | ||
669 | return -ENOMEM; | ||
670 | |||
671 | capture_dma_data = devm_kzalloc(dai->dev, | ||
672 | sizeof(*capture_dma_data), | ||
673 | GFP_KERNEL); | ||
674 | if (!capture_dma_data) | ||
675 | return -ENOMEM; | ||
676 | |||
677 | playback_dma_data->addr = drvdata->msp->playback_dma_data.tx_rx_addr; | ||
678 | capture_dma_data->addr = drvdata->msp->capture_dma_data.tx_rx_addr; | ||
679 | |||
680 | playback_dma_data->maxburst = 4; | ||
681 | capture_dma_data->maxburst = 4; | ||
682 | |||
683 | snd_soc_dai_init_dma_data(dai, playback_dma_data, capture_dma_data); | ||
684 | |||
685 | return 0; | ||
686 | } | ||
687 | |||
657 | static int ux500_msp_dai_probe(struct snd_soc_dai *dai) | 688 | static int ux500_msp_dai_probe(struct snd_soc_dai *dai) |
658 | { | 689 | { |
659 | struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev); | 690 | struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev); |
691 | struct msp_i2s_platform_data *pdata = dai->dev->platform_data; | ||
692 | int ret; | ||
660 | 693 | ||
661 | dai->playback_dma_data = &drvdata->msp->playback_dma_data; | 694 | if (!pdata) { |
662 | dai->capture_dma_data = &drvdata->msp->capture_dma_data; | 695 | ret = ux500_msp_dai_of_probe(dai); |
696 | return ret; | ||
697 | } | ||
663 | 698 | ||
664 | drvdata->msp->playback_dma_data.data_size = drvdata->slot_width; | 699 | drvdata->msp->playback_dma_data.data_size = drvdata->slot_width; |
665 | drvdata->msp->capture_dma_data.data_size = drvdata->slot_width; | 700 | drvdata->msp->capture_dma_data.data_size = drvdata->slot_width; |
666 | 701 | ||
702 | snd_soc_dai_init_dma_data(dai, | ||
703 | &drvdata->msp->playback_dma_data, | ||
704 | &drvdata->msp->capture_dma_data); | ||
667 | return 0; | 705 | return 0; |
668 | } | 706 | } |
669 | 707 | ||
@@ -680,87 +718,19 @@ static struct snd_soc_dai_ops ux500_msp_dai_ops[] = { | |||
680 | } | 718 | } |
681 | }; | 719 | }; |
682 | 720 | ||
683 | static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = { | 721 | static struct snd_soc_dai_driver ux500_msp_dai_drv = { |
684 | { | 722 | .probe = ux500_msp_dai_probe, |
685 | .name = "ux500-msp-i2s.0", | 723 | .suspend = NULL, |
686 | .probe = ux500_msp_dai_probe, | 724 | .resume = NULL, |
687 | .id = 0, | 725 | .playback.channels_min = UX500_MSP_MIN_CHANNELS, |
688 | .suspend = NULL, | 726 | .playback.channels_max = UX500_MSP_MAX_CHANNELS, |
689 | .resume = NULL, | 727 | .playback.rates = UX500_I2S_RATES, |
690 | .playback = { | 728 | .playback.formats = UX500_I2S_FORMATS, |
691 | .channels_min = UX500_MSP_MIN_CHANNELS, | 729 | .capture.channels_min = UX500_MSP_MIN_CHANNELS, |
692 | .channels_max = UX500_MSP_MAX_CHANNELS, | 730 | .capture.channels_max = UX500_MSP_MAX_CHANNELS, |
693 | .rates = UX500_I2S_RATES, | 731 | .capture.rates = UX500_I2S_RATES, |
694 | .formats = UX500_I2S_FORMATS, | 732 | .capture.formats = UX500_I2S_FORMATS, |
695 | }, | 733 | .ops = ux500_msp_dai_ops, |
696 | .capture = { | ||
697 | .channels_min = UX500_MSP_MIN_CHANNELS, | ||
698 | .channels_max = UX500_MSP_MAX_CHANNELS, | ||
699 | .rates = UX500_I2S_RATES, | ||
700 | .formats = UX500_I2S_FORMATS, | ||
701 | }, | ||
702 | .ops = ux500_msp_dai_ops, | ||
703 | }, | ||
704 | { | ||
705 | .name = "ux500-msp-i2s.1", | ||
706 | .probe = ux500_msp_dai_probe, | ||
707 | .id = 1, | ||
708 | .suspend = NULL, | ||
709 | .resume = NULL, | ||
710 | .playback = { | ||
711 | .channels_min = UX500_MSP_MIN_CHANNELS, | ||
712 | .channels_max = UX500_MSP_MAX_CHANNELS, | ||
713 | .rates = UX500_I2S_RATES, | ||
714 | .formats = UX500_I2S_FORMATS, | ||
715 | }, | ||
716 | .capture = { | ||
717 | .channels_min = UX500_MSP_MIN_CHANNELS, | ||
718 | .channels_max = UX500_MSP_MAX_CHANNELS, | ||
719 | .rates = UX500_I2S_RATES, | ||
720 | .formats = UX500_I2S_FORMATS, | ||
721 | }, | ||
722 | .ops = ux500_msp_dai_ops, | ||
723 | }, | ||
724 | { | ||
725 | .name = "ux500-msp-i2s.2", | ||
726 | .id = 2, | ||
727 | .probe = ux500_msp_dai_probe, | ||
728 | .suspend = NULL, | ||
729 | .resume = NULL, | ||
730 | .playback = { | ||
731 | .channels_min = UX500_MSP_MIN_CHANNELS, | ||
732 | .channels_max = UX500_MSP_MAX_CHANNELS, | ||
733 | .rates = UX500_I2S_RATES, | ||
734 | .formats = UX500_I2S_FORMATS, | ||
735 | }, | ||
736 | .capture = { | ||
737 | .channels_min = UX500_MSP_MIN_CHANNELS, | ||
738 | .channels_max = UX500_MSP_MAX_CHANNELS, | ||
739 | .rates = UX500_I2S_RATES, | ||
740 | .formats = UX500_I2S_FORMATS, | ||
741 | }, | ||
742 | .ops = ux500_msp_dai_ops, | ||
743 | }, | ||
744 | { | ||
745 | .name = "ux500-msp-i2s.3", | ||
746 | .probe = ux500_msp_dai_probe, | ||
747 | .id = 3, | ||
748 | .suspend = NULL, | ||
749 | .resume = NULL, | ||
750 | .playback = { | ||
751 | .channels_min = UX500_MSP_MIN_CHANNELS, | ||
752 | .channels_max = UX500_MSP_MAX_CHANNELS, | ||
753 | .rates = UX500_I2S_RATES, | ||
754 | .formats = UX500_I2S_FORMATS, | ||
755 | }, | ||
756 | .capture = { | ||
757 | .channels_min = UX500_MSP_MIN_CHANNELS, | ||
758 | .channels_max = UX500_MSP_MAX_CHANNELS, | ||
759 | .rates = UX500_I2S_RATES, | ||
760 | .formats = UX500_I2S_FORMATS, | ||
761 | }, | ||
762 | .ops = ux500_msp_dai_ops, | ||
763 | }, | ||
764 | }; | 734 | }; |
765 | 735 | ||
766 | static const struct snd_soc_component_driver ux500_msp_component = { | 736 | static const struct snd_soc_component_driver ux500_msp_component = { |
@@ -771,10 +741,14 @@ static const struct snd_soc_component_driver ux500_msp_component = { | |||
771 | static int ux500_msp_drv_probe(struct platform_device *pdev) | 741 | static int ux500_msp_drv_probe(struct platform_device *pdev) |
772 | { | 742 | { |
773 | struct ux500_msp_i2s_drvdata *drvdata; | 743 | struct ux500_msp_i2s_drvdata *drvdata; |
744 | struct msp_i2s_platform_data *pdata = pdev->dev.platform_data; | ||
745 | struct device_node *np = pdev->dev.of_node; | ||
774 | int ret = 0; | 746 | int ret = 0; |
775 | 747 | ||
776 | dev_dbg(&pdev->dev, "%s: Enter (pdev->name = %s).\n", __func__, | 748 | if (!pdata && !np) { |
777 | pdev->name); | 749 | dev_err(&pdev->dev, "No platform data or Device Tree found\n"); |
750 | return -ENODEV; | ||
751 | } | ||
778 | 752 | ||
779 | drvdata = devm_kzalloc(&pdev->dev, | 753 | drvdata = devm_kzalloc(&pdev->dev, |
780 | sizeof(struct ux500_msp_i2s_drvdata), | 754 | sizeof(struct ux500_msp_i2s_drvdata), |
@@ -826,7 +800,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev) | |||
826 | dev_set_drvdata(&pdev->dev, drvdata); | 800 | dev_set_drvdata(&pdev->dev, drvdata); |
827 | 801 | ||
828 | ret = snd_soc_register_component(&pdev->dev, &ux500_msp_component, | 802 | ret = snd_soc_register_component(&pdev->dev, &ux500_msp_component, |
829 | &ux500_msp_dai_drv[drvdata->msp->id], 1); | 803 | &ux500_msp_dai_drv, 1); |
830 | if (ret < 0) { | 804 | if (ret < 0) { |
831 | dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n", | 805 | dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n", |
832 | __func__, drvdata->msp->id); | 806 | __func__, drvdata->msp->id); |
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 1ca8b08ae993..959d7b4edf56 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c | |||
@@ -646,6 +646,34 @@ int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir) | |||
646 | 646 | ||
647 | } | 647 | } |
648 | 648 | ||
649 | static int ux500_msp_i2s_of_init_msp(struct platform_device *pdev, | ||
650 | struct ux500_msp *msp, | ||
651 | struct msp_i2s_platform_data **platform_data) | ||
652 | { | ||
653 | struct msp_i2s_platform_data *pdata; | ||
654 | |||
655 | *platform_data = devm_kzalloc(&pdev->dev, | ||
656 | sizeof(struct msp_i2s_platform_data), | ||
657 | GFP_KERNEL); | ||
658 | pdata = *platform_data; | ||
659 | if (!pdata) | ||
660 | return -ENOMEM; | ||
661 | |||
662 | msp->playback_dma_data.dma_cfg = devm_kzalloc(&pdev->dev, | ||
663 | sizeof(struct stedma40_chan_cfg), | ||
664 | GFP_KERNEL); | ||
665 | if (!msp->playback_dma_data.dma_cfg) | ||
666 | return -ENOMEM; | ||
667 | |||
668 | msp->capture_dma_data.dma_cfg = devm_kzalloc(&pdev->dev, | ||
669 | sizeof(struct stedma40_chan_cfg), | ||
670 | GFP_KERNEL); | ||
671 | if (!msp->capture_dma_data.dma_cfg) | ||
672 | return -ENOMEM; | ||
673 | |||
674 | return 0; | ||
675 | } | ||
676 | |||
649 | int ux500_msp_i2s_init_msp(struct platform_device *pdev, | 677 | int ux500_msp_i2s_init_msp(struct platform_device *pdev, |
650 | struct ux500_msp **msp_p, | 678 | struct ux500_msp **msp_p, |
651 | struct msp_i2s_platform_data *platform_data) | 679 | struct msp_i2s_platform_data *platform_data) |
@@ -653,30 +681,28 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, | |||
653 | struct resource *res = NULL; | 681 | struct resource *res = NULL; |
654 | struct device_node *np = pdev->dev.of_node; | 682 | struct device_node *np = pdev->dev.of_node; |
655 | struct ux500_msp *msp; | 683 | struct ux500_msp *msp; |
684 | int ret; | ||
656 | 685 | ||
657 | *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); | 686 | *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); |
658 | msp = *msp_p; | 687 | msp = *msp_p; |
659 | if (!msp) | 688 | if (!msp) |
660 | return -ENOMEM; | 689 | return -ENOMEM; |
661 | 690 | ||
662 | if (np) { | 691 | if (!platform_data) { |
663 | if (!platform_data) { | 692 | if (np) { |
664 | platform_data = devm_kzalloc(&pdev->dev, | 693 | ret = ux500_msp_i2s_of_init_msp(pdev, msp, |
665 | sizeof(struct msp_i2s_platform_data), GFP_KERNEL); | 694 | &platform_data); |
666 | if (!platform_data) | 695 | if (ret) |
667 | return -ENOMEM; | 696 | return ret; |
668 | } | 697 | } else |
669 | } else | ||
670 | if (!platform_data) | ||
671 | return -EINVAL; | 698 | return -EINVAL; |
699 | } else { | ||
700 | msp->playback_dma_data.dma_cfg = platform_data->msp_i2s_dma_tx; | ||
701 | msp->capture_dma_data.dma_cfg = platform_data->msp_i2s_dma_rx; | ||
702 | msp->id = platform_data->id; | ||
703 | } | ||
672 | 704 | ||
673 | dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__, | ||
674 | pdev->name, platform_data->id); | ||
675 | |||
676 | msp->id = platform_data->id; | ||
677 | msp->dev = &pdev->dev; | 705 | msp->dev = &pdev->dev; |
678 | msp->playback_dma_data.dma_cfg = platform_data->msp_i2s_dma_tx; | ||
679 | msp->capture_dma_data.dma_cfg = platform_data->msp_i2s_dma_rx; | ||
680 | 706 | ||
681 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 707 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
682 | if (res == NULL) { | 708 | if (res == NULL) { |
diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h index 258d0bcee0bd..875de0f68b85 100644 --- a/sound/soc/ux500/ux500_msp_i2s.h +++ b/sound/soc/ux500/ux500_msp_i2s.h | |||
@@ -475,7 +475,7 @@ struct ux500_msp_dma_params { | |||
475 | }; | 475 | }; |
476 | 476 | ||
477 | struct ux500_msp { | 477 | struct ux500_msp { |
478 | enum msp_i2s_id id; | 478 | int id; |
479 | void __iomem *registers; | 479 | void __iomem *registers; |
480 | struct device *dev; | 480 | struct device *dev; |
481 | struct ux500_msp_dma_params playback_dma_data; | 481 | struct ux500_msp_dma_params playback_dma_data; |
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index ce554de5d9dc..51a66a87305a 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c | |||
@@ -28,12 +28,6 @@ | |||
28 | #include "ux500_msp_i2s.h" | 28 | #include "ux500_msp_i2s.h" |
29 | #include "ux500_pcm.h" | 29 | #include "ux500_pcm.h" |
30 | 30 | ||
31 | #define UX500_PLATFORM_MIN_RATE 8000 | ||
32 | #define UX500_PLATFORM_MAX_RATE 48000 | ||
33 | |||
34 | #define UX500_PLATFORM_MIN_CHANNELS 1 | ||
35 | #define UX500_PLATFORM_MAX_CHANNELS 8 | ||
36 | |||
37 | #define UX500_PLATFORM_PERIODS_BYTES_MIN 128 | 31 | #define UX500_PLATFORM_PERIODS_BYTES_MIN 128 |
38 | #define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE) | 32 | #define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE) |
39 | #define UX500_PLATFORM_PERIODS_MIN 2 | 33 | #define UX500_PLATFORM_PERIODS_MIN 2 |
@@ -45,15 +39,6 @@ static const struct snd_pcm_hardware ux500_pcm_hw = { | |||
45 | SNDRV_PCM_INFO_MMAP | | 39 | SNDRV_PCM_INFO_MMAP | |
46 | SNDRV_PCM_INFO_RESUME | | 40 | SNDRV_PCM_INFO_RESUME | |
47 | SNDRV_PCM_INFO_PAUSE, | 41 | SNDRV_PCM_INFO_PAUSE, |
48 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
49 | SNDRV_PCM_FMTBIT_U16_LE | | ||
50 | SNDRV_PCM_FMTBIT_S16_BE | | ||
51 | SNDRV_PCM_FMTBIT_U16_BE, | ||
52 | .rates = SNDRV_PCM_RATE_KNOT, | ||
53 | .rate_min = UX500_PLATFORM_MIN_RATE, | ||
54 | .rate_max = UX500_PLATFORM_MAX_RATE, | ||
55 | .channels_min = UX500_PLATFORM_MIN_CHANNELS, | ||
56 | .channels_max = UX500_PLATFORM_MAX_CHANNELS, | ||
57 | .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, | 42 | .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, |
58 | .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN, | 43 | .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN, |
59 | .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX, | 44 | .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX, |
@@ -65,14 +50,10 @@ static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd, | |||
65 | struct snd_pcm_substream *substream) | 50 | struct snd_pcm_substream *substream) |
66 | { | 51 | { |
67 | struct snd_soc_dai *dai = rtd->cpu_dai; | 52 | struct snd_soc_dai *dai = rtd->cpu_dai; |
68 | struct device *dev = dai->dev; | ||
69 | u16 per_data_width, mem_data_width; | 53 | u16 per_data_width, mem_data_width; |
70 | struct stedma40_chan_cfg *dma_cfg; | 54 | struct stedma40_chan_cfg *dma_cfg; |
71 | struct ux500_msp_dma_params *dma_params; | 55 | struct ux500_msp_dma_params *dma_params; |
72 | 56 | ||
73 | dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id, | ||
74 | snd_pcm_stream_str(substream)); | ||
75 | |||
76 | dma_params = snd_soc_dai_get_dma_data(dai, substream); | 57 | dma_params = snd_soc_dai_get_dma_data(dai, substream); |
77 | dma_cfg = dma_params->dma_cfg; | 58 | dma_cfg = dma_params->dma_cfg; |
78 | 59 | ||
@@ -108,26 +89,36 @@ static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream, | |||
108 | struct dma_slave_config *slave_config) | 89 | struct dma_slave_config *slave_config) |
109 | { | 90 | { |
110 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 91 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
111 | struct ux500_msp_dma_params *dma_params; | 92 | struct msp_i2s_platform_data *pdata = rtd->cpu_dai->dev->platform_data; |
112 | struct stedma40_chan_cfg *dma_cfg; | 93 | struct snd_dmaengine_dai_dma_data *snd_dma_params; |
94 | struct ux500_msp_dma_params *ste_dma_params; | ||
95 | dma_addr_t dma_addr; | ||
113 | int ret; | 96 | int ret; |
114 | 97 | ||
115 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 98 | if (pdata) { |
116 | dma_cfg = dma_params->dma_cfg; | 99 | ste_dma_params = |
100 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
101 | dma_addr = ste_dma_params->tx_rx_addr; | ||
102 | } else { | ||
103 | snd_dma_params = | ||
104 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
105 | dma_addr = snd_dma_params->addr; | ||
106 | } | ||
117 | 107 | ||
118 | ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); | 108 | ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); |
119 | if (ret) | 109 | if (ret) |
120 | return ret; | 110 | return ret; |
121 | 111 | ||
122 | slave_config->dst_maxburst = 4; | 112 | slave_config->dst_maxburst = 4; |
123 | slave_config->dst_addr_width = dma_cfg->dst_info.data_width; | ||
124 | slave_config->src_maxburst = 4; | 113 | slave_config->src_maxburst = 4; |
125 | slave_config->src_addr_width = dma_cfg->src_info.data_width; | 114 | |
115 | slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
116 | slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
126 | 117 | ||
127 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 118 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
128 | slave_config->dst_addr = dma_params->tx_rx_addr; | 119 | slave_config->dst_addr = dma_addr; |
129 | else | 120 | else |
130 | slave_config->src_addr = dma_params->tx_rx_addr; | 121 | slave_config->src_addr = dma_addr; |
131 | 122 | ||
132 | return 0; | 123 | return 0; |
133 | } | 124 | } |
@@ -139,15 +130,25 @@ static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = { | |||
139 | .prepare_slave_config = ux500_pcm_prepare_slave_config, | 130 | .prepare_slave_config = ux500_pcm_prepare_slave_config, |
140 | }; | 131 | }; |
141 | 132 | ||
133 | static const struct snd_dmaengine_pcm_config ux500_dmaengine_of_pcm_config = { | ||
134 | .compat_request_channel = ux500_pcm_request_chan, | ||
135 | .prepare_slave_config = ux500_pcm_prepare_slave_config, | ||
136 | }; | ||
137 | |||
142 | int ux500_pcm_register_platform(struct platform_device *pdev) | 138 | int ux500_pcm_register_platform(struct platform_device *pdev) |
143 | { | 139 | { |
140 | const struct snd_dmaengine_pcm_config *pcm_config; | ||
141 | struct device_node *np = pdev->dev.of_node; | ||
144 | int ret; | 142 | int ret; |
145 | 143 | ||
146 | ret = snd_dmaengine_pcm_register(&pdev->dev, | 144 | if (np) |
147 | &ux500_dmaengine_pcm_config, | 145 | pcm_config = &ux500_dmaengine_of_pcm_config; |
148 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | 146 | else |
149 | SND_DMAENGINE_PCM_FLAG_COMPAT | | 147 | pcm_config = &ux500_dmaengine_pcm_config; |
150 | SND_DMAENGINE_PCM_FLAG_NO_DT); | 148 | |
149 | ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config, | ||
150 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | ||
151 | SND_DMAENGINE_PCM_FLAG_COMPAT); | ||
151 | if (ret < 0) { | 152 | if (ret < 0) { |
152 | dev_err(&pdev->dev, | 153 | dev_err(&pdev->dev, |
153 | "%s: ERROR: Failed to register platform '%s' (%d)!\n", | 154 | "%s: ERROR: Failed to register platform '%s' (%d)!\n", |