diff options
Diffstat (limited to 'sound/soc')
157 files changed, 13763 insertions, 3150 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 0060b31cc3f3..0e9623368ab0 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -47,6 +47,7 @@ source "sound/soc/kirkwood/Kconfig" | |||
47 | source "sound/soc/intel/Kconfig" | 47 | source "sound/soc/intel/Kconfig" |
48 | source "sound/soc/mxs/Kconfig" | 48 | source "sound/soc/mxs/Kconfig" |
49 | source "sound/soc/pxa/Kconfig" | 49 | source "sound/soc/pxa/Kconfig" |
50 | source "sound/soc/rockchip/Kconfig" | ||
50 | source "sound/soc/samsung/Kconfig" | 51 | source "sound/soc/samsung/Kconfig" |
51 | source "sound/soc/s6000/Kconfig" | 52 | source "sound/soc/s6000/Kconfig" |
52 | source "sound/soc/sh/Kconfig" | 53 | source "sound/soc/sh/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 5f1df02984f8..534714a1ca44 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -24,6 +24,7 @@ obj-$(CONFIG_SND_SOC) += nuc900/ | |||
24 | obj-$(CONFIG_SND_SOC) += omap/ | 24 | obj-$(CONFIG_SND_SOC) += omap/ |
25 | obj-$(CONFIG_SND_SOC) += kirkwood/ | 25 | obj-$(CONFIG_SND_SOC) += kirkwood/ |
26 | obj-$(CONFIG_SND_SOC) += pxa/ | 26 | obj-$(CONFIG_SND_SOC) += pxa/ |
27 | obj-$(CONFIG_SND_SOC) += rockchip/ | ||
27 | obj-$(CONFIG_SND_SOC) += samsung/ | 28 | obj-$(CONFIG_SND_SOC) += samsung/ |
28 | obj-$(CONFIG_SND_SOC) += s6000/ | 29 | obj-$(CONFIG_SND_SOC) += s6000/ |
29 | obj-$(CONFIG_SND_SOC) += sh/ | 30 | obj-$(CONFIG_SND_SOC) += sh/ |
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index de433cfd044c..f403f399808a 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
347 | u32 tfmr, rfmr, tcmr, rcmr; | 347 | u32 tfmr, rfmr, tcmr, rcmr; |
348 | int start_event; | 348 | int start_event; |
349 | int ret; | 349 | int ret; |
350 | int fslen, fslen_ext; | ||
350 | 351 | ||
351 | /* | 352 | /* |
352 | * Currently, there is only one set of dma params for | 353 | * Currently, there is only one set of dma params for |
@@ -388,18 +389,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
388 | } | 389 | } |
389 | 390 | ||
390 | /* | 391 | /* |
391 | * The SSC only supports up to 16-bit samples in I2S format, due | ||
392 | * to the size of the Frame Mode Register FSLEN field. | ||
393 | */ | ||
394 | if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S | ||
395 | && bits > 16) { | ||
396 | printk(KERN_WARNING | ||
397 | "atmel_ssc_dai: sample size %d " | ||
398 | "is too large for I2S\n", bits); | ||
399 | return -EINVAL; | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * Compute SSC register settings. | 392 | * Compute SSC register settings. |
404 | */ | 393 | */ |
405 | switch (ssc_p->daifmt | 394 | switch (ssc_p->daifmt |
@@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
413 | * from the MCK divider, and the BCLK signal | 402 | * from the MCK divider, and the BCLK signal |
414 | * is output on the SSC TK line. | 403 | * is output on the SSC TK line. |
415 | */ | 404 | */ |
405 | |||
406 | if (bits > 16 && !ssc->pdata->has_fslen_ext) { | ||
407 | dev_err(dai->dev, | ||
408 | "sample size %d is too large for SSC device\n", | ||
409 | bits); | ||
410 | return -EINVAL; | ||
411 | } | ||
412 | |||
413 | fslen_ext = (bits - 1) / 16; | ||
414 | fslen = (bits - 1) % 16; | ||
415 | |||
416 | rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | 416 | rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
417 | | SSC_BF(RCMR_STTDLY, START_DELAY) | 417 | | SSC_BF(RCMR_STTDLY, START_DELAY) |
418 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | 418 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) |
@@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
420 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | 420 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
421 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); | 421 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); |
422 | 422 | ||
423 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | 423 | rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext) |
424 | | SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
424 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | 425 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) |
425 | | SSC_BF(RFMR_FSLEN, (bits - 1)) | 426 | | SSC_BF(RFMR_FSLEN, fslen) |
426 | | SSC_BF(RFMR_DATNB, (channels - 1)) | 427 | | SSC_BF(RFMR_DATNB, (channels - 1)) |
427 | | SSC_BIT(RFMR_MSBF) | 428 | | SSC_BIT(RFMR_MSBF) |
428 | | SSC_BF(RFMR_LOOP, 0) | 429 | | SSC_BF(RFMR_LOOP, 0) |
@@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
435 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | 436 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
436 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); | 437 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); |
437 | 438 | ||
438 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | 439 | tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext) |
440 | | SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
439 | | SSC_BF(TFMR_FSDEN, 0) | 441 | | SSC_BF(TFMR_FSDEN, 0) |
440 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | 442 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) |
441 | | SSC_BF(TFMR_FSLEN, (bits - 1)) | 443 | | SSC_BF(TFMR_FSLEN, fslen) |
442 | | SSC_BF(TFMR_DATNB, (channels - 1)) | 444 | | SSC_BF(TFMR_DATNB, (channels - 1)) |
443 | | SSC_BIT(TFMR_MSBF) | 445 | | SSC_BIT(TFMR_MSBF) |
444 | | SSC_BF(TFMR_DATDEF, 0) | 446 | | SSC_BF(TFMR_DATDEF, 0) |
diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c index b4e36901a40b..4052268ce462 100644 --- a/sound/soc/atmel/atmel_wm8904.c +++ b/sound/soc/atmel/atmel_wm8904.c | |||
@@ -18,10 +18,6 @@ | |||
18 | #include "../codecs/wm8904.h" | 18 | #include "../codecs/wm8904.h" |
19 | #include "atmel_ssc_dai.h" | 19 | #include "atmel_ssc_dai.h" |
20 | 20 | ||
21 | #define MCLK_RATE 32768 | ||
22 | |||
23 | static struct clk *mclk; | ||
24 | |||
25 | static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = { | 21 | static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = { |
26 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | 22 | SND_SOC_DAPM_HP("Headphone Jack", NULL), |
27 | SND_SOC_DAPM_MIC("Mic", NULL), | 23 | SND_SOC_DAPM_MIC("Mic", NULL), |
@@ -61,26 +57,6 @@ static struct snd_soc_ops atmel_asoc_wm8904_ops = { | |||
61 | .hw_params = atmel_asoc_wm8904_hw_params, | 57 | .hw_params = atmel_asoc_wm8904_hw_params, |
62 | }; | 58 | }; |
63 | 59 | ||
64 | static int atmel_set_bias_level(struct snd_soc_card *card, | ||
65 | struct snd_soc_dapm_context *dapm, | ||
66 | enum snd_soc_bias_level level) | ||
67 | { | ||
68 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { | ||
69 | switch (level) { | ||
70 | case SND_SOC_BIAS_PREPARE: | ||
71 | clk_prepare_enable(mclk); | ||
72 | break; | ||
73 | case SND_SOC_BIAS_OFF: | ||
74 | clk_disable_unprepare(mclk); | ||
75 | break; | ||
76 | default: | ||
77 | break; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | }; | ||
83 | |||
84 | static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = { | 60 | static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = { |
85 | .name = "WM8904", | 61 | .name = "WM8904", |
86 | .stream_name = "WM8904 PCM", | 62 | .stream_name = "WM8904 PCM", |
@@ -94,7 +70,6 @@ static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = { | |||
94 | static struct snd_soc_card atmel_asoc_wm8904_card = { | 70 | static struct snd_soc_card atmel_asoc_wm8904_card = { |
95 | .name = "atmel_asoc_wm8904", | 71 | .name = "atmel_asoc_wm8904", |
96 | .owner = THIS_MODULE, | 72 | .owner = THIS_MODULE, |
97 | .set_bias_level = atmel_set_bias_level, | ||
98 | .dai_link = &atmel_asoc_wm8904_dailink, | 73 | .dai_link = &atmel_asoc_wm8904_dailink, |
99 | .num_links = 1, | 74 | .num_links = 1, |
100 | .dapm_widgets = atmel_asoc_wm8904_dapm_widgets, | 75 | .dapm_widgets = atmel_asoc_wm8904_dapm_widgets, |
@@ -153,7 +128,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev) | |||
153 | { | 128 | { |
154 | struct snd_soc_card *card = &atmel_asoc_wm8904_card; | 129 | struct snd_soc_card *card = &atmel_asoc_wm8904_card; |
155 | struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; | 130 | struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; |
156 | struct clk *clk_src; | ||
157 | int id, ret; | 131 | int id, ret; |
158 | 132 | ||
159 | card->dev = &pdev->dev; | 133 | card->dev = &pdev->dev; |
@@ -170,30 +144,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev) | |||
170 | return ret; | 144 | return ret; |
171 | } | 145 | } |
172 | 146 | ||
173 | mclk = clk_get(NULL, "pck0"); | ||
174 | if (IS_ERR(mclk)) { | ||
175 | dev_err(&pdev->dev, "failed to get pck0\n"); | ||
176 | ret = PTR_ERR(mclk); | ||
177 | goto err_set_audio; | ||
178 | } | ||
179 | |||
180 | clk_src = clk_get(NULL, "clk32k"); | ||
181 | if (IS_ERR(clk_src)) { | ||
182 | dev_err(&pdev->dev, "failed to get clk32k\n"); | ||
183 | ret = PTR_ERR(clk_src); | ||
184 | goto err_set_audio; | ||
185 | } | ||
186 | |||
187 | ret = clk_set_parent(mclk, clk_src); | ||
188 | clk_put(clk_src); | ||
189 | if (ret != 0) { | ||
190 | dev_err(&pdev->dev, "failed to set MCLK parent\n"); | ||
191 | goto err_set_audio; | ||
192 | } | ||
193 | |||
194 | dev_info(&pdev->dev, "setting pck0 to %dHz\n", MCLK_RATE); | ||
195 | clk_set_rate(mclk, MCLK_RATE); | ||
196 | |||
197 | ret = snd_soc_register_card(card); | 147 | ret = snd_soc_register_card(card); |
198 | if (ret) { | 148 | if (ret) { |
199 | dev_err(&pdev->dev, "snd_soc_register_card failed\n"); | 149 | dev_err(&pdev->dev, "snd_soc_register_card failed\n"); |
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index a3881c4381c9..bcf591373a7a 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -290,19 +290,19 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, | |||
290 | unsigned int sample_size = runtime->sample_bits / 8; | 290 | unsigned int sample_size = runtime->sample_bits / 8; |
291 | void *buf = runtime->dma_area; | 291 | void *buf = runtime->dma_area; |
292 | struct bf5xx_i2s_pcm_data *dma_data; | 292 | struct bf5xx_i2s_pcm_data *dma_data; |
293 | unsigned int offset, size; | 293 | unsigned int offset, samples; |
294 | 294 | ||
295 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 295 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
296 | 296 | ||
297 | if (dma_data->tdm_mode) { | 297 | if (dma_data->tdm_mode) { |
298 | offset = pos * 8 * sample_size; | 298 | offset = pos * 8 * sample_size; |
299 | size = count * 8 * sample_size; | 299 | samples = count * 8; |
300 | } else { | 300 | } else { |
301 | offset = frames_to_bytes(runtime, pos); | 301 | offset = frames_to_bytes(runtime, pos); |
302 | size = frames_to_bytes(runtime, count); | 302 | samples = count * runtime->channels; |
303 | } | 303 | } |
304 | 304 | ||
305 | snd_pcm_format_set_silence(runtime->format, buf + offset, size); | 305 | snd_pcm_format_set_silence(runtime->format, buf + offset, samples); |
306 | 306 | ||
307 | return 0; | 307 | return 0; |
308 | } | 308 | } |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index cbfa1e18f651..a445b448d41d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -47,6 +47,7 @@ config SND_SOC_ALL_CODECS | |||
47 | select SND_SOC_CS42L52 if I2C && INPUT | 47 | select SND_SOC_CS42L52 if I2C && INPUT |
48 | select SND_SOC_CS42L56 if I2C && INPUT | 48 | select SND_SOC_CS42L56 if I2C && INPUT |
49 | select SND_SOC_CS42L73 if I2C | 49 | select SND_SOC_CS42L73 if I2C |
50 | select SND_SOC_CS4265 if I2C | ||
50 | select SND_SOC_CS4270 if I2C | 51 | select SND_SOC_CS4270 if I2C |
51 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI | 52 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI |
52 | select SND_SOC_CS42XX8_I2C if I2C | 53 | select SND_SOC_CS42XX8_I2C if I2C |
@@ -74,10 +75,12 @@ config SND_SOC_ALL_CODECS | |||
74 | select SND_SOC_PCM3008 | 75 | select SND_SOC_PCM3008 |
75 | select SND_SOC_PCM512x_I2C if I2C | 76 | select SND_SOC_PCM512x_I2C if I2C |
76 | select SND_SOC_PCM512x_SPI if SPI_MASTER | 77 | select SND_SOC_PCM512x_SPI if SPI_MASTER |
78 | select SND_SOC_RT286 if I2C | ||
77 | select SND_SOC_RT5631 if I2C | 79 | select SND_SOC_RT5631 if I2C |
78 | select SND_SOC_RT5640 if I2C | 80 | select SND_SOC_RT5640 if I2C |
79 | select SND_SOC_RT5645 if I2C | 81 | select SND_SOC_RT5645 if I2C |
80 | select SND_SOC_RT5651 if I2C | 82 | select SND_SOC_RT5651 if I2C |
83 | select SND_SOC_RT5670 if I2C | ||
81 | select SND_SOC_RT5677 if I2C | 84 | select SND_SOC_RT5677 if I2C |
82 | select SND_SOC_SGTL5000 if I2C | 85 | select SND_SOC_SGTL5000 if I2C |
83 | select SND_SOC_SI476X if MFD_SI476X_CORE | 86 | select SND_SOC_SI476X if MFD_SI476X_CORE |
@@ -225,11 +228,11 @@ config SND_SOC_ADAU1373 | |||
225 | config SND_SOC_ADAU1701 | 228 | config SND_SOC_ADAU1701 |
226 | tristate "Analog Devices ADAU1701 CODEC" | 229 | tristate "Analog Devices ADAU1701 CODEC" |
227 | depends on I2C | 230 | depends on I2C |
228 | select SND_SOC_SIGMADSP | 231 | select SND_SOC_SIGMADSP_I2C |
229 | 232 | ||
230 | config SND_SOC_ADAU17X1 | 233 | config SND_SOC_ADAU17X1 |
231 | tristate | 234 | tristate |
232 | select SND_SOC_SIGMADSP | 235 | select SND_SOC_SIGMADSP_REGMAP |
233 | 236 | ||
234 | config SND_SOC_ADAU1761 | 237 | config SND_SOC_ADAU1761 |
235 | tristate | 238 | tristate |
@@ -338,6 +341,11 @@ config SND_SOC_CS42L73 | |||
338 | tristate "Cirrus Logic CS42L73 CODEC" | 341 | tristate "Cirrus Logic CS42L73 CODEC" |
339 | depends on I2C | 342 | depends on I2C |
340 | 343 | ||
344 | config SND_SOC_CS4265 | ||
345 | tristate "Cirrus Logic CS4265 CODEC" | ||
346 | depends on I2C | ||
347 | select REGMAP_I2C | ||
348 | |||
341 | # Cirrus Logic CS4270 Codec | 349 | # Cirrus Logic CS4270 Codec |
342 | config SND_SOC_CS4270 | 350 | config SND_SOC_CS4270 |
343 | tristate "Cirrus Logic CS4270 CODEC" | 351 | tristate "Cirrus Logic CS4270 CODEC" |
@@ -445,9 +453,16 @@ config SND_SOC_RL6231 | |||
445 | default y if SND_SOC_RT5640=y | 453 | default y if SND_SOC_RT5640=y |
446 | default y if SND_SOC_RT5645=y | 454 | default y if SND_SOC_RT5645=y |
447 | default y if SND_SOC_RT5651=y | 455 | default y if SND_SOC_RT5651=y |
456 | default y if SND_SOC_RT5670=y | ||
457 | default y if SND_SOC_RT5677=y | ||
448 | default m if SND_SOC_RT5640=m | 458 | default m if SND_SOC_RT5640=m |
449 | default m if SND_SOC_RT5645=m | 459 | default m if SND_SOC_RT5645=m |
450 | default m if SND_SOC_RT5651=m | 460 | default m if SND_SOC_RT5651=m |
461 | default m if SND_SOC_RT5670=m | ||
462 | default m if SND_SOC_RT5677=m | ||
463 | |||
464 | config SND_SOC_RT286 | ||
465 | tristate | ||
451 | 466 | ||
452 | config SND_SOC_RT5631 | 467 | config SND_SOC_RT5631 |
453 | tristate | 468 | tristate |
@@ -461,6 +476,9 @@ config SND_SOC_RT5645 | |||
461 | config SND_SOC_RT5651 | 476 | config SND_SOC_RT5651 |
462 | tristate | 477 | tristate |
463 | 478 | ||
479 | config SND_SOC_RT5670 | ||
480 | tristate | ||
481 | |||
464 | config SND_SOC_RT5677 | 482 | config SND_SOC_RT5677 |
465 | tristate | 483 | tristate |
466 | 484 | ||
@@ -476,6 +494,14 @@ config SND_SOC_SIGMADSP | |||
476 | tristate | 494 | tristate |
477 | select CRC32 | 495 | select CRC32 |
478 | 496 | ||
497 | config SND_SOC_SIGMADSP_I2C | ||
498 | tristate | ||
499 | select SND_SOC_SIGMADSP | ||
500 | |||
501 | config SND_SOC_SIGMADSP_REGMAP | ||
502 | tristate | ||
503 | select SND_SOC_SIGMADSP | ||
504 | |||
479 | config SND_SOC_SIRF_AUDIO_CODEC | 505 | config SND_SOC_SIRF_AUDIO_CODEC |
480 | tristate "SiRF SoC internal audio codec" | 506 | tristate "SiRF SoC internal audio codec" |
481 | select REGMAP_MMIO | 507 | select REGMAP_MMIO |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index be3377b8d73f..a29da79a4359 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -37,6 +37,7 @@ snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o | |||
37 | snd-soc-cs42l52-objs := cs42l52.o | 37 | snd-soc-cs42l52-objs := cs42l52.o |
38 | snd-soc-cs42l56-objs := cs42l56.o | 38 | snd-soc-cs42l56-objs := cs42l56.o |
39 | snd-soc-cs42l73-objs := cs42l73.o | 39 | snd-soc-cs42l73-objs := cs42l73.o |
40 | snd-soc-cs4265-objs := cs4265.o | ||
40 | snd-soc-cs4270-objs := cs4270.o | 41 | snd-soc-cs4270-objs := cs4270.o |
41 | snd-soc-cs4271-objs := cs4271.o | 42 | snd-soc-cs4271-objs := cs4271.o |
42 | snd-soc-cs42xx8-objs := cs42xx8.o | 43 | snd-soc-cs42xx8-objs := cs42xx8.o |
@@ -68,15 +69,19 @@ snd-soc-pcm512x-objs := pcm512x.o | |||
68 | snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o | 69 | snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o |
69 | snd-soc-pcm512x-spi-objs := pcm512x-spi.o | 70 | snd-soc-pcm512x-spi-objs := pcm512x-spi.o |
70 | snd-soc-rl6231-objs := rl6231.o | 71 | snd-soc-rl6231-objs := rl6231.o |
72 | snd-soc-rt286-objs := rt286.o | ||
71 | snd-soc-rt5631-objs := rt5631.o | 73 | snd-soc-rt5631-objs := rt5631.o |
72 | snd-soc-rt5640-objs := rt5640.o | 74 | snd-soc-rt5640-objs := rt5640.o |
73 | snd-soc-rt5645-objs := rt5645.o | 75 | snd-soc-rt5645-objs := rt5645.o |
74 | snd-soc-rt5651-objs := rt5651.o | 76 | snd-soc-rt5651-objs := rt5651.o |
77 | snd-soc-rt5670-objs := rt5670.o | ||
75 | snd-soc-rt5677-objs := rt5677.o | 78 | snd-soc-rt5677-objs := rt5677.o |
76 | snd-soc-sgtl5000-objs := sgtl5000.o | 79 | snd-soc-sgtl5000-objs := sgtl5000.o |
77 | snd-soc-alc5623-objs := alc5623.o | 80 | snd-soc-alc5623-objs := alc5623.o |
78 | snd-soc-alc5632-objs := alc5632.o | 81 | snd-soc-alc5632-objs := alc5632.o |
79 | snd-soc-sigmadsp-objs := sigmadsp.o | 82 | snd-soc-sigmadsp-objs := sigmadsp.o |
83 | snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o | ||
84 | snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o | ||
80 | snd-soc-si476x-objs := si476x.o | 85 | snd-soc-si476x-objs := si476x.o |
81 | snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o | 86 | snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o |
82 | snd-soc-sn95031-objs := sn95031.o | 87 | snd-soc-sn95031-objs := sn95031.o |
@@ -202,6 +207,7 @@ obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o | |||
202 | obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o | 207 | obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o |
203 | obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o | 208 | obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o |
204 | obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o | 209 | obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o |
210 | obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o | ||
205 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | 211 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o |
206 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o | 212 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o |
207 | obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o | 213 | obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o |
@@ -233,13 +239,17 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o | |||
233 | obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o | 239 | obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o |
234 | obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o | 240 | obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o |
235 | obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o | 241 | obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o |
242 | obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o | ||
236 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o | 243 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o |
237 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o | 244 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o |
238 | obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o | 245 | obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o |
239 | obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o | 246 | obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o |
247 | obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o | ||
240 | obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o | 248 | obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o |
241 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | 249 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
242 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o | 250 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o |
251 | obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o | ||
252 | obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o | ||
243 | obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o | 253 | obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o |
244 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o | 254 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o |
245 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o | 255 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 8d9ba4ba4bfe..e889e1b84192 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -89,8 +89,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) | |||
89 | int ret; | 89 | int ret; |
90 | 90 | ||
91 | /* add codec as bus device for standard ac97 */ | 91 | /* add codec as bus device for standard ac97 */ |
92 | ret = snd_ac97_bus(codec->card->snd_card, 0, soc_ac97_ops, NULL, | 92 | ret = snd_ac97_bus(codec->component.card->snd_card, 0, soc_ac97_ops, |
93 | &ac97_bus); | 93 | NULL, &ac97_bus); |
94 | if (ret < 0) | 94 | if (ret < 0) |
95 | return ret; | 95 | return ret; |
96 | 96 | ||
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index d71c59cf7bdd..370b742117ef 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
@@ -230,8 +230,10 @@ static int adau1701_reg_read(void *context, unsigned int reg, | |||
230 | 230 | ||
231 | *value = 0; | 231 | *value = 0; |
232 | 232 | ||
233 | for (i = 0; i < size; i++) | 233 | for (i = 0; i < size; i++) { |
234 | *value |= recv_buf[i] << (i * 8); | 234 | *value <<= 8; |
235 | *value |= recv_buf[i]; | ||
236 | } | ||
235 | 237 | ||
236 | return 0; | 238 | return 0; |
237 | } | 239 | } |
diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c index fd55da7cb9d4..70ab35744aba 100644 --- a/sound/soc/codecs/adau1977.c +++ b/sound/soc/codecs/adau1977.c | |||
@@ -968,7 +968,7 @@ int adau1977_probe(struct device *dev, struct regmap *regmap, | |||
968 | if (adau1977->dvdd_reg) | 968 | if (adau1977->dvdd_reg) |
969 | power_off_mask = ~0; | 969 | power_off_mask = ~0; |
970 | else | 970 | else |
971 | power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN; | 971 | power_off_mask = (unsigned int)~ADAU1977_BLOCK_POWER_SAI_LDO_EN; |
972 | 972 | ||
973 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, | 973 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, |
974 | power_off_mask, 0x00); | 974 | power_off_mask, 0x00); |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 3ba4c0f11418..041712592e29 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -547,7 +547,7 @@ static const struct ak4642_drvdata ak4648_drvdata = { | |||
547 | .extended_frequencies = 1, | 547 | .extended_frequencies = 1, |
548 | }; | 548 | }; |
549 | 549 | ||
550 | static struct of_device_id ak4642_of_match[]; | 550 | static const struct of_device_id ak4642_of_match[]; |
551 | static int ak4642_i2c_probe(struct i2c_client *i2c, | 551 | static int ak4642_i2c_probe(struct i2c_client *i2c, |
552 | const struct i2c_device_id *id) | 552 | const struct i2c_device_id *id) |
553 | { | 553 | { |
@@ -593,7 +593,7 @@ static int ak4642_i2c_remove(struct i2c_client *client) | |||
593 | return 0; | 593 | return 0; |
594 | } | 594 | } |
595 | 595 | ||
596 | static struct of_device_id ak4642_of_match[] = { | 596 | static const struct of_device_id ak4642_of_match[] = { |
597 | { .compatible = "asahi-kasei,ak4642", .data = &ak4642_drvdata}, | 597 | { .compatible = "asahi-kasei,ak4642", .data = &ak4642_drvdata}, |
598 | { .compatible = "asahi-kasei,ak4643", .data = &ak4643_drvdata}, | 598 | { .compatible = "asahi-kasei,ak4643", .data = &ak4643_drvdata}, |
599 | { .compatible = "asahi-kasei,ak4648", .data = &ak4648_drvdata}, | 599 | { .compatible = "asahi-kasei,ak4648", .data = &ak4648_drvdata}, |
diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c index 72e953b2cb41..8107a1cac876 100644 --- a/sound/soc/codecs/ak5386.c +++ b/sound/soc/codecs/ak5386.c | |||
@@ -14,12 +14,18 @@ | |||
14 | #include <linux/of.h> | 14 | #include <linux/of.h> |
15 | #include <linux/of_gpio.h> | 15 | #include <linux/of_gpio.h> |
16 | #include <linux/of_device.h> | 16 | #include <linux/of_device.h> |
17 | #include <linux/regulator/consumer.h> | ||
17 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
18 | #include <sound/pcm.h> | 19 | #include <sound/pcm.h> |
19 | #include <sound/initval.h> | 20 | #include <sound/initval.h> |
20 | 21 | ||
22 | static const char * const supply_names[] = { | ||
23 | "va", "vd" | ||
24 | }; | ||
25 | |||
21 | struct ak5386_priv { | 26 | struct ak5386_priv { |
22 | int reset_gpio; | 27 | int reset_gpio; |
28 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | ||
23 | }; | 29 | }; |
24 | 30 | ||
25 | static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = { | 31 | static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = { |
@@ -32,7 +38,42 @@ static const struct snd_soc_dapm_route ak5386_dapm_routes[] = { | |||
32 | { "Capture", NULL, "AINR" }, | 38 | { "Capture", NULL, "AINR" }, |
33 | }; | 39 | }; |
34 | 40 | ||
41 | static int ak5386_soc_probe(struct snd_soc_codec *codec) | ||
42 | { | ||
43 | struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
44 | return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
45 | } | ||
46 | |||
47 | static int ak5386_soc_remove(struct snd_soc_codec *codec) | ||
48 | { | ||
49 | struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
50 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | #ifdef CONFIG_PM | ||
55 | static int ak5386_soc_suspend(struct snd_soc_codec *codec) | ||
56 | { | ||
57 | struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
58 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static int ak5386_soc_resume(struct snd_soc_codec *codec) | ||
63 | { | ||
64 | struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
65 | return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
66 | } | ||
67 | #else | ||
68 | #define ak5386_soc_suspend NULL | ||
69 | #define ak5386_soc_resume NULL | ||
70 | #endif /* CONFIG_PM */ | ||
71 | |||
35 | static struct snd_soc_codec_driver soc_codec_ak5386 = { | 72 | static struct snd_soc_codec_driver soc_codec_ak5386 = { |
73 | .probe = ak5386_soc_probe, | ||
74 | .remove = ak5386_soc_remove, | ||
75 | .suspend = ak5386_soc_suspend, | ||
76 | .resume = ak5386_soc_resume, | ||
36 | .dapm_widgets = ak5386_dapm_widgets, | 77 | .dapm_widgets = ak5386_dapm_widgets, |
37 | .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets), | 78 | .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets), |
38 | .dapm_routes = ak5386_dapm_routes, | 79 | .dapm_routes = ak5386_dapm_routes, |
@@ -122,6 +163,7 @@ static int ak5386_probe(struct platform_device *pdev) | |||
122 | { | 163 | { |
123 | struct device *dev = &pdev->dev; | 164 | struct device *dev = &pdev->dev; |
124 | struct ak5386_priv *priv; | 165 | struct ak5386_priv *priv; |
166 | int ret, i; | ||
125 | 167 | ||
126 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 168 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
127 | if (!priv) | 169 | if (!priv) |
@@ -130,6 +172,14 @@ static int ak5386_probe(struct platform_device *pdev) | |||
130 | priv->reset_gpio = -EINVAL; | 172 | priv->reset_gpio = -EINVAL; |
131 | dev_set_drvdata(dev, priv); | 173 | dev_set_drvdata(dev, priv); |
132 | 174 | ||
175 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
176 | priv->supplies[i].supply = supply_names[i]; | ||
177 | |||
178 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies), | ||
179 | priv->supplies); | ||
180 | if (ret < 0) | ||
181 | return ret; | ||
182 | |||
133 | if (of_match_device(of_match_ptr(ak5386_dt_ids), dev)) | 183 | if (of_match_device(of_match_ptr(ak5386_dt_ids), dev)) |
134 | priv->reset_gpio = of_get_named_gpio(dev->of_node, | 184 | priv->reset_gpio = of_get_named_gpio(dev->of_node, |
135 | "reset-gpio", 0); | 185 | "reset-gpio", 0); |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 29e198f57d4c..2f2e91ac690f 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -243,6 +243,31 @@ int arizona_init_spk(struct snd_soc_codec *codec) | |||
243 | } | 243 | } |
244 | EXPORT_SYMBOL_GPL(arizona_init_spk); | 244 | EXPORT_SYMBOL_GPL(arizona_init_spk); |
245 | 245 | ||
246 | static const struct snd_soc_dapm_route arizona_mono_routes[] = { | ||
247 | { "OUT1R", NULL, "OUT1L" }, | ||
248 | { "OUT2R", NULL, "OUT2L" }, | ||
249 | { "OUT3R", NULL, "OUT3L" }, | ||
250 | { "OUT4R", NULL, "OUT4L" }, | ||
251 | { "OUT5R", NULL, "OUT5L" }, | ||
252 | { "OUT6R", NULL, "OUT6L" }, | ||
253 | }; | ||
254 | |||
255 | int arizona_init_mono(struct snd_soc_codec *codec) | ||
256 | { | ||
257 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
258 | struct arizona *arizona = priv->arizona; | ||
259 | int i; | ||
260 | |||
261 | for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) { | ||
262 | if (arizona->pdata.out_mono[i]) | ||
263 | snd_soc_dapm_add_routes(&codec->dapm, | ||
264 | &arizona_mono_routes[i], 1); | ||
265 | } | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | EXPORT_SYMBOL_GPL(arizona_init_mono); | ||
270 | |||
246 | int arizona_init_gpio(struct snd_soc_codec *codec) | 271 | int arizona_init_gpio(struct snd_soc_codec *codec) |
247 | { | 272 | { |
248 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | 273 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); |
@@ -1127,6 +1152,31 @@ static int arizona_startup(struct snd_pcm_substream *substream, | |||
1127 | constraint); | 1152 | constraint); |
1128 | } | 1153 | } |
1129 | 1154 | ||
1155 | static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec, | ||
1156 | unsigned int rate) | ||
1157 | { | ||
1158 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
1159 | struct arizona *arizona = priv->arizona; | ||
1160 | struct reg_default dac_comp[] = { | ||
1161 | { 0x80, 0x3 }, | ||
1162 | { ARIZONA_DAC_COMP_1, 0 }, | ||
1163 | { ARIZONA_DAC_COMP_2, 0 }, | ||
1164 | { 0x80, 0x0 }, | ||
1165 | }; | ||
1166 | |||
1167 | mutex_lock(&codec->mutex); | ||
1168 | |||
1169 | dac_comp[1].def = arizona->dac_comp_coeff; | ||
1170 | if (rate >= 176400) | ||
1171 | dac_comp[2].def = arizona->dac_comp_enabled; | ||
1172 | |||
1173 | mutex_unlock(&codec->mutex); | ||
1174 | |||
1175 | regmap_multi_reg_write(arizona->regmap, | ||
1176 | dac_comp, | ||
1177 | ARRAY_SIZE(dac_comp)); | ||
1178 | } | ||
1179 | |||
1130 | static int arizona_hw_params_rate(struct snd_pcm_substream *substream, | 1180 | static int arizona_hw_params_rate(struct snd_pcm_substream *substream, |
1131 | struct snd_pcm_hw_params *params, | 1181 | struct snd_pcm_hw_params *params, |
1132 | struct snd_soc_dai *dai) | 1182 | struct snd_soc_dai *dai) |
@@ -1153,6 +1203,15 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream, | |||
1153 | 1203 | ||
1154 | switch (dai_priv->clk) { | 1204 | switch (dai_priv->clk) { |
1155 | case ARIZONA_CLK_SYSCLK: | 1205 | case ARIZONA_CLK_SYSCLK: |
1206 | switch (priv->arizona->type) { | ||
1207 | case WM5102: | ||
1208 | arizona_wm5102_set_dac_comp(codec, | ||
1209 | params_rate(params)); | ||
1210 | break; | ||
1211 | default: | ||
1212 | break; | ||
1213 | } | ||
1214 | |||
1156 | snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1, | 1215 | snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1, |
1157 | ARIZONA_SAMPLE_RATE_1_MASK, sr_val); | 1216 | ARIZONA_SAMPLE_RATE_1_MASK, sr_val); |
1158 | if (base) | 1217 | if (base) |
@@ -1175,6 +1234,27 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream, | |||
1175 | return 0; | 1234 | return 0; |
1176 | } | 1235 | } |
1177 | 1236 | ||
1237 | static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec, | ||
1238 | int base, int bclk, int lrclk, int frame) | ||
1239 | { | ||
1240 | int val; | ||
1241 | |||
1242 | val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL); | ||
1243 | if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK)) | ||
1244 | return true; | ||
1245 | |||
1246 | val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE); | ||
1247 | if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK)) | ||
1248 | return true; | ||
1249 | |||
1250 | val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1); | ||
1251 | if (frame != (val & (ARIZONA_AIF1TX_WL_MASK | | ||
1252 | ARIZONA_AIF1TX_SLOT_LEN_MASK))) | ||
1253 | return true; | ||
1254 | |||
1255 | return false; | ||
1256 | } | ||
1257 | |||
1178 | static int arizona_hw_params(struct snd_pcm_substream *substream, | 1258 | static int arizona_hw_params(struct snd_pcm_substream *substream, |
1179 | struct snd_pcm_hw_params *params, | 1259 | struct snd_pcm_hw_params *params, |
1180 | struct snd_soc_dai *dai) | 1260 | struct snd_soc_dai *dai) |
@@ -1185,26 +1265,40 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
1185 | int base = dai->driver->base; | 1265 | int base = dai->driver->base; |
1186 | const int *rates; | 1266 | const int *rates; |
1187 | int i, ret, val; | 1267 | int i, ret, val; |
1268 | int channels = params_channels(params); | ||
1188 | int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1]; | 1269 | int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1]; |
1270 | int tdm_width = arizona->tdm_width[dai->id - 1]; | ||
1271 | int tdm_slots = arizona->tdm_slots[dai->id - 1]; | ||
1189 | int bclk, lrclk, wl, frame, bclk_target; | 1272 | int bclk, lrclk, wl, frame, bclk_target; |
1273 | bool reconfig; | ||
1274 | unsigned int aif_tx_state, aif_rx_state; | ||
1190 | 1275 | ||
1191 | if (params_rate(params) % 8000) | 1276 | if (params_rate(params) % 8000) |
1192 | rates = &arizona_44k1_bclk_rates[0]; | 1277 | rates = &arizona_44k1_bclk_rates[0]; |
1193 | else | 1278 | else |
1194 | rates = &arizona_48k_bclk_rates[0]; | 1279 | rates = &arizona_48k_bclk_rates[0]; |
1195 | 1280 | ||
1196 | bclk_target = snd_soc_params_to_bclk(params); | 1281 | if (tdm_slots) { |
1197 | if (chan_limit && chan_limit < params_channels(params)) { | 1282 | arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n", |
1283 | tdm_slots, tdm_width); | ||
1284 | bclk_target = tdm_slots * tdm_width * params_rate(params); | ||
1285 | channels = tdm_slots; | ||
1286 | } else { | ||
1287 | bclk_target = snd_soc_params_to_bclk(params); | ||
1288 | } | ||
1289 | |||
1290 | if (chan_limit && chan_limit < channels) { | ||
1198 | arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit); | 1291 | arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit); |
1199 | bclk_target /= params_channels(params); | 1292 | bclk_target /= channels; |
1200 | bclk_target *= chan_limit; | 1293 | bclk_target *= chan_limit; |
1201 | } | 1294 | } |
1202 | 1295 | ||
1203 | /* Force stereo for I2S mode */ | 1296 | /* Force multiple of 2 channels for I2S mode */ |
1204 | val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); | 1297 | val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); |
1205 | if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) { | 1298 | if ((channels & 1) && (val & ARIZONA_AIF1_FMT_MASK)) { |
1206 | arizona_aif_dbg(dai, "Forcing stereo mode\n"); | 1299 | arizona_aif_dbg(dai, "Forcing stereo mode\n"); |
1207 | bclk_target *= 2; | 1300 | bclk_target /= channels; |
1301 | bclk_target *= channels + 1; | ||
1208 | } | 1302 | } |
1209 | 1303 | ||
1210 | for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { | 1304 | for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { |
@@ -1228,28 +1322,56 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
1228 | wl = snd_pcm_format_width(params_format(params)); | 1322 | wl = snd_pcm_format_width(params_format(params)); |
1229 | frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; | 1323 | frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; |
1230 | 1324 | ||
1325 | reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame); | ||
1326 | |||
1327 | if (reconfig) { | ||
1328 | /* Save AIF TX/RX state */ | ||
1329 | aif_tx_state = snd_soc_read(codec, | ||
1330 | base + ARIZONA_AIF_TX_ENABLES); | ||
1331 | aif_rx_state = snd_soc_read(codec, | ||
1332 | base + ARIZONA_AIF_RX_ENABLES); | ||
1333 | /* Disable AIF TX/RX before reconfiguring it */ | ||
1334 | regmap_update_bits_async(arizona->regmap, | ||
1335 | base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0); | ||
1336 | regmap_update_bits(arizona->regmap, | ||
1337 | base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0); | ||
1338 | } | ||
1339 | |||
1231 | ret = arizona_hw_params_rate(substream, params, dai); | 1340 | ret = arizona_hw_params_rate(substream, params, dai); |
1232 | if (ret != 0) | 1341 | if (ret != 0) |
1233 | return ret; | 1342 | goto restore_aif; |
1234 | 1343 | ||
1235 | regmap_update_bits_async(arizona->regmap, | 1344 | if (reconfig) { |
1236 | base + ARIZONA_AIF_BCLK_CTRL, | 1345 | regmap_update_bits_async(arizona->regmap, |
1237 | ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); | 1346 | base + ARIZONA_AIF_BCLK_CTRL, |
1238 | regmap_update_bits_async(arizona->regmap, | 1347 | ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); |
1239 | base + ARIZONA_AIF_TX_BCLK_RATE, | 1348 | regmap_update_bits_async(arizona->regmap, |
1240 | ARIZONA_AIF1TX_BCPF_MASK, lrclk); | 1349 | base + ARIZONA_AIF_TX_BCLK_RATE, |
1241 | regmap_update_bits_async(arizona->regmap, | 1350 | ARIZONA_AIF1TX_BCPF_MASK, lrclk); |
1242 | base + ARIZONA_AIF_RX_BCLK_RATE, | 1351 | regmap_update_bits_async(arizona->regmap, |
1243 | ARIZONA_AIF1RX_BCPF_MASK, lrclk); | 1352 | base + ARIZONA_AIF_RX_BCLK_RATE, |
1244 | regmap_update_bits_async(arizona->regmap, | 1353 | ARIZONA_AIF1RX_BCPF_MASK, lrclk); |
1245 | base + ARIZONA_AIF_FRAME_CTRL_1, | 1354 | regmap_update_bits_async(arizona->regmap, |
1246 | ARIZONA_AIF1TX_WL_MASK | | 1355 | base + ARIZONA_AIF_FRAME_CTRL_1, |
1247 | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); | 1356 | ARIZONA_AIF1TX_WL_MASK | |
1248 | regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2, | 1357 | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); |
1249 | ARIZONA_AIF1RX_WL_MASK | | 1358 | regmap_update_bits(arizona->regmap, |
1250 | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); | 1359 | base + ARIZONA_AIF_FRAME_CTRL_2, |
1360 | ARIZONA_AIF1RX_WL_MASK | | ||
1361 | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); | ||
1362 | } | ||
1251 | 1363 | ||
1252 | return 0; | 1364 | restore_aif: |
1365 | if (reconfig) { | ||
1366 | /* Restore AIF TX/RX state */ | ||
1367 | regmap_update_bits_async(arizona->regmap, | ||
1368 | base + ARIZONA_AIF_TX_ENABLES, | ||
1369 | 0xff, aif_tx_state); | ||
1370 | regmap_update_bits(arizona->regmap, | ||
1371 | base + ARIZONA_AIF_RX_ENABLES, | ||
1372 | 0xff, aif_rx_state); | ||
1373 | } | ||
1374 | return ret; | ||
1253 | } | 1375 | } |
1254 | 1376 | ||
1255 | static const char *arizona_dai_clk_str(int clk_id) | 1377 | static const char *arizona_dai_clk_str(int clk_id) |
@@ -1324,9 +1446,63 @@ static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate) | |||
1324 | ARIZONA_AIF1_TRI, reg); | 1446 | ARIZONA_AIF1_TRI, reg); |
1325 | } | 1447 | } |
1326 | 1448 | ||
1449 | static void arizona_set_channels_to_mask(struct snd_soc_dai *dai, | ||
1450 | unsigned int base, | ||
1451 | int channels, unsigned int mask) | ||
1452 | { | ||
1453 | struct snd_soc_codec *codec = dai->codec; | ||
1454 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
1455 | struct arizona *arizona = priv->arizona; | ||
1456 | int slot, i; | ||
1457 | |||
1458 | for (i = 0; i < channels; ++i) { | ||
1459 | slot = ffs(mask) - 1; | ||
1460 | if (slot < 0) | ||
1461 | return; | ||
1462 | |||
1463 | regmap_write(arizona->regmap, base + i, slot); | ||
1464 | |||
1465 | mask &= ~(1 << slot); | ||
1466 | } | ||
1467 | |||
1468 | if (mask) | ||
1469 | arizona_aif_warn(dai, "Too many channels in TDM mask\n"); | ||
1470 | } | ||
1471 | |||
1472 | static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
1473 | unsigned int rx_mask, int slots, int slot_width) | ||
1474 | { | ||
1475 | struct snd_soc_codec *codec = dai->codec; | ||
1476 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
1477 | struct arizona *arizona = priv->arizona; | ||
1478 | int base = dai->driver->base; | ||
1479 | int rx_max_chan = dai->driver->playback.channels_max; | ||
1480 | int tx_max_chan = dai->driver->capture.channels_max; | ||
1481 | |||
1482 | /* Only support TDM for the physical AIFs */ | ||
1483 | if (dai->id > ARIZONA_MAX_AIF) | ||
1484 | return -ENOTSUPP; | ||
1485 | |||
1486 | if (slots == 0) { | ||
1487 | tx_mask = (1 << tx_max_chan) - 1; | ||
1488 | rx_mask = (1 << rx_max_chan) - 1; | ||
1489 | } | ||
1490 | |||
1491 | arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3, | ||
1492 | tx_max_chan, tx_mask); | ||
1493 | arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11, | ||
1494 | rx_max_chan, rx_mask); | ||
1495 | |||
1496 | arizona->tdm_width[dai->id - 1] = slot_width; | ||
1497 | arizona->tdm_slots[dai->id - 1] = slots; | ||
1498 | |||
1499 | return 0; | ||
1500 | } | ||
1501 | |||
1327 | const struct snd_soc_dai_ops arizona_dai_ops = { | 1502 | const struct snd_soc_dai_ops arizona_dai_ops = { |
1328 | .startup = arizona_startup, | 1503 | .startup = arizona_startup, |
1329 | .set_fmt = arizona_set_fmt, | 1504 | .set_fmt = arizona_set_fmt, |
1505 | .set_tdm_slot = arizona_set_tdm_slot, | ||
1330 | .hw_params = arizona_hw_params, | 1506 | .hw_params = arizona_hw_params, |
1331 | .set_sysclk = arizona_dai_set_sysclk, | 1507 | .set_sysclk = arizona_dai_set_sysclk, |
1332 | .set_tristate = arizona_set_tristate, | 1508 | .set_tristate = arizona_set_tristate, |
@@ -1400,6 +1576,12 @@ static int arizona_validate_fll(struct arizona_fll *fll, | |||
1400 | { | 1576 | { |
1401 | unsigned int Fvco_min; | 1577 | unsigned int Fvco_min; |
1402 | 1578 | ||
1579 | if (fll->fout && Fout != fll->fout) { | ||
1580 | arizona_fll_err(fll, | ||
1581 | "Can't change output on active FLL\n"); | ||
1582 | return -EINVAL; | ||
1583 | } | ||
1584 | |||
1403 | if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) { | 1585 | if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) { |
1404 | arizona_fll_err(fll, | 1586 | arizona_fll_err(fll, |
1405 | "Can't scale %dMHz in to <=13.5MHz\n", | 1587 | "Can't scale %dMHz in to <=13.5MHz\n", |
@@ -1478,6 +1660,10 @@ static int arizona_calc_fratio(struct arizona_fll *fll, | |||
1478 | while (div <= ARIZONA_FLL_MAX_REFDIV) { | 1660 | while (div <= ARIZONA_FLL_MAX_REFDIV) { |
1479 | for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO; | 1661 | for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO; |
1480 | ratio++) { | 1662 | ratio++) { |
1663 | if ((ARIZONA_FLL_VCO_CORNER / 2) / | ||
1664 | (fll->vco_mult * ratio) < Fref) | ||
1665 | break; | ||
1666 | |||
1481 | if (target % (ratio * Fref)) { | 1667 | if (target % (ratio * Fref)) { |
1482 | cfg->refdiv = refdiv; | 1668 | cfg->refdiv = refdiv; |
1483 | cfg->fratio = ratio - 1; | 1669 | cfg->fratio = ratio - 1; |
@@ -1485,11 +1671,7 @@ static int arizona_calc_fratio(struct arizona_fll *fll, | |||
1485 | } | 1671 | } |
1486 | } | 1672 | } |
1487 | 1673 | ||
1488 | for (ratio = init_ratio - 1; ratio >= 0; ratio--) { | 1674 | for (ratio = init_ratio - 1; ratio > 0; ratio--) { |
1489 | if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) < | ||
1490 | Fref) | ||
1491 | break; | ||
1492 | |||
1493 | if (target % (ratio * Fref)) { | 1675 | if (target % (ratio * Fref)) { |
1494 | cfg->refdiv = refdiv; | 1676 | cfg->refdiv = refdiv; |
1495 | cfg->fratio = ratio - 1; | 1677 | cfg->fratio = ratio - 1; |
@@ -1616,7 +1798,7 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, | |||
1616 | ARIZONA_FLL1_CTRL_UPD | cfg->n); | 1798 | ARIZONA_FLL1_CTRL_UPD | cfg->n); |
1617 | } | 1799 | } |
1618 | 1800 | ||
1619 | static bool arizona_is_enabled_fll(struct arizona_fll *fll) | 1801 | static int arizona_is_enabled_fll(struct arizona_fll *fll) |
1620 | { | 1802 | { |
1621 | struct arizona *arizona = fll->arizona; | 1803 | struct arizona *arizona = fll->arizona; |
1622 | unsigned int reg; | 1804 | unsigned int reg; |
@@ -1632,13 +1814,26 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll) | |||
1632 | return reg & ARIZONA_FLL1_ENA; | 1814 | return reg & ARIZONA_FLL1_ENA; |
1633 | } | 1815 | } |
1634 | 1816 | ||
1635 | static void arizona_enable_fll(struct arizona_fll *fll) | 1817 | static int arizona_enable_fll(struct arizona_fll *fll) |
1636 | { | 1818 | { |
1637 | struct arizona *arizona = fll->arizona; | 1819 | struct arizona *arizona = fll->arizona; |
1638 | int ret; | 1820 | int ret; |
1639 | bool use_sync = false; | 1821 | bool use_sync = false; |
1822 | int already_enabled = arizona_is_enabled_fll(fll); | ||
1640 | struct arizona_fll_cfg cfg; | 1823 | struct arizona_fll_cfg cfg; |
1641 | 1824 | ||
1825 | if (already_enabled < 0) | ||
1826 | return already_enabled; | ||
1827 | |||
1828 | if (already_enabled) { | ||
1829 | /* Facilitate smooth refclk across the transition */ | ||
1830 | regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x7, | ||
1831 | ARIZONA_FLL1_GAIN_MASK, 0); | ||
1832 | regmap_update_bits_async(fll->arizona->regmap, fll->base + 1, | ||
1833 | ARIZONA_FLL1_FREERUN, | ||
1834 | ARIZONA_FLL1_FREERUN); | ||
1835 | } | ||
1836 | |||
1642 | /* | 1837 | /* |
1643 | * If we have both REFCLK and SYNCCLK then enable both, | 1838 | * If we have both REFCLK and SYNCCLK then enable both, |
1644 | * otherwise apply the SYNCCLK settings to REFCLK. | 1839 | * otherwise apply the SYNCCLK settings to REFCLK. |
@@ -1666,7 +1861,7 @@ static void arizona_enable_fll(struct arizona_fll *fll) | |||
1666 | ARIZONA_FLL1_SYNC_ENA, 0); | 1861 | ARIZONA_FLL1_SYNC_ENA, 0); |
1667 | } else { | 1862 | } else { |
1668 | arizona_fll_err(fll, "No clocks provided\n"); | 1863 | arizona_fll_err(fll, "No clocks provided\n"); |
1669 | return; | 1864 | return -EINVAL; |
1670 | } | 1865 | } |
1671 | 1866 | ||
1672 | /* | 1867 | /* |
@@ -1681,25 +1876,29 @@ static void arizona_enable_fll(struct arizona_fll *fll) | |||
1681 | ARIZONA_FLL1_SYNC_BW, | 1876 | ARIZONA_FLL1_SYNC_BW, |
1682 | ARIZONA_FLL1_SYNC_BW); | 1877 | ARIZONA_FLL1_SYNC_BW); |
1683 | 1878 | ||
1684 | if (!arizona_is_enabled_fll(fll)) | 1879 | if (!already_enabled) |
1685 | pm_runtime_get(arizona->dev); | 1880 | pm_runtime_get(arizona->dev); |
1686 | 1881 | ||
1687 | /* Clear any pending completions */ | 1882 | /* Clear any pending completions */ |
1688 | try_wait_for_completion(&fll->ok); | 1883 | try_wait_for_completion(&fll->ok); |
1689 | 1884 | ||
1690 | regmap_update_bits_async(arizona->regmap, fll->base + 1, | 1885 | regmap_update_bits_async(arizona->regmap, fll->base + 1, |
1691 | ARIZONA_FLL1_FREERUN, 0); | ||
1692 | regmap_update_bits_async(arizona->regmap, fll->base + 1, | ||
1693 | ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); | 1886 | ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); |
1694 | if (use_sync) | 1887 | if (use_sync) |
1695 | regmap_update_bits_async(arizona->regmap, fll->base + 0x11, | 1888 | regmap_update_bits_async(arizona->regmap, fll->base + 0x11, |
1696 | ARIZONA_FLL1_SYNC_ENA, | 1889 | ARIZONA_FLL1_SYNC_ENA, |
1697 | ARIZONA_FLL1_SYNC_ENA); | 1890 | ARIZONA_FLL1_SYNC_ENA); |
1698 | 1891 | ||
1892 | if (already_enabled) | ||
1893 | regmap_update_bits_async(arizona->regmap, fll->base + 1, | ||
1894 | ARIZONA_FLL1_FREERUN, 0); | ||
1895 | |||
1699 | ret = wait_for_completion_timeout(&fll->ok, | 1896 | ret = wait_for_completion_timeout(&fll->ok, |
1700 | msecs_to_jiffies(250)); | 1897 | msecs_to_jiffies(250)); |
1701 | if (ret == 0) | 1898 | if (ret == 0) |
1702 | arizona_fll_warn(fll, "Timed out waiting for lock\n"); | 1899 | arizona_fll_warn(fll, "Timed out waiting for lock\n"); |
1900 | |||
1901 | return 0; | ||
1703 | } | 1902 | } |
1704 | 1903 | ||
1705 | static void arizona_disable_fll(struct arizona_fll *fll) | 1904 | static void arizona_disable_fll(struct arizona_fll *fll) |
@@ -1713,6 +1912,8 @@ static void arizona_disable_fll(struct arizona_fll *fll) | |||
1713 | ARIZONA_FLL1_ENA, 0, &change); | 1912 | ARIZONA_FLL1_ENA, 0, &change); |
1714 | regmap_update_bits(arizona->regmap, fll->base + 0x11, | 1913 | regmap_update_bits(arizona->regmap, fll->base + 0x11, |
1715 | ARIZONA_FLL1_SYNC_ENA, 0); | 1914 | ARIZONA_FLL1_SYNC_ENA, 0); |
1915 | regmap_update_bits_async(arizona->regmap, fll->base + 1, | ||
1916 | ARIZONA_FLL1_FREERUN, 0); | ||
1716 | 1917 | ||
1717 | if (change) | 1918 | if (change) |
1718 | pm_runtime_put_autosuspend(arizona->dev); | 1919 | pm_runtime_put_autosuspend(arizona->dev); |
@@ -1721,7 +1922,7 @@ static void arizona_disable_fll(struct arizona_fll *fll) | |||
1721 | int arizona_set_fll_refclk(struct arizona_fll *fll, int source, | 1922 | int arizona_set_fll_refclk(struct arizona_fll *fll, int source, |
1722 | unsigned int Fref, unsigned int Fout) | 1923 | unsigned int Fref, unsigned int Fout) |
1723 | { | 1924 | { |
1724 | int ret; | 1925 | int ret = 0; |
1725 | 1926 | ||
1726 | if (fll->ref_src == source && fll->ref_freq == Fref) | 1927 | if (fll->ref_src == source && fll->ref_freq == Fref) |
1727 | return 0; | 1928 | return 0; |
@@ -1736,17 +1937,17 @@ int arizona_set_fll_refclk(struct arizona_fll *fll, int source, | |||
1736 | fll->ref_freq = Fref; | 1937 | fll->ref_freq = Fref; |
1737 | 1938 | ||
1738 | if (fll->fout && Fref > 0) { | 1939 | if (fll->fout && Fref > 0) { |
1739 | arizona_enable_fll(fll); | 1940 | ret = arizona_enable_fll(fll); |
1740 | } | 1941 | } |
1741 | 1942 | ||
1742 | return 0; | 1943 | return ret; |
1743 | } | 1944 | } |
1744 | EXPORT_SYMBOL_GPL(arizona_set_fll_refclk); | 1945 | EXPORT_SYMBOL_GPL(arizona_set_fll_refclk); |
1745 | 1946 | ||
1746 | int arizona_set_fll(struct arizona_fll *fll, int source, | 1947 | int arizona_set_fll(struct arizona_fll *fll, int source, |
1747 | unsigned int Fref, unsigned int Fout) | 1948 | unsigned int Fref, unsigned int Fout) |
1748 | { | 1949 | { |
1749 | int ret; | 1950 | int ret = 0; |
1750 | 1951 | ||
1751 | if (fll->sync_src == source && | 1952 | if (fll->sync_src == source && |
1752 | fll->sync_freq == Fref && fll->fout == Fout) | 1953 | fll->sync_freq == Fref && fll->fout == Fout) |
@@ -1768,13 +1969,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source, | |||
1768 | fll->sync_freq = Fref; | 1969 | fll->sync_freq = Fref; |
1769 | fll->fout = Fout; | 1970 | fll->fout = Fout; |
1770 | 1971 | ||
1771 | if (Fout) { | 1972 | if (Fout) |
1772 | arizona_enable_fll(fll); | 1973 | ret = arizona_enable_fll(fll); |
1773 | } else { | 1974 | else |
1774 | arizona_disable_fll(fll); | 1975 | arizona_disable_fll(fll); |
1775 | } | ||
1776 | 1976 | ||
1777 | return 0; | 1977 | return ret; |
1778 | } | 1978 | } |
1779 | EXPORT_SYMBOL_GPL(arizona_set_fll); | 1979 | EXPORT_SYMBOL_GPL(arizona_set_fll); |
1780 | 1980 | ||
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 05ae17f5bca3..942cfb197b6d 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -249,6 +249,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source, | |||
249 | 249 | ||
250 | extern int arizona_init_spk(struct snd_soc_codec *codec); | 250 | extern int arizona_init_spk(struct snd_soc_codec *codec); |
251 | extern int arizona_init_gpio(struct snd_soc_codec *codec); | 251 | extern int arizona_init_gpio(struct snd_soc_codec *codec); |
252 | extern int arizona_init_mono(struct snd_soc_codec *codec); | ||
252 | 253 | ||
253 | extern int arizona_init_dai(struct arizona_priv *priv, int dai); | 254 | extern int arizona_init_dai(struct arizona_priv *priv, int dai); |
254 | 255 | ||
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c new file mode 100644 index 000000000000..a20b30ca52c0 --- /dev/null +++ b/sound/soc/codecs/cs4265.c | |||
@@ -0,0 +1,682 @@ | |||
1 | /* | ||
2 | * cs4265.c -- CS4265 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2014 Cirrus Logic, Inc. | ||
5 | * | ||
6 | * Author: Paul Handrigan <paul.handrigan@cirrus.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/gpio/consumer.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <sound/core.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/pcm_params.h> | ||
28 | #include <sound/soc.h> | ||
29 | #include <sound/soc-dapm.h> | ||
30 | #include <sound/initval.h> | ||
31 | #include <sound/tlv.h> | ||
32 | #include "cs4265.h" | ||
33 | |||
34 | struct cs4265_private { | ||
35 | struct device *dev; | ||
36 | struct regmap *regmap; | ||
37 | struct gpio_desc *reset_gpio; | ||
38 | u8 format; | ||
39 | u32 sysclk; | ||
40 | }; | ||
41 | |||
42 | static const struct reg_default cs4265_reg_defaults[] = { | ||
43 | { CS4265_PWRCTL, 0x0F }, | ||
44 | { CS4265_DAC_CTL, 0x08 }, | ||
45 | { CS4265_ADC_CTL, 0x00 }, | ||
46 | { CS4265_MCLK_FREQ, 0x00 }, | ||
47 | { CS4265_SIG_SEL, 0x40 }, | ||
48 | { CS4265_CHB_PGA_CTL, 0x00 }, | ||
49 | { CS4265_CHA_PGA_CTL, 0x00 }, | ||
50 | { CS4265_ADC_CTL2, 0x19 }, | ||
51 | { CS4265_DAC_CHA_VOL, 0x00 }, | ||
52 | { CS4265_DAC_CHB_VOL, 0x00 }, | ||
53 | { CS4265_DAC_CTL2, 0xC0 }, | ||
54 | { CS4265_SPDIF_CTL1, 0x00 }, | ||
55 | { CS4265_SPDIF_CTL2, 0x00 }, | ||
56 | { CS4265_INT_MASK, 0x00 }, | ||
57 | { CS4265_STATUS_MODE_MSB, 0x00 }, | ||
58 | { CS4265_STATUS_MODE_LSB, 0x00 }, | ||
59 | }; | ||
60 | |||
61 | static bool cs4265_readable_register(struct device *dev, unsigned int reg) | ||
62 | { | ||
63 | switch (reg) { | ||
64 | case CS4265_PWRCTL: | ||
65 | case CS4265_DAC_CTL: | ||
66 | case CS4265_ADC_CTL: | ||
67 | case CS4265_MCLK_FREQ: | ||
68 | case CS4265_SIG_SEL: | ||
69 | case CS4265_CHB_PGA_CTL: | ||
70 | case CS4265_CHA_PGA_CTL: | ||
71 | case CS4265_ADC_CTL2: | ||
72 | case CS4265_DAC_CHA_VOL: | ||
73 | case CS4265_DAC_CHB_VOL: | ||
74 | case CS4265_DAC_CTL2: | ||
75 | case CS4265_SPDIF_CTL1: | ||
76 | case CS4265_SPDIF_CTL2: | ||
77 | case CS4265_INT_MASK: | ||
78 | case CS4265_STATUS_MODE_MSB: | ||
79 | case CS4265_STATUS_MODE_LSB: | ||
80 | return true; | ||
81 | default: | ||
82 | return false; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | static bool cs4265_volatile_register(struct device *dev, unsigned int reg) | ||
87 | { | ||
88 | switch (reg) { | ||
89 | case CS4265_INT_STATUS: | ||
90 | return true; | ||
91 | default: | ||
92 | return false; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | static DECLARE_TLV_DB_SCALE(pga_tlv, -1200, 50, 0); | ||
97 | |||
98 | static DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 0); | ||
99 | |||
100 | static const char * const digital_input_mux_text[] = { | ||
101 | "SDIN1", "SDIN2" | ||
102 | }; | ||
103 | |||
104 | static SOC_ENUM_SINGLE_DECL(digital_input_mux_enum, CS4265_SIG_SEL, 7, | ||
105 | digital_input_mux_text); | ||
106 | |||
107 | static const struct snd_kcontrol_new digital_input_mux = | ||
108 | SOC_DAPM_ENUM("Digital Input Mux", digital_input_mux_enum); | ||
109 | |||
110 | static const char * const mic_linein_text[] = { | ||
111 | "MIC", "LINEIN" | ||
112 | }; | ||
113 | |||
114 | static SOC_ENUM_SINGLE_DECL(mic_linein_enum, CS4265_ADC_CTL2, 0, | ||
115 | mic_linein_text); | ||
116 | |||
117 | static const char * const cam_mode_text[] = { | ||
118 | "One Byte", "Two Byte" | ||
119 | }; | ||
120 | |||
121 | static SOC_ENUM_SINGLE_DECL(cam_mode_enum, CS4265_SPDIF_CTL1, 5, | ||
122 | cam_mode_text); | ||
123 | |||
124 | static const char * const cam_mono_stereo_text[] = { | ||
125 | "Stereo", "Mono" | ||
126 | }; | ||
127 | |||
128 | static SOC_ENUM_SINGLE_DECL(spdif_mono_stereo_enum, CS4265_SPDIF_CTL2, 2, | ||
129 | cam_mono_stereo_text); | ||
130 | |||
131 | static const char * const mono_select_text[] = { | ||
132 | "Channel A", "Channel B" | ||
133 | }; | ||
134 | |||
135 | static SOC_ENUM_SINGLE_DECL(spdif_mono_select_enum, CS4265_SPDIF_CTL2, 0, | ||
136 | mono_select_text); | ||
137 | |||
138 | static const struct snd_kcontrol_new mic_linein_mux = | ||
139 | SOC_DAPM_ENUM("ADC Input Capture Mux", mic_linein_enum); | ||
140 | |||
141 | static const struct snd_kcontrol_new loopback_ctl = | ||
142 | SOC_DAPM_SINGLE("Switch", CS4265_SIG_SEL, 1, 1, 0); | ||
143 | |||
144 | static const struct snd_kcontrol_new spdif_switch = | ||
145 | SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 0, 0); | ||
146 | |||
147 | static const struct snd_kcontrol_new dac_switch = | ||
148 | SOC_DAPM_SINGLE("Switch", CS4265_PWRCTL, 1, 1, 0); | ||
149 | |||
150 | static const struct snd_kcontrol_new cs4265_snd_controls[] = { | ||
151 | |||
152 | SOC_DOUBLE_R_SX_TLV("PGA Volume", CS4265_CHA_PGA_CTL, | ||
153 | CS4265_CHB_PGA_CTL, 0, 0x28, 0x30, pga_tlv), | ||
154 | SOC_DOUBLE_R_TLV("DAC Volume", CS4265_DAC_CHA_VOL, | ||
155 | CS4265_DAC_CHB_VOL, 0, 0xFF, 1, dac_tlv), | ||
156 | SOC_SINGLE("De-emp 44.1kHz Switch", CS4265_DAC_CTL, 1, | ||
157 | 1, 0), | ||
158 | SOC_SINGLE("DAC INV Switch", CS4265_DAC_CTL2, 5, | ||
159 | 1, 0), | ||
160 | SOC_SINGLE("DAC Zero Cross Switch", CS4265_DAC_CTL2, 6, | ||
161 | 1, 0), | ||
162 | SOC_SINGLE("DAC Soft Ramp Switch", CS4265_DAC_CTL2, 7, | ||
163 | 1, 0), | ||
164 | SOC_SINGLE("ADC HPF Switch", CS4265_ADC_CTL, 1, | ||
165 | 1, 0), | ||
166 | SOC_SINGLE("ADC Zero Cross Switch", CS4265_ADC_CTL2, 3, | ||
167 | 1, 1), | ||
168 | SOC_SINGLE("ADC Soft Ramp Switch", CS4265_ADC_CTL2, 7, | ||
169 | 1, 0), | ||
170 | SOC_SINGLE("E to F Buffer Disable Switch", CS4265_SPDIF_CTL1, | ||
171 | 6, 1, 0), | ||
172 | SOC_ENUM("C Data Access", cam_mode_enum), | ||
173 | SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2, | ||
174 | 3, 1, 0), | ||
175 | SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum), | ||
176 | SOC_SINGLE("MMTLR Data Switch", 0, | ||
177 | 1, 1, 0), | ||
178 | SOC_ENUM("Mono Channel Select", spdif_mono_select_enum), | ||
179 | SND_SOC_BYTES("C Data Buffer", CS4265_C_DATA_BUFF, 24), | ||
180 | }; | ||
181 | |||
182 | static const struct snd_soc_dapm_widget cs4265_dapm_widgets[] = { | ||
183 | |||
184 | SND_SOC_DAPM_INPUT("LINEINL"), | ||
185 | SND_SOC_DAPM_INPUT("LINEINR"), | ||
186 | SND_SOC_DAPM_INPUT("MICL"), | ||
187 | SND_SOC_DAPM_INPUT("MICR"), | ||
188 | |||
189 | SND_SOC_DAPM_AIF_OUT("DOUT", NULL, 0, | ||
190 | SND_SOC_NOPM, 0, 0), | ||
191 | SND_SOC_DAPM_AIF_OUT("SPDIFOUT", NULL, 0, | ||
192 | SND_SOC_NOPM, 0, 0), | ||
193 | |||
194 | SND_SOC_DAPM_MUX("ADC Mux", SND_SOC_NOPM, 0, 0, &mic_linein_mux), | ||
195 | |||
196 | SND_SOC_DAPM_ADC("ADC", NULL, CS4265_PWRCTL, 2, 1), | ||
197 | SND_SOC_DAPM_PGA("Pre-amp MIC", CS4265_PWRCTL, 3, | ||
198 | 1, NULL, 0), | ||
199 | |||
200 | SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, | ||
201 | 0, 0, &digital_input_mux), | ||
202 | |||
203 | SND_SOC_DAPM_MIXER("SDIN1 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
204 | SND_SOC_DAPM_MIXER("SDIN2 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
205 | SND_SOC_DAPM_MIXER("SPDIF Transmitter", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
206 | |||
207 | SND_SOC_DAPM_SWITCH("Loopback", SND_SOC_NOPM, 0, 0, | ||
208 | &loopback_ctl), | ||
209 | SND_SOC_DAPM_SWITCH("SPDIF", SND_SOC_NOPM, 0, 0, | ||
210 | &spdif_switch), | ||
211 | SND_SOC_DAPM_SWITCH("DAC", CS4265_PWRCTL, 1, 1, | ||
212 | &dac_switch), | ||
213 | |||
214 | SND_SOC_DAPM_AIF_IN("DIN1", NULL, 0, | ||
215 | SND_SOC_NOPM, 0, 0), | ||
216 | SND_SOC_DAPM_AIF_IN("DIN2", NULL, 0, | ||
217 | SND_SOC_NOPM, 0, 0), | ||
218 | SND_SOC_DAPM_AIF_IN("TXIN", NULL, 0, | ||
219 | CS4265_SPDIF_CTL2, 5, 1), | ||
220 | |||
221 | SND_SOC_DAPM_OUTPUT("LINEOUTL"), | ||
222 | SND_SOC_DAPM_OUTPUT("LINEOUTR"), | ||
223 | |||
224 | }; | ||
225 | |||
226 | static const struct snd_soc_dapm_route cs4265_audio_map[] = { | ||
227 | |||
228 | {"DIN1", NULL, "DAI1 Playback"}, | ||
229 | {"DIN2", NULL, "DAI2 Playback"}, | ||
230 | {"SDIN1 Input Mixer", NULL, "DIN1"}, | ||
231 | {"SDIN2 Input Mixer", NULL, "DIN2"}, | ||
232 | {"Input Mux", "SDIN1", "SDIN1 Input Mixer"}, | ||
233 | {"Input Mux", "SDIN2", "SDIN2 Input Mixer"}, | ||
234 | {"DAC", "Switch", "Input Mux"}, | ||
235 | {"SPDIF", "Switch", "Input Mux"}, | ||
236 | {"LINEOUTL", NULL, "DAC"}, | ||
237 | {"LINEOUTR", NULL, "DAC"}, | ||
238 | {"SPDIFOUT", NULL, "SPDIF"}, | ||
239 | |||
240 | {"ADC Mux", "LINEIN", "LINEINL"}, | ||
241 | {"ADC Mux", "LINEIN", "LINEINR"}, | ||
242 | {"ADC Mux", "MIC", "MICL"}, | ||
243 | {"ADC Mux", "MIC", "MICR"}, | ||
244 | {"ADC", NULL, "ADC Mux"}, | ||
245 | {"DOUT", NULL, "ADC"}, | ||
246 | {"DAI1 Capture", NULL, "DOUT"}, | ||
247 | {"DAI2 Capture", NULL, "DOUT"}, | ||
248 | |||
249 | /* Loopback */ | ||
250 | {"Loopback", "Switch", "ADC"}, | ||
251 | {"DAC", NULL, "Loopback"}, | ||
252 | }; | ||
253 | |||
254 | struct cs4265_clk_para { | ||
255 | u32 mclk; | ||
256 | u32 rate; | ||
257 | u8 fm_mode; /* values 1, 2, or 4 */ | ||
258 | u8 mclkdiv; | ||
259 | }; | ||
260 | |||
261 | static const struct cs4265_clk_para clk_map_table[] = { | ||
262 | /*32k*/ | ||
263 | {8192000, 32000, 0, 0}, | ||
264 | {12288000, 32000, 0, 1}, | ||
265 | {16384000, 32000, 0, 2}, | ||
266 | {24576000, 32000, 0, 3}, | ||
267 | {32768000, 32000, 0, 4}, | ||
268 | |||
269 | /*44.1k*/ | ||
270 | {11289600, 44100, 0, 0}, | ||
271 | {16934400, 44100, 0, 1}, | ||
272 | {22579200, 44100, 0, 2}, | ||
273 | {33868000, 44100, 0, 3}, | ||
274 | {45158400, 44100, 0, 4}, | ||
275 | |||
276 | /*48k*/ | ||
277 | {12288000, 48000, 0, 0}, | ||
278 | {18432000, 48000, 0, 1}, | ||
279 | {24576000, 48000, 0, 2}, | ||
280 | {36864000, 48000, 0, 3}, | ||
281 | {49152000, 48000, 0, 4}, | ||
282 | |||
283 | /*64k*/ | ||
284 | {8192000, 64000, 1, 0}, | ||
285 | {1228800, 64000, 1, 1}, | ||
286 | {1693440, 64000, 1, 2}, | ||
287 | {2457600, 64000, 1, 3}, | ||
288 | {3276800, 64000, 1, 4}, | ||
289 | |||
290 | /* 88.2k */ | ||
291 | {11289600, 88200, 1, 0}, | ||
292 | {16934400, 88200, 1, 1}, | ||
293 | {22579200, 88200, 1, 2}, | ||
294 | {33868000, 88200, 1, 3}, | ||
295 | {45158400, 88200, 1, 4}, | ||
296 | |||
297 | /* 96k */ | ||
298 | {12288000, 96000, 1, 0}, | ||
299 | {18432000, 96000, 1, 1}, | ||
300 | {24576000, 96000, 1, 2}, | ||
301 | {36864000, 96000, 1, 3}, | ||
302 | {49152000, 96000, 1, 4}, | ||
303 | |||
304 | /* 128k */ | ||
305 | {8192000, 128000, 2, 0}, | ||
306 | {12288000, 128000, 2, 1}, | ||
307 | {16934400, 128000, 2, 2}, | ||
308 | {24576000, 128000, 2, 3}, | ||
309 | {32768000, 128000, 2, 4}, | ||
310 | |||
311 | /* 176.4k */ | ||
312 | {11289600, 176400, 2, 0}, | ||
313 | {16934400, 176400, 2, 1}, | ||
314 | {22579200, 176400, 2, 2}, | ||
315 | {33868000, 176400, 2, 3}, | ||
316 | {49152000, 176400, 2, 4}, | ||
317 | |||
318 | /* 192k */ | ||
319 | {12288000, 192000, 2, 0}, | ||
320 | {18432000, 192000, 2, 1}, | ||
321 | {24576000, 192000, 2, 2}, | ||
322 | {36864000, 192000, 2, 3}, | ||
323 | {49152000, 192000, 2, 4}, | ||
324 | }; | ||
325 | |||
326 | static int cs4265_get_clk_index(int mclk, int rate) | ||
327 | { | ||
328 | int i; | ||
329 | |||
330 | for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) { | ||
331 | if (clk_map_table[i].rate == rate && | ||
332 | clk_map_table[i].mclk == mclk) | ||
333 | return i; | ||
334 | } | ||
335 | return -EINVAL; | ||
336 | } | ||
337 | |||
338 | static int cs4265_set_sysclk(struct snd_soc_dai *codec_dai, int clk_id, | ||
339 | unsigned int freq, int dir) | ||
340 | { | ||
341 | struct snd_soc_codec *codec = codec_dai->codec; | ||
342 | struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec); | ||
343 | int i; | ||
344 | |||
345 | if (clk_id != 0) { | ||
346 | dev_err(codec->dev, "Invalid clk_id %d\n", clk_id); | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) { | ||
350 | if (clk_map_table[i].mclk == freq) { | ||
351 | cs4265->sysclk = freq; | ||
352 | return 0; | ||
353 | } | ||
354 | } | ||
355 | cs4265->sysclk = 0; | ||
356 | dev_err(codec->dev, "Invalid freq parameter %d\n", freq); | ||
357 | return -EINVAL; | ||
358 | } | ||
359 | |||
360 | static int cs4265_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
361 | { | ||
362 | struct snd_soc_codec *codec = codec_dai->codec; | ||
363 | struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec); | ||
364 | u8 iface = 0; | ||
365 | |||
366 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
367 | case SND_SOC_DAIFMT_CBM_CFM: | ||
368 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
369 | CS4265_ADC_MASTER, | ||
370 | CS4265_ADC_MASTER); | ||
371 | break; | ||
372 | case SND_SOC_DAIFMT_CBS_CFS: | ||
373 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
374 | CS4265_ADC_MASTER, | ||
375 | 0); | ||
376 | break; | ||
377 | default: | ||
378 | return -EINVAL; | ||
379 | } | ||
380 | |||
381 | /* interface format */ | ||
382 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
383 | case SND_SOC_DAIFMT_I2S: | ||
384 | iface |= SND_SOC_DAIFMT_I2S; | ||
385 | break; | ||
386 | case SND_SOC_DAIFMT_RIGHT_J: | ||
387 | iface |= SND_SOC_DAIFMT_RIGHT_J; | ||
388 | break; | ||
389 | case SND_SOC_DAIFMT_LEFT_J: | ||
390 | iface |= SND_SOC_DAIFMT_LEFT_J; | ||
391 | break; | ||
392 | default: | ||
393 | return -EINVAL; | ||
394 | } | ||
395 | |||
396 | cs4265->format = iface; | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static int cs4265_digital_mute(struct snd_soc_dai *dai, int mute) | ||
401 | { | ||
402 | struct snd_soc_codec *codec = dai->codec; | ||
403 | |||
404 | if (mute) { | ||
405 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
406 | CS4265_DAC_CTL_MUTE, | ||
407 | CS4265_DAC_CTL_MUTE); | ||
408 | snd_soc_update_bits(codec, CS4265_SPDIF_CTL2, | ||
409 | CS4265_SPDIF_CTL2_MUTE, | ||
410 | CS4265_SPDIF_CTL2_MUTE); | ||
411 | } else { | ||
412 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
413 | CS4265_DAC_CTL_MUTE, | ||
414 | 0); | ||
415 | snd_soc_update_bits(codec, CS4265_SPDIF_CTL2, | ||
416 | CS4265_SPDIF_CTL2_MUTE, | ||
417 | 0); | ||
418 | } | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int cs4265_pcm_hw_params(struct snd_pcm_substream *substream, | ||
423 | struct snd_pcm_hw_params *params, | ||
424 | struct snd_soc_dai *dai) | ||
425 | { | ||
426 | struct snd_soc_codec *codec = dai->codec; | ||
427 | struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec); | ||
428 | int index; | ||
429 | |||
430 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && | ||
431 | ((cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK) | ||
432 | == SND_SOC_DAIFMT_RIGHT_J)) | ||
433 | return -EINVAL; | ||
434 | |||
435 | index = cs4265_get_clk_index(cs4265->sysclk, params_rate(params)); | ||
436 | if (index >= 0) { | ||
437 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
438 | CS4265_ADC_FM, clk_map_table[index].fm_mode); | ||
439 | snd_soc_update_bits(codec, CS4265_MCLK_FREQ, | ||
440 | CS4265_MCLK_FREQ_MASK, | ||
441 | clk_map_table[index].mclkdiv); | ||
442 | |||
443 | } else { | ||
444 | dev_err(codec->dev, "can't get correct mclk\n"); | ||
445 | return -EINVAL; | ||
446 | } | ||
447 | |||
448 | switch (cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
449 | case SND_SOC_DAIFMT_I2S: | ||
450 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
451 | CS4265_DAC_CTL_DIF, (1 << 4)); | ||
452 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
453 | CS4265_ADC_DIF, (1 << 4)); | ||
454 | snd_soc_update_bits(codec, CS4265_SPDIF_CTL2, | ||
455 | CS4265_SPDIF_CTL2_DIF, (1 << 6)); | ||
456 | break; | ||
457 | case SND_SOC_DAIFMT_RIGHT_J: | ||
458 | if (params_width(params) == 16) { | ||
459 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
460 | CS4265_DAC_CTL_DIF, (1 << 5)); | ||
461 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
462 | CS4265_SPDIF_CTL2_DIF, (1 << 7)); | ||
463 | } else { | ||
464 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
465 | CS4265_DAC_CTL_DIF, (3 << 5)); | ||
466 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
467 | CS4265_SPDIF_CTL2_DIF, (1 << 7)); | ||
468 | } | ||
469 | break; | ||
470 | case SND_SOC_DAIFMT_LEFT_J: | ||
471 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
472 | CS4265_DAC_CTL_DIF, 0); | ||
473 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
474 | CS4265_ADC_DIF, 0); | ||
475 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
476 | CS4265_SPDIF_CTL2_DIF, (1 << 6)); | ||
477 | |||
478 | break; | ||
479 | default: | ||
480 | return -EINVAL; | ||
481 | } | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static int cs4265_set_bias_level(struct snd_soc_codec *codec, | ||
486 | enum snd_soc_bias_level level) | ||
487 | { | ||
488 | switch (level) { | ||
489 | case SND_SOC_BIAS_ON: | ||
490 | break; | ||
491 | case SND_SOC_BIAS_PREPARE: | ||
492 | snd_soc_update_bits(codec, CS4265_PWRCTL, | ||
493 | CS4265_PWRCTL_PDN, 0); | ||
494 | break; | ||
495 | case SND_SOC_BIAS_STANDBY: | ||
496 | snd_soc_update_bits(codec, CS4265_PWRCTL, | ||
497 | CS4265_PWRCTL_PDN, | ||
498 | CS4265_PWRCTL_PDN); | ||
499 | break; | ||
500 | case SND_SOC_BIAS_OFF: | ||
501 | snd_soc_update_bits(codec, CS4265_PWRCTL, | ||
502 | CS4265_PWRCTL_PDN, | ||
503 | CS4265_PWRCTL_PDN); | ||
504 | break; | ||
505 | } | ||
506 | codec->dapm.bias_level = level; | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | #define CS4265_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
511 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ | ||
512 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ | ||
513 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) | ||
514 | |||
515 | #define CS4265_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \ | ||
516 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE) | ||
517 | |||
518 | static const struct snd_soc_dai_ops cs4265_ops = { | ||
519 | .hw_params = cs4265_pcm_hw_params, | ||
520 | .digital_mute = cs4265_digital_mute, | ||
521 | .set_fmt = cs4265_set_fmt, | ||
522 | .set_sysclk = cs4265_set_sysclk, | ||
523 | }; | ||
524 | |||
525 | static struct snd_soc_dai_driver cs4265_dai[] = { | ||
526 | { | ||
527 | .name = "cs4265-dai1", | ||
528 | .playback = { | ||
529 | .stream_name = "DAI1 Playback", | ||
530 | .channels_min = 1, | ||
531 | .channels_max = 2, | ||
532 | .rates = CS4265_RATES, | ||
533 | .formats = CS4265_FORMATS, | ||
534 | }, | ||
535 | .capture = { | ||
536 | .stream_name = "DAI1 Capture", | ||
537 | .channels_min = 1, | ||
538 | .channels_max = 2, | ||
539 | .rates = CS4265_RATES, | ||
540 | .formats = CS4265_FORMATS, | ||
541 | }, | ||
542 | .ops = &cs4265_ops, | ||
543 | }, | ||
544 | { | ||
545 | .name = "cs4265-dai2", | ||
546 | .playback = { | ||
547 | .stream_name = "DAI2 Playback", | ||
548 | .channels_min = 1, | ||
549 | .channels_max = 2, | ||
550 | .rates = CS4265_RATES, | ||
551 | .formats = CS4265_FORMATS, | ||
552 | }, | ||
553 | .capture = { | ||
554 | .stream_name = "DAI2 Capture", | ||
555 | .channels_min = 1, | ||
556 | .channels_max = 2, | ||
557 | .rates = CS4265_RATES, | ||
558 | .formats = CS4265_FORMATS, | ||
559 | }, | ||
560 | .ops = &cs4265_ops, | ||
561 | }, | ||
562 | }; | ||
563 | |||
564 | static const struct snd_soc_codec_driver soc_codec_cs4265 = { | ||
565 | .set_bias_level = cs4265_set_bias_level, | ||
566 | |||
567 | .dapm_widgets = cs4265_dapm_widgets, | ||
568 | .num_dapm_widgets = ARRAY_SIZE(cs4265_dapm_widgets), | ||
569 | .dapm_routes = cs4265_audio_map, | ||
570 | .num_dapm_routes = ARRAY_SIZE(cs4265_audio_map), | ||
571 | |||
572 | .controls = cs4265_snd_controls, | ||
573 | .num_controls = ARRAY_SIZE(cs4265_snd_controls), | ||
574 | }; | ||
575 | |||
576 | static const struct regmap_config cs4265_regmap = { | ||
577 | .reg_bits = 8, | ||
578 | .val_bits = 8, | ||
579 | |||
580 | .max_register = CS4265_MAX_REGISTER, | ||
581 | .reg_defaults = cs4265_reg_defaults, | ||
582 | .num_reg_defaults = ARRAY_SIZE(cs4265_reg_defaults), | ||
583 | .readable_reg = cs4265_readable_register, | ||
584 | .volatile_reg = cs4265_volatile_register, | ||
585 | .cache_type = REGCACHE_RBTREE, | ||
586 | }; | ||
587 | |||
588 | static int cs4265_i2c_probe(struct i2c_client *i2c_client, | ||
589 | const struct i2c_device_id *id) | ||
590 | { | ||
591 | struct cs4265_private *cs4265; | ||
592 | int ret = 0; | ||
593 | unsigned int devid = 0; | ||
594 | unsigned int reg; | ||
595 | |||
596 | cs4265 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4265_private), | ||
597 | GFP_KERNEL); | ||
598 | if (cs4265 == NULL) | ||
599 | return -ENOMEM; | ||
600 | cs4265->dev = &i2c_client->dev; | ||
601 | |||
602 | cs4265->regmap = devm_regmap_init_i2c(i2c_client, &cs4265_regmap); | ||
603 | if (IS_ERR(cs4265->regmap)) { | ||
604 | ret = PTR_ERR(cs4265->regmap); | ||
605 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); | ||
606 | return ret; | ||
607 | } | ||
608 | |||
609 | cs4265->reset_gpio = devm_gpiod_get(&i2c_client->dev, | ||
610 | "reset-gpios"); | ||
611 | if (IS_ERR(cs4265->reset_gpio)) { | ||
612 | ret = PTR_ERR(cs4265->reset_gpio); | ||
613 | if (ret != -ENOENT && ret != -ENOSYS) | ||
614 | return ret; | ||
615 | |||
616 | cs4265->reset_gpio = NULL; | ||
617 | } else { | ||
618 | ret = gpiod_direction_output(cs4265->reset_gpio, 0); | ||
619 | if (ret) | ||
620 | return ret; | ||
621 | mdelay(1); | ||
622 | gpiod_set_value_cansleep(cs4265->reset_gpio, 1); | ||
623 | |||
624 | } | ||
625 | |||
626 | i2c_set_clientdata(i2c_client, cs4265); | ||
627 | |||
628 | ret = regmap_read(cs4265->regmap, CS4265_CHIP_ID, ®); | ||
629 | devid = reg & CS4265_CHIP_ID_MASK; | ||
630 | if (devid != CS4265_CHIP_ID_VAL) { | ||
631 | ret = -ENODEV; | ||
632 | dev_err(&i2c_client->dev, | ||
633 | "CS4265 Device ID (%X). Expected %X\n", | ||
634 | devid, CS4265_CHIP_ID); | ||
635 | return ret; | ||
636 | } | ||
637 | dev_info(&i2c_client->dev, | ||
638 | "CS4265 Version %x\n", | ||
639 | reg & CS4265_REV_ID_MASK); | ||
640 | |||
641 | regmap_write(cs4265->regmap, CS4265_PWRCTL, 0x0F); | ||
642 | |||
643 | ret = snd_soc_register_codec(&i2c_client->dev, | ||
644 | &soc_codec_cs4265, cs4265_dai, | ||
645 | ARRAY_SIZE(cs4265_dai)); | ||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | static int cs4265_i2c_remove(struct i2c_client *client) | ||
650 | { | ||
651 | snd_soc_unregister_codec(&client->dev); | ||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | static const struct of_device_id cs4265_of_match[] = { | ||
656 | { .compatible = "cirrus,cs4265", }, | ||
657 | { } | ||
658 | }; | ||
659 | MODULE_DEVICE_TABLE(of, cs4265_of_match); | ||
660 | |||
661 | static const struct i2c_device_id cs4265_id[] = { | ||
662 | { "cs4265", 0 }, | ||
663 | { } | ||
664 | }; | ||
665 | MODULE_DEVICE_TABLE(i2c, cs4265_id); | ||
666 | |||
667 | static struct i2c_driver cs4265_i2c_driver = { | ||
668 | .driver = { | ||
669 | .name = "cs4265", | ||
670 | .owner = THIS_MODULE, | ||
671 | .of_match_table = cs4265_of_match, | ||
672 | }, | ||
673 | .id_table = cs4265_id, | ||
674 | .probe = cs4265_i2c_probe, | ||
675 | .remove = cs4265_i2c_remove, | ||
676 | }; | ||
677 | |||
678 | module_i2c_driver(cs4265_i2c_driver); | ||
679 | |||
680 | MODULE_DESCRIPTION("ASoC CS4265 driver"); | ||
681 | MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paul.handrigan@cirrus.com>"); | ||
682 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cs4265.h b/sound/soc/codecs/cs4265.h new file mode 100644 index 000000000000..0a80a8dcec67 --- /dev/null +++ b/sound/soc/codecs/cs4265.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * cs4265.h -- CS4265 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2014 Cirrus Logic, Inc. | ||
5 | * | ||
6 | * Author: Paul Handrigan <paul.handrigan@cirrus.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef __CS4265_H__ | ||
15 | #define __CS4265_H__ | ||
16 | |||
17 | #define CS4265_CHIP_ID 0x1 | ||
18 | #define CS4265_CHIP_ID_VAL 0xD0 | ||
19 | #define CS4265_CHIP_ID_MASK 0xF0 | ||
20 | #define CS4265_REV_ID_MASK 0x0F | ||
21 | |||
22 | #define CS4265_PWRCTL 0x02 | ||
23 | #define CS4265_PWRCTL_PDN 1 | ||
24 | |||
25 | #define CS4265_DAC_CTL 0x3 | ||
26 | #define CS4265_DAC_CTL_MUTE (1 << 2) | ||
27 | #define CS4265_DAC_CTL_DIF (3 << 4) | ||
28 | |||
29 | #define CS4265_ADC_CTL 0x4 | ||
30 | #define CS4265_ADC_MASTER 1 | ||
31 | #define CS4265_ADC_DIF (1 << 4) | ||
32 | #define CS4265_ADC_FM (3 << 6) | ||
33 | |||
34 | #define CS4265_MCLK_FREQ 0x5 | ||
35 | #define CS4265_MCLK_FREQ_MASK (7 << 4) | ||
36 | |||
37 | #define CS4265_SIG_SEL 0x6 | ||
38 | #define CS4265_SIG_SEL_LOOP (1 << 1) | ||
39 | |||
40 | #define CS4265_CHB_PGA_CTL 0x7 | ||
41 | #define CS4265_CHA_PGA_CTL 0x8 | ||
42 | |||
43 | #define CS4265_ADC_CTL2 0x9 | ||
44 | |||
45 | #define CS4265_DAC_CHA_VOL 0xA | ||
46 | #define CS4265_DAC_CHB_VOL 0xB | ||
47 | |||
48 | #define CS4265_DAC_CTL2 0xC | ||
49 | |||
50 | #define CS4265_INT_STATUS 0xD | ||
51 | #define CS4265_INT_MASK 0xE | ||
52 | #define CS4265_STATUS_MODE_MSB 0xF | ||
53 | #define CS4265_STATUS_MODE_LSB 0x10 | ||
54 | |||
55 | #define CS4265_SPDIF_CTL1 0x11 | ||
56 | |||
57 | #define CS4265_SPDIF_CTL2 0x12 | ||
58 | #define CS4265_SPDIF_CTL2_MUTE (1 << 4) | ||
59 | #define CS4265_SPDIF_CTL2_DIF (3 << 6) | ||
60 | |||
61 | #define CS4265_C_DATA_BUFF 0x13 | ||
62 | #define CS4265_MAX_REGISTER 0x2A | ||
63 | |||
64 | #endif | ||
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 9947a9583679..e6d4ff9fd992 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -664,10 +664,8 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
664 | 664 | ||
665 | cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), | 665 | cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), |
666 | GFP_KERNEL); | 666 | GFP_KERNEL); |
667 | if (!cs4270) { | 667 | if (!cs4270) |
668 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
669 | return -ENOMEM; | 668 | return -ENOMEM; |
670 | } | ||
671 | 669 | ||
672 | /* get the power supply regulators */ | 670 | /* get the power supply regulators */ |
673 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | 671 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) |
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 071fc77f2f06..969167d8b71e 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -399,15 +399,15 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = { | |||
399 | CS42L52_MASTERB_VOL, 0, 0x34, 0xE4, hl_tlv), | 399 | CS42L52_MASTERB_VOL, 0, 0x34, 0xE4, hl_tlv), |
400 | 400 | ||
401 | SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L52_HPA_VOL, | 401 | SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L52_HPA_VOL, |
402 | CS42L52_HPB_VOL, 0, 0x34, 0xCC, hpd_tlv), | 402 | CS42L52_HPB_VOL, 0, 0x34, 0xC0, hpd_tlv), |
403 | 403 | ||
404 | SOC_ENUM("Headphone Analog Gain", hp_gain_enum), | 404 | SOC_ENUM("Headphone Analog Gain", hp_gain_enum), |
405 | 405 | ||
406 | SOC_DOUBLE_R_SX_TLV("Speaker Volume", CS42L52_SPKA_VOL, | 406 | SOC_DOUBLE_R_SX_TLV("Speaker Volume", CS42L52_SPKA_VOL, |
407 | CS42L52_SPKB_VOL, 0, 0x1, 0xff, hl_tlv), | 407 | CS42L52_SPKB_VOL, 0, 0x40, 0xC0, hl_tlv), |
408 | 408 | ||
409 | SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL, | 409 | SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL, |
410 | CS42L52_PASSTHRUB_VOL, 6, 0x18, 0x90, pga_tlv), | 410 | CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pga_tlv), |
411 | 411 | ||
412 | SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0), | 412 | SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0), |
413 | 413 | ||
@@ -417,10 +417,10 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = { | |||
417 | SOC_ENUM("MIC Bias Level", mic_bias_level_enum), | 417 | SOC_ENUM("MIC Bias Level", mic_bias_level_enum), |
418 | 418 | ||
419 | SOC_DOUBLE_R_SX_TLV("ADC Volume", CS42L52_ADCA_VOL, | 419 | SOC_DOUBLE_R_SX_TLV("ADC Volume", CS42L52_ADCA_VOL, |
420 | CS42L52_ADCB_VOL, 7, 0x80, 0xA0, ipd_tlv), | 420 | CS42L52_ADCB_VOL, 0, 0xA0, 0x78, ipd_tlv), |
421 | SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", | 421 | SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", |
422 | CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL, | 422 | CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL, |
423 | 6, 0x7f, 0x19, ipd_tlv), | 423 | 0, 0x19, 0x7F, ipd_tlv), |
424 | 424 | ||
425 | SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0), | 425 | SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0), |
426 | 426 | ||
@@ -428,11 +428,11 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = { | |||
428 | CS42L52_ADCB_MIXER_VOL, 7, 1, 1), | 428 | CS42L52_ADCB_MIXER_VOL, 7, 1, 1), |
429 | 429 | ||
430 | SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L52_PGAA_CTL, | 430 | SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L52_PGAA_CTL, |
431 | CS42L52_PGAB_CTL, 0, 0x28, 0x30, pga_tlv), | 431 | CS42L52_PGAB_CTL, 0, 0x28, 0x24, pga_tlv), |
432 | 432 | ||
433 | SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", | 433 | SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", |
434 | CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, | 434 | CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, |
435 | 0, 0x7f, 0x19, mix_tlv), | 435 | 0, 0x19, 0x7f, mix_tlv), |
436 | SOC_DOUBLE_R("PCM Mixer Switch", | 436 | SOC_DOUBLE_R("PCM Mixer Switch", |
437 | CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 7, 1, 1), | 437 | CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 7, 1, 1), |
438 | 438 | ||
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index fdc4bd27b0df..c766a5a9ce80 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c | |||
@@ -318,24 +318,32 @@ static const struct soc_enum adca_swap_enum = | |||
318 | ARRAY_SIZE(left_swap_text), | 318 | ARRAY_SIZE(left_swap_text), |
319 | left_swap_text, | 319 | left_swap_text, |
320 | swap_values); | 320 | swap_values); |
321 | static const struct snd_kcontrol_new adca_swap_mux = | ||
322 | SOC_DAPM_ENUM("Route", adca_swap_enum); | ||
321 | 323 | ||
322 | static const struct soc_enum pcma_swap_enum = | 324 | static const struct soc_enum pcma_swap_enum = |
323 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 4, 3, | 325 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 4, 3, |
324 | ARRAY_SIZE(left_swap_text), | 326 | ARRAY_SIZE(left_swap_text), |
325 | left_swap_text, | 327 | left_swap_text, |
326 | swap_values); | 328 | swap_values); |
329 | static const struct snd_kcontrol_new pcma_swap_mux = | ||
330 | SOC_DAPM_ENUM("Route", pcma_swap_enum); | ||
327 | 331 | ||
328 | static const struct soc_enum adcb_swap_enum = | 332 | static const struct soc_enum adcb_swap_enum = |
329 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 2, 3, | 333 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 2, 3, |
330 | ARRAY_SIZE(right_swap_text), | 334 | ARRAY_SIZE(right_swap_text), |
331 | right_swap_text, | 335 | right_swap_text, |
332 | swap_values); | 336 | swap_values); |
337 | static const struct snd_kcontrol_new adcb_swap_mux = | ||
338 | SOC_DAPM_ENUM("Route", adcb_swap_enum); | ||
333 | 339 | ||
334 | static const struct soc_enum pcmb_swap_enum = | 340 | static const struct soc_enum pcmb_swap_enum = |
335 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 6, 3, | 341 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 6, 3, |
336 | ARRAY_SIZE(right_swap_text), | 342 | ARRAY_SIZE(right_swap_text), |
337 | right_swap_text, | 343 | right_swap_text, |
338 | swap_values); | 344 | swap_values); |
345 | static const struct snd_kcontrol_new pcmb_swap_mux = | ||
346 | SOC_DAPM_ENUM("Route", pcmb_swap_enum); | ||
339 | 347 | ||
340 | static const struct snd_kcontrol_new hpa_switch = | 348 | static const struct snd_kcontrol_new hpa_switch = |
341 | SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 6, 1, 1); | 349 | SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 6, 1, 1); |
@@ -421,15 +429,15 @@ static const struct soc_enum ng_delay_enum = | |||
421 | static const struct snd_kcontrol_new cs42l56_snd_controls[] = { | 429 | static const struct snd_kcontrol_new cs42l56_snd_controls[] = { |
422 | 430 | ||
423 | SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L56_MASTER_A_VOLUME, | 431 | SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L56_MASTER_A_VOLUME, |
424 | CS42L56_MASTER_B_VOLUME, 0, 0x34, 0xfd, adv_tlv), | 432 | CS42L56_MASTER_B_VOLUME, 0, 0x34, 0xE4, adv_tlv), |
425 | SOC_DOUBLE("Master Mute Switch", CS42L56_DSP_MUTE_CTL, 0, 1, 1, 1), | 433 | SOC_DOUBLE("Master Mute Switch", CS42L56_DSP_MUTE_CTL, 0, 1, 1, 1), |
426 | 434 | ||
427 | SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L56_ADCA_MIX_VOLUME, | 435 | SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L56_ADCA_MIX_VOLUME, |
428 | CS42L56_ADCB_MIX_VOLUME, 0, 0x88, 0xa9, hl_tlv), | 436 | CS42L56_ADCB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv), |
429 | SOC_DOUBLE("ADC Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 6, 7, 1, 1), | 437 | SOC_DOUBLE("ADC Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 6, 7, 1, 1), |
430 | 438 | ||
431 | SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", CS42L56_PCMA_MIX_VOLUME, | 439 | SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", CS42L56_PCMA_MIX_VOLUME, |
432 | CS42L56_PCMB_MIX_VOLUME, 0, 0x88, 0xa9, hl_tlv), | 440 | CS42L56_PCMB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv), |
433 | SOC_DOUBLE("PCM Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 4, 5, 1, 1), | 441 | SOC_DOUBLE("PCM Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 4, 5, 1, 1), |
434 | 442 | ||
435 | SOC_SINGLE_TLV("Analog Advisory Volume", | 443 | SOC_SINGLE_TLV("Analog Advisory Volume", |
@@ -438,16 +446,16 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = { | |||
438 | CS42L56_DIGINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv), | 446 | CS42L56_DIGINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv), |
439 | 447 | ||
440 | SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L56_PGAA_MUX_VOLUME, | 448 | SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L56_PGAA_MUX_VOLUME, |
441 | CS42L56_PGAB_MUX_VOLUME, 0, 0x34, 0xfd, pga_tlv), | 449 | CS42L56_PGAB_MUX_VOLUME, 0, 0x34, 0x24, pga_tlv), |
442 | SOC_DOUBLE_R_TLV("ADC Volume", CS42L56_ADCA_ATTENUATOR, | 450 | SOC_DOUBLE_R_TLV("ADC Volume", CS42L56_ADCA_ATTENUATOR, |
443 | CS42L56_ADCB_ATTENUATOR, 0, 0x00, 1, adc_tlv), | 451 | CS42L56_ADCB_ATTENUATOR, 0, 0x00, 1, adc_tlv), |
444 | SOC_DOUBLE("ADC Mute Switch", CS42L56_MISC_ADC_CTL, 2, 3, 1, 1), | 452 | SOC_DOUBLE("ADC Mute Switch", CS42L56_MISC_ADC_CTL, 2, 3, 1, 1), |
445 | SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1), | 453 | SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1), |
446 | 454 | ||
447 | SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME, | 455 | SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME, |
448 | CS42L56_HPA_VOLUME, 0, 0x44, 0x55, hl_tlv), | 456 | CS42L56_HPB_VOLUME, 0, 0x84, 0x48, hl_tlv), |
449 | SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME, | 457 | SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME, |
450 | CS42L56_LOA_VOLUME, 0, 0x44, 0x55, hl_tlv), | 458 | CS42L56_LOB_VOLUME, 0, 0x84, 0x48, hl_tlv), |
451 | 459 | ||
452 | SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL, | 460 | SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL, |
453 | 0, 0x00, 1, tone_tlv), | 461 | 0, 0x00, 1, tone_tlv), |
@@ -467,11 +475,6 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = { | |||
467 | SOC_SINGLE("ADCA Invert", CS42L56_MISC_ADC_CTL, 2, 1, 1), | 475 | SOC_SINGLE("ADCA Invert", CS42L56_MISC_ADC_CTL, 2, 1, 1), |
468 | SOC_SINGLE("ADCB Invert", CS42L56_MISC_ADC_CTL, 3, 1, 1), | 476 | SOC_SINGLE("ADCB Invert", CS42L56_MISC_ADC_CTL, 3, 1, 1), |
469 | 477 | ||
470 | SOC_ENUM("PCMA Swap", pcma_swap_enum), | ||
471 | SOC_ENUM("PCMB Swap", pcmb_swap_enum), | ||
472 | SOC_ENUM("ADCA Swap", adca_swap_enum), | ||
473 | SOC_ENUM("ADCB Swap", adcb_swap_enum), | ||
474 | |||
475 | SOC_DOUBLE("HPF Switch", CS42L56_HPF_CTL, 5, 7, 1, 1), | 478 | SOC_DOUBLE("HPF Switch", CS42L56_HPF_CTL, 5, 7, 1, 1), |
476 | SOC_DOUBLE("HPF Freeze Switch", CS42L56_HPF_CTL, 4, 6, 1, 1), | 479 | SOC_DOUBLE("HPF Freeze Switch", CS42L56_HPF_CTL, 4, 6, 1, 1), |
477 | SOC_ENUM("HPFA Corner Freq", hpfa_freq_enum), | 480 | SOC_ENUM("HPFA Corner Freq", hpfa_freq_enum), |
@@ -570,6 +573,16 @@ static const struct snd_soc_dapm_widget cs42l56_dapm_widgets[] = { | |||
570 | SND_SOC_DAPM_ADC("ADCA", NULL, CS42L56_PWRCTL_1, 1, 1), | 573 | SND_SOC_DAPM_ADC("ADCA", NULL, CS42L56_PWRCTL_1, 1, 1), |
571 | SND_SOC_DAPM_ADC("ADCB", NULL, CS42L56_PWRCTL_1, 2, 1), | 574 | SND_SOC_DAPM_ADC("ADCB", NULL, CS42L56_PWRCTL_1, 2, 1), |
572 | 575 | ||
576 | SND_SOC_DAPM_MUX("ADCA Swap Mux", SND_SOC_NOPM, 0, 0, | ||
577 | &adca_swap_mux), | ||
578 | SND_SOC_DAPM_MUX("ADCB Swap Mux", SND_SOC_NOPM, 0, 0, | ||
579 | &adcb_swap_mux), | ||
580 | |||
581 | SND_SOC_DAPM_MUX("PCMA Swap Mux", SND_SOC_NOPM, 0, 0, | ||
582 | &pcma_swap_mux), | ||
583 | SND_SOC_DAPM_MUX("PCMB Swap Mux", SND_SOC_NOPM, 0, 0, | ||
584 | &pcmb_swap_mux), | ||
585 | |||
573 | SND_SOC_DAPM_DAC("DACA", NULL, SND_SOC_NOPM, 0, 0), | 586 | SND_SOC_DAPM_DAC("DACA", NULL, SND_SOC_NOPM, 0, 0), |
574 | SND_SOC_DAPM_DAC("DACB", NULL, SND_SOC_NOPM, 0, 0), | 587 | SND_SOC_DAPM_DAC("DACB", NULL, SND_SOC_NOPM, 0, 0), |
575 | 588 | ||
@@ -607,8 +620,19 @@ static const struct snd_soc_dapm_route cs42l56_audio_map[] = { | |||
607 | {"Digital Output Mux", NULL, "ADCA"}, | 620 | {"Digital Output Mux", NULL, "ADCA"}, |
608 | {"Digital Output Mux", NULL, "ADCB"}, | 621 | {"Digital Output Mux", NULL, "ADCB"}, |
609 | 622 | ||
610 | {"ADCB", NULL, "ADCB Mux"}, | 623 | {"ADCB", NULL, "ADCB Swap Mux"}, |
611 | {"ADCA", NULL, "ADCA Mux"}, | 624 | {"ADCA", NULL, "ADCA Swap Mux"}, |
625 | |||
626 | {"ADCA Swap Mux", NULL, "ADCA"}, | ||
627 | {"ADCB Swap Mux", NULL, "ADCB"}, | ||
628 | |||
629 | {"DACA", "Left", "ADCA Swap Mux"}, | ||
630 | {"DACA", "LR 2", "ADCA Swap Mux"}, | ||
631 | {"DACA", "Right", "ADCA Swap Mux"}, | ||
632 | |||
633 | {"DACB", "Left", "ADCB Swap Mux"}, | ||
634 | {"DACB", "LR 2", "ADCB Swap Mux"}, | ||
635 | {"DACB", "Right", "ADCB Swap Mux"}, | ||
612 | 636 | ||
613 | {"ADCA Mux", NULL, "AIN3A"}, | 637 | {"ADCA Mux", NULL, "AIN3A"}, |
614 | {"ADCA Mux", NULL, "AIN2A"}, | 638 | {"ADCA Mux", NULL, "AIN2A"}, |
@@ -633,30 +657,32 @@ static const struct snd_soc_dapm_route cs42l56_audio_map[] = { | |||
633 | {"PGAB Input Mux", NULL, "AIN2B"}, | 657 | {"PGAB Input Mux", NULL, "AIN2B"}, |
634 | {"PGAB Input Mux", NULL, "AIN3B"}, | 658 | {"PGAB Input Mux", NULL, "AIN3B"}, |
635 | 659 | ||
636 | {"LOB", NULL, "Lineout Right"}, | 660 | {"LOB", "Switch", "LINEOUTB Input Mux"}, |
637 | {"LOA", NULL, "Lineout Left"}, | 661 | {"LOA", "Switch", "LINEOUTA Input Mux"}, |
638 | |||
639 | {"Lineout Right", "Switch", "LINEOUTB Input Mux"}, | ||
640 | {"Lineout Left", "Switch", "LINEOUTA Input Mux"}, | ||
641 | 662 | ||
642 | {"LINEOUTA Input Mux", "PGAA", "PGAA"}, | 663 | {"LINEOUTA Input Mux", "PGAA", "PGAA"}, |
643 | {"LINEOUTB Input Mux", "PGAB", "PGAB"}, | 664 | {"LINEOUTB Input Mux", "PGAB", "PGAB"}, |
644 | {"LINEOUTA Input Mux", "DACA", "DACA"}, | 665 | {"LINEOUTA Input Mux", "DACA", "DACA"}, |
645 | {"LINEOUTB Input Mux", "DACB", "DACB"}, | 666 | {"LINEOUTB Input Mux", "DACB", "DACB"}, |
646 | 667 | ||
647 | {"HPA", NULL, "Headphone Left"}, | 668 | {"HPA", "Switch", "HPB Input Mux"}, |
648 | {"HPB", NULL, "Headphone Right"}, | 669 | {"HPB", "Switch", "HPA Input Mux"}, |
649 | |||
650 | {"Headphone Right", "Switch", "HPB Input Mux"}, | ||
651 | {"Headphone Left", "Switch", "HPA Input Mux"}, | ||
652 | 670 | ||
653 | {"HPA Input Mux", "PGAA", "PGAA"}, | 671 | {"HPA Input Mux", "PGAA", "PGAA"}, |
654 | {"HPB Input Mux", "PGAB", "PGAB"}, | 672 | {"HPB Input Mux", "PGAB", "PGAB"}, |
655 | {"HPA Input Mux", "DACA", "DACA"}, | 673 | {"HPA Input Mux", "DACA", "DACA"}, |
656 | {"HPB Input Mux", "DACB", "DACB"}, | 674 | {"HPB Input Mux", "DACB", "DACB"}, |
657 | 675 | ||
658 | {"DACB", NULL, "HiFi Playback"}, | 676 | {"DACA", NULL, "PCMA Swap Mux"}, |
659 | {"DACA", NULL, "HiFi Playback"}, | 677 | {"DACB", NULL, "PCMB Swap Mux"}, |
678 | |||
679 | {"PCMB Swap Mux", "Left", "HiFi Playback"}, | ||
680 | {"PCMB Swap Mux", "LR 2", "HiFi Playback"}, | ||
681 | {"PCMB Swap Mux", "Right", "HiFi Playback"}, | ||
682 | |||
683 | {"PCMA Swap Mux", "Left", "HiFi Playback"}, | ||
684 | {"PCMA Swap Mux", "LR 2", "HiFi Playback"}, | ||
685 | {"PCMA Swap Mux", "Right", "HiFi Playback"}, | ||
660 | 686 | ||
661 | }; | 687 | }; |
662 | 688 | ||
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index ae3717992d56..0e7b9eb2ba61 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -401,7 +401,7 @@ static const struct snd_kcontrol_new cs42l73_snd_controls[] = { | |||
401 | CS42L73_LOBAVOL, 0, 0x41, 0x4B, hpaloa_tlv), | 401 | CS42L73_LOBAVOL, 0, 0x41, 0x4B, hpaloa_tlv), |
402 | 402 | ||
403 | SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL, | 403 | SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL, |
404 | CS42L73_MICBPREPGABVOL, 5, 0x34, | 404 | CS42L73_MICBPREPGABVOL, 0, 0x34, |
405 | 0x24, micpga_tlv), | 405 | 0x24, micpga_tlv), |
406 | 406 | ||
407 | SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL, | 407 | SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL, |
@@ -1408,10 +1408,8 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client, | |||
1408 | 1408 | ||
1409 | cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private), | 1409 | cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private), |
1410 | GFP_KERNEL); | 1410 | GFP_KERNEL); |
1411 | if (!cs42l73) { | 1411 | if (!cs42l73) |
1412 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
1413 | return -ENOMEM; | 1412 | return -ENOMEM; |
1414 | } | ||
1415 | 1413 | ||
1416 | cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap); | 1414 | cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap); |
1417 | if (IS_ERR(cs42l73->regmap)) { | 1415 | if (IS_ERR(cs42l73->regmap)) { |
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index a25bc6061a30..02b1520ae0bc 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c | |||
@@ -219,6 +219,9 @@ static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
219 | case SND_SOC_DAIFMT_RIGHT_J: | 219 | case SND_SOC_DAIFMT_RIGHT_J: |
220 | val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ; | 220 | val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ; |
221 | break; | 221 | break; |
222 | case SND_SOC_DAIFMT_DSP_A: | ||
223 | val = CS42XX8_INTF_DAC_DIF_TDM | CS42XX8_INTF_ADC_DIF_TDM; | ||
224 | break; | ||
222 | default: | 225 | default: |
223 | dev_err(codec->dev, "unsupported dai format\n"); | 226 | dev_err(codec->dev, "unsupported dai format\n"); |
224 | return -EINVAL; | 227 | return -EINVAL; |
@@ -422,7 +425,7 @@ const struct cs42xx8_driver_data cs42888_data = { | |||
422 | }; | 425 | }; |
423 | EXPORT_SYMBOL_GPL(cs42888_data); | 426 | EXPORT_SYMBOL_GPL(cs42888_data); |
424 | 427 | ||
425 | const struct of_device_id cs42xx8_of_match[] = { | 428 | static const struct of_device_id cs42xx8_of_match[] = { |
426 | { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, | 429 | { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, |
427 | { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, | 430 | { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, |
428 | { /* sentinel */ } | 431 | { /* sentinel */ } |
diff --git a/sound/soc/codecs/cs42xx8.h b/sound/soc/codecs/cs42xx8.h index da0b94aee419..b2c10e537ef6 100644 --- a/sound/soc/codecs/cs42xx8.h +++ b/sound/soc/codecs/cs42xx8.h | |||
@@ -128,8 +128,8 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap); | |||
128 | #define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT) | 128 | #define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT) |
129 | #define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT) | 129 | #define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT) |
130 | #define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT) | 130 | #define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT) |
131 | #define CS42XX8_INTF_DAC_DIF_ONELINE_24 (6 << CS42XX8_INTF_DAC_DIF_SHIFT) | 131 | #define CS42XX8_INTF_DAC_DIF_ONELINE_24 (5 << CS42XX8_INTF_DAC_DIF_SHIFT) |
132 | #define CS42XX8_INTF_DAC_DIF_TDM (7 << CS42XX8_INTF_DAC_DIF_SHIFT) | 132 | #define CS42XX8_INTF_DAC_DIF_TDM (6 << CS42XX8_INTF_DAC_DIF_SHIFT) |
133 | #define CS42XX8_INTF_ADC_DIF_SHIFT 0 | 133 | #define CS42XX8_INTF_ADC_DIF_SHIFT 0 |
134 | #define CS42XX8_INTF_ADC_DIF_WIDTH 3 | 134 | #define CS42XX8_INTF_ADC_DIF_WIDTH 3 |
135 | #define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT) | 135 | #define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT) |
@@ -138,8 +138,8 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap); | |||
138 | #define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT) | 138 | #define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT) |
139 | #define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT) | 139 | #define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT) |
140 | #define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT) | 140 | #define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT) |
141 | #define CS42XX8_INTF_ADC_DIF_ONELINE_24 (6 << CS42XX8_INTF_ADC_DIF_SHIFT) | 141 | #define CS42XX8_INTF_ADC_DIF_ONELINE_24 (5 << CS42XX8_INTF_ADC_DIF_SHIFT) |
142 | #define CS42XX8_INTF_ADC_DIF_TDM (7 << CS42XX8_INTF_ADC_DIF_SHIFT) | 142 | #define CS42XX8_INTF_ADC_DIF_TDM (6 << CS42XX8_INTF_ADC_DIF_SHIFT) |
143 | 143 | ||
144 | /* ADC Control & DAC De-Emphasis (Address 05h) */ | 144 | /* ADC Control & DAC De-Emphasis (Address 05h) */ |
145 | #define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7 | 145 | #define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7 |
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index d5fd00a64748..8f95b0300f1a 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c | |||
@@ -253,7 +253,7 @@ static void v253_close(struct tty_struct *tty) | |||
253 | /* Prevent the codec driver from further accessing the modem */ | 253 | /* Prevent the codec driver from further accessing the modem */ |
254 | codec->hw_write = NULL; | 254 | codec->hw_write = NULL; |
255 | cx20442->control_data = NULL; | 255 | cx20442->control_data = NULL; |
256 | codec->card->pop_time = 0; | 256 | codec->component.card->pop_time = 0; |
257 | } | 257 | } |
258 | 258 | ||
259 | /* Line discipline .hangup() */ | 259 | /* Line discipline .hangup() */ |
@@ -281,7 +281,7 @@ static void v253_receive(struct tty_struct *tty, | |||
281 | /* Set up codec driver access to modem controls */ | 281 | /* Set up codec driver access to modem controls */ |
282 | cx20442->control_data = tty; | 282 | cx20442->control_data = tty; |
283 | codec->hw_write = (hw_write_t)tty->ops->write; | 283 | codec->hw_write = (hw_write_t)tty->ops->write; |
284 | codec->card->pop_time = 1; | 284 | codec->component.card->pop_time = 1; |
285 | } | 285 | } |
286 | } | 286 | } |
287 | 287 | ||
@@ -372,7 +372,7 @@ static int cx20442_codec_probe(struct snd_soc_codec *codec) | |||
372 | 372 | ||
373 | snd_soc_codec_set_drvdata(codec, cx20442); | 373 | snd_soc_codec_set_drvdata(codec, cx20442); |
374 | codec->hw_write = NULL; | 374 | codec->hw_write = NULL; |
375 | codec->card->pop_time = 0; | 375 | codec->component.card->pop_time = 0; |
376 | 376 | ||
377 | return 0; | 377 | return 0; |
378 | } | 378 | } |
@@ -383,8 +383,8 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec) | |||
383 | struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); | 383 | struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); |
384 | 384 | ||
385 | if (cx20442->control_data) { | 385 | if (cx20442->control_data) { |
386 | struct tty_struct *tty = cx20442->control_data; | 386 | struct tty_struct *tty = cx20442->control_data; |
387 | tty_hangup(tty); | 387 | tty_hangup(tty); |
388 | } | 388 | } |
389 | 389 | ||
390 | if (!IS_ERR(cx20442->por)) { | 390 | if (!IS_ERR(cx20442->por)) { |
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index f5fccc7a8e89..4a063fa88526 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -26,10 +26,6 @@ | |||
26 | #include <sound/max98090.h> | 26 | #include <sound/max98090.h> |
27 | #include "max98090.h" | 27 | #include "max98090.h" |
28 | 28 | ||
29 | #define DEBUG | ||
30 | #define EXTMIC_METHOD | ||
31 | #define EXTMIC_METHOD_TEST | ||
32 | |||
33 | /* Allows for sparsely populated register maps */ | 29 | /* Allows for sparsely populated register maps */ |
34 | static struct reg_default max98090_reg[] = { | 30 | static struct reg_default max98090_reg[] = { |
35 | { 0x00, 0x00 }, /* 00 Software Reset */ | 31 | { 0x00, 0x00 }, /* 00 Software Reset */ |
@@ -820,7 +816,6 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w, | |||
820 | else | 816 | else |
821 | val = (val & M98090_MIC_PA2EN_MASK) >> M98090_MIC_PA2EN_SHIFT; | 817 | val = (val & M98090_MIC_PA2EN_MASK) >> M98090_MIC_PA2EN_SHIFT; |
822 | 818 | ||
823 | |||
824 | if (val >= 1) { | 819 | if (val >= 1) { |
825 | if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) { | 820 | if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) { |
826 | max98090->pa1en = val - 1; /* Update for volatile */ | 821 | max98090->pa1en = val - 1; /* Update for volatile */ |
@@ -1140,7 +1135,6 @@ static const struct snd_kcontrol_new max98090_mixhprsel_mux = | |||
1140 | SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum); | 1135 | SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum); |
1141 | 1136 | ||
1142 | static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { | 1137 | static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { |
1143 | |||
1144 | SND_SOC_DAPM_INPUT("MIC1"), | 1138 | SND_SOC_DAPM_INPUT("MIC1"), |
1145 | SND_SOC_DAPM_INPUT("MIC2"), | 1139 | SND_SOC_DAPM_INPUT("MIC2"), |
1146 | SND_SOC_DAPM_INPUT("DMICL"), | 1140 | SND_SOC_DAPM_INPUT("DMICL"), |
@@ -1304,7 +1298,6 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { | |||
1304 | }; | 1298 | }; |
1305 | 1299 | ||
1306 | static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = { | 1300 | static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = { |
1307 | |||
1308 | SND_SOC_DAPM_INPUT("DMIC3"), | 1301 | SND_SOC_DAPM_INPUT("DMIC3"), |
1309 | SND_SOC_DAPM_INPUT("DMIC4"), | 1302 | SND_SOC_DAPM_INPUT("DMIC4"), |
1310 | 1303 | ||
@@ -1315,7 +1308,6 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = { | |||
1315 | }; | 1308 | }; |
1316 | 1309 | ||
1317 | static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | 1310 | static const struct snd_soc_dapm_route max98090_dapm_routes[] = { |
1318 | |||
1319 | {"MIC1 Input", NULL, "MIC1"}, | 1311 | {"MIC1 Input", NULL, "MIC1"}, |
1320 | {"MIC2 Input", NULL, "MIC2"}, | 1312 | {"MIC2 Input", NULL, "MIC2"}, |
1321 | 1313 | ||
@@ -1493,17 +1485,14 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | |||
1493 | {"SPKR", NULL, "SPK Right Out"}, | 1485 | {"SPKR", NULL, "SPK Right Out"}, |
1494 | {"RCVL", NULL, "RCV Left Out"}, | 1486 | {"RCVL", NULL, "RCV Left Out"}, |
1495 | {"RCVR", NULL, "RCV Right Out"}, | 1487 | {"RCVR", NULL, "RCV Right Out"}, |
1496 | |||
1497 | }; | 1488 | }; |
1498 | 1489 | ||
1499 | static const struct snd_soc_dapm_route max98091_dapm_routes[] = { | 1490 | static const struct snd_soc_dapm_route max98091_dapm_routes[] = { |
1500 | |||
1501 | /* DMIC inputs */ | 1491 | /* DMIC inputs */ |
1502 | {"DMIC3", NULL, "DMIC3_ENA"}, | 1492 | {"DMIC3", NULL, "DMIC3_ENA"}, |
1503 | {"DMIC4", NULL, "DMIC4_ENA"}, | 1493 | {"DMIC4", NULL, "DMIC4_ENA"}, |
1504 | {"DMIC3", NULL, "AHPF"}, | 1494 | {"DMIC3", NULL, "AHPF"}, |
1505 | {"DMIC4", NULL, "AHPF"}, | 1495 | {"DMIC4", NULL, "AHPF"}, |
1506 | |||
1507 | }; | 1496 | }; |
1508 | 1497 | ||
1509 | static int max98090_add_widgets(struct snd_soc_codec *codec) | 1498 | static int max98090_add_widgets(struct snd_soc_codec *codec) |
@@ -1531,7 +1520,6 @@ static int max98090_add_widgets(struct snd_soc_codec *codec) | |||
1531 | 1520 | ||
1532 | snd_soc_dapm_add_routes(dapm, max98091_dapm_routes, | 1521 | snd_soc_dapm_add_routes(dapm, max98091_dapm_routes, |
1533 | ARRAY_SIZE(max98091_dapm_routes)); | 1522 | ARRAY_SIZE(max98091_dapm_routes)); |
1534 | |||
1535 | } | 1523 | } |
1536 | 1524 | ||
1537 | return 0; | 1525 | return 0; |
@@ -2212,22 +2200,11 @@ static struct snd_soc_dai_driver max98090_dai[] = { | |||
2212 | } | 2200 | } |
2213 | }; | 2201 | }; |
2214 | 2202 | ||
2215 | static void max98090_handle_pdata(struct snd_soc_codec *codec) | ||
2216 | { | ||
2217 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | ||
2218 | struct max98090_pdata *pdata = max98090->pdata; | ||
2219 | |||
2220 | if (!pdata) { | ||
2221 | dev_err(codec->dev, "No platform data\n"); | ||
2222 | return; | ||
2223 | } | ||
2224 | |||
2225 | } | ||
2226 | |||
2227 | static int max98090_probe(struct snd_soc_codec *codec) | 2203 | static int max98090_probe(struct snd_soc_codec *codec) |
2228 | { | 2204 | { |
2229 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | 2205 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); |
2230 | struct max98090_cdata *cdata; | 2206 | struct max98090_cdata *cdata; |
2207 | enum max98090_type devtype; | ||
2231 | int ret = 0; | 2208 | int ret = 0; |
2232 | 2209 | ||
2233 | dev_dbg(codec->dev, "max98090_probe\n"); | 2210 | dev_dbg(codec->dev, "max98090_probe\n"); |
@@ -2263,16 +2240,21 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2263 | } | 2240 | } |
2264 | 2241 | ||
2265 | if ((ret >= M98090_REVA) && (ret <= M98090_REVA + 0x0f)) { | 2242 | if ((ret >= M98090_REVA) && (ret <= M98090_REVA + 0x0f)) { |
2266 | max98090->devtype = MAX98090; | 2243 | devtype = MAX98090; |
2267 | dev_info(codec->dev, "MAX98090 REVID=0x%02x\n", ret); | 2244 | dev_info(codec->dev, "MAX98090 REVID=0x%02x\n", ret); |
2268 | } else if ((ret >= M98091_REVA) && (ret <= M98091_REVA + 0x0f)) { | 2245 | } else if ((ret >= M98091_REVA) && (ret <= M98091_REVA + 0x0f)) { |
2269 | max98090->devtype = MAX98091; | 2246 | devtype = MAX98091; |
2270 | dev_info(codec->dev, "MAX98091 REVID=0x%02x\n", ret); | 2247 | dev_info(codec->dev, "MAX98091 REVID=0x%02x\n", ret); |
2271 | } else { | 2248 | } else { |
2272 | max98090->devtype = MAX98090; | 2249 | devtype = MAX98090; |
2273 | dev_err(codec->dev, "Unrecognized revision 0x%02x\n", ret); | 2250 | dev_err(codec->dev, "Unrecognized revision 0x%02x\n", ret); |
2274 | } | 2251 | } |
2275 | 2252 | ||
2253 | if (max98090->devtype != devtype) { | ||
2254 | dev_warn(codec->dev, "Mismatch in DT specified CODEC type.\n"); | ||
2255 | max98090->devtype = devtype; | ||
2256 | } | ||
2257 | |||
2276 | max98090->jack_state = M98090_JACK_STATE_NO_HEADSET; | 2258 | max98090->jack_state = M98090_JACK_STATE_NO_HEADSET; |
2277 | 2259 | ||
2278 | INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work); | 2260 | INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work); |
@@ -2284,7 +2266,7 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2284 | /* Register for interrupts */ | 2266 | /* Register for interrupts */ |
2285 | dev_dbg(codec->dev, "irq = %d\n", max98090->irq); | 2267 | dev_dbg(codec->dev, "irq = %d\n", max98090->irq); |
2286 | 2268 | ||
2287 | ret = request_threaded_irq(max98090->irq, NULL, | 2269 | ret = devm_request_threaded_irq(codec->dev, max98090->irq, NULL, |
2288 | max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 2270 | max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
2289 | "max98090_interrupt", codec); | 2271 | "max98090_interrupt", codec); |
2290 | if (ret < 0) { | 2272 | if (ret < 0) { |
@@ -2317,8 +2299,6 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2317 | snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE, | 2299 | snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE, |
2318 | M98090_MBVSEL_MASK, M98090_MBVSEL_2V8); | 2300 | M98090_MBVSEL_MASK, M98090_MBVSEL_2V8); |
2319 | 2301 | ||
2320 | max98090_handle_pdata(codec); | ||
2321 | |||
2322 | max98090_add_widgets(codec); | 2302 | max98090_add_widgets(codec); |
2323 | 2303 | ||
2324 | err_access: | 2304 | err_access: |
@@ -2428,7 +2408,7 @@ static int max98090_runtime_suspend(struct device *dev) | |||
2428 | } | 2408 | } |
2429 | #endif | 2409 | #endif |
2430 | 2410 | ||
2431 | #ifdef CONFIG_PM | 2411 | #ifdef CONFIG_PM_SLEEP |
2432 | static int max98090_resume(struct device *dev) | 2412 | static int max98090_resume(struct device *dev) |
2433 | { | 2413 | { |
2434 | struct max98090_priv *max98090 = dev_get_drvdata(dev); | 2414 | struct max98090_priv *max98090 = dev_get_drvdata(dev); |
@@ -2460,12 +2440,14 @@ static const struct dev_pm_ops max98090_pm = { | |||
2460 | 2440 | ||
2461 | static const struct i2c_device_id max98090_i2c_id[] = { | 2441 | static const struct i2c_device_id max98090_i2c_id[] = { |
2462 | { "max98090", MAX98090 }, | 2442 | { "max98090", MAX98090 }, |
2443 | { "max98091", MAX98091 }, | ||
2463 | { } | 2444 | { } |
2464 | }; | 2445 | }; |
2465 | MODULE_DEVICE_TABLE(i2c, max98090_i2c_id); | 2446 | MODULE_DEVICE_TABLE(i2c, max98090_i2c_id); |
2466 | 2447 | ||
2467 | static const struct of_device_id max98090_of_match[] = { | 2448 | static const struct of_device_id max98090_of_match[] = { |
2468 | { .compatible = "maxim,max98090", }, | 2449 | { .compatible = "maxim,max98090", }, |
2450 | { .compatible = "maxim,max98091", }, | ||
2469 | { } | 2451 | { } |
2470 | }; | 2452 | }; |
2471 | MODULE_DEVICE_TABLE(of, max98090_of_match); | 2453 | MODULE_DEVICE_TABLE(of, max98090_of_match); |
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 9965277b595a..388f90a597fa 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
@@ -766,11 +766,11 @@ static int __init mc13783_codec_probe(struct platform_device *pdev) | |||
766 | 766 | ||
767 | ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port); | 767 | ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port); |
768 | if (ret) | 768 | if (ret) |
769 | return ret; | 769 | goto out; |
770 | 770 | ||
771 | ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port); | 771 | ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port); |
772 | if (ret) | 772 | if (ret) |
773 | return ret; | 773 | goto out; |
774 | } | 774 | } |
775 | 775 | ||
776 | dev_set_drvdata(&pdev->dev, priv); | 776 | dev_set_drvdata(&pdev->dev, priv); |
@@ -783,6 +783,8 @@ static int __init mc13783_codec_probe(struct platform_device *pdev) | |||
783 | ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783, | 783 | ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783, |
784 | mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async)); | 784 | mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async)); |
785 | 785 | ||
786 | out: | ||
787 | of_node_put(np); | ||
786 | return ret; | 788 | return ret; |
787 | } | 789 | } |
788 | 790 | ||
diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c index 3a80ba4452df..57b0c94a710b 100644 --- a/sound/soc/codecs/pcm1792a.c +++ b/sound/soc/codecs/pcm1792a.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #define PCM1792A_DAC_VOL_LEFT 0x10 | 36 | #define PCM1792A_DAC_VOL_LEFT 0x10 |
37 | #define PCM1792A_DAC_VOL_RIGHT 0x11 | 37 | #define PCM1792A_DAC_VOL_RIGHT 0x11 |
38 | #define PCM1792A_FMT_CONTROL 0x12 | 38 | #define PCM1792A_FMT_CONTROL 0x12 |
39 | #define PCM1792A_MODE_CONTROL 0x13 | ||
39 | #define PCM1792A_SOFT_MUTE PCM1792A_FMT_CONTROL | 40 | #define PCM1792A_SOFT_MUTE PCM1792A_FMT_CONTROL |
40 | 41 | ||
41 | #define PCM1792A_FMT_MASK 0x70 | 42 | #define PCM1792A_FMT_MASK 0x70 |
@@ -164,6 +165,8 @@ static const struct snd_kcontrol_new pcm1792a_controls[] = { | |||
164 | SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT, | 165 | SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT, |
165 | PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0, | 166 | PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0, |
166 | pcm1792a_dac_tlv), | 167 | pcm1792a_dac_tlv), |
168 | SOC_SINGLE("DAC Invert Output Switch", PCM1792A_MODE_CONTROL, 7, 1, 0), | ||
169 | SOC_SINGLE("DAC Rolloff Filter Switch", PCM1792A_MODE_CONTROL, 1, 1, 0), | ||
167 | }; | 170 | }; |
168 | 171 | ||
169 | static const struct snd_soc_dapm_widget pcm1792a_dapm_widgets[] = { | 172 | static const struct snd_soc_dapm_widget pcm1792a_dapm_widgets[] = { |
diff --git a/sound/soc/codecs/pcm1792a.h b/sound/soc/codecs/pcm1792a.h index 7a83d1fc102a..51d5470fee16 100644 --- a/sound/soc/codecs/pcm1792a.h +++ b/sound/soc/codecs/pcm1792a.h | |||
@@ -18,7 +18,8 @@ | |||
18 | #define __PCM1792A_H__ | 18 | #define __PCM1792A_H__ |
19 | 19 | ||
20 | #define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \ | 20 | #define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \ |
21 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) | 21 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ |
22 | SNDRV_PCM_RATE_192000) | ||
22 | 23 | ||
23 | #define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ | 24 | #define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ |
24 | SNDRV_PCM_FMTBIT_S16_LE) | 25 | SNDRV_PCM_FMTBIT_S16_LE) |
diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c index 7b82fbe0d14c..56650d6c2f53 100644 --- a/sound/soc/codecs/rl6231.c +++ b/sound/soc/codecs/rl6231.c | |||
@@ -11,25 +11,6 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/regmap.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/of_gpio.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/spi/spi.h> | ||
25 | #include <linux/acpi.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/pcm.h> | ||
28 | #include <sound/pcm_params.h> | ||
29 | #include <sound/soc.h> | ||
30 | #include <sound/soc-dapm.h> | ||
31 | #include <sound/initval.h> | ||
32 | #include <sound/tlv.h> | ||
33 | 14 | ||
34 | #include "rl6231.h" | 15 | #include "rl6231.h" |
35 | 16 | ||
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c new file mode 100644 index 000000000000..e4f6102efc1a --- /dev/null +++ b/sound/soc/codecs/rt286.c | |||
@@ -0,0 +1,1222 @@ | |||
1 | /* | ||
2 | * rt286.c -- RT286 ALSA SoC audio codec driver | ||
3 | * | ||
4 | * Copyright 2013 Realtek Semiconductor Corp. | ||
5 | * Author: Bard Liao <bardliao@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/pm.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | #include <linux/acpi.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/soc-dapm.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/tlv.h> | ||
28 | #include <sound/jack.h> | ||
29 | #include <linux/workqueue.h> | ||
30 | #include <sound/rt286.h> | ||
31 | #include <sound/hda_verbs.h> | ||
32 | |||
33 | #include "rt286.h" | ||
34 | |||
35 | #define RT286_VENDOR_ID 0x10ec0286 | ||
36 | |||
37 | struct rt286_priv { | ||
38 | struct regmap *regmap; | ||
39 | struct rt286_platform_data pdata; | ||
40 | struct i2c_client *i2c; | ||
41 | struct snd_soc_jack *jack; | ||
42 | struct delayed_work jack_detect_work; | ||
43 | int sys_clk; | ||
44 | struct reg_default *index_cache; | ||
45 | }; | ||
46 | |||
47 | static struct reg_default rt286_index_def[] = { | ||
48 | { 0x01, 0xaaaa }, | ||
49 | { 0x02, 0x8aaa }, | ||
50 | { 0x03, 0x0002 }, | ||
51 | { 0x04, 0xaf01 }, | ||
52 | { 0x08, 0x000d }, | ||
53 | { 0x09, 0xd810 }, | ||
54 | { 0x0a, 0x0060 }, | ||
55 | { 0x0b, 0x0000 }, | ||
56 | { 0x0d, 0x2800 }, | ||
57 | { 0x0f, 0x0000 }, | ||
58 | { 0x19, 0x0a17 }, | ||
59 | { 0x20, 0x0020 }, | ||
60 | { 0x33, 0x0208 }, | ||
61 | { 0x49, 0x0004 }, | ||
62 | { 0x4f, 0x50e9 }, | ||
63 | { 0x50, 0x2c00 }, | ||
64 | { 0x63, 0x2902 }, | ||
65 | { 0x67, 0x1111 }, | ||
66 | { 0x68, 0x1016 }, | ||
67 | { 0x69, 0x273f }, | ||
68 | }; | ||
69 | #define INDEX_CACHE_SIZE ARRAY_SIZE(rt286_index_def) | ||
70 | |||
71 | static const struct reg_default rt286_reg[] = { | ||
72 | { 0x00170500, 0x00000400 }, | ||
73 | { 0x00220000, 0x00000031 }, | ||
74 | { 0x00239000, 0x0000007f }, | ||
75 | { 0x0023a000, 0x0000007f }, | ||
76 | { 0x00270500, 0x00000400 }, | ||
77 | { 0x00370500, 0x00000400 }, | ||
78 | { 0x00870500, 0x00000400 }, | ||
79 | { 0x00920000, 0x00000031 }, | ||
80 | { 0x00935000, 0x000000c3 }, | ||
81 | { 0x00936000, 0x000000c3 }, | ||
82 | { 0x00970500, 0x00000400 }, | ||
83 | { 0x00b37000, 0x00000097 }, | ||
84 | { 0x00b37200, 0x00000097 }, | ||
85 | { 0x00b37300, 0x00000097 }, | ||
86 | { 0x00c37000, 0x00000000 }, | ||
87 | { 0x00c37100, 0x00000080 }, | ||
88 | { 0x01270500, 0x00000400 }, | ||
89 | { 0x01370500, 0x00000400 }, | ||
90 | { 0x01371f00, 0x411111f0 }, | ||
91 | { 0x01439000, 0x00000080 }, | ||
92 | { 0x0143a000, 0x00000080 }, | ||
93 | { 0x01470700, 0x00000000 }, | ||
94 | { 0x01470500, 0x00000400 }, | ||
95 | { 0x01470c00, 0x00000000 }, | ||
96 | { 0x01470100, 0x00000000 }, | ||
97 | { 0x01837000, 0x00000000 }, | ||
98 | { 0x01870500, 0x00000400 }, | ||
99 | { 0x02050000, 0x00000000 }, | ||
100 | { 0x02139000, 0x00000080 }, | ||
101 | { 0x0213a000, 0x00000080 }, | ||
102 | { 0x02170100, 0x00000000 }, | ||
103 | { 0x02170500, 0x00000400 }, | ||
104 | { 0x02170700, 0x00000000 }, | ||
105 | { 0x02270100, 0x00000000 }, | ||
106 | { 0x02370100, 0x00000000 }, | ||
107 | { 0x02040000, 0x00004002 }, | ||
108 | { 0x01870700, 0x00000020 }, | ||
109 | { 0x00830000, 0x000000c3 }, | ||
110 | { 0x00930000, 0x000000c3 }, | ||
111 | { 0x01270700, 0x00000000 }, | ||
112 | }; | ||
113 | |||
114 | static bool rt286_volatile_register(struct device *dev, unsigned int reg) | ||
115 | { | ||
116 | switch (reg) { | ||
117 | case 0 ... 0xff: | ||
118 | case RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): | ||
119 | case RT286_GET_HP_SENSE: | ||
120 | case RT286_GET_MIC1_SENSE: | ||
121 | case RT286_PROC_COEF: | ||
122 | return true; | ||
123 | default: | ||
124 | return false; | ||
125 | } | ||
126 | |||
127 | |||
128 | } | ||
129 | |||
130 | static bool rt286_readable_register(struct device *dev, unsigned int reg) | ||
131 | { | ||
132 | switch (reg) { | ||
133 | case 0 ... 0xff: | ||
134 | case RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): | ||
135 | case RT286_GET_HP_SENSE: | ||
136 | case RT286_GET_MIC1_SENSE: | ||
137 | case RT286_SET_AUDIO_POWER: | ||
138 | case RT286_SET_HPO_POWER: | ||
139 | case RT286_SET_SPK_POWER: | ||
140 | case RT286_SET_DMIC1_POWER: | ||
141 | case RT286_SPK_MUX: | ||
142 | case RT286_HPO_MUX: | ||
143 | case RT286_ADC0_MUX: | ||
144 | case RT286_ADC1_MUX: | ||
145 | case RT286_SET_MIC1: | ||
146 | case RT286_SET_PIN_HPO: | ||
147 | case RT286_SET_PIN_SPK: | ||
148 | case RT286_SET_PIN_DMIC1: | ||
149 | case RT286_SPK_EAPD: | ||
150 | case RT286_SET_AMP_GAIN_HPO: | ||
151 | case RT286_SET_DMIC2_DEFAULT: | ||
152 | case RT286_DACL_GAIN: | ||
153 | case RT286_DACR_GAIN: | ||
154 | case RT286_ADCL_GAIN: | ||
155 | case RT286_ADCR_GAIN: | ||
156 | case RT286_MIC_GAIN: | ||
157 | case RT286_SPOL_GAIN: | ||
158 | case RT286_SPOR_GAIN: | ||
159 | case RT286_HPOL_GAIN: | ||
160 | case RT286_HPOR_GAIN: | ||
161 | case RT286_F_DAC_SWITCH: | ||
162 | case RT286_F_RECMIX_SWITCH: | ||
163 | case RT286_REC_MIC_SWITCH: | ||
164 | case RT286_REC_I2S_SWITCH: | ||
165 | case RT286_REC_LINE_SWITCH: | ||
166 | case RT286_REC_BEEP_SWITCH: | ||
167 | case RT286_DAC_FORMAT: | ||
168 | case RT286_ADC_FORMAT: | ||
169 | case RT286_COEF_INDEX: | ||
170 | case RT286_PROC_COEF: | ||
171 | case RT286_SET_AMP_GAIN_ADC_IN1: | ||
172 | case RT286_SET_AMP_GAIN_ADC_IN2: | ||
173 | case RT286_SET_POWER(RT286_DAC_OUT1): | ||
174 | case RT286_SET_POWER(RT286_DAC_OUT2): | ||
175 | case RT286_SET_POWER(RT286_ADC_IN1): | ||
176 | case RT286_SET_POWER(RT286_ADC_IN2): | ||
177 | case RT286_SET_POWER(RT286_DMIC2): | ||
178 | case RT286_SET_POWER(RT286_MIC1): | ||
179 | return true; | ||
180 | default: | ||
181 | return false; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | static int rt286_hw_write(void *context, unsigned int reg, unsigned int value) | ||
186 | { | ||
187 | struct i2c_client *client = context; | ||
188 | struct rt286_priv *rt286 = i2c_get_clientdata(client); | ||
189 | u8 data[4]; | ||
190 | int ret, i; | ||
191 | |||
192 | /*handle index registers*/ | ||
193 | if (reg <= 0xff) { | ||
194 | rt286_hw_write(client, RT286_COEF_INDEX, reg); | ||
195 | reg = RT286_PROC_COEF; | ||
196 | for (i = 0; i < INDEX_CACHE_SIZE; i++) { | ||
197 | if (reg == rt286->index_cache[i].reg) { | ||
198 | rt286->index_cache[i].def = value; | ||
199 | break; | ||
200 | } | ||
201 | |||
202 | } | ||
203 | } | ||
204 | |||
205 | data[0] = (reg >> 24) & 0xff; | ||
206 | data[1] = (reg >> 16) & 0xff; | ||
207 | /* | ||
208 | * 4 bit VID: reg should be 0 | ||
209 | * 12 bit VID: value should be 0 | ||
210 | * So we use an OR operator to handle it rather than use if condition. | ||
211 | */ | ||
212 | data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff); | ||
213 | data[3] = value & 0xff; | ||
214 | |||
215 | ret = i2c_master_send(client, data, 4); | ||
216 | |||
217 | if (ret == 4) | ||
218 | return 0; | ||
219 | else | ||
220 | pr_err("ret=%d\n", ret); | ||
221 | if (ret < 0) | ||
222 | return ret; | ||
223 | else | ||
224 | return -EIO; | ||
225 | } | ||
226 | |||
227 | static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value) | ||
228 | { | ||
229 | struct i2c_client *client = context; | ||
230 | struct i2c_msg xfer[2]; | ||
231 | int ret; | ||
232 | __be32 be_reg; | ||
233 | unsigned int index, vid, buf = 0x0; | ||
234 | |||
235 | /*handle index registers*/ | ||
236 | if (reg <= 0xff) { | ||
237 | rt286_hw_write(client, RT286_COEF_INDEX, reg); | ||
238 | reg = RT286_PROC_COEF; | ||
239 | } | ||
240 | |||
241 | reg = reg | 0x80000; | ||
242 | vid = (reg >> 8) & 0xfff; | ||
243 | |||
244 | if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) { | ||
245 | index = (reg >> 8) & 0xf; | ||
246 | reg = (reg & ~0xf0f) | index; | ||
247 | } | ||
248 | be_reg = cpu_to_be32(reg); | ||
249 | |||
250 | /* Write register */ | ||
251 | xfer[0].addr = client->addr; | ||
252 | xfer[0].flags = 0; | ||
253 | xfer[0].len = 4; | ||
254 | xfer[0].buf = (u8 *)&be_reg; | ||
255 | |||
256 | /* Read data */ | ||
257 | xfer[1].addr = client->addr; | ||
258 | xfer[1].flags = I2C_M_RD; | ||
259 | xfer[1].len = 4; | ||
260 | xfer[1].buf = (u8 *)&buf; | ||
261 | |||
262 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
263 | if (ret < 0) | ||
264 | return ret; | ||
265 | else if (ret != 2) | ||
266 | return -EIO; | ||
267 | |||
268 | *value = be32_to_cpu(buf); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static void rt286_index_sync(struct snd_soc_codec *codec) | ||
274 | { | ||
275 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
276 | int i; | ||
277 | |||
278 | for (i = 0; i < INDEX_CACHE_SIZE; i++) { | ||
279 | snd_soc_write(codec, rt286->index_cache[i].reg, | ||
280 | rt286->index_cache[i].def); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static int rt286_support_power_controls[] = { | ||
285 | RT286_DAC_OUT1, | ||
286 | RT286_DAC_OUT2, | ||
287 | RT286_ADC_IN1, | ||
288 | RT286_ADC_IN2, | ||
289 | RT286_MIC1, | ||
290 | RT286_DMIC1, | ||
291 | RT286_DMIC2, | ||
292 | RT286_SPK_OUT, | ||
293 | RT286_HP_OUT, | ||
294 | }; | ||
295 | #define RT286_POWER_REG_LEN ARRAY_SIZE(rt286_support_power_controls) | ||
296 | |||
297 | static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | ||
298 | { | ||
299 | unsigned int val, buf; | ||
300 | int i; | ||
301 | |||
302 | *hp = false; | ||
303 | *mic = false; | ||
304 | |||
305 | if (rt286->pdata.cbj_en) { | ||
306 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); | ||
307 | *hp = buf & 0x80000000; | ||
308 | if (*hp) { | ||
309 | /* power on HV,VERF */ | ||
310 | regmap_update_bits(rt286->regmap, | ||
311 | RT286_POWER_CTRL1, 0x1001, 0x0); | ||
312 | /* power LDO1 */ | ||
313 | regmap_update_bits(rt286->regmap, | ||
314 | RT286_POWER_CTRL2, 0x4, 0x4); | ||
315 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); | ||
316 | regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val); | ||
317 | |||
318 | msleep(200); | ||
319 | i = 40; | ||
320 | while (((val & 0x0800) == 0) && (i > 0)) { | ||
321 | regmap_read(rt286->regmap, | ||
322 | RT286_CBJ_CTRL2, &val); | ||
323 | i--; | ||
324 | msleep(20); | ||
325 | } | ||
326 | |||
327 | if (0x0400 == (val & 0x0700)) { | ||
328 | *mic = false; | ||
329 | |||
330 | regmap_write(rt286->regmap, | ||
331 | RT286_SET_MIC1, 0x20); | ||
332 | /* power off HV,VERF */ | ||
333 | regmap_update_bits(rt286->regmap, | ||
334 | RT286_POWER_CTRL1, 0x1001, 0x1001); | ||
335 | regmap_update_bits(rt286->regmap, | ||
336 | RT286_A_BIAS_CTRL3, 0xc000, 0x0000); | ||
337 | regmap_update_bits(rt286->regmap, | ||
338 | RT286_CBJ_CTRL1, 0x0030, 0x0000); | ||
339 | regmap_update_bits(rt286->regmap, | ||
340 | RT286_A_BIAS_CTRL2, 0xc000, 0x0000); | ||
341 | } else if ((0x0200 == (val & 0x0700)) || | ||
342 | (0x0100 == (val & 0x0700))) { | ||
343 | *mic = true; | ||
344 | regmap_update_bits(rt286->regmap, | ||
345 | RT286_A_BIAS_CTRL3, 0xc000, 0x8000); | ||
346 | regmap_update_bits(rt286->regmap, | ||
347 | RT286_CBJ_CTRL1, 0x0030, 0x0020); | ||
348 | regmap_update_bits(rt286->regmap, | ||
349 | RT286_A_BIAS_CTRL2, 0xc000, 0x8000); | ||
350 | } else { | ||
351 | *mic = false; | ||
352 | } | ||
353 | |||
354 | regmap_update_bits(rt286->regmap, | ||
355 | RT286_MISC_CTRL1, | ||
356 | 0x0060, 0x0000); | ||
357 | } else { | ||
358 | regmap_update_bits(rt286->regmap, | ||
359 | RT286_MISC_CTRL1, | ||
360 | 0x0060, 0x0020); | ||
361 | regmap_update_bits(rt286->regmap, | ||
362 | RT286_A_BIAS_CTRL3, | ||
363 | 0xc000, 0x8000); | ||
364 | regmap_update_bits(rt286->regmap, | ||
365 | RT286_CBJ_CTRL1, | ||
366 | 0x0030, 0x0020); | ||
367 | regmap_update_bits(rt286->regmap, | ||
368 | RT286_A_BIAS_CTRL2, | ||
369 | 0xc000, 0x8000); | ||
370 | |||
371 | *mic = false; | ||
372 | } | ||
373 | } else { | ||
374 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); | ||
375 | *hp = buf & 0x80000000; | ||
376 | regmap_read(rt286->regmap, RT286_GET_MIC1_SENSE, &buf); | ||
377 | *mic = buf & 0x80000000; | ||
378 | } | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static void rt286_jack_detect_work(struct work_struct *work) | ||
384 | { | ||
385 | struct rt286_priv *rt286 = | ||
386 | container_of(work, struct rt286_priv, jack_detect_work.work); | ||
387 | int status = 0; | ||
388 | bool hp = false; | ||
389 | bool mic = false; | ||
390 | |||
391 | rt286_jack_detect(rt286, &hp, &mic); | ||
392 | |||
393 | if (hp == true) | ||
394 | status |= SND_JACK_HEADPHONE; | ||
395 | |||
396 | if (mic == true) | ||
397 | status |= SND_JACK_MICROPHONE; | ||
398 | |||
399 | snd_soc_jack_report(rt286->jack, status, | ||
400 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
401 | } | ||
402 | |||
403 | int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | ||
404 | { | ||
405 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
406 | |||
407 | rt286->jack = jack; | ||
408 | |||
409 | /* Send an initial empty report */ | ||
410 | snd_soc_jack_report(rt286->jack, 0, | ||
411 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | EXPORT_SYMBOL_GPL(rt286_mic_detect); | ||
416 | |||
417 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); | ||
418 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); | ||
419 | |||
420 | static const struct snd_kcontrol_new rt286_snd_controls[] = { | ||
421 | SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT286_DACL_GAIN, | ||
422 | RT286_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv), | ||
423 | SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT286_ADCL_GAIN, | ||
424 | RT286_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv), | ||
425 | SOC_SINGLE_TLV("AMIC Volume", RT286_MIC_GAIN, | ||
426 | 0, 0x3, 0, mic_vol_tlv), | ||
427 | SOC_DOUBLE_R("Speaker Playback Switch", RT286_SPOL_GAIN, | ||
428 | RT286_SPOR_GAIN, RT286_MUTE_SFT, 1, 1), | ||
429 | }; | ||
430 | |||
431 | /* Digital Mixer */ | ||
432 | static const struct snd_kcontrol_new rt286_front_mix[] = { | ||
433 | SOC_DAPM_SINGLE("DAC Switch", RT286_F_DAC_SWITCH, | ||
434 | RT286_MUTE_SFT, 1, 1), | ||
435 | SOC_DAPM_SINGLE("RECMIX Switch", RT286_F_RECMIX_SWITCH, | ||
436 | RT286_MUTE_SFT, 1, 1), | ||
437 | }; | ||
438 | |||
439 | /* Analog Input Mixer */ | ||
440 | static const struct snd_kcontrol_new rt286_rec_mix[] = { | ||
441 | SOC_DAPM_SINGLE("Mic1 Switch", RT286_REC_MIC_SWITCH, | ||
442 | RT286_MUTE_SFT, 1, 1), | ||
443 | SOC_DAPM_SINGLE("I2S Switch", RT286_REC_I2S_SWITCH, | ||
444 | RT286_MUTE_SFT, 1, 1), | ||
445 | SOC_DAPM_SINGLE("Line1 Switch", RT286_REC_LINE_SWITCH, | ||
446 | RT286_MUTE_SFT, 1, 1), | ||
447 | SOC_DAPM_SINGLE("Beep Switch", RT286_REC_BEEP_SWITCH, | ||
448 | RT286_MUTE_SFT, 1, 1), | ||
449 | }; | ||
450 | |||
451 | static const struct snd_kcontrol_new spo_enable_control = | ||
452 | SOC_DAPM_SINGLE("Switch", RT286_SET_PIN_SPK, | ||
453 | RT286_SET_PIN_SFT, 1, 0); | ||
454 | |||
455 | static const struct snd_kcontrol_new hpol_enable_control = | ||
456 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT286_HPOL_GAIN, | ||
457 | RT286_MUTE_SFT, 1, 1); | ||
458 | |||
459 | static const struct snd_kcontrol_new hpor_enable_control = | ||
460 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT286_HPOR_GAIN, | ||
461 | RT286_MUTE_SFT, 1, 1); | ||
462 | |||
463 | /* ADC0 source */ | ||
464 | static const char * const rt286_adc_src[] = { | ||
465 | "Mic", "RECMIX", "Dmic" | ||
466 | }; | ||
467 | |||
468 | static const int rt286_adc_values[] = { | ||
469 | 0, 4, 5, | ||
470 | }; | ||
471 | |||
472 | static SOC_VALUE_ENUM_SINGLE_DECL( | ||
473 | rt286_adc0_enum, RT286_ADC0_MUX, RT286_ADC_SEL_SFT, | ||
474 | RT286_ADC_SEL_MASK, rt286_adc_src, rt286_adc_values); | ||
475 | |||
476 | static const struct snd_kcontrol_new rt286_adc0_mux = | ||
477 | SOC_DAPM_ENUM("ADC 0 source", rt286_adc0_enum); | ||
478 | |||
479 | static SOC_VALUE_ENUM_SINGLE_DECL( | ||
480 | rt286_adc1_enum, RT286_ADC1_MUX, RT286_ADC_SEL_SFT, | ||
481 | RT286_ADC_SEL_MASK, rt286_adc_src, rt286_adc_values); | ||
482 | |||
483 | static const struct snd_kcontrol_new rt286_adc1_mux = | ||
484 | SOC_DAPM_ENUM("ADC 1 source", rt286_adc1_enum); | ||
485 | |||
486 | static const char * const rt286_dac_src[] = { | ||
487 | "Front", "Surround" | ||
488 | }; | ||
489 | /* HP-OUT source */ | ||
490 | static SOC_ENUM_SINGLE_DECL(rt286_hpo_enum, RT286_HPO_MUX, | ||
491 | 0, rt286_dac_src); | ||
492 | |||
493 | static const struct snd_kcontrol_new rt286_hpo_mux = | ||
494 | SOC_DAPM_ENUM("HPO source", rt286_hpo_enum); | ||
495 | |||
496 | /* SPK-OUT source */ | ||
497 | static SOC_ENUM_SINGLE_DECL(rt286_spo_enum, RT286_SPK_MUX, | ||
498 | 0, rt286_dac_src); | ||
499 | |||
500 | static const struct snd_kcontrol_new rt286_spo_mux = | ||
501 | SOC_DAPM_ENUM("SPO source", rt286_spo_enum); | ||
502 | |||
503 | static int rt286_spk_event(struct snd_soc_dapm_widget *w, | ||
504 | struct snd_kcontrol *kcontrol, int event) | ||
505 | { | ||
506 | struct snd_soc_codec *codec = w->codec; | ||
507 | |||
508 | switch (event) { | ||
509 | case SND_SOC_DAPM_POST_PMU: | ||
510 | snd_soc_write(codec, | ||
511 | RT286_SPK_EAPD, RT286_SET_EAPD_HIGH); | ||
512 | break; | ||
513 | case SND_SOC_DAPM_PRE_PMD: | ||
514 | snd_soc_write(codec, | ||
515 | RT286_SPK_EAPD, RT286_SET_EAPD_LOW); | ||
516 | break; | ||
517 | |||
518 | default: | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w, | ||
526 | struct snd_kcontrol *kcontrol, int event) | ||
527 | { | ||
528 | struct snd_soc_codec *codec = w->codec; | ||
529 | |||
530 | switch (event) { | ||
531 | case SND_SOC_DAPM_POST_PMU: | ||
532 | snd_soc_write(codec, RT286_SET_PIN_DMIC1, 0x20); | ||
533 | break; | ||
534 | case SND_SOC_DAPM_PRE_PMD: | ||
535 | snd_soc_write(codec, RT286_SET_PIN_DMIC1, 0); | ||
536 | break; | ||
537 | default: | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static int rt286_adc_event(struct snd_soc_dapm_widget *w, | ||
545 | struct snd_kcontrol *kcontrol, int event) | ||
546 | { | ||
547 | struct snd_soc_codec *codec = w->codec; | ||
548 | unsigned int nid; | ||
549 | |||
550 | nid = (w->reg >> 20) & 0xff; | ||
551 | |||
552 | switch (event) { | ||
553 | case SND_SOC_DAPM_POST_PMU: | ||
554 | snd_soc_update_bits(codec, | ||
555 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
556 | 0x7080, 0x7000); | ||
557 | break; | ||
558 | case SND_SOC_DAPM_PRE_PMD: | ||
559 | snd_soc_update_bits(codec, | ||
560 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
561 | 0x7080, 0x7080); | ||
562 | break; | ||
563 | default: | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { | ||
571 | /* Input Lines */ | ||
572 | SND_SOC_DAPM_INPUT("DMIC1 Pin"), | ||
573 | SND_SOC_DAPM_INPUT("DMIC2 Pin"), | ||
574 | SND_SOC_DAPM_INPUT("MIC1"), | ||
575 | SND_SOC_DAPM_INPUT("LINE1"), | ||
576 | SND_SOC_DAPM_INPUT("Beep"), | ||
577 | |||
578 | /* DMIC */ | ||
579 | SND_SOC_DAPM_PGA_E("DMIC1", RT286_SET_POWER(RT286_DMIC1), 0, 1, | ||
580 | NULL, 0, rt286_set_dmic1_event, | ||
581 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
582 | SND_SOC_DAPM_PGA("DMIC2", RT286_SET_POWER(RT286_DMIC2), 0, 1, | ||
583 | NULL, 0), | ||
584 | SND_SOC_DAPM_SUPPLY("DMIC Receiver", SND_SOC_NOPM, | ||
585 | 0, 0, NULL, 0), | ||
586 | |||
587 | /* REC Mixer */ | ||
588 | SND_SOC_DAPM_MIXER("RECMIX", SND_SOC_NOPM, 0, 0, | ||
589 | rt286_rec_mix, ARRAY_SIZE(rt286_rec_mix)), | ||
590 | |||
591 | /* ADCs */ | ||
592 | SND_SOC_DAPM_ADC("ADC 0", NULL, SND_SOC_NOPM, 0, 0), | ||
593 | SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), | ||
594 | |||
595 | /* ADC Mux */ | ||
596 | SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT286_SET_POWER(RT286_ADC_IN1), 0, 1, | ||
597 | &rt286_adc0_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD | | ||
598 | SND_SOC_DAPM_POST_PMU), | ||
599 | SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT286_SET_POWER(RT286_ADC_IN2), 0, 1, | ||
600 | &rt286_adc1_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD | | ||
601 | SND_SOC_DAPM_POST_PMU), | ||
602 | |||
603 | /* Audio Interface */ | ||
604 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
605 | SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
606 | SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
607 | SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
608 | |||
609 | /* Output Side */ | ||
610 | /* DACs */ | ||
611 | SND_SOC_DAPM_DAC("DAC 0", NULL, SND_SOC_NOPM, 0, 0), | ||
612 | SND_SOC_DAPM_DAC("DAC 1", NULL, SND_SOC_NOPM, 0, 0), | ||
613 | |||
614 | /* Output Mux */ | ||
615 | SND_SOC_DAPM_MUX("SPK Mux", SND_SOC_NOPM, 0, 0, &rt286_spo_mux), | ||
616 | SND_SOC_DAPM_MUX("HPO Mux", SND_SOC_NOPM, 0, 0, &rt286_hpo_mux), | ||
617 | |||
618 | SND_SOC_DAPM_SUPPLY("HP Power", RT286_SET_PIN_HPO, | ||
619 | RT286_SET_PIN_SFT, 0, NULL, 0), | ||
620 | |||
621 | /* Output Mixer */ | ||
622 | SND_SOC_DAPM_MIXER("Front", RT286_SET_POWER(RT286_DAC_OUT1), 0, 1, | ||
623 | rt286_front_mix, ARRAY_SIZE(rt286_front_mix)), | ||
624 | SND_SOC_DAPM_PGA("Surround", RT286_SET_POWER(RT286_DAC_OUT2), 0, 1, | ||
625 | NULL, 0), | ||
626 | |||
627 | /* Output Pga */ | ||
628 | SND_SOC_DAPM_SWITCH_E("SPO", SND_SOC_NOPM, 0, 0, | ||
629 | &spo_enable_control, rt286_spk_event, | ||
630 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
631 | SND_SOC_DAPM_SWITCH("HPO L", SND_SOC_NOPM, 0, 0, | ||
632 | &hpol_enable_control), | ||
633 | SND_SOC_DAPM_SWITCH("HPO R", SND_SOC_NOPM, 0, 0, | ||
634 | &hpor_enable_control), | ||
635 | |||
636 | /* Output Lines */ | ||
637 | SND_SOC_DAPM_OUTPUT("SPOL"), | ||
638 | SND_SOC_DAPM_OUTPUT("SPOR"), | ||
639 | SND_SOC_DAPM_OUTPUT("HPO Pin"), | ||
640 | SND_SOC_DAPM_OUTPUT("SPDIF"), | ||
641 | }; | ||
642 | |||
643 | static const struct snd_soc_dapm_route rt286_dapm_routes[] = { | ||
644 | {"DMIC1", NULL, "DMIC1 Pin"}, | ||
645 | {"DMIC2", NULL, "DMIC2 Pin"}, | ||
646 | {"DMIC1", NULL, "DMIC Receiver"}, | ||
647 | {"DMIC2", NULL, "DMIC Receiver"}, | ||
648 | |||
649 | {"RECMIX", "Beep Switch", "Beep"}, | ||
650 | {"RECMIX", "Line1 Switch", "LINE1"}, | ||
651 | {"RECMIX", "Mic1 Switch", "MIC1"}, | ||
652 | |||
653 | {"ADC 0 Mux", "Dmic", "DMIC1"}, | ||
654 | {"ADC 0 Mux", "RECMIX", "RECMIX"}, | ||
655 | {"ADC 0 Mux", "Mic", "MIC1"}, | ||
656 | {"ADC 1 Mux", "Dmic", "DMIC2"}, | ||
657 | {"ADC 1 Mux", "RECMIX", "RECMIX"}, | ||
658 | {"ADC 1 Mux", "Mic", "MIC1"}, | ||
659 | |||
660 | {"ADC 0", NULL, "ADC 0 Mux"}, | ||
661 | {"ADC 1", NULL, "ADC 1 Mux"}, | ||
662 | |||
663 | {"AIF1TX", NULL, "ADC 0"}, | ||
664 | {"AIF2TX", NULL, "ADC 1"}, | ||
665 | |||
666 | {"DAC 0", NULL, "AIF1RX"}, | ||
667 | {"DAC 1", NULL, "AIF2RX"}, | ||
668 | |||
669 | {"Front", "DAC Switch", "DAC 0"}, | ||
670 | {"Front", "RECMIX Switch", "RECMIX"}, | ||
671 | |||
672 | {"Surround", NULL, "DAC 1"}, | ||
673 | |||
674 | {"SPK Mux", "Front", "Front"}, | ||
675 | {"SPK Mux", "Surround", "Surround"}, | ||
676 | |||
677 | {"HPO Mux", "Front", "Front"}, | ||
678 | {"HPO Mux", "Surround", "Surround"}, | ||
679 | |||
680 | {"SPO", "Switch", "SPK Mux"}, | ||
681 | {"HPO L", "Switch", "HPO Mux"}, | ||
682 | {"HPO R", "Switch", "HPO Mux"}, | ||
683 | {"HPO L", NULL, "HP Power"}, | ||
684 | {"HPO R", NULL, "HP Power"}, | ||
685 | |||
686 | {"SPOL", NULL, "SPO"}, | ||
687 | {"SPOR", NULL, "SPO"}, | ||
688 | {"HPO Pin", NULL, "HPO L"}, | ||
689 | {"HPO Pin", NULL, "HPO R"}, | ||
690 | }; | ||
691 | |||
692 | static int rt286_hw_params(struct snd_pcm_substream *substream, | ||
693 | struct snd_pcm_hw_params *params, | ||
694 | struct snd_soc_dai *dai) | ||
695 | { | ||
696 | struct snd_soc_codec *codec = dai->codec; | ||
697 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
698 | unsigned int val = 0; | ||
699 | int d_len_code; | ||
700 | |||
701 | switch (params_rate(params)) { | ||
702 | /* bit 14 0:48K 1:44.1K */ | ||
703 | case 44100: | ||
704 | val |= 0x4000; | ||
705 | break; | ||
706 | case 48000: | ||
707 | break; | ||
708 | default: | ||
709 | dev_err(codec->dev, "Unsupported sample rate %d\n", | ||
710 | params_rate(params)); | ||
711 | return -EINVAL; | ||
712 | } | ||
713 | switch (rt286->sys_clk) { | ||
714 | case 12288000: | ||
715 | case 24576000: | ||
716 | if (params_rate(params) != 48000) { | ||
717 | dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n", | ||
718 | params_rate(params), rt286->sys_clk); | ||
719 | return -EINVAL; | ||
720 | } | ||
721 | break; | ||
722 | case 11289600: | ||
723 | case 22579200: | ||
724 | if (params_rate(params) != 44100) { | ||
725 | dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n", | ||
726 | params_rate(params), rt286->sys_clk); | ||
727 | return -EINVAL; | ||
728 | } | ||
729 | break; | ||
730 | } | ||
731 | |||
732 | if (params_channels(params) <= 16) { | ||
733 | /* bit 3:0 Number of Channel */ | ||
734 | val |= (params_channels(params) - 1); | ||
735 | } else { | ||
736 | dev_err(codec->dev, "Unsupported channels %d\n", | ||
737 | params_channels(params)); | ||
738 | return -EINVAL; | ||
739 | } | ||
740 | |||
741 | d_len_code = 0; | ||
742 | switch (params_width(params)) { | ||
743 | /* bit 6:4 Bits per Sample */ | ||
744 | case 16: | ||
745 | d_len_code = 0; | ||
746 | val |= (0x1 << 4); | ||
747 | break; | ||
748 | case 32: | ||
749 | d_len_code = 2; | ||
750 | val |= (0x4 << 4); | ||
751 | break; | ||
752 | case 20: | ||
753 | d_len_code = 1; | ||
754 | val |= (0x2 << 4); | ||
755 | break; | ||
756 | case 24: | ||
757 | d_len_code = 2; | ||
758 | val |= (0x3 << 4); | ||
759 | break; | ||
760 | case 8: | ||
761 | d_len_code = 3; | ||
762 | break; | ||
763 | default: | ||
764 | return -EINVAL; | ||
765 | } | ||
766 | |||
767 | snd_soc_update_bits(codec, | ||
768 | RT286_I2S_CTRL1, 0x0018, d_len_code << 3); | ||
769 | dev_dbg(codec->dev, "format val = 0x%x\n", val); | ||
770 | |||
771 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
772 | snd_soc_update_bits(codec, RT286_DAC_FORMAT, 0x407f, val); | ||
773 | else | ||
774 | snd_soc_update_bits(codec, RT286_ADC_FORMAT, 0x407f, val); | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static int rt286_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
780 | { | ||
781 | struct snd_soc_codec *codec = dai->codec; | ||
782 | |||
783 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
784 | case SND_SOC_DAIFMT_CBM_CFM: | ||
785 | snd_soc_update_bits(codec, | ||
786 | RT286_I2S_CTRL1, 0x800, 0x800); | ||
787 | break; | ||
788 | case SND_SOC_DAIFMT_CBS_CFS: | ||
789 | snd_soc_update_bits(codec, | ||
790 | RT286_I2S_CTRL1, 0x800, 0x0); | ||
791 | break; | ||
792 | default: | ||
793 | return -EINVAL; | ||
794 | } | ||
795 | |||
796 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
797 | case SND_SOC_DAIFMT_I2S: | ||
798 | snd_soc_update_bits(codec, | ||
799 | RT286_I2S_CTRL1, 0x300, 0x0); | ||
800 | break; | ||
801 | case SND_SOC_DAIFMT_LEFT_J: | ||
802 | snd_soc_update_bits(codec, | ||
803 | RT286_I2S_CTRL1, 0x300, 0x1 << 8); | ||
804 | break; | ||
805 | case SND_SOC_DAIFMT_DSP_A: | ||
806 | snd_soc_update_bits(codec, | ||
807 | RT286_I2S_CTRL1, 0x300, 0x2 << 8); | ||
808 | break; | ||
809 | case SND_SOC_DAIFMT_DSP_B: | ||
810 | snd_soc_update_bits(codec, | ||
811 | RT286_I2S_CTRL1, 0x300, 0x3 << 8); | ||
812 | break; | ||
813 | default: | ||
814 | return -EINVAL; | ||
815 | } | ||
816 | /* bit 15 Stream Type 0:PCM 1:Non-PCM */ | ||
817 | snd_soc_update_bits(codec, RT286_DAC_FORMAT, 0x8000, 0); | ||
818 | snd_soc_update_bits(codec, RT286_ADC_FORMAT, 0x8000, 0); | ||
819 | |||
820 | return 0; | ||
821 | } | ||
822 | |||
823 | static int rt286_set_dai_sysclk(struct snd_soc_dai *dai, | ||
824 | int clk_id, unsigned int freq, int dir) | ||
825 | { | ||
826 | struct snd_soc_codec *codec = dai->codec; | ||
827 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
828 | |||
829 | dev_dbg(codec->dev, "%s freq=%d\n", __func__, freq); | ||
830 | |||
831 | if (RT286_SCLK_S_MCLK == clk_id) { | ||
832 | snd_soc_update_bits(codec, | ||
833 | RT286_I2S_CTRL2, 0x0100, 0x0); | ||
834 | snd_soc_update_bits(codec, | ||
835 | RT286_PLL_CTRL1, 0x20, 0x20); | ||
836 | } else { | ||
837 | snd_soc_update_bits(codec, | ||
838 | RT286_I2S_CTRL2, 0x0100, 0x0100); | ||
839 | snd_soc_update_bits(codec, | ||
840 | RT286_PLL_CTRL, 0x4, 0x4); | ||
841 | snd_soc_update_bits(codec, | ||
842 | RT286_PLL_CTRL1, 0x20, 0x0); | ||
843 | } | ||
844 | |||
845 | switch (freq) { | ||
846 | case 19200000: | ||
847 | if (RT286_SCLK_S_MCLK == clk_id) { | ||
848 | dev_err(codec->dev, "Should not use MCLK\n"); | ||
849 | return -EINVAL; | ||
850 | } | ||
851 | snd_soc_update_bits(codec, | ||
852 | RT286_I2S_CTRL2, 0x40, 0x40); | ||
853 | break; | ||
854 | case 24000000: | ||
855 | if (RT286_SCLK_S_MCLK == clk_id) { | ||
856 | dev_err(codec->dev, "Should not use MCLK\n"); | ||
857 | return -EINVAL; | ||
858 | } | ||
859 | snd_soc_update_bits(codec, | ||
860 | RT286_I2S_CTRL2, 0x40, 0x0); | ||
861 | break; | ||
862 | case 12288000: | ||
863 | case 11289600: | ||
864 | snd_soc_update_bits(codec, | ||
865 | RT286_I2S_CTRL2, 0x8, 0x0); | ||
866 | snd_soc_update_bits(codec, | ||
867 | RT286_CLK_DIV, 0xfc1e, 0x0004); | ||
868 | break; | ||
869 | case 24576000: | ||
870 | case 22579200: | ||
871 | snd_soc_update_bits(codec, | ||
872 | RT286_I2S_CTRL2, 0x8, 0x8); | ||
873 | snd_soc_update_bits(codec, | ||
874 | RT286_CLK_DIV, 0xfc1e, 0x5406); | ||
875 | break; | ||
876 | default: | ||
877 | dev_err(codec->dev, "Unsupported system clock\n"); | ||
878 | return -EINVAL; | ||
879 | } | ||
880 | |||
881 | rt286->sys_clk = freq; | ||
882 | |||
883 | return 0; | ||
884 | } | ||
885 | |||
886 | static int rt286_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) | ||
887 | { | ||
888 | struct snd_soc_codec *codec = dai->codec; | ||
889 | |||
890 | dev_dbg(codec->dev, "%s ratio=%d\n", __func__, ratio); | ||
891 | if (50 == ratio) | ||
892 | snd_soc_update_bits(codec, | ||
893 | RT286_I2S_CTRL1, 0x1000, 0x1000); | ||
894 | else | ||
895 | snd_soc_update_bits(codec, | ||
896 | RT286_I2S_CTRL1, 0x1000, 0x0); | ||
897 | |||
898 | |||
899 | return 0; | ||
900 | } | ||
901 | |||
902 | static int rt286_set_bias_level(struct snd_soc_codec *codec, | ||
903 | enum snd_soc_bias_level level) | ||
904 | { | ||
905 | switch (level) { | ||
906 | case SND_SOC_BIAS_PREPARE: | ||
907 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { | ||
908 | snd_soc_write(codec, | ||
909 | RT286_SET_AUDIO_POWER, AC_PWRST_D0); | ||
910 | snd_soc_update_bits(codec, | ||
911 | RT286_DC_GAIN, 0x200, 0x200); | ||
912 | } | ||
913 | break; | ||
914 | |||
915 | case SND_SOC_BIAS_ON: | ||
916 | mdelay(10); | ||
917 | break; | ||
918 | |||
919 | case SND_SOC_BIAS_STANDBY: | ||
920 | snd_soc_write(codec, | ||
921 | RT286_SET_AUDIO_POWER, AC_PWRST_D3); | ||
922 | snd_soc_update_bits(codec, | ||
923 | RT286_DC_GAIN, 0x200, 0x0); | ||
924 | break; | ||
925 | |||
926 | default: | ||
927 | break; | ||
928 | } | ||
929 | codec->dapm.bias_level = level; | ||
930 | |||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | static irqreturn_t rt286_irq(int irq, void *data) | ||
935 | { | ||
936 | struct rt286_priv *rt286 = data; | ||
937 | bool hp = false; | ||
938 | bool mic = false; | ||
939 | int status = 0; | ||
940 | |||
941 | rt286_jack_detect(rt286, &hp, &mic); | ||
942 | |||
943 | /* Clear IRQ */ | ||
944 | regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x1, 0x1); | ||
945 | |||
946 | if (hp == true) | ||
947 | status |= SND_JACK_HEADPHONE; | ||
948 | |||
949 | if (mic == true) | ||
950 | status |= SND_JACK_MICROPHONE; | ||
951 | |||
952 | snd_soc_jack_report(rt286->jack, status, | ||
953 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
954 | |||
955 | pm_wakeup_event(&rt286->i2c->dev, 300); | ||
956 | |||
957 | return IRQ_HANDLED; | ||
958 | } | ||
959 | |||
960 | static int rt286_probe(struct snd_soc_codec *codec) | ||
961 | { | ||
962 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
963 | |||
964 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | ||
965 | |||
966 | if (rt286->i2c->irq) { | ||
967 | regmap_update_bits(rt286->regmap, | ||
968 | RT286_IRQ_CTRL, 0x2, 0x2); | ||
969 | |||
970 | INIT_DELAYED_WORK(&rt286->jack_detect_work, | ||
971 | rt286_jack_detect_work); | ||
972 | schedule_delayed_work(&rt286->jack_detect_work, | ||
973 | msecs_to_jiffies(1250)); | ||
974 | } | ||
975 | |||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | static int rt286_remove(struct snd_soc_codec *codec) | ||
980 | { | ||
981 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
982 | |||
983 | cancel_delayed_work_sync(&rt286->jack_detect_work); | ||
984 | |||
985 | return 0; | ||
986 | } | ||
987 | |||
988 | #ifdef CONFIG_PM | ||
989 | static int rt286_suspend(struct snd_soc_codec *codec) | ||
990 | { | ||
991 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
992 | |||
993 | regcache_cache_only(rt286->regmap, true); | ||
994 | regcache_mark_dirty(rt286->regmap); | ||
995 | |||
996 | return 0; | ||
997 | } | ||
998 | |||
999 | static int rt286_resume(struct snd_soc_codec *codec) | ||
1000 | { | ||
1001 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
1002 | |||
1003 | regcache_cache_only(rt286->regmap, false); | ||
1004 | rt286_index_sync(codec); | ||
1005 | regcache_sync(rt286->regmap); | ||
1006 | |||
1007 | return 0; | ||
1008 | } | ||
1009 | #else | ||
1010 | #define rt286_suspend NULL | ||
1011 | #define rt286_resume NULL | ||
1012 | #endif | ||
1013 | |||
1014 | #define RT286_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | ||
1015 | #define RT286_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
1016 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | ||
1017 | |||
1018 | static const struct snd_soc_dai_ops rt286_aif_dai_ops = { | ||
1019 | .hw_params = rt286_hw_params, | ||
1020 | .set_fmt = rt286_set_dai_fmt, | ||
1021 | .set_sysclk = rt286_set_dai_sysclk, | ||
1022 | .set_bclk_ratio = rt286_set_bclk_ratio, | ||
1023 | }; | ||
1024 | |||
1025 | static struct snd_soc_dai_driver rt286_dai[] = { | ||
1026 | { | ||
1027 | .name = "rt286-aif1", | ||
1028 | .id = RT286_AIF1, | ||
1029 | .playback = { | ||
1030 | .stream_name = "AIF1 Playback", | ||
1031 | .channels_min = 1, | ||
1032 | .channels_max = 2, | ||
1033 | .rates = RT286_STEREO_RATES, | ||
1034 | .formats = RT286_FORMATS, | ||
1035 | }, | ||
1036 | .capture = { | ||
1037 | .stream_name = "AIF1 Capture", | ||
1038 | .channels_min = 1, | ||
1039 | .channels_max = 2, | ||
1040 | .rates = RT286_STEREO_RATES, | ||
1041 | .formats = RT286_FORMATS, | ||
1042 | }, | ||
1043 | .ops = &rt286_aif_dai_ops, | ||
1044 | .symmetric_rates = 1, | ||
1045 | }, | ||
1046 | { | ||
1047 | .name = "rt286-aif2", | ||
1048 | .id = RT286_AIF2, | ||
1049 | .playback = { | ||
1050 | .stream_name = "AIF2 Playback", | ||
1051 | .channels_min = 1, | ||
1052 | .channels_max = 2, | ||
1053 | .rates = RT286_STEREO_RATES, | ||
1054 | .formats = RT286_FORMATS, | ||
1055 | }, | ||
1056 | .capture = { | ||
1057 | .stream_name = "AIF2 Capture", | ||
1058 | .channels_min = 1, | ||
1059 | .channels_max = 2, | ||
1060 | .rates = RT286_STEREO_RATES, | ||
1061 | .formats = RT286_FORMATS, | ||
1062 | }, | ||
1063 | .ops = &rt286_aif_dai_ops, | ||
1064 | .symmetric_rates = 1, | ||
1065 | }, | ||
1066 | |||
1067 | }; | ||
1068 | |||
1069 | static struct snd_soc_codec_driver soc_codec_dev_rt286 = { | ||
1070 | .probe = rt286_probe, | ||
1071 | .remove = rt286_remove, | ||
1072 | .suspend = rt286_suspend, | ||
1073 | .resume = rt286_resume, | ||
1074 | .set_bias_level = rt286_set_bias_level, | ||
1075 | .idle_bias_off = true, | ||
1076 | .controls = rt286_snd_controls, | ||
1077 | .num_controls = ARRAY_SIZE(rt286_snd_controls), | ||
1078 | .dapm_widgets = rt286_dapm_widgets, | ||
1079 | .num_dapm_widgets = ARRAY_SIZE(rt286_dapm_widgets), | ||
1080 | .dapm_routes = rt286_dapm_routes, | ||
1081 | .num_dapm_routes = ARRAY_SIZE(rt286_dapm_routes), | ||
1082 | }; | ||
1083 | |||
1084 | static const struct regmap_config rt286_regmap = { | ||
1085 | .reg_bits = 32, | ||
1086 | .val_bits = 32, | ||
1087 | .max_register = 0x02370100, | ||
1088 | .volatile_reg = rt286_volatile_register, | ||
1089 | .readable_reg = rt286_readable_register, | ||
1090 | .reg_write = rt286_hw_write, | ||
1091 | .reg_read = rt286_hw_read, | ||
1092 | .cache_type = REGCACHE_RBTREE, | ||
1093 | .reg_defaults = rt286_reg, | ||
1094 | .num_reg_defaults = ARRAY_SIZE(rt286_reg), | ||
1095 | }; | ||
1096 | |||
1097 | static const struct i2c_device_id rt286_i2c_id[] = { | ||
1098 | {"rt286", 0}, | ||
1099 | {} | ||
1100 | }; | ||
1101 | MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); | ||
1102 | |||
1103 | static const struct acpi_device_id rt286_acpi_match[] = { | ||
1104 | { "INT343A", 0 }, | ||
1105 | {}, | ||
1106 | }; | ||
1107 | MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); | ||
1108 | |||
1109 | static int rt286_i2c_probe(struct i2c_client *i2c, | ||
1110 | const struct i2c_device_id *id) | ||
1111 | { | ||
1112 | struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
1113 | struct rt286_priv *rt286; | ||
1114 | int i, ret; | ||
1115 | |||
1116 | rt286 = devm_kzalloc(&i2c->dev, sizeof(*rt286), | ||
1117 | GFP_KERNEL); | ||
1118 | if (NULL == rt286) | ||
1119 | return -ENOMEM; | ||
1120 | |||
1121 | rt286->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt286_regmap); | ||
1122 | if (IS_ERR(rt286->regmap)) { | ||
1123 | ret = PTR_ERR(rt286->regmap); | ||
1124 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
1125 | ret); | ||
1126 | return ret; | ||
1127 | } | ||
1128 | |||
1129 | regmap_read(rt286->regmap, | ||
1130 | RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret); | ||
1131 | if (ret != RT286_VENDOR_ID) { | ||
1132 | dev_err(&i2c->dev, | ||
1133 | "Device with ID register %x is not rt286\n", ret); | ||
1134 | return -ENODEV; | ||
1135 | } | ||
1136 | |||
1137 | rt286->index_cache = rt286_index_def; | ||
1138 | rt286->i2c = i2c; | ||
1139 | i2c_set_clientdata(i2c, rt286); | ||
1140 | |||
1141 | if (pdata) | ||
1142 | rt286->pdata = *pdata; | ||
1143 | |||
1144 | regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); | ||
1145 | |||
1146 | for (i = 0; i < RT286_POWER_REG_LEN; i++) | ||
1147 | regmap_write(rt286->regmap, | ||
1148 | RT286_SET_POWER(rt286_support_power_controls[i]), | ||
1149 | AC_PWRST_D1); | ||
1150 | |||
1151 | if (!rt286->pdata.cbj_en) { | ||
1152 | regmap_write(rt286->regmap, RT286_CBJ_CTRL2, 0x0000); | ||
1153 | regmap_write(rt286->regmap, RT286_MIC1_DET_CTRL, 0x0816); | ||
1154 | regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000); | ||
1155 | regmap_update_bits(rt286->regmap, | ||
1156 | RT286_CBJ_CTRL1, 0xf000, 0xb000); | ||
1157 | } else { | ||
1158 | regmap_update_bits(rt286->regmap, | ||
1159 | RT286_CBJ_CTRL1, 0xf000, 0x5000); | ||
1160 | } | ||
1161 | |||
1162 | mdelay(10); | ||
1163 | |||
1164 | if (!rt286->pdata.gpio2_en) | ||
1165 | regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0x4000); | ||
1166 | else | ||
1167 | regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0); | ||
1168 | |||
1169 | mdelay(10); | ||
1170 | |||
1171 | /*Power down LDO2*/ | ||
1172 | regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0x8, 0x0); | ||
1173 | |||
1174 | /*Set depop parameter*/ | ||
1175 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL2, 0x403a, 0x401a); | ||
1176 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); | ||
1177 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); | ||
1178 | |||
1179 | if (rt286->i2c->irq) { | ||
1180 | ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq, | ||
1181 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286); | ||
1182 | if (ret != 0) { | ||
1183 | dev_err(&i2c->dev, | ||
1184 | "Failed to reguest IRQ: %d\n", ret); | ||
1185 | return ret; | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt286, | ||
1190 | rt286_dai, ARRAY_SIZE(rt286_dai)); | ||
1191 | |||
1192 | return ret; | ||
1193 | } | ||
1194 | |||
1195 | static int rt286_i2c_remove(struct i2c_client *i2c) | ||
1196 | { | ||
1197 | struct rt286_priv *rt286 = i2c_get_clientdata(i2c); | ||
1198 | |||
1199 | if (i2c->irq) | ||
1200 | free_irq(i2c->irq, rt286); | ||
1201 | snd_soc_unregister_codec(&i2c->dev); | ||
1202 | |||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1206 | |||
1207 | static struct i2c_driver rt286_i2c_driver = { | ||
1208 | .driver = { | ||
1209 | .name = "rt286", | ||
1210 | .owner = THIS_MODULE, | ||
1211 | .acpi_match_table = ACPI_PTR(rt286_acpi_match), | ||
1212 | }, | ||
1213 | .probe = rt286_i2c_probe, | ||
1214 | .remove = rt286_i2c_remove, | ||
1215 | .id_table = rt286_i2c_id, | ||
1216 | }; | ||
1217 | |||
1218 | module_i2c_driver(rt286_i2c_driver); | ||
1219 | |||
1220 | MODULE_DESCRIPTION("ASoC RT286 driver"); | ||
1221 | MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>"); | ||
1222 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/rt286.h b/sound/soc/codecs/rt286.h new file mode 100644 index 000000000000..b539b7320a79 --- /dev/null +++ b/sound/soc/codecs/rt286.h | |||
@@ -0,0 +1,198 @@ | |||
1 | /* | ||
2 | * rt286.h -- RT286 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2011 Realtek Microelectronics | ||
5 | * Author: Johnny Hsu <johnnyhsu@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __RT286_H__ | ||
13 | #define __RT286_H__ | ||
14 | |||
15 | #define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D) | ||
16 | |||
17 | #define RT286_AUDIO_FUNCTION_GROUP 0x01 | ||
18 | #define RT286_DAC_OUT1 0x02 | ||
19 | #define RT286_DAC_OUT2 0x03 | ||
20 | #define RT286_ADC_IN1 0x09 | ||
21 | #define RT286_ADC_IN2 0x08 | ||
22 | #define RT286_MIXER_IN 0x0b | ||
23 | #define RT286_MIXER_OUT1 0x0c | ||
24 | #define RT286_MIXER_OUT2 0x0d | ||
25 | #define RT286_DMIC1 0x12 | ||
26 | #define RT286_DMIC2 0x13 | ||
27 | #define RT286_SPK_OUT 0x14 | ||
28 | #define RT286_MIC1 0x18 | ||
29 | #define RT286_LINE1 0x1a | ||
30 | #define RT286_BEEP 0x1d | ||
31 | #define RT286_SPDIF 0x1e | ||
32 | #define RT286_VENDOR_REGISTERS 0x20 | ||
33 | #define RT286_HP_OUT 0x21 | ||
34 | #define RT286_MIXER_IN1 0x22 | ||
35 | #define RT286_MIXER_IN2 0x23 | ||
36 | |||
37 | #define RT286_SET_PIN_SFT 6 | ||
38 | #define RT286_SET_PIN_ENABLE 0x40 | ||
39 | #define RT286_SET_PIN_DISABLE 0 | ||
40 | #define RT286_SET_EAPD_HIGH 0x2 | ||
41 | #define RT286_SET_EAPD_LOW 0 | ||
42 | |||
43 | #define RT286_MUTE_SFT 7 | ||
44 | |||
45 | /* Verb commands */ | ||
46 | #define RT286_GET_PARAM(NID, PARAM) VERB_CMD(AC_VERB_PARAMETERS, NID, PARAM) | ||
47 | #define RT286_SET_POWER(NID) VERB_CMD(AC_VERB_SET_POWER_STATE, NID, 0) | ||
48 | #define RT286_SET_AUDIO_POWER RT286_SET_POWER(RT286_AUDIO_FUNCTION_GROUP) | ||
49 | #define RT286_SET_HPO_POWER RT286_SET_POWER(RT286_HP_OUT) | ||
50 | #define RT286_SET_SPK_POWER RT286_SET_POWER(RT286_SPK_OUT) | ||
51 | #define RT286_SET_DMIC1_POWER RT286_SET_POWER(RT286_DMIC1) | ||
52 | #define RT286_SPK_MUX\ | ||
53 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_SPK_OUT, 0) | ||
54 | #define RT286_HPO_MUX\ | ||
55 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_HP_OUT, 0) | ||
56 | #define RT286_ADC0_MUX\ | ||
57 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN1, 0) | ||
58 | #define RT286_ADC1_MUX\ | ||
59 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN2, 0) | ||
60 | #define RT286_SET_MIC1\ | ||
61 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_MIC1, 0) | ||
62 | #define RT286_SET_PIN_HPO\ | ||
63 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_HP_OUT, 0) | ||
64 | #define RT286_SET_PIN_SPK\ | ||
65 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_SPK_OUT, 0) | ||
66 | #define RT286_SET_PIN_DMIC1\ | ||
67 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_DMIC1, 0) | ||
68 | #define RT286_SPK_EAPD\ | ||
69 | VERB_CMD(AC_VERB_SET_EAPD_BTLENABLE, RT286_SPK_OUT, 0) | ||
70 | #define RT286_SET_AMP_GAIN_HPO\ | ||
71 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0) | ||
72 | #define RT286_SET_AMP_GAIN_ADC_IN1\ | ||
73 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0) | ||
74 | #define RT286_SET_AMP_GAIN_ADC_IN2\ | ||
75 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN2, 0) | ||
76 | #define RT286_GET_HP_SENSE\ | ||
77 | VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_HP_OUT, 0) | ||
78 | #define RT286_GET_MIC1_SENSE\ | ||
79 | VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_MIC1, 0) | ||
80 | #define RT286_SET_DMIC2_DEFAULT\ | ||
81 | VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT286_DMIC2, 0) | ||
82 | #define RT286_DACL_GAIN\ | ||
83 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0xa000) | ||
84 | #define RT286_DACR_GAIN\ | ||
85 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0x9000) | ||
86 | #define RT286_ADCL_GAIN\ | ||
87 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x6000) | ||
88 | #define RT286_ADCR_GAIN\ | ||
89 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x5000) | ||
90 | #define RT286_MIC_GAIN\ | ||
91 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIC1, 0x7000) | ||
92 | #define RT286_SPOL_GAIN\ | ||
93 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0xa000) | ||
94 | #define RT286_SPOR_GAIN\ | ||
95 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0x9000) | ||
96 | #define RT286_HPOL_GAIN\ | ||
97 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0xa000) | ||
98 | #define RT286_HPOR_GAIN\ | ||
99 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0x9000) | ||
100 | #define RT286_F_DAC_SWITCH\ | ||
101 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7000) | ||
102 | #define RT286_F_RECMIX_SWITCH\ | ||
103 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7100) | ||
104 | #define RT286_REC_MIC_SWITCH\ | ||
105 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7000) | ||
106 | #define RT286_REC_I2S_SWITCH\ | ||
107 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7100) | ||
108 | #define RT286_REC_LINE_SWITCH\ | ||
109 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7200) | ||
110 | #define RT286_REC_BEEP_SWITCH\ | ||
111 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7300) | ||
112 | #define RT286_DAC_FORMAT\ | ||
113 | VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_DAC_OUT1, 0) | ||
114 | #define RT286_ADC_FORMAT\ | ||
115 | VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_ADC_IN1, 0) | ||
116 | #define RT286_COEF_INDEX\ | ||
117 | VERB_CMD(AC_VERB_SET_COEF_INDEX, RT286_VENDOR_REGISTERS, 0) | ||
118 | #define RT286_PROC_COEF\ | ||
119 | VERB_CMD(AC_VERB_SET_PROC_COEF, RT286_VENDOR_REGISTERS, 0) | ||
120 | |||
121 | /* Index registers */ | ||
122 | #define RT286_A_BIAS_CTRL1 0x01 | ||
123 | #define RT286_A_BIAS_CTRL2 0x02 | ||
124 | #define RT286_POWER_CTRL1 0x03 | ||
125 | #define RT286_A_BIAS_CTRL3 0x04 | ||
126 | #define RT286_POWER_CTRL2 0x08 | ||
127 | #define RT286_I2S_CTRL1 0x09 | ||
128 | #define RT286_I2S_CTRL2 0x0a | ||
129 | #define RT286_CLK_DIV 0x0b | ||
130 | #define RT286_DC_GAIN 0x0d | ||
131 | #define RT286_POWER_CTRL3 0x0f | ||
132 | #define RT286_MIC1_DET_CTRL 0x19 | ||
133 | #define RT286_MISC_CTRL1 0x20 | ||
134 | #define RT286_IRQ_CTRL 0x33 | ||
135 | #define RT286_PLL_CTRL1 0x49 | ||
136 | #define RT286_CBJ_CTRL1 0x4f | ||
137 | #define RT286_CBJ_CTRL2 0x50 | ||
138 | #define RT286_PLL_CTRL 0x63 | ||
139 | #define RT286_DEPOP_CTRL1 0x66 | ||
140 | #define RT286_DEPOP_CTRL2 0x67 | ||
141 | #define RT286_DEPOP_CTRL3 0x68 | ||
142 | #define RT286_DEPOP_CTRL4 0x69 | ||
143 | |||
144 | /* SPDIF (0x06) */ | ||
145 | #define RT286_SPDIF_SEL_SFT 0 | ||
146 | #define RT286_SPDIF_SEL_PCM0 0 | ||
147 | #define RT286_SPDIF_SEL_PCM1 1 | ||
148 | #define RT286_SPDIF_SEL_SPOUT 2 | ||
149 | #define RT286_SPDIF_SEL_PP 3 | ||
150 | |||
151 | /* RECMIX (0x0b) */ | ||
152 | #define RT286_M_REC_BEEP_SFT 0 | ||
153 | #define RT286_M_REC_LINE1_SFT 1 | ||
154 | #define RT286_M_REC_MIC1_SFT 2 | ||
155 | #define RT286_M_REC_I2S_SFT 3 | ||
156 | |||
157 | /* Front (0x0c) */ | ||
158 | #define RT286_M_FRONT_DAC_SFT 0 | ||
159 | #define RT286_M_FRONT_REC_SFT 1 | ||
160 | |||
161 | /* SPK-OUT (0x14) */ | ||
162 | #define RT286_M_SPK_MUX_SFT 14 | ||
163 | #define RT286_SPK_SEL_MASK 0x1 | ||
164 | #define RT286_SPK_SEL_SFT 0 | ||
165 | #define RT286_SPK_SEL_F 0 | ||
166 | #define RT286_SPK_SEL_S 1 | ||
167 | |||
168 | /* HP-OUT (0x21) */ | ||
169 | #define RT286_M_HP_MUX_SFT 14 | ||
170 | #define RT286_HP_SEL_MASK 0x1 | ||
171 | #define RT286_HP_SEL_SFT 0 | ||
172 | #define RT286_HP_SEL_F 0 | ||
173 | #define RT286_HP_SEL_S 1 | ||
174 | |||
175 | /* ADC (0x22) (0x23) */ | ||
176 | #define RT286_ADC_SEL_MASK 0x7 | ||
177 | #define RT286_ADC_SEL_SFT 0 | ||
178 | #define RT286_ADC_SEL_SURR 0 | ||
179 | #define RT286_ADC_SEL_FRONT 1 | ||
180 | #define RT286_ADC_SEL_DMIC 2 | ||
181 | #define RT286_ADC_SEL_BEEP 4 | ||
182 | #define RT286_ADC_SEL_LINE1 5 | ||
183 | #define RT286_ADC_SEL_I2S 6 | ||
184 | #define RT286_ADC_SEL_MIC1 7 | ||
185 | |||
186 | #define RT286_SCLK_S_MCLK 0 | ||
187 | #define RT286_SCLK_S_PLL 1 | ||
188 | |||
189 | enum { | ||
190 | RT286_AIF1, | ||
191 | RT286_AIF2, | ||
192 | RT286_AIFS, | ||
193 | }; | ||
194 | |||
195 | int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack); | ||
196 | |||
197 | #endif /* __RT286_H__ */ | ||
198 | |||
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index de80e89b5fd8..6bc6efdec550 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c | |||
@@ -2215,14 +2215,8 @@ static int rt5640_i2c_probe(struct i2c_client *i2c, | |||
2215 | 2215 | ||
2216 | rt5640->hp_mute = 1; | 2216 | rt5640->hp_mute = 1; |
2217 | 2217 | ||
2218 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640, | 2218 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640, |
2219 | rt5640_dai, ARRAY_SIZE(rt5640_dai)); | 2219 | rt5640_dai, ARRAY_SIZE(rt5640_dai)); |
2220 | if (ret < 0) | ||
2221 | goto err; | ||
2222 | |||
2223 | return 0; | ||
2224 | err: | ||
2225 | return ret; | ||
2226 | } | 2220 | } |
2227 | 2221 | ||
2228 | static int rt5640_i2c_remove(struct i2c_client *i2c) | 2222 | static int rt5640_i2c_remove(struct i2c_client *i2c) |
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 02147be2b302..a7762d0a623e 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -2345,14 +2345,8 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2345 | 2345 | ||
2346 | } | 2346 | } |
2347 | 2347 | ||
2348 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, | 2348 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, |
2349 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); | 2349 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); |
2350 | if (ret < 0) | ||
2351 | goto err; | ||
2352 | |||
2353 | return 0; | ||
2354 | err: | ||
2355 | return ret; | ||
2356 | } | 2350 | } |
2357 | 2351 | ||
2358 | static int rt5645_i2c_remove(struct i2c_client *i2c) | 2352 | static int rt5645_i2c_remove(struct i2c_client *i2c) |
diff --git a/sound/soc/codecs/rt5670-dsp.h b/sound/soc/codecs/rt5670-dsp.h new file mode 100644 index 000000000000..a34d0cdb8198 --- /dev/null +++ b/sound/soc/codecs/rt5670-dsp.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * rt5670-dsp.h -- RT5670 ALSA SoC DSP driver | ||
3 | * | ||
4 | * Copyright 2014 Realtek Microelectronics | ||
5 | * Author: Bard Liao <bardliao@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __RT5670_DSP_H__ | ||
13 | #define __RT5670_DSP_H__ | ||
14 | |||
15 | #define RT5670_DSP_CTRL1 0xe0 | ||
16 | #define RT5670_DSP_CTRL2 0xe1 | ||
17 | #define RT5670_DSP_CTRL3 0xe2 | ||
18 | #define RT5670_DSP_CTRL4 0xe3 | ||
19 | #define RT5670_DSP_CTRL5 0xe4 | ||
20 | |||
21 | /* DSP Control 1 (0xe0) */ | ||
22 | #define RT5670_DSP_CMD_MASK (0xff << 8) | ||
23 | #define RT5670_DSP_CMD_PE (0x0d << 8) /* Patch Entry */ | ||
24 | #define RT5670_DSP_CMD_MW (0x3b << 8) /* Memory Write */ | ||
25 | #define RT5670_DSP_CMD_MR (0x37 << 8) /* Memory Read */ | ||
26 | #define RT5670_DSP_CMD_RR (0x60 << 8) /* Register Read */ | ||
27 | #define RT5670_DSP_CMD_RW (0x68 << 8) /* Register Write */ | ||
28 | #define RT5670_DSP_REG_DATHI (0x26 << 8) /* High Data Addr */ | ||
29 | #define RT5670_DSP_REG_DATLO (0x25 << 8) /* Low Data Addr */ | ||
30 | #define RT5670_DSP_CLK_MASK (0x3 << 6) | ||
31 | #define RT5670_DSP_CLK_SFT 6 | ||
32 | #define RT5670_DSP_CLK_768K (0x0 << 6) | ||
33 | #define RT5670_DSP_CLK_384K (0x1 << 6) | ||
34 | #define RT5670_DSP_CLK_192K (0x2 << 6) | ||
35 | #define RT5670_DSP_CLK_96K (0x3 << 6) | ||
36 | #define RT5670_DSP_BUSY_MASK (0x1 << 5) | ||
37 | #define RT5670_DSP_RW_MASK (0x1 << 4) | ||
38 | #define RT5670_DSP_DL_MASK (0x3 << 2) | ||
39 | #define RT5670_DSP_DL_0 (0x0 << 2) | ||
40 | #define RT5670_DSP_DL_1 (0x1 << 2) | ||
41 | #define RT5670_DSP_DL_2 (0x2 << 2) | ||
42 | #define RT5670_DSP_DL_3 (0x3 << 2) | ||
43 | #define RT5670_DSP_I2C_AL_16 (0x1 << 1) | ||
44 | #define RT5670_DSP_CMD_EN (0x1) | ||
45 | |||
46 | struct rt5670_dsp_param { | ||
47 | u16 cmd_fmt; | ||
48 | u16 addr; | ||
49 | u16 data; | ||
50 | u8 cmd; | ||
51 | }; | ||
52 | |||
53 | #endif /* __RT5670_DSP_H__ */ | ||
54 | |||
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c new file mode 100644 index 000000000000..ba9d9b4d4857 --- /dev/null +++ b/sound/soc/codecs/rt5670.c | |||
@@ -0,0 +1,2657 @@ | |||
1 | /* | ||
2 | * rt5670.c -- RT5670 ALSA SoC audio codec driver | ||
3 | * | ||
4 | * Copyright 2014 Realtek Semiconductor Corp. | ||
5 | * Author: Bard Liao <bardliao@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/pm.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | #include <sound/core.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | #include <sound/jack.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/soc-dapm.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/tlv.h> | ||
28 | #include <sound/rt5670.h> | ||
29 | |||
30 | #include "rl6231.h" | ||
31 | #include "rt5670.h" | ||
32 | #include "rt5670-dsp.h" | ||
33 | |||
34 | #define RT5670_DEVICE_ID 0x6271 | ||
35 | |||
36 | #define RT5670_PR_RANGE_BASE (0xff + 1) | ||
37 | #define RT5670_PR_SPACING 0x100 | ||
38 | |||
39 | #define RT5670_PR_BASE (RT5670_PR_RANGE_BASE + (0 * RT5670_PR_SPACING)) | ||
40 | |||
41 | static const struct regmap_range_cfg rt5670_ranges[] = { | ||
42 | { .name = "PR", .range_min = RT5670_PR_BASE, | ||
43 | .range_max = RT5670_PR_BASE + 0xf8, | ||
44 | .selector_reg = RT5670_PRIV_INDEX, | ||
45 | .selector_mask = 0xff, | ||
46 | .selector_shift = 0x0, | ||
47 | .window_start = RT5670_PRIV_DATA, | ||
48 | .window_len = 0x1, }, | ||
49 | }; | ||
50 | |||
51 | static struct reg_default init_list[] = { | ||
52 | { RT5670_PR_BASE + 0x14, 0x9a8a }, | ||
53 | { RT5670_PR_BASE + 0x38, 0x3ba1 }, | ||
54 | { RT5670_PR_BASE + 0x3d, 0x3640 }, | ||
55 | }; | ||
56 | #define RT5670_INIT_REG_LEN ARRAY_SIZE(init_list) | ||
57 | |||
58 | static const struct reg_default rt5670_reg[] = { | ||
59 | { 0x00, 0x0000 }, | ||
60 | { 0x02, 0x8888 }, | ||
61 | { 0x03, 0x8888 }, | ||
62 | { 0x0a, 0x0001 }, | ||
63 | { 0x0b, 0x0827 }, | ||
64 | { 0x0c, 0x0000 }, | ||
65 | { 0x0d, 0x0008 }, | ||
66 | { 0x0e, 0x0000 }, | ||
67 | { 0x0f, 0x0808 }, | ||
68 | { 0x19, 0xafaf }, | ||
69 | { 0x1a, 0xafaf }, | ||
70 | { 0x1b, 0x0011 }, | ||
71 | { 0x1c, 0x2f2f }, | ||
72 | { 0x1d, 0x2f2f }, | ||
73 | { 0x1e, 0x0000 }, | ||
74 | { 0x1f, 0x2f2f }, | ||
75 | { 0x20, 0x0000 }, | ||
76 | { 0x26, 0x7860 }, | ||
77 | { 0x27, 0x7860 }, | ||
78 | { 0x28, 0x7871 }, | ||
79 | { 0x29, 0x8080 }, | ||
80 | { 0x2a, 0x5656 }, | ||
81 | { 0x2b, 0x5454 }, | ||
82 | { 0x2c, 0xaaa0 }, | ||
83 | { 0x2d, 0x0000 }, | ||
84 | { 0x2e, 0x2f2f }, | ||
85 | { 0x2f, 0x1002 }, | ||
86 | { 0x30, 0x0000 }, | ||
87 | { 0x31, 0x5f00 }, | ||
88 | { 0x32, 0x0000 }, | ||
89 | { 0x33, 0x0000 }, | ||
90 | { 0x34, 0x0000 }, | ||
91 | { 0x35, 0x0000 }, | ||
92 | { 0x36, 0x0000 }, | ||
93 | { 0x37, 0x0000 }, | ||
94 | { 0x38, 0x0000 }, | ||
95 | { 0x3b, 0x0000 }, | ||
96 | { 0x3c, 0x007f }, | ||
97 | { 0x3d, 0x0000 }, | ||
98 | { 0x3e, 0x007f }, | ||
99 | { 0x45, 0xe00f }, | ||
100 | { 0x4c, 0x5380 }, | ||
101 | { 0x4f, 0x0073 }, | ||
102 | { 0x52, 0x00d3 }, | ||
103 | { 0x53, 0xf0f0 }, | ||
104 | { 0x61, 0x0000 }, | ||
105 | { 0x62, 0x0001 }, | ||
106 | { 0x63, 0x00c3 }, | ||
107 | { 0x64, 0x0000 }, | ||
108 | { 0x65, 0x0000 }, | ||
109 | { 0x66, 0x0000 }, | ||
110 | { 0x6f, 0x8000 }, | ||
111 | { 0x70, 0x8000 }, | ||
112 | { 0x71, 0x8000 }, | ||
113 | { 0x72, 0x8000 }, | ||
114 | { 0x73, 0x1110 }, | ||
115 | { 0x74, 0x0e00 }, | ||
116 | { 0x75, 0x1505 }, | ||
117 | { 0x76, 0x0015 }, | ||
118 | { 0x77, 0x0c00 }, | ||
119 | { 0x78, 0x4000 }, | ||
120 | { 0x79, 0x0123 }, | ||
121 | { 0x7f, 0x1100 }, | ||
122 | { 0x80, 0x0000 }, | ||
123 | { 0x81, 0x0000 }, | ||
124 | { 0x82, 0x0000 }, | ||
125 | { 0x83, 0x0000 }, | ||
126 | { 0x84, 0x0000 }, | ||
127 | { 0x85, 0x0000 }, | ||
128 | { 0x86, 0x0008 }, | ||
129 | { 0x87, 0x0000 }, | ||
130 | { 0x88, 0x0000 }, | ||
131 | { 0x89, 0x0000 }, | ||
132 | { 0x8a, 0x0000 }, | ||
133 | { 0x8b, 0x0000 }, | ||
134 | { 0x8c, 0x0007 }, | ||
135 | { 0x8d, 0x0000 }, | ||
136 | { 0x8e, 0x0004 }, | ||
137 | { 0x8f, 0x1100 }, | ||
138 | { 0x90, 0x0646 }, | ||
139 | { 0x91, 0x0c06 }, | ||
140 | { 0x93, 0x0000 }, | ||
141 | { 0x94, 0x0000 }, | ||
142 | { 0x95, 0x0000 }, | ||
143 | { 0x97, 0x0000 }, | ||
144 | { 0x98, 0x0000 }, | ||
145 | { 0x99, 0x0000 }, | ||
146 | { 0x9a, 0x2184 }, | ||
147 | { 0x9b, 0x010a }, | ||
148 | { 0x9c, 0x0aea }, | ||
149 | { 0x9d, 0x000c }, | ||
150 | { 0x9e, 0x0400 }, | ||
151 | { 0xae, 0x7000 }, | ||
152 | { 0xaf, 0x0000 }, | ||
153 | { 0xb0, 0x6000 }, | ||
154 | { 0xb1, 0x0000 }, | ||
155 | { 0xb2, 0x0000 }, | ||
156 | { 0xb3, 0x001f }, | ||
157 | { 0xb4, 0x2206 }, | ||
158 | { 0xb5, 0x1f00 }, | ||
159 | { 0xb6, 0x0000 }, | ||
160 | { 0xb7, 0x0000 }, | ||
161 | { 0xbb, 0x0000 }, | ||
162 | { 0xbc, 0x0000 }, | ||
163 | { 0xbd, 0x0000 }, | ||
164 | { 0xbe, 0x0000 }, | ||
165 | { 0xbf, 0x0000 }, | ||
166 | { 0xc0, 0x0000 }, | ||
167 | { 0xc1, 0x0000 }, | ||
168 | { 0xc2, 0x0000 }, | ||
169 | { 0xcd, 0x0000 }, | ||
170 | { 0xce, 0x0000 }, | ||
171 | { 0xcf, 0x1813 }, | ||
172 | { 0xd0, 0x0690 }, | ||
173 | { 0xd1, 0x1c17 }, | ||
174 | { 0xd3, 0xb320 }, | ||
175 | { 0xd4, 0x0000 }, | ||
176 | { 0xd6, 0x0400 }, | ||
177 | { 0xd9, 0x0809 }, | ||
178 | { 0xda, 0x0000 }, | ||
179 | { 0xdb, 0x0001 }, | ||
180 | { 0xdc, 0x0049 }, | ||
181 | { 0xdd, 0x0009 }, | ||
182 | { 0xe6, 0x8000 }, | ||
183 | { 0xe7, 0x0000 }, | ||
184 | { 0xec, 0xb300 }, | ||
185 | { 0xed, 0x0000 }, | ||
186 | { 0xee, 0xb300 }, | ||
187 | { 0xef, 0x0000 }, | ||
188 | { 0xf8, 0x0000 }, | ||
189 | { 0xf9, 0x0000 }, | ||
190 | { 0xfa, 0x8010 }, | ||
191 | { 0xfb, 0x0033 }, | ||
192 | { 0xfc, 0x0080 }, | ||
193 | }; | ||
194 | |||
195 | static bool rt5670_volatile_register(struct device *dev, unsigned int reg) | ||
196 | { | ||
197 | int i; | ||
198 | |||
199 | for (i = 0; i < ARRAY_SIZE(rt5670_ranges); i++) { | ||
200 | if ((reg >= rt5670_ranges[i].window_start && | ||
201 | reg <= rt5670_ranges[i].window_start + | ||
202 | rt5670_ranges[i].window_len) || | ||
203 | (reg >= rt5670_ranges[i].range_min && | ||
204 | reg <= rt5670_ranges[i].range_max)) { | ||
205 | return true; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | switch (reg) { | ||
210 | case RT5670_RESET: | ||
211 | case RT5670_PDM_DATA_CTRL1: | ||
212 | case RT5670_PDM1_DATA_CTRL4: | ||
213 | case RT5670_PDM2_DATA_CTRL4: | ||
214 | case RT5670_PRIV_DATA: | ||
215 | case RT5670_ASRC_5: | ||
216 | case RT5670_CJ_CTRL1: | ||
217 | case RT5670_CJ_CTRL2: | ||
218 | case RT5670_CJ_CTRL3: | ||
219 | case RT5670_A_JD_CTRL1: | ||
220 | case RT5670_A_JD_CTRL2: | ||
221 | case RT5670_VAD_CTRL5: | ||
222 | case RT5670_ADC_EQ_CTRL1: | ||
223 | case RT5670_EQ_CTRL1: | ||
224 | case RT5670_ALC_CTRL_1: | ||
225 | case RT5670_IRQ_CTRL1: | ||
226 | case RT5670_IRQ_CTRL2: | ||
227 | case RT5670_INT_IRQ_ST: | ||
228 | case RT5670_IL_CMD: | ||
229 | case RT5670_DSP_CTRL1: | ||
230 | case RT5670_DSP_CTRL2: | ||
231 | case RT5670_DSP_CTRL3: | ||
232 | case RT5670_DSP_CTRL4: | ||
233 | case RT5670_DSP_CTRL5: | ||
234 | case RT5670_VENDOR_ID: | ||
235 | case RT5670_VENDOR_ID1: | ||
236 | case RT5670_VENDOR_ID2: | ||
237 | return true; | ||
238 | default: | ||
239 | return false; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | static bool rt5670_readable_register(struct device *dev, unsigned int reg) | ||
244 | { | ||
245 | int i; | ||
246 | |||
247 | for (i = 0; i < ARRAY_SIZE(rt5670_ranges); i++) { | ||
248 | if ((reg >= rt5670_ranges[i].window_start && | ||
249 | reg <= rt5670_ranges[i].window_start + | ||
250 | rt5670_ranges[i].window_len) || | ||
251 | (reg >= rt5670_ranges[i].range_min && | ||
252 | reg <= rt5670_ranges[i].range_max)) { | ||
253 | return true; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | switch (reg) { | ||
258 | case RT5670_RESET: | ||
259 | case RT5670_HP_VOL: | ||
260 | case RT5670_LOUT1: | ||
261 | case RT5670_CJ_CTRL1: | ||
262 | case RT5670_CJ_CTRL2: | ||
263 | case RT5670_CJ_CTRL3: | ||
264 | case RT5670_IN2: | ||
265 | case RT5670_INL1_INR1_VOL: | ||
266 | case RT5670_DAC1_DIG_VOL: | ||
267 | case RT5670_DAC2_DIG_VOL: | ||
268 | case RT5670_DAC_CTRL: | ||
269 | case RT5670_STO1_ADC_DIG_VOL: | ||
270 | case RT5670_MONO_ADC_DIG_VOL: | ||
271 | case RT5670_STO2_ADC_DIG_VOL: | ||
272 | case RT5670_ADC_BST_VOL1: | ||
273 | case RT5670_ADC_BST_VOL2: | ||
274 | case RT5670_STO2_ADC_MIXER: | ||
275 | case RT5670_STO1_ADC_MIXER: | ||
276 | case RT5670_MONO_ADC_MIXER: | ||
277 | case RT5670_AD_DA_MIXER: | ||
278 | case RT5670_STO_DAC_MIXER: | ||
279 | case RT5670_DD_MIXER: | ||
280 | case RT5670_DIG_MIXER: | ||
281 | case RT5670_DSP_PATH1: | ||
282 | case RT5670_DSP_PATH2: | ||
283 | case RT5670_DIG_INF1_DATA: | ||
284 | case RT5670_DIG_INF2_DATA: | ||
285 | case RT5670_PDM_OUT_CTRL: | ||
286 | case RT5670_PDM_DATA_CTRL1: | ||
287 | case RT5670_PDM1_DATA_CTRL2: | ||
288 | case RT5670_PDM1_DATA_CTRL3: | ||
289 | case RT5670_PDM1_DATA_CTRL4: | ||
290 | case RT5670_PDM2_DATA_CTRL2: | ||
291 | case RT5670_PDM2_DATA_CTRL3: | ||
292 | case RT5670_PDM2_DATA_CTRL4: | ||
293 | case RT5670_REC_L1_MIXER: | ||
294 | case RT5670_REC_L2_MIXER: | ||
295 | case RT5670_REC_R1_MIXER: | ||
296 | case RT5670_REC_R2_MIXER: | ||
297 | case RT5670_HPO_MIXER: | ||
298 | case RT5670_MONO_MIXER: | ||
299 | case RT5670_OUT_L1_MIXER: | ||
300 | case RT5670_OUT_R1_MIXER: | ||
301 | case RT5670_LOUT_MIXER: | ||
302 | case RT5670_PWR_DIG1: | ||
303 | case RT5670_PWR_DIG2: | ||
304 | case RT5670_PWR_ANLG1: | ||
305 | case RT5670_PWR_ANLG2: | ||
306 | case RT5670_PWR_MIXER: | ||
307 | case RT5670_PWR_VOL: | ||
308 | case RT5670_PRIV_INDEX: | ||
309 | case RT5670_PRIV_DATA: | ||
310 | case RT5670_I2S4_SDP: | ||
311 | case RT5670_I2S1_SDP: | ||
312 | case RT5670_I2S2_SDP: | ||
313 | case RT5670_I2S3_SDP: | ||
314 | case RT5670_ADDA_CLK1: | ||
315 | case RT5670_ADDA_CLK2: | ||
316 | case RT5670_DMIC_CTRL1: | ||
317 | case RT5670_DMIC_CTRL2: | ||
318 | case RT5670_TDM_CTRL_1: | ||
319 | case RT5670_TDM_CTRL_2: | ||
320 | case RT5670_TDM_CTRL_3: | ||
321 | case RT5670_DSP_CLK: | ||
322 | case RT5670_GLB_CLK: | ||
323 | case RT5670_PLL_CTRL1: | ||
324 | case RT5670_PLL_CTRL2: | ||
325 | case RT5670_ASRC_1: | ||
326 | case RT5670_ASRC_2: | ||
327 | case RT5670_ASRC_3: | ||
328 | case RT5670_ASRC_4: | ||
329 | case RT5670_ASRC_5: | ||
330 | case RT5670_ASRC_7: | ||
331 | case RT5670_ASRC_8: | ||
332 | case RT5670_ASRC_9: | ||
333 | case RT5670_ASRC_10: | ||
334 | case RT5670_ASRC_11: | ||
335 | case RT5670_ASRC_12: | ||
336 | case RT5670_ASRC_13: | ||
337 | case RT5670_ASRC_14: | ||
338 | case RT5670_DEPOP_M1: | ||
339 | case RT5670_DEPOP_M2: | ||
340 | case RT5670_DEPOP_M3: | ||
341 | case RT5670_CHARGE_PUMP: | ||
342 | case RT5670_MICBIAS: | ||
343 | case RT5670_A_JD_CTRL1: | ||
344 | case RT5670_A_JD_CTRL2: | ||
345 | case RT5670_VAD_CTRL1: | ||
346 | case RT5670_VAD_CTRL2: | ||
347 | case RT5670_VAD_CTRL3: | ||
348 | case RT5670_VAD_CTRL4: | ||
349 | case RT5670_VAD_CTRL5: | ||
350 | case RT5670_ADC_EQ_CTRL1: | ||
351 | case RT5670_ADC_EQ_CTRL2: | ||
352 | case RT5670_EQ_CTRL1: | ||
353 | case RT5670_EQ_CTRL2: | ||
354 | case RT5670_ALC_DRC_CTRL1: | ||
355 | case RT5670_ALC_DRC_CTRL2: | ||
356 | case RT5670_ALC_CTRL_1: | ||
357 | case RT5670_ALC_CTRL_2: | ||
358 | case RT5670_ALC_CTRL_3: | ||
359 | case RT5670_JD_CTRL: | ||
360 | case RT5670_IRQ_CTRL1: | ||
361 | case RT5670_IRQ_CTRL2: | ||
362 | case RT5670_INT_IRQ_ST: | ||
363 | case RT5670_GPIO_CTRL1: | ||
364 | case RT5670_GPIO_CTRL2: | ||
365 | case RT5670_GPIO_CTRL3: | ||
366 | case RT5670_SCRABBLE_FUN: | ||
367 | case RT5670_SCRABBLE_CTRL: | ||
368 | case RT5670_BASE_BACK: | ||
369 | case RT5670_MP3_PLUS1: | ||
370 | case RT5670_MP3_PLUS2: | ||
371 | case RT5670_ADJ_HPF1: | ||
372 | case RT5670_ADJ_HPF2: | ||
373 | case RT5670_HP_CALIB_AMP_DET: | ||
374 | case RT5670_SV_ZCD1: | ||
375 | case RT5670_SV_ZCD2: | ||
376 | case RT5670_IL_CMD: | ||
377 | case RT5670_IL_CMD2: | ||
378 | case RT5670_IL_CMD3: | ||
379 | case RT5670_DRC_HL_CTRL1: | ||
380 | case RT5670_DRC_HL_CTRL2: | ||
381 | case RT5670_ADC_MONO_HP_CTRL1: | ||
382 | case RT5670_ADC_MONO_HP_CTRL2: | ||
383 | case RT5670_ADC_STO2_HP_CTRL1: | ||
384 | case RT5670_ADC_STO2_HP_CTRL2: | ||
385 | case RT5670_JD_CTRL3: | ||
386 | case RT5670_JD_CTRL4: | ||
387 | case RT5670_DIG_MISC: | ||
388 | case RT5670_DSP_CTRL1: | ||
389 | case RT5670_DSP_CTRL2: | ||
390 | case RT5670_DSP_CTRL3: | ||
391 | case RT5670_DSP_CTRL4: | ||
392 | case RT5670_DSP_CTRL5: | ||
393 | case RT5670_GEN_CTRL2: | ||
394 | case RT5670_GEN_CTRL3: | ||
395 | case RT5670_VENDOR_ID: | ||
396 | case RT5670_VENDOR_ID1: | ||
397 | case RT5670_VENDOR_ID2: | ||
398 | return true; | ||
399 | default: | ||
400 | return false; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); | ||
405 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); | ||
406 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); | ||
407 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); | ||
408 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | ||
409 | |||
410 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ | ||
411 | static unsigned int bst_tlv[] = { | ||
412 | TLV_DB_RANGE_HEAD(7), | ||
413 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | ||
414 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), | ||
415 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), | ||
416 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), | ||
417 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), | ||
418 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), | ||
419 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), | ||
420 | }; | ||
421 | |||
422 | /* Interface data select */ | ||
423 | static const char * const rt5670_data_select[] = { | ||
424 | "Normal", "Swap", "left copy to right", "right copy to left" | ||
425 | }; | ||
426 | |||
427 | static SOC_ENUM_SINGLE_DECL(rt5670_if2_dac_enum, RT5670_DIG_INF1_DATA, | ||
428 | RT5670_IF2_DAC_SEL_SFT, rt5670_data_select); | ||
429 | |||
430 | static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_enum, RT5670_DIG_INF1_DATA, | ||
431 | RT5670_IF2_ADC_SEL_SFT, rt5670_data_select); | ||
432 | |||
433 | static const struct snd_kcontrol_new rt5670_snd_controls[] = { | ||
434 | /* Headphone Output Volume */ | ||
435 | SOC_DOUBLE("HP Playback Switch", RT5670_HP_VOL, | ||
436 | RT5670_L_MUTE_SFT, RT5670_R_MUTE_SFT, 1, 1), | ||
437 | SOC_DOUBLE_TLV("HP Playback Volume", RT5670_HP_VOL, | ||
438 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, | ||
439 | 39, 0, out_vol_tlv), | ||
440 | /* OUTPUT Control */ | ||
441 | SOC_DOUBLE("OUT Channel Switch", RT5670_LOUT1, | ||
442 | RT5670_VOL_L_SFT, RT5670_VOL_R_SFT, 1, 1), | ||
443 | SOC_DOUBLE_TLV("OUT Playback Volume", RT5670_LOUT1, | ||
444 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, 39, 1, out_vol_tlv), | ||
445 | /* DAC Digital Volume */ | ||
446 | SOC_DOUBLE("DAC2 Playback Switch", RT5670_DAC_CTRL, | ||
447 | RT5670_M_DAC_L2_VOL_SFT, RT5670_M_DAC_R2_VOL_SFT, 1, 1), | ||
448 | SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5670_DAC1_DIG_VOL, | ||
449 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, | ||
450 | 175, 0, dac_vol_tlv), | ||
451 | SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5670_DAC2_DIG_VOL, | ||
452 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, | ||
453 | 175, 0, dac_vol_tlv), | ||
454 | /* IN1/IN2 Control */ | ||
455 | SOC_SINGLE_TLV("IN1 Boost Volume", RT5670_CJ_CTRL1, | ||
456 | RT5670_BST_SFT1, 8, 0, bst_tlv), | ||
457 | SOC_SINGLE_TLV("IN2 Boost Volume", RT5670_IN2, | ||
458 | RT5670_BST_SFT1, 8, 0, bst_tlv), | ||
459 | /* INL/INR Volume Control */ | ||
460 | SOC_DOUBLE_TLV("IN Capture Volume", RT5670_INL1_INR1_VOL, | ||
461 | RT5670_INL_VOL_SFT, RT5670_INR_VOL_SFT, | ||
462 | 31, 1, in_vol_tlv), | ||
463 | /* ADC Digital Volume Control */ | ||
464 | SOC_DOUBLE("ADC Capture Switch", RT5670_STO1_ADC_DIG_VOL, | ||
465 | RT5670_L_MUTE_SFT, RT5670_R_MUTE_SFT, 1, 1), | ||
466 | SOC_DOUBLE_TLV("ADC Capture Volume", RT5670_STO1_ADC_DIG_VOL, | ||
467 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, | ||
468 | 127, 0, adc_vol_tlv), | ||
469 | |||
470 | SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5670_MONO_ADC_DIG_VOL, | ||
471 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, | ||
472 | 127, 0, adc_vol_tlv), | ||
473 | |||
474 | /* ADC Boost Volume Control */ | ||
475 | SOC_DOUBLE_TLV("STO1 ADC Boost Gain Volume", RT5670_ADC_BST_VOL1, | ||
476 | RT5670_STO1_ADC_L_BST_SFT, RT5670_STO1_ADC_R_BST_SFT, | ||
477 | 3, 0, adc_bst_tlv), | ||
478 | |||
479 | SOC_DOUBLE_TLV("STO2 ADC Boost Gain Volume", RT5670_ADC_BST_VOL1, | ||
480 | RT5670_STO2_ADC_L_BST_SFT, RT5670_STO2_ADC_R_BST_SFT, | ||
481 | 3, 0, adc_bst_tlv), | ||
482 | |||
483 | SOC_ENUM("ADC IF2 Data Switch", rt5670_if2_adc_enum), | ||
484 | SOC_ENUM("DAC IF2 Data Switch", rt5670_if2_dac_enum), | ||
485 | }; | ||
486 | |||
487 | /** | ||
488 | * set_dmic_clk - Set parameter of dmic. | ||
489 | * | ||
490 | * @w: DAPM widget. | ||
491 | * @kcontrol: The kcontrol of this widget. | ||
492 | * @event: Event id. | ||
493 | * | ||
494 | * Choose dmic clock between 1MHz and 3MHz. | ||
495 | * It is better for clock to approximate 3MHz. | ||
496 | */ | ||
497 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, | ||
498 | struct snd_kcontrol *kcontrol, int event) | ||
499 | { | ||
500 | struct snd_soc_codec *codec = w->codec; | ||
501 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
502 | int idx = -EINVAL; | ||
503 | |||
504 | idx = rl6231_calc_dmic_clk(rt5670->sysclk); | ||
505 | |||
506 | if (idx < 0) | ||
507 | dev_err(codec->dev, "Failed to set DMIC clock\n"); | ||
508 | else | ||
509 | snd_soc_update_bits(codec, RT5670_DMIC_CTRL1, | ||
510 | RT5670_DMIC_CLK_MASK, idx << RT5670_DMIC_CLK_SFT); | ||
511 | return idx; | ||
512 | } | ||
513 | |||
514 | static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | ||
515 | struct snd_soc_dapm_widget *sink) | ||
516 | { | ||
517 | unsigned int val; | ||
518 | |||
519 | val = snd_soc_read(source->codec, RT5670_GLB_CLK); | ||
520 | val &= RT5670_SCLK_SRC_MASK; | ||
521 | if (val == RT5670_SCLK_SRC_PLL1) | ||
522 | return 1; | ||
523 | else | ||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static int is_using_asrc(struct snd_soc_dapm_widget *source, | ||
528 | struct snd_soc_dapm_widget *sink) | ||
529 | { | ||
530 | unsigned int reg, shift, val; | ||
531 | |||
532 | switch (source->shift) { | ||
533 | case 0: | ||
534 | reg = RT5670_ASRC_3; | ||
535 | shift = 0; | ||
536 | break; | ||
537 | case 1: | ||
538 | reg = RT5670_ASRC_3; | ||
539 | shift = 4; | ||
540 | break; | ||
541 | case 2: | ||
542 | reg = RT5670_ASRC_5; | ||
543 | shift = 12; | ||
544 | break; | ||
545 | case 3: | ||
546 | reg = RT5670_ASRC_2; | ||
547 | shift = 0; | ||
548 | break; | ||
549 | case 8: | ||
550 | reg = RT5670_ASRC_2; | ||
551 | shift = 4; | ||
552 | break; | ||
553 | case 9: | ||
554 | reg = RT5670_ASRC_2; | ||
555 | shift = 8; | ||
556 | break; | ||
557 | case 10: | ||
558 | reg = RT5670_ASRC_2; | ||
559 | shift = 12; | ||
560 | break; | ||
561 | default: | ||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | val = (snd_soc_read(source->codec, reg) >> shift) & 0xf; | ||
566 | switch (val) { | ||
567 | case 1: | ||
568 | case 2: | ||
569 | case 3: | ||
570 | case 4: | ||
571 | return 1; | ||
572 | default: | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | } | ||
577 | |||
578 | /* Digital Mixer */ | ||
579 | static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = { | ||
580 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, | ||
581 | RT5670_M_ADC_L1_SFT, 1, 1), | ||
582 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO1_ADC_MIXER, | ||
583 | RT5670_M_ADC_L2_SFT, 1, 1), | ||
584 | }; | ||
585 | |||
586 | static const struct snd_kcontrol_new rt5670_sto1_adc_r_mix[] = { | ||
587 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, | ||
588 | RT5670_M_ADC_R1_SFT, 1, 1), | ||
589 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO1_ADC_MIXER, | ||
590 | RT5670_M_ADC_R2_SFT, 1, 1), | ||
591 | }; | ||
592 | |||
593 | static const struct snd_kcontrol_new rt5670_sto2_adc_l_mix[] = { | ||
594 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO2_ADC_MIXER, | ||
595 | RT5670_M_ADC_L1_SFT, 1, 1), | ||
596 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO2_ADC_MIXER, | ||
597 | RT5670_M_ADC_L2_SFT, 1, 1), | ||
598 | }; | ||
599 | |||
600 | static const struct snd_kcontrol_new rt5670_sto2_adc_r_mix[] = { | ||
601 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO2_ADC_MIXER, | ||
602 | RT5670_M_ADC_R1_SFT, 1, 1), | ||
603 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO2_ADC_MIXER, | ||
604 | RT5670_M_ADC_R2_SFT, 1, 1), | ||
605 | }; | ||
606 | |||
607 | static const struct snd_kcontrol_new rt5670_mono_adc_l_mix[] = { | ||
608 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_MONO_ADC_MIXER, | ||
609 | RT5670_M_MONO_ADC_L1_SFT, 1, 1), | ||
610 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_MONO_ADC_MIXER, | ||
611 | RT5670_M_MONO_ADC_L2_SFT, 1, 1), | ||
612 | }; | ||
613 | |||
614 | static const struct snd_kcontrol_new rt5670_mono_adc_r_mix[] = { | ||
615 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_MONO_ADC_MIXER, | ||
616 | RT5670_M_MONO_ADC_R1_SFT, 1, 1), | ||
617 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_MONO_ADC_MIXER, | ||
618 | RT5670_M_MONO_ADC_R2_SFT, 1, 1), | ||
619 | }; | ||
620 | |||
621 | static const struct snd_kcontrol_new rt5670_dac_l_mix[] = { | ||
622 | SOC_DAPM_SINGLE("Stereo ADC Switch", RT5670_AD_DA_MIXER, | ||
623 | RT5670_M_ADCMIX_L_SFT, 1, 1), | ||
624 | SOC_DAPM_SINGLE("DAC1 Switch", RT5670_AD_DA_MIXER, | ||
625 | RT5670_M_DAC1_L_SFT, 1, 1), | ||
626 | }; | ||
627 | |||
628 | static const struct snd_kcontrol_new rt5670_dac_r_mix[] = { | ||
629 | SOC_DAPM_SINGLE("Stereo ADC Switch", RT5670_AD_DA_MIXER, | ||
630 | RT5670_M_ADCMIX_R_SFT, 1, 1), | ||
631 | SOC_DAPM_SINGLE("DAC1 Switch", RT5670_AD_DA_MIXER, | ||
632 | RT5670_M_DAC1_R_SFT, 1, 1), | ||
633 | }; | ||
634 | |||
635 | static const struct snd_kcontrol_new rt5670_sto_dac_l_mix[] = { | ||
636 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_STO_DAC_MIXER, | ||
637 | RT5670_M_DAC_L1_SFT, 1, 1), | ||
638 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_STO_DAC_MIXER, | ||
639 | RT5670_M_DAC_L2_SFT, 1, 1), | ||
640 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_STO_DAC_MIXER, | ||
641 | RT5670_M_DAC_R1_STO_L_SFT, 1, 1), | ||
642 | }; | ||
643 | |||
644 | static const struct snd_kcontrol_new rt5670_sto_dac_r_mix[] = { | ||
645 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_STO_DAC_MIXER, | ||
646 | RT5670_M_DAC_R1_SFT, 1, 1), | ||
647 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_STO_DAC_MIXER, | ||
648 | RT5670_M_DAC_R2_SFT, 1, 1), | ||
649 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_STO_DAC_MIXER, | ||
650 | RT5670_M_DAC_L1_STO_R_SFT, 1, 1), | ||
651 | }; | ||
652 | |||
653 | static const struct snd_kcontrol_new rt5670_mono_dac_l_mix[] = { | ||
654 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_DD_MIXER, | ||
655 | RT5670_M_DAC_L1_MONO_L_SFT, 1, 1), | ||
656 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DD_MIXER, | ||
657 | RT5670_M_DAC_L2_MONO_L_SFT, 1, 1), | ||
658 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DD_MIXER, | ||
659 | RT5670_M_DAC_R2_MONO_L_SFT, 1, 1), | ||
660 | }; | ||
661 | |||
662 | static const struct snd_kcontrol_new rt5670_mono_dac_r_mix[] = { | ||
663 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_DD_MIXER, | ||
664 | RT5670_M_DAC_R1_MONO_R_SFT, 1, 1), | ||
665 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DD_MIXER, | ||
666 | RT5670_M_DAC_R2_MONO_R_SFT, 1, 1), | ||
667 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DD_MIXER, | ||
668 | RT5670_M_DAC_L2_MONO_R_SFT, 1, 1), | ||
669 | }; | ||
670 | |||
671 | static const struct snd_kcontrol_new rt5670_dig_l_mix[] = { | ||
672 | SOC_DAPM_SINGLE("Sto DAC Mix L Switch", RT5670_DIG_MIXER, | ||
673 | RT5670_M_STO_L_DAC_L_SFT, 1, 1), | ||
674 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DIG_MIXER, | ||
675 | RT5670_M_DAC_L2_DAC_L_SFT, 1, 1), | ||
676 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DIG_MIXER, | ||
677 | RT5670_M_DAC_R2_DAC_L_SFT, 1, 1), | ||
678 | }; | ||
679 | |||
680 | static const struct snd_kcontrol_new rt5670_dig_r_mix[] = { | ||
681 | SOC_DAPM_SINGLE("Sto DAC Mix R Switch", RT5670_DIG_MIXER, | ||
682 | RT5670_M_STO_R_DAC_R_SFT, 1, 1), | ||
683 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DIG_MIXER, | ||
684 | RT5670_M_DAC_R2_DAC_R_SFT, 1, 1), | ||
685 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DIG_MIXER, | ||
686 | RT5670_M_DAC_L2_DAC_R_SFT, 1, 1), | ||
687 | }; | ||
688 | |||
689 | /* Analog Input Mixer */ | ||
690 | static const struct snd_kcontrol_new rt5670_rec_l_mix[] = { | ||
691 | SOC_DAPM_SINGLE("INL Switch", RT5670_REC_L2_MIXER, | ||
692 | RT5670_M_IN_L_RM_L_SFT, 1, 1), | ||
693 | SOC_DAPM_SINGLE("BST2 Switch", RT5670_REC_L2_MIXER, | ||
694 | RT5670_M_BST2_RM_L_SFT, 1, 1), | ||
695 | SOC_DAPM_SINGLE("BST1 Switch", RT5670_REC_L2_MIXER, | ||
696 | RT5670_M_BST1_RM_L_SFT, 1, 1), | ||
697 | }; | ||
698 | |||
699 | static const struct snd_kcontrol_new rt5670_rec_r_mix[] = { | ||
700 | SOC_DAPM_SINGLE("INR Switch", RT5670_REC_R2_MIXER, | ||
701 | RT5670_M_IN_R_RM_R_SFT, 1, 1), | ||
702 | SOC_DAPM_SINGLE("BST2 Switch", RT5670_REC_R2_MIXER, | ||
703 | RT5670_M_BST2_RM_R_SFT, 1, 1), | ||
704 | SOC_DAPM_SINGLE("BST1 Switch", RT5670_REC_R2_MIXER, | ||
705 | RT5670_M_BST1_RM_R_SFT, 1, 1), | ||
706 | }; | ||
707 | |||
708 | static const struct snd_kcontrol_new rt5670_out_l_mix[] = { | ||
709 | SOC_DAPM_SINGLE("BST1 Switch", RT5670_OUT_L1_MIXER, | ||
710 | RT5670_M_BST1_OM_L_SFT, 1, 1), | ||
711 | SOC_DAPM_SINGLE("INL Switch", RT5670_OUT_L1_MIXER, | ||
712 | RT5670_M_IN_L_OM_L_SFT, 1, 1), | ||
713 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_OUT_L1_MIXER, | ||
714 | RT5670_M_DAC_L2_OM_L_SFT, 1, 1), | ||
715 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_OUT_L1_MIXER, | ||
716 | RT5670_M_DAC_L1_OM_L_SFT, 1, 1), | ||
717 | }; | ||
718 | |||
719 | static const struct snd_kcontrol_new rt5670_out_r_mix[] = { | ||
720 | SOC_DAPM_SINGLE("BST2 Switch", RT5670_OUT_R1_MIXER, | ||
721 | RT5670_M_BST2_OM_R_SFT, 1, 1), | ||
722 | SOC_DAPM_SINGLE("INR Switch", RT5670_OUT_R1_MIXER, | ||
723 | RT5670_M_IN_R_OM_R_SFT, 1, 1), | ||
724 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_OUT_R1_MIXER, | ||
725 | RT5670_M_DAC_R2_OM_R_SFT, 1, 1), | ||
726 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_OUT_R1_MIXER, | ||
727 | RT5670_M_DAC_R1_OM_R_SFT, 1, 1), | ||
728 | }; | ||
729 | |||
730 | static const struct snd_kcontrol_new rt5670_hpo_mix[] = { | ||
731 | SOC_DAPM_SINGLE("DAC1 Switch", RT5670_HPO_MIXER, | ||
732 | RT5670_M_DAC1_HM_SFT, 1, 1), | ||
733 | SOC_DAPM_SINGLE("HPVOL Switch", RT5670_HPO_MIXER, | ||
734 | RT5670_M_HPVOL_HM_SFT, 1, 1), | ||
735 | }; | ||
736 | |||
737 | static const struct snd_kcontrol_new rt5670_hpvoll_mix[] = { | ||
738 | SOC_DAPM_SINGLE("DAC1 Switch", RT5670_HPO_MIXER, | ||
739 | RT5670_M_DACL1_HML_SFT, 1, 1), | ||
740 | SOC_DAPM_SINGLE("INL Switch", RT5670_HPO_MIXER, | ||
741 | RT5670_M_INL1_HML_SFT, 1, 1), | ||
742 | }; | ||
743 | |||
744 | static const struct snd_kcontrol_new rt5670_hpvolr_mix[] = { | ||
745 | SOC_DAPM_SINGLE("DAC1 Switch", RT5670_HPO_MIXER, | ||
746 | RT5670_M_DACR1_HMR_SFT, 1, 1), | ||
747 | SOC_DAPM_SINGLE("INR Switch", RT5670_HPO_MIXER, | ||
748 | RT5670_M_INR1_HMR_SFT, 1, 1), | ||
749 | }; | ||
750 | |||
751 | static const struct snd_kcontrol_new rt5670_lout_mix[] = { | ||
752 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_LOUT_MIXER, | ||
753 | RT5670_M_DAC_L1_LM_SFT, 1, 1), | ||
754 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_LOUT_MIXER, | ||
755 | RT5670_M_DAC_R1_LM_SFT, 1, 1), | ||
756 | SOC_DAPM_SINGLE("OUTMIX L Switch", RT5670_LOUT_MIXER, | ||
757 | RT5670_M_OV_L_LM_SFT, 1, 1), | ||
758 | SOC_DAPM_SINGLE("OUTMIX R Switch", RT5670_LOUT_MIXER, | ||
759 | RT5670_M_OV_R_LM_SFT, 1, 1), | ||
760 | }; | ||
761 | |||
762 | static const struct snd_kcontrol_new rt5670_hpl_mix[] = { | ||
763 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_HPO_MIXER, | ||
764 | RT5670_M_DACL1_HML_SFT, 1, 1), | ||
765 | SOC_DAPM_SINGLE("INL1 Switch", RT5670_HPO_MIXER, | ||
766 | RT5670_M_INL1_HML_SFT, 1, 1), | ||
767 | }; | ||
768 | |||
769 | static const struct snd_kcontrol_new rt5670_hpr_mix[] = { | ||
770 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_HPO_MIXER, | ||
771 | RT5670_M_DACR1_HMR_SFT, 1, 1), | ||
772 | SOC_DAPM_SINGLE("INR1 Switch", RT5670_HPO_MIXER, | ||
773 | RT5670_M_INR1_HMR_SFT, 1, 1), | ||
774 | }; | ||
775 | |||
776 | static const struct snd_kcontrol_new lout_l_enable_control = | ||
777 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5670_LOUT1, | ||
778 | RT5670_L_MUTE_SFT, 1, 1); | ||
779 | |||
780 | static const struct snd_kcontrol_new lout_r_enable_control = | ||
781 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5670_LOUT1, | ||
782 | RT5670_R_MUTE_SFT, 1, 1); | ||
783 | |||
784 | /* DAC1 L/R source */ /* MX-29 [9:8] [11:10] */ | ||
785 | static const char * const rt5670_dac1_src[] = { | ||
786 | "IF1 DAC", "IF2 DAC" | ||
787 | }; | ||
788 | |||
789 | static SOC_ENUM_SINGLE_DECL(rt5670_dac1l_enum, RT5670_AD_DA_MIXER, | ||
790 | RT5670_DAC1_L_SEL_SFT, rt5670_dac1_src); | ||
791 | |||
792 | static const struct snd_kcontrol_new rt5670_dac1l_mux = | ||
793 | SOC_DAPM_ENUM("DAC1 L source", rt5670_dac1l_enum); | ||
794 | |||
795 | static SOC_ENUM_SINGLE_DECL(rt5670_dac1r_enum, RT5670_AD_DA_MIXER, | ||
796 | RT5670_DAC1_R_SEL_SFT, rt5670_dac1_src); | ||
797 | |||
798 | static const struct snd_kcontrol_new rt5670_dac1r_mux = | ||
799 | SOC_DAPM_ENUM("DAC1 R source", rt5670_dac1r_enum); | ||
800 | |||
801 | /*DAC2 L/R source*/ /* MX-1B [6:4] [2:0] */ | ||
802 | /* TODO Use SOC_VALUE_ENUM_SINGLE_DECL */ | ||
803 | static const char * const rt5670_dac12_src[] = { | ||
804 | "IF1 DAC", "IF2 DAC", "IF3 DAC", "TxDC DAC", | ||
805 | "Bass", "VAD_ADC", "IF4 DAC" | ||
806 | }; | ||
807 | |||
808 | static SOC_ENUM_SINGLE_DECL(rt5670_dac2l_enum, RT5670_DAC_CTRL, | ||
809 | RT5670_DAC2_L_SEL_SFT, rt5670_dac12_src); | ||
810 | |||
811 | static const struct snd_kcontrol_new rt5670_dac_l2_mux = | ||
812 | SOC_DAPM_ENUM("DAC2 L source", rt5670_dac2l_enum); | ||
813 | |||
814 | static const char * const rt5670_dacr2_src[] = { | ||
815 | "IF1 DAC", "IF2 DAC", "IF3 DAC", "TxDC DAC", "TxDP ADC", "IF4 DAC" | ||
816 | }; | ||
817 | |||
818 | static SOC_ENUM_SINGLE_DECL(rt5670_dac2r_enum, RT5670_DAC_CTRL, | ||
819 | RT5670_DAC2_R_SEL_SFT, rt5670_dacr2_src); | ||
820 | |||
821 | static const struct snd_kcontrol_new rt5670_dac_r2_mux = | ||
822 | SOC_DAPM_ENUM("DAC2 R source", rt5670_dac2r_enum); | ||
823 | |||
824 | /*RxDP source*/ /* MX-2D [15:13] */ | ||
825 | static const char * const rt5670_rxdp_src[] = { | ||
826 | "IF2 DAC", "IF1 DAC", "STO1 ADC Mixer", "STO2 ADC Mixer", | ||
827 | "Mono ADC Mixer L", "Mono ADC Mixer R", "DAC1" | ||
828 | }; | ||
829 | |||
830 | static SOC_ENUM_SINGLE_DECL(rt5670_rxdp_enum, RT5670_DSP_PATH1, | ||
831 | RT5670_RXDP_SEL_SFT, rt5670_rxdp_src); | ||
832 | |||
833 | static const struct snd_kcontrol_new rt5670_rxdp_mux = | ||
834 | SOC_DAPM_ENUM("DAC2 L source", rt5670_rxdp_enum); | ||
835 | |||
836 | /* MX-2D [1] [0] */ | ||
837 | static const char * const rt5670_dsp_bypass_src[] = { | ||
838 | "DSP", "Bypass" | ||
839 | }; | ||
840 | |||
841 | static SOC_ENUM_SINGLE_DECL(rt5670_dsp_ul_enum, RT5670_DSP_PATH1, | ||
842 | RT5670_DSP_UL_SFT, rt5670_dsp_bypass_src); | ||
843 | |||
844 | static const struct snd_kcontrol_new rt5670_dsp_ul_mux = | ||
845 | SOC_DAPM_ENUM("DSP UL source", rt5670_dsp_ul_enum); | ||
846 | |||
847 | static SOC_ENUM_SINGLE_DECL(rt5670_dsp_dl_enum, RT5670_DSP_PATH1, | ||
848 | RT5670_DSP_DL_SFT, rt5670_dsp_bypass_src); | ||
849 | |||
850 | static const struct snd_kcontrol_new rt5670_dsp_dl_mux = | ||
851 | SOC_DAPM_ENUM("DSP DL source", rt5670_dsp_dl_enum); | ||
852 | |||
853 | /* Stereo2 ADC source */ | ||
854 | /* MX-26 [15] */ | ||
855 | static const char * const rt5670_stereo2_adc_lr_src[] = { | ||
856 | "L", "LR" | ||
857 | }; | ||
858 | |||
859 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc_lr_enum, RT5670_STO2_ADC_MIXER, | ||
860 | RT5670_STO2_ADC_SRC_SFT, rt5670_stereo2_adc_lr_src); | ||
861 | |||
862 | static const struct snd_kcontrol_new rt5670_sto2_adc_lr_mux = | ||
863 | SOC_DAPM_ENUM("Stereo2 ADC LR source", rt5670_stereo2_adc_lr_enum); | ||
864 | |||
865 | /* Stereo1 ADC source */ | ||
866 | /* MX-27 MX-26 [12] */ | ||
867 | static const char * const rt5670_stereo_adc1_src[] = { | ||
868 | "DAC MIX", "ADC" | ||
869 | }; | ||
870 | |||
871 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc1_enum, RT5670_STO1_ADC_MIXER, | ||
872 | RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src); | ||
873 | |||
874 | static const struct snd_kcontrol_new rt5670_sto_adc_l1_mux = | ||
875 | SOC_DAPM_ENUM("Stereo1 ADC L1 source", rt5670_stereo1_adc1_enum); | ||
876 | |||
877 | static const struct snd_kcontrol_new rt5670_sto_adc_r1_mux = | ||
878 | SOC_DAPM_ENUM("Stereo1 ADC R1 source", rt5670_stereo1_adc1_enum); | ||
879 | |||
880 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc1_enum, RT5670_STO2_ADC_MIXER, | ||
881 | RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src); | ||
882 | |||
883 | static const struct snd_kcontrol_new rt5670_sto2_adc_l1_mux = | ||
884 | SOC_DAPM_ENUM("Stereo2 ADC L1 source", rt5670_stereo2_adc1_enum); | ||
885 | |||
886 | static const struct snd_kcontrol_new rt5670_sto2_adc_r1_mux = | ||
887 | SOC_DAPM_ENUM("Stereo2 ADC R1 source", rt5670_stereo2_adc1_enum); | ||
888 | |||
889 | /* MX-27 MX-26 [11] */ | ||
890 | static const char * const rt5670_stereo_adc2_src[] = { | ||
891 | "DAC MIX", "DMIC" | ||
892 | }; | ||
893 | |||
894 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc2_enum, RT5670_STO1_ADC_MIXER, | ||
895 | RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src); | ||
896 | |||
897 | static const struct snd_kcontrol_new rt5670_sto_adc_l2_mux = | ||
898 | SOC_DAPM_ENUM("Stereo1 ADC L2 source", rt5670_stereo1_adc2_enum); | ||
899 | |||
900 | static const struct snd_kcontrol_new rt5670_sto_adc_r2_mux = | ||
901 | SOC_DAPM_ENUM("Stereo1 ADC R2 source", rt5670_stereo1_adc2_enum); | ||
902 | |||
903 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc2_enum, RT5670_STO2_ADC_MIXER, | ||
904 | RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src); | ||
905 | |||
906 | static const struct snd_kcontrol_new rt5670_sto2_adc_l2_mux = | ||
907 | SOC_DAPM_ENUM("Stereo2 ADC L2 source", rt5670_stereo2_adc2_enum); | ||
908 | |||
909 | static const struct snd_kcontrol_new rt5670_sto2_adc_r2_mux = | ||
910 | SOC_DAPM_ENUM("Stereo2 ADC R2 source", rt5670_stereo2_adc2_enum); | ||
911 | |||
912 | /* MX-27 MX26 [10] */ | ||
913 | static const char * const rt5670_stereo_adc_src[] = { | ||
914 | "ADC1L ADC2R", "ADC3" | ||
915 | }; | ||
916 | |||
917 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc_enum, RT5670_STO1_ADC_MIXER, | ||
918 | RT5670_ADC_SRC_SFT, rt5670_stereo_adc_src); | ||
919 | |||
920 | static const struct snd_kcontrol_new rt5670_sto_adc_mux = | ||
921 | SOC_DAPM_ENUM("Stereo1 ADC source", rt5670_stereo1_adc_enum); | ||
922 | |||
923 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc_enum, RT5670_STO2_ADC_MIXER, | ||
924 | RT5670_ADC_SRC_SFT, rt5670_stereo_adc_src); | ||
925 | |||
926 | static const struct snd_kcontrol_new rt5670_sto2_adc_mux = | ||
927 | SOC_DAPM_ENUM("Stereo2 ADC source", rt5670_stereo2_adc_enum); | ||
928 | |||
929 | /* MX-27 MX-26 [9:8] */ | ||
930 | static const char * const rt5670_stereo_dmic_src[] = { | ||
931 | "DMIC1", "DMIC2", "DMIC3" | ||
932 | }; | ||
933 | |||
934 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_dmic_enum, RT5670_STO1_ADC_MIXER, | ||
935 | RT5670_DMIC_SRC_SFT, rt5670_stereo_dmic_src); | ||
936 | |||
937 | static const struct snd_kcontrol_new rt5670_sto1_dmic_mux = | ||
938 | SOC_DAPM_ENUM("Stereo1 DMIC source", rt5670_stereo1_dmic_enum); | ||
939 | |||
940 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_dmic_enum, RT5670_STO2_ADC_MIXER, | ||
941 | RT5670_DMIC_SRC_SFT, rt5670_stereo_dmic_src); | ||
942 | |||
943 | static const struct snd_kcontrol_new rt5670_sto2_dmic_mux = | ||
944 | SOC_DAPM_ENUM("Stereo2 DMIC source", rt5670_stereo2_dmic_enum); | ||
945 | |||
946 | /* MX-27 [0] */ | ||
947 | static const char * const rt5670_stereo_dmic3_src[] = { | ||
948 | "DMIC3", "PDM ADC" | ||
949 | }; | ||
950 | |||
951 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo_dmic3_enum, RT5670_STO1_ADC_MIXER, | ||
952 | RT5670_DMIC3_SRC_SFT, rt5670_stereo_dmic3_src); | ||
953 | |||
954 | static const struct snd_kcontrol_new rt5670_sto_dmic3_mux = | ||
955 | SOC_DAPM_ENUM("Stereo DMIC3 source", rt5670_stereo_dmic3_enum); | ||
956 | |||
957 | /* Mono ADC source */ | ||
958 | /* MX-28 [12] */ | ||
959 | static const char * const rt5670_mono_adc_l1_src[] = { | ||
960 | "Mono DAC MIXL", "ADC1" | ||
961 | }; | ||
962 | |||
963 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_l1_enum, RT5670_MONO_ADC_MIXER, | ||
964 | RT5670_MONO_ADC_L1_SRC_SFT, rt5670_mono_adc_l1_src); | ||
965 | |||
966 | static const struct snd_kcontrol_new rt5670_mono_adc_l1_mux = | ||
967 | SOC_DAPM_ENUM("Mono ADC1 left source", rt5670_mono_adc_l1_enum); | ||
968 | /* MX-28 [11] */ | ||
969 | static const char * const rt5670_mono_adc_l2_src[] = { | ||
970 | "Mono DAC MIXL", "DMIC" | ||
971 | }; | ||
972 | |||
973 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_l2_enum, RT5670_MONO_ADC_MIXER, | ||
974 | RT5670_MONO_ADC_L2_SRC_SFT, rt5670_mono_adc_l2_src); | ||
975 | |||
976 | static const struct snd_kcontrol_new rt5670_mono_adc_l2_mux = | ||
977 | SOC_DAPM_ENUM("Mono ADC2 left source", rt5670_mono_adc_l2_enum); | ||
978 | |||
979 | /* MX-28 [9:8] */ | ||
980 | static const char * const rt5670_mono_dmic_src[] = { | ||
981 | "DMIC1", "DMIC2", "DMIC3" | ||
982 | }; | ||
983 | |||
984 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_dmic_l_enum, RT5670_MONO_ADC_MIXER, | ||
985 | RT5670_MONO_DMIC_L_SRC_SFT, rt5670_mono_dmic_src); | ||
986 | |||
987 | static const struct snd_kcontrol_new rt5670_mono_dmic_l_mux = | ||
988 | SOC_DAPM_ENUM("Mono DMIC left source", rt5670_mono_dmic_l_enum); | ||
989 | /* MX-28 [1:0] */ | ||
990 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_dmic_r_enum, RT5670_MONO_ADC_MIXER, | ||
991 | RT5670_MONO_DMIC_R_SRC_SFT, rt5670_mono_dmic_src); | ||
992 | |||
993 | static const struct snd_kcontrol_new rt5670_mono_dmic_r_mux = | ||
994 | SOC_DAPM_ENUM("Mono DMIC Right source", rt5670_mono_dmic_r_enum); | ||
995 | /* MX-28 [4] */ | ||
996 | static const char * const rt5670_mono_adc_r1_src[] = { | ||
997 | "Mono DAC MIXR", "ADC2" | ||
998 | }; | ||
999 | |||
1000 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_r1_enum, RT5670_MONO_ADC_MIXER, | ||
1001 | RT5670_MONO_ADC_R1_SRC_SFT, rt5670_mono_adc_r1_src); | ||
1002 | |||
1003 | static const struct snd_kcontrol_new rt5670_mono_adc_r1_mux = | ||
1004 | SOC_DAPM_ENUM("Mono ADC1 right source", rt5670_mono_adc_r1_enum); | ||
1005 | /* MX-28 [3] */ | ||
1006 | static const char * const rt5670_mono_adc_r2_src[] = { | ||
1007 | "Mono DAC MIXR", "DMIC" | ||
1008 | }; | ||
1009 | |||
1010 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_r2_enum, RT5670_MONO_ADC_MIXER, | ||
1011 | RT5670_MONO_ADC_R2_SRC_SFT, rt5670_mono_adc_r2_src); | ||
1012 | |||
1013 | static const struct snd_kcontrol_new rt5670_mono_adc_r2_mux = | ||
1014 | SOC_DAPM_ENUM("Mono ADC2 right source", rt5670_mono_adc_r2_enum); | ||
1015 | |||
1016 | /* MX-2D [3:2] */ | ||
1017 | static const char * const rt5670_txdp_slot_src[] = { | ||
1018 | "Slot 0-1", "Slot 2-3", "Slot 4-5", "Slot 6-7" | ||
1019 | }; | ||
1020 | |||
1021 | static SOC_ENUM_SINGLE_DECL(rt5670_txdp_slot_enum, RT5670_DSP_PATH1, | ||
1022 | RT5670_TXDP_SLOT_SEL_SFT, rt5670_txdp_slot_src); | ||
1023 | |||
1024 | static const struct snd_kcontrol_new rt5670_txdp_slot_mux = | ||
1025 | SOC_DAPM_ENUM("TxDP Slot source", rt5670_txdp_slot_enum); | ||
1026 | |||
1027 | /* MX-2F [15] */ | ||
1028 | static const char * const rt5670_if1_adc2_in_src[] = { | ||
1029 | "IF_ADC2", "VAD_ADC" | ||
1030 | }; | ||
1031 | |||
1032 | static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc2_in_enum, RT5670_DIG_INF1_DATA, | ||
1033 | RT5670_IF1_ADC2_IN_SFT, rt5670_if1_adc2_in_src); | ||
1034 | |||
1035 | static const struct snd_kcontrol_new rt5670_if1_adc2_in_mux = | ||
1036 | SOC_DAPM_ENUM("IF1 ADC2 IN source", rt5670_if1_adc2_in_enum); | ||
1037 | |||
1038 | /* MX-2F [14:12] */ | ||
1039 | static const char * const rt5670_if2_adc_in_src[] = { | ||
1040 | "IF_ADC1", "IF_ADC2", "IF_ADC3", "TxDC_DAC", "TxDP_ADC", "VAD_ADC" | ||
1041 | }; | ||
1042 | |||
1043 | static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_in_enum, RT5670_DIG_INF1_DATA, | ||
1044 | RT5670_IF2_ADC_IN_SFT, rt5670_if2_adc_in_src); | ||
1045 | |||
1046 | static const struct snd_kcontrol_new rt5670_if2_adc_in_mux = | ||
1047 | SOC_DAPM_ENUM("IF2 ADC IN source", rt5670_if2_adc_in_enum); | ||
1048 | |||
1049 | /* MX-30 [5:4] */ | ||
1050 | static const char * const rt5670_if4_adc_in_src[] = { | ||
1051 | "IF_ADC1", "IF_ADC2", "IF_ADC3" | ||
1052 | }; | ||
1053 | |||
1054 | static SOC_ENUM_SINGLE_DECL(rt5670_if4_adc_in_enum, RT5670_DIG_INF2_DATA, | ||
1055 | RT5670_IF4_ADC_IN_SFT, rt5670_if4_adc_in_src); | ||
1056 | |||
1057 | static const struct snd_kcontrol_new rt5670_if4_adc_in_mux = | ||
1058 | SOC_DAPM_ENUM("IF4 ADC IN source", rt5670_if4_adc_in_enum); | ||
1059 | |||
1060 | /* MX-31 [15] [13] [11] [9] */ | ||
1061 | static const char * const rt5670_pdm_src[] = { | ||
1062 | "Mono DAC", "Stereo DAC" | ||
1063 | }; | ||
1064 | |||
1065 | static SOC_ENUM_SINGLE_DECL(rt5670_pdm1_l_enum, RT5670_PDM_OUT_CTRL, | ||
1066 | RT5670_PDM1_L_SFT, rt5670_pdm_src); | ||
1067 | |||
1068 | static const struct snd_kcontrol_new rt5670_pdm1_l_mux = | ||
1069 | SOC_DAPM_ENUM("PDM1 L source", rt5670_pdm1_l_enum); | ||
1070 | |||
1071 | static SOC_ENUM_SINGLE_DECL(rt5670_pdm1_r_enum, RT5670_PDM_OUT_CTRL, | ||
1072 | RT5670_PDM1_R_SFT, rt5670_pdm_src); | ||
1073 | |||
1074 | static const struct snd_kcontrol_new rt5670_pdm1_r_mux = | ||
1075 | SOC_DAPM_ENUM("PDM1 R source", rt5670_pdm1_r_enum); | ||
1076 | |||
1077 | static SOC_ENUM_SINGLE_DECL(rt5670_pdm2_l_enum, RT5670_PDM_OUT_CTRL, | ||
1078 | RT5670_PDM2_L_SFT, rt5670_pdm_src); | ||
1079 | |||
1080 | static const struct snd_kcontrol_new rt5670_pdm2_l_mux = | ||
1081 | SOC_DAPM_ENUM("PDM2 L source", rt5670_pdm2_l_enum); | ||
1082 | |||
1083 | static SOC_ENUM_SINGLE_DECL(rt5670_pdm2_r_enum, RT5670_PDM_OUT_CTRL, | ||
1084 | RT5670_PDM2_R_SFT, rt5670_pdm_src); | ||
1085 | |||
1086 | static const struct snd_kcontrol_new rt5670_pdm2_r_mux = | ||
1087 | SOC_DAPM_ENUM("PDM2 R source", rt5670_pdm2_r_enum); | ||
1088 | |||
1089 | /* MX-FA [12] */ | ||
1090 | static const char * const rt5670_if1_adc1_in1_src[] = { | ||
1091 | "IF_ADC1", "IF1_ADC3" | ||
1092 | }; | ||
1093 | |||
1094 | static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc1_in1_enum, RT5670_DIG_MISC, | ||
1095 | RT5670_IF1_ADC1_IN1_SFT, rt5670_if1_adc1_in1_src); | ||
1096 | |||
1097 | static const struct snd_kcontrol_new rt5670_if1_adc1_in1_mux = | ||
1098 | SOC_DAPM_ENUM("IF1 ADC1 IN1 source", rt5670_if1_adc1_in1_enum); | ||
1099 | |||
1100 | /* MX-FA [11] */ | ||
1101 | static const char * const rt5670_if1_adc1_in2_src[] = { | ||
1102 | "IF1_ADC1_IN1", "IF1_ADC4" | ||
1103 | }; | ||
1104 | |||
1105 | static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc1_in2_enum, RT5670_DIG_MISC, | ||
1106 | RT5670_IF1_ADC1_IN2_SFT, rt5670_if1_adc1_in2_src); | ||
1107 | |||
1108 | static const struct snd_kcontrol_new rt5670_if1_adc1_in2_mux = | ||
1109 | SOC_DAPM_ENUM("IF1 ADC1 IN2 source", rt5670_if1_adc1_in2_enum); | ||
1110 | |||
1111 | /* MX-FA [10] */ | ||
1112 | static const char * const rt5670_if1_adc2_in1_src[] = { | ||
1113 | "IF1_ADC2_IN", "IF1_ADC4" | ||
1114 | }; | ||
1115 | |||
1116 | static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc2_in1_enum, RT5670_DIG_MISC, | ||
1117 | RT5670_IF1_ADC2_IN1_SFT, rt5670_if1_adc2_in1_src); | ||
1118 | |||
1119 | static const struct snd_kcontrol_new rt5670_if1_adc2_in1_mux = | ||
1120 | SOC_DAPM_ENUM("IF1 ADC2 IN1 source", rt5670_if1_adc2_in1_enum); | ||
1121 | |||
1122 | /* MX-9D [9:8] */ | ||
1123 | static const char * const rt5670_vad_adc_src[] = { | ||
1124 | "Sto1 ADC L", "Mono ADC L", "Mono ADC R", "Sto2 ADC L" | ||
1125 | }; | ||
1126 | |||
1127 | static SOC_ENUM_SINGLE_DECL(rt5670_vad_adc_enum, RT5670_VAD_CTRL4, | ||
1128 | RT5670_VAD_SEL_SFT, rt5670_vad_adc_src); | ||
1129 | |||
1130 | static const struct snd_kcontrol_new rt5670_vad_adc_mux = | ||
1131 | SOC_DAPM_ENUM("VAD ADC source", rt5670_vad_adc_enum); | ||
1132 | |||
1133 | static int rt5670_hp_power_event(struct snd_soc_dapm_widget *w, | ||
1134 | struct snd_kcontrol *kcontrol, int event) | ||
1135 | { | ||
1136 | struct snd_soc_codec *codec = w->codec; | ||
1137 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
1138 | |||
1139 | switch (event) { | ||
1140 | case SND_SOC_DAPM_POST_PMU: | ||
1141 | regmap_update_bits(rt5670->regmap, RT5670_CHARGE_PUMP, | ||
1142 | RT5670_PM_HP_MASK, RT5670_PM_HP_HV); | ||
1143 | regmap_update_bits(rt5670->regmap, RT5670_GEN_CTRL2, | ||
1144 | 0x0400, 0x0400); | ||
1145 | /* headphone amp power on */ | ||
1146 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1, | ||
1147 | RT5670_PWR_HA | RT5670_PWR_FV1 | | ||
1148 | RT5670_PWR_FV2, RT5670_PWR_HA | | ||
1149 | RT5670_PWR_FV1 | RT5670_PWR_FV2); | ||
1150 | /* depop parameters */ | ||
1151 | regmap_write(rt5670->regmap, RT5670_DEPOP_M2, 0x3100); | ||
1152 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8009); | ||
1153 | regmap_write(rt5670->regmap, RT5670_PR_BASE + | ||
1154 | RT5670_HP_DCC_INT1, 0x9f00); | ||
1155 | mdelay(20); | ||
1156 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8019); | ||
1157 | break; | ||
1158 | case SND_SOC_DAPM_PRE_PMD: | ||
1159 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x0004); | ||
1160 | msleep(30); | ||
1161 | break; | ||
1162 | default: | ||
1163 | return 0; | ||
1164 | } | ||
1165 | |||
1166 | return 0; | ||
1167 | } | ||
1168 | |||
1169 | static int rt5670_hp_event(struct snd_soc_dapm_widget *w, | ||
1170 | struct snd_kcontrol *kcontrol, int event) | ||
1171 | { | ||
1172 | struct snd_soc_codec *codec = w->codec; | ||
1173 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
1174 | |||
1175 | switch (event) { | ||
1176 | case SND_SOC_DAPM_POST_PMU: | ||
1177 | /* headphone unmute sequence */ | ||
1178 | regmap_write(rt5670->regmap, RT5670_PR_BASE + | ||
1179 | RT5670_MAMP_INT_REG2, 0xb400); | ||
1180 | regmap_write(rt5670->regmap, RT5670_DEPOP_M3, 0x0772); | ||
1181 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x805d); | ||
1182 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x831d); | ||
1183 | regmap_update_bits(rt5670->regmap, RT5670_GEN_CTRL2, | ||
1184 | 0x0300, 0x0300); | ||
1185 | regmap_update_bits(rt5670->regmap, RT5670_HP_VOL, | ||
1186 | RT5670_L_MUTE | RT5670_R_MUTE, 0); | ||
1187 | msleep(80); | ||
1188 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8019); | ||
1189 | break; | ||
1190 | |||
1191 | case SND_SOC_DAPM_PRE_PMD: | ||
1192 | /* headphone mute sequence */ | ||
1193 | regmap_write(rt5670->regmap, RT5670_PR_BASE + | ||
1194 | RT5670_MAMP_INT_REG2, 0xb400); | ||
1195 | regmap_write(rt5670->regmap, RT5670_DEPOP_M3, 0x0772); | ||
1196 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x803d); | ||
1197 | mdelay(10); | ||
1198 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x831d); | ||
1199 | mdelay(10); | ||
1200 | regmap_update_bits(rt5670->regmap, RT5670_HP_VOL, | ||
1201 | RT5670_L_MUTE | RT5670_R_MUTE, | ||
1202 | RT5670_L_MUTE | RT5670_R_MUTE); | ||
1203 | msleep(20); | ||
1204 | regmap_update_bits(rt5670->regmap, | ||
1205 | RT5670_GEN_CTRL2, 0x0300, 0x0); | ||
1206 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8019); | ||
1207 | regmap_write(rt5670->regmap, RT5670_DEPOP_M3, 0x0707); | ||
1208 | regmap_write(rt5670->regmap, RT5670_PR_BASE + | ||
1209 | RT5670_MAMP_INT_REG2, 0xfc00); | ||
1210 | break; | ||
1211 | |||
1212 | default: | ||
1213 | return 0; | ||
1214 | } | ||
1215 | |||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | static int rt5670_bst1_event(struct snd_soc_dapm_widget *w, | ||
1220 | struct snd_kcontrol *kcontrol, int event) | ||
1221 | { | ||
1222 | struct snd_soc_codec *codec = w->codec; | ||
1223 | |||
1224 | switch (event) { | ||
1225 | case SND_SOC_DAPM_POST_PMU: | ||
1226 | snd_soc_update_bits(codec, RT5670_PWR_ANLG2, | ||
1227 | RT5670_PWR_BST1_P, RT5670_PWR_BST1_P); | ||
1228 | break; | ||
1229 | |||
1230 | case SND_SOC_DAPM_PRE_PMD: | ||
1231 | snd_soc_update_bits(codec, RT5670_PWR_ANLG2, | ||
1232 | RT5670_PWR_BST1_P, 0); | ||
1233 | break; | ||
1234 | |||
1235 | default: | ||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1239 | return 0; | ||
1240 | } | ||
1241 | |||
1242 | static int rt5670_bst2_event(struct snd_soc_dapm_widget *w, | ||
1243 | struct snd_kcontrol *kcontrol, int event) | ||
1244 | { | ||
1245 | struct snd_soc_codec *codec = w->codec; | ||
1246 | |||
1247 | switch (event) { | ||
1248 | case SND_SOC_DAPM_POST_PMU: | ||
1249 | snd_soc_update_bits(codec, RT5670_PWR_ANLG2, | ||
1250 | RT5670_PWR_BST2_P, RT5670_PWR_BST2_P); | ||
1251 | break; | ||
1252 | |||
1253 | case SND_SOC_DAPM_PRE_PMD: | ||
1254 | snd_soc_update_bits(codec, RT5670_PWR_ANLG2, | ||
1255 | RT5670_PWR_BST2_P, 0); | ||
1256 | break; | ||
1257 | |||
1258 | default: | ||
1259 | return 0; | ||
1260 | } | ||
1261 | |||
1262 | return 0; | ||
1263 | } | ||
1264 | |||
1265 | static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] = { | ||
1266 | SND_SOC_DAPM_SUPPLY("PLL1", RT5670_PWR_ANLG2, | ||
1267 | RT5670_PWR_PLL_BIT, 0, NULL, 0), | ||
1268 | SND_SOC_DAPM_SUPPLY("I2S DSP", RT5670_PWR_DIG2, | ||
1269 | RT5670_PWR_I2S_DSP_BIT, 0, NULL, 0), | ||
1270 | SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5670_PWR_VOL, | ||
1271 | RT5670_PWR_MIC_DET_BIT, 0, NULL, 0), | ||
1272 | |||
1273 | /* ASRC */ | ||
1274 | SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5670_ASRC_1, | ||
1275 | 11, 0, NULL, 0), | ||
1276 | SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5670_ASRC_1, | ||
1277 | 12, 0, NULL, 0), | ||
1278 | SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5670_ASRC_1, | ||
1279 | 10, 0, NULL, 0), | ||
1280 | SND_SOC_DAPM_SUPPLY_S("DAC MONO L ASRC", 1, RT5670_ASRC_1, | ||
1281 | 9, 0, NULL, 0), | ||
1282 | SND_SOC_DAPM_SUPPLY_S("DAC MONO R ASRC", 1, RT5670_ASRC_1, | ||
1283 | 8, 0, NULL, 0), | ||
1284 | SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5670_ASRC_1, | ||
1285 | 3, 0, NULL, 0), | ||
1286 | SND_SOC_DAPM_SUPPLY_S("ADC STO2 ASRC", 1, RT5670_ASRC_1, | ||
1287 | 2, 0, NULL, 0), | ||
1288 | SND_SOC_DAPM_SUPPLY_S("ADC MONO L ASRC", 1, RT5670_ASRC_1, | ||
1289 | 1, 0, NULL, 0), | ||
1290 | SND_SOC_DAPM_SUPPLY_S("ADC MONO R ASRC", 1, RT5670_ASRC_1, | ||
1291 | 0, 0, NULL, 0), | ||
1292 | |||
1293 | /* Input Side */ | ||
1294 | /* micbias */ | ||
1295 | SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5670_PWR_ANLG2, | ||
1296 | RT5670_PWR_MB1_BIT, 0, NULL, 0), | ||
1297 | |||
1298 | /* Input Lines */ | ||
1299 | SND_SOC_DAPM_INPUT("DMIC L1"), | ||
1300 | SND_SOC_DAPM_INPUT("DMIC R1"), | ||
1301 | SND_SOC_DAPM_INPUT("DMIC L2"), | ||
1302 | SND_SOC_DAPM_INPUT("DMIC R2"), | ||
1303 | SND_SOC_DAPM_INPUT("DMIC L3"), | ||
1304 | SND_SOC_DAPM_INPUT("DMIC R3"), | ||
1305 | |||
1306 | SND_SOC_DAPM_INPUT("IN1P"), | ||
1307 | SND_SOC_DAPM_INPUT("IN1N"), | ||
1308 | SND_SOC_DAPM_INPUT("IN2P"), | ||
1309 | SND_SOC_DAPM_INPUT("IN2N"), | ||
1310 | |||
1311 | SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1312 | SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1313 | SND_SOC_DAPM_PGA("DMIC3", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1314 | |||
1315 | SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0, | ||
1316 | set_dmic_clk, SND_SOC_DAPM_PRE_PMU), | ||
1317 | SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5670_DMIC_CTRL1, | ||
1318 | RT5670_DMIC_1_EN_SFT, 0, NULL, 0), | ||
1319 | SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5670_DMIC_CTRL1, | ||
1320 | RT5670_DMIC_2_EN_SFT, 0, NULL, 0), | ||
1321 | SND_SOC_DAPM_SUPPLY("DMIC3 Power", RT5670_DMIC_CTRL1, | ||
1322 | RT5670_DMIC_3_EN_SFT, 0, NULL, 0), | ||
1323 | /* Boost */ | ||
1324 | SND_SOC_DAPM_PGA_E("BST1", RT5670_PWR_ANLG2, RT5670_PWR_BST1_BIT, | ||
1325 | 0, NULL, 0, rt5670_bst1_event, | ||
1326 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
1327 | SND_SOC_DAPM_PGA_E("BST2", RT5670_PWR_ANLG2, RT5670_PWR_BST2_BIT, | ||
1328 | 0, NULL, 0, rt5670_bst2_event, | ||
1329 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
1330 | /* Input Volume */ | ||
1331 | SND_SOC_DAPM_PGA("INL VOL", RT5670_PWR_VOL, | ||
1332 | RT5670_PWR_IN_L_BIT, 0, NULL, 0), | ||
1333 | SND_SOC_DAPM_PGA("INR VOL", RT5670_PWR_VOL, | ||
1334 | RT5670_PWR_IN_R_BIT, 0, NULL, 0), | ||
1335 | |||
1336 | /* REC Mixer */ | ||
1337 | SND_SOC_DAPM_MIXER("RECMIXL", RT5670_PWR_MIXER, RT5670_PWR_RM_L_BIT, 0, | ||
1338 | rt5670_rec_l_mix, ARRAY_SIZE(rt5670_rec_l_mix)), | ||
1339 | SND_SOC_DAPM_MIXER("RECMIXR", RT5670_PWR_MIXER, RT5670_PWR_RM_R_BIT, 0, | ||
1340 | rt5670_rec_r_mix, ARRAY_SIZE(rt5670_rec_r_mix)), | ||
1341 | /* ADCs */ | ||
1342 | SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), | ||
1343 | SND_SOC_DAPM_ADC("ADC 2", NULL, SND_SOC_NOPM, 0, 0), | ||
1344 | |||
1345 | SND_SOC_DAPM_PGA("ADC 1_2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1346 | |||
1347 | SND_SOC_DAPM_SUPPLY("ADC 1 power", RT5670_PWR_DIG1, | ||
1348 | RT5670_PWR_ADC_L_BIT, 0, NULL, 0), | ||
1349 | SND_SOC_DAPM_SUPPLY("ADC 2 power", RT5670_PWR_DIG1, | ||
1350 | RT5670_PWR_ADC_R_BIT, 0, NULL, 0), | ||
1351 | SND_SOC_DAPM_SUPPLY("ADC clock", RT5670_PR_BASE + | ||
1352 | RT5670_CHOP_DAC_ADC, 12, 0, NULL, 0), | ||
1353 | /* ADC Mux */ | ||
1354 | SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0, | ||
1355 | &rt5670_sto1_dmic_mux), | ||
1356 | SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0, | ||
1357 | &rt5670_sto_adc_l2_mux), | ||
1358 | SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0, | ||
1359 | &rt5670_sto_adc_r2_mux), | ||
1360 | SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0, | ||
1361 | &rt5670_sto_adc_l1_mux), | ||
1362 | SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0, | ||
1363 | &rt5670_sto_adc_r1_mux), | ||
1364 | SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0, | ||
1365 | &rt5670_sto2_dmic_mux), | ||
1366 | SND_SOC_DAPM_MUX("Stereo2 ADC L2 Mux", SND_SOC_NOPM, 0, 0, | ||
1367 | &rt5670_sto2_adc_l2_mux), | ||
1368 | SND_SOC_DAPM_MUX("Stereo2 ADC R2 Mux", SND_SOC_NOPM, 0, 0, | ||
1369 | &rt5670_sto2_adc_r2_mux), | ||
1370 | SND_SOC_DAPM_MUX("Stereo2 ADC L1 Mux", SND_SOC_NOPM, 0, 0, | ||
1371 | &rt5670_sto2_adc_l1_mux), | ||
1372 | SND_SOC_DAPM_MUX("Stereo2 ADC R1 Mux", SND_SOC_NOPM, 0, 0, | ||
1373 | &rt5670_sto2_adc_r1_mux), | ||
1374 | SND_SOC_DAPM_MUX("Stereo2 ADC LR Mux", SND_SOC_NOPM, 0, 0, | ||
1375 | &rt5670_sto2_adc_lr_mux), | ||
1376 | SND_SOC_DAPM_MUX("Mono DMIC L Mux", SND_SOC_NOPM, 0, 0, | ||
1377 | &rt5670_mono_dmic_l_mux), | ||
1378 | SND_SOC_DAPM_MUX("Mono DMIC R Mux", SND_SOC_NOPM, 0, 0, | ||
1379 | &rt5670_mono_dmic_r_mux), | ||
1380 | SND_SOC_DAPM_MUX("Mono ADC L2 Mux", SND_SOC_NOPM, 0, 0, | ||
1381 | &rt5670_mono_adc_l2_mux), | ||
1382 | SND_SOC_DAPM_MUX("Mono ADC L1 Mux", SND_SOC_NOPM, 0, 0, | ||
1383 | &rt5670_mono_adc_l1_mux), | ||
1384 | SND_SOC_DAPM_MUX("Mono ADC R1 Mux", SND_SOC_NOPM, 0, 0, | ||
1385 | &rt5670_mono_adc_r1_mux), | ||
1386 | SND_SOC_DAPM_MUX("Mono ADC R2 Mux", SND_SOC_NOPM, 0, 0, | ||
1387 | &rt5670_mono_adc_r2_mux), | ||
1388 | /* ADC Mixer */ | ||
1389 | SND_SOC_DAPM_SUPPLY("ADC Stereo1 Filter", RT5670_PWR_DIG2, | ||
1390 | RT5670_PWR_ADC_S1F_BIT, 0, NULL, 0), | ||
1391 | SND_SOC_DAPM_SUPPLY("ADC Stereo2 Filter", RT5670_PWR_DIG2, | ||
1392 | RT5670_PWR_ADC_S2F_BIT, 0, NULL, 0), | ||
1393 | SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", RT5670_STO1_ADC_DIG_VOL, | ||
1394 | RT5670_L_MUTE_SFT, 1, rt5670_sto1_adc_l_mix, | ||
1395 | ARRAY_SIZE(rt5670_sto1_adc_l_mix)), | ||
1396 | SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", RT5670_STO1_ADC_DIG_VOL, | ||
1397 | RT5670_R_MUTE_SFT, 1, rt5670_sto1_adc_r_mix, | ||
1398 | ARRAY_SIZE(rt5670_sto1_adc_r_mix)), | ||
1399 | SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0, | ||
1400 | rt5670_sto2_adc_l_mix, | ||
1401 | ARRAY_SIZE(rt5670_sto2_adc_l_mix)), | ||
1402 | SND_SOC_DAPM_MIXER("Sto2 ADC MIXR", SND_SOC_NOPM, 0, 0, | ||
1403 | rt5670_sto2_adc_r_mix, | ||
1404 | ARRAY_SIZE(rt5670_sto2_adc_r_mix)), | ||
1405 | SND_SOC_DAPM_SUPPLY("ADC Mono Left Filter", RT5670_PWR_DIG2, | ||
1406 | RT5670_PWR_ADC_MF_L_BIT, 0, NULL, 0), | ||
1407 | SND_SOC_DAPM_MIXER("Mono ADC MIXL", RT5670_MONO_ADC_DIG_VOL, | ||
1408 | RT5670_L_MUTE_SFT, 1, rt5670_mono_adc_l_mix, | ||
1409 | ARRAY_SIZE(rt5670_mono_adc_l_mix)), | ||
1410 | SND_SOC_DAPM_SUPPLY("ADC Mono Right Filter", RT5670_PWR_DIG2, | ||
1411 | RT5670_PWR_ADC_MF_R_BIT, 0, NULL, 0), | ||
1412 | SND_SOC_DAPM_MIXER("Mono ADC MIXR", RT5670_MONO_ADC_DIG_VOL, | ||
1413 | RT5670_R_MUTE_SFT, 1, rt5670_mono_adc_r_mix, | ||
1414 | ARRAY_SIZE(rt5670_mono_adc_r_mix)), | ||
1415 | |||
1416 | /* ADC PGA */ | ||
1417 | SND_SOC_DAPM_PGA("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1418 | SND_SOC_DAPM_PGA("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1419 | SND_SOC_DAPM_PGA("Stereo2 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1420 | SND_SOC_DAPM_PGA("Stereo2 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1421 | SND_SOC_DAPM_PGA("Sto2 ADC LR MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1422 | SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1423 | SND_SOC_DAPM_PGA("Stereo2 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1424 | SND_SOC_DAPM_PGA("Mono ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1425 | SND_SOC_DAPM_PGA("VAD_ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1426 | SND_SOC_DAPM_PGA("IF_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1427 | SND_SOC_DAPM_PGA("IF_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1428 | SND_SOC_DAPM_PGA("IF_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1429 | SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1430 | SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1431 | SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1432 | SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1433 | |||
1434 | /* DSP */ | ||
1435 | SND_SOC_DAPM_PGA("TxDP_ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1436 | SND_SOC_DAPM_PGA("TxDP_ADC_L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1437 | SND_SOC_DAPM_PGA("TxDP_ADC_R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1438 | SND_SOC_DAPM_PGA("TxDC_DAC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1439 | |||
1440 | SND_SOC_DAPM_MUX("TDM Data Mux", SND_SOC_NOPM, 0, 0, | ||
1441 | &rt5670_txdp_slot_mux), | ||
1442 | |||
1443 | SND_SOC_DAPM_MUX("DSP UL Mux", SND_SOC_NOPM, 0, 0, | ||
1444 | &rt5670_dsp_ul_mux), | ||
1445 | SND_SOC_DAPM_MUX("DSP DL Mux", SND_SOC_NOPM, 0, 0, | ||
1446 | &rt5670_dsp_dl_mux), | ||
1447 | |||
1448 | SND_SOC_DAPM_MUX("RxDP Mux", SND_SOC_NOPM, 0, 0, | ||
1449 | &rt5670_rxdp_mux), | ||
1450 | |||
1451 | /* IF2 Mux */ | ||
1452 | SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM, 0, 0, | ||
1453 | &rt5670_if2_adc_in_mux), | ||
1454 | |||
1455 | /* Digital Interface */ | ||
1456 | SND_SOC_DAPM_SUPPLY("I2S1", RT5670_PWR_DIG1, | ||
1457 | RT5670_PWR_I2S1_BIT, 0, NULL, 0), | ||
1458 | SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1459 | SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1460 | SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1461 | SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1462 | SND_SOC_DAPM_PGA("IF1 DAC2 L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1463 | SND_SOC_DAPM_PGA("IF1 DAC2 R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1464 | SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1465 | SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1466 | SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1467 | SND_SOC_DAPM_SUPPLY("I2S2", RT5670_PWR_DIG1, | ||
1468 | RT5670_PWR_I2S2_BIT, 0, NULL, 0), | ||
1469 | SND_SOC_DAPM_PGA("IF2 DAC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1470 | SND_SOC_DAPM_PGA("IF2 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1471 | SND_SOC_DAPM_PGA("IF2 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1472 | SND_SOC_DAPM_PGA("IF2 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1473 | SND_SOC_DAPM_PGA("IF2 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1474 | SND_SOC_DAPM_PGA("IF2 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1475 | |||
1476 | /* Digital Interface Select */ | ||
1477 | SND_SOC_DAPM_MUX("IF1 ADC1 IN1 Mux", SND_SOC_NOPM, 0, 0, | ||
1478 | &rt5670_if1_adc1_in1_mux), | ||
1479 | SND_SOC_DAPM_MUX("IF1 ADC1 IN2 Mux", SND_SOC_NOPM, 0, 0, | ||
1480 | &rt5670_if1_adc1_in2_mux), | ||
1481 | SND_SOC_DAPM_MUX("IF1 ADC2 IN Mux", SND_SOC_NOPM, 0, 0, | ||
1482 | &rt5670_if1_adc2_in_mux), | ||
1483 | SND_SOC_DAPM_MUX("IF1 ADC2 IN1 Mux", SND_SOC_NOPM, 0, 0, | ||
1484 | &rt5670_if1_adc2_in1_mux), | ||
1485 | SND_SOC_DAPM_MUX("VAD ADC Mux", SND_SOC_NOPM, 0, 0, | ||
1486 | &rt5670_vad_adc_mux), | ||
1487 | |||
1488 | /* Audio Interface */ | ||
1489 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
1490 | SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
1491 | SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
1492 | SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, | ||
1493 | RT5670_GPIO_CTRL1, RT5670_I2S2_PIN_SFT, 1), | ||
1494 | |||
1495 | /* Audio DSP */ | ||
1496 | SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1497 | |||
1498 | /* Output Side */ | ||
1499 | /* DAC mixer before sound effect */ | ||
1500 | SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0, | ||
1501 | rt5670_dac_l_mix, ARRAY_SIZE(rt5670_dac_l_mix)), | ||
1502 | SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0, | ||
1503 | rt5670_dac_r_mix, ARRAY_SIZE(rt5670_dac_r_mix)), | ||
1504 | SND_SOC_DAPM_PGA("DAC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1505 | |||
1506 | /* DAC2 channel Mux */ | ||
1507 | SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0, | ||
1508 | &rt5670_dac_l2_mux), | ||
1509 | SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0, | ||
1510 | &rt5670_dac_r2_mux), | ||
1511 | SND_SOC_DAPM_PGA("DAC L2 Volume", RT5670_PWR_DIG1, | ||
1512 | RT5670_PWR_DAC_L2_BIT, 0, NULL, 0), | ||
1513 | SND_SOC_DAPM_PGA("DAC R2 Volume", RT5670_PWR_DIG1, | ||
1514 | RT5670_PWR_DAC_R2_BIT, 0, NULL, 0), | ||
1515 | |||
1516 | SND_SOC_DAPM_MUX("DAC1 L Mux", SND_SOC_NOPM, 0, 0, &rt5670_dac1l_mux), | ||
1517 | SND_SOC_DAPM_MUX("DAC1 R Mux", SND_SOC_NOPM, 0, 0, &rt5670_dac1r_mux), | ||
1518 | |||
1519 | /* DAC Mixer */ | ||
1520 | SND_SOC_DAPM_SUPPLY("DAC Stereo1 Filter", RT5670_PWR_DIG2, | ||
1521 | RT5670_PWR_DAC_S1F_BIT, 0, NULL, 0), | ||
1522 | SND_SOC_DAPM_SUPPLY("DAC Mono Left Filter", RT5670_PWR_DIG2, | ||
1523 | RT5670_PWR_DAC_MF_L_BIT, 0, NULL, 0), | ||
1524 | SND_SOC_DAPM_SUPPLY("DAC Mono Right Filter", RT5670_PWR_DIG2, | ||
1525 | RT5670_PWR_DAC_MF_R_BIT, 0, NULL, 0), | ||
1526 | SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0, | ||
1527 | rt5670_sto_dac_l_mix, | ||
1528 | ARRAY_SIZE(rt5670_sto_dac_l_mix)), | ||
1529 | SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0, | ||
1530 | rt5670_sto_dac_r_mix, | ||
1531 | ARRAY_SIZE(rt5670_sto_dac_r_mix)), | ||
1532 | SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0, | ||
1533 | rt5670_mono_dac_l_mix, | ||
1534 | ARRAY_SIZE(rt5670_mono_dac_l_mix)), | ||
1535 | SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0, | ||
1536 | rt5670_mono_dac_r_mix, | ||
1537 | ARRAY_SIZE(rt5670_mono_dac_r_mix)), | ||
1538 | SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0, | ||
1539 | rt5670_dig_l_mix, | ||
1540 | ARRAY_SIZE(rt5670_dig_l_mix)), | ||
1541 | SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0, | ||
1542 | rt5670_dig_r_mix, | ||
1543 | ARRAY_SIZE(rt5670_dig_r_mix)), | ||
1544 | |||
1545 | /* DACs */ | ||
1546 | SND_SOC_DAPM_SUPPLY("DAC L1 Power", RT5670_PWR_DIG1, | ||
1547 | RT5670_PWR_DAC_L1_BIT, 0, NULL, 0), | ||
1548 | SND_SOC_DAPM_SUPPLY("DAC R1 Power", RT5670_PWR_DIG1, | ||
1549 | RT5670_PWR_DAC_R1_BIT, 0, NULL, 0), | ||
1550 | SND_SOC_DAPM_DAC("DAC L1", NULL, SND_SOC_NOPM, 0, 0), | ||
1551 | SND_SOC_DAPM_DAC("DAC R1", NULL, SND_SOC_NOPM, 0, 0), | ||
1552 | SND_SOC_DAPM_DAC("DAC L2", NULL, RT5670_PWR_DIG1, | ||
1553 | RT5670_PWR_DAC_L2_BIT, 0), | ||
1554 | |||
1555 | SND_SOC_DAPM_DAC("DAC R2", NULL, RT5670_PWR_DIG1, | ||
1556 | RT5670_PWR_DAC_R2_BIT, 0), | ||
1557 | /* OUT Mixer */ | ||
1558 | |||
1559 | SND_SOC_DAPM_MIXER("OUT MIXL", RT5670_PWR_MIXER, RT5670_PWR_OM_L_BIT, | ||
1560 | 0, rt5670_out_l_mix, ARRAY_SIZE(rt5670_out_l_mix)), | ||
1561 | SND_SOC_DAPM_MIXER("OUT MIXR", RT5670_PWR_MIXER, RT5670_PWR_OM_R_BIT, | ||
1562 | 0, rt5670_out_r_mix, ARRAY_SIZE(rt5670_out_r_mix)), | ||
1563 | /* Ouput Volume */ | ||
1564 | SND_SOC_DAPM_MIXER("HPOVOL MIXL", RT5670_PWR_VOL, | ||
1565 | RT5670_PWR_HV_L_BIT, 0, | ||
1566 | rt5670_hpvoll_mix, ARRAY_SIZE(rt5670_hpvoll_mix)), | ||
1567 | SND_SOC_DAPM_MIXER("HPOVOL MIXR", RT5670_PWR_VOL, | ||
1568 | RT5670_PWR_HV_R_BIT, 0, | ||
1569 | rt5670_hpvolr_mix, ARRAY_SIZE(rt5670_hpvolr_mix)), | ||
1570 | SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1571 | SND_SOC_DAPM_PGA("DAC 2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1572 | SND_SOC_DAPM_PGA("HPOVOL", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1573 | |||
1574 | /* HPO/LOUT/Mono Mixer */ | ||
1575 | SND_SOC_DAPM_MIXER("HPO MIX", SND_SOC_NOPM, 0, 0, | ||
1576 | rt5670_hpo_mix, ARRAY_SIZE(rt5670_hpo_mix)), | ||
1577 | SND_SOC_DAPM_MIXER("LOUT MIX", RT5670_PWR_ANLG1, RT5670_PWR_LM_BIT, | ||
1578 | 0, rt5670_lout_mix, ARRAY_SIZE(rt5670_lout_mix)), | ||
1579 | SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM, 0, 0, | ||
1580 | rt5670_hp_power_event, SND_SOC_DAPM_POST_PMU | | ||
1581 | SND_SOC_DAPM_PRE_PMD), | ||
1582 | SND_SOC_DAPM_SUPPLY("HP L Amp", RT5670_PWR_ANLG1, | ||
1583 | RT5670_PWR_HP_L_BIT, 0, NULL, 0), | ||
1584 | SND_SOC_DAPM_SUPPLY("HP R Amp", RT5670_PWR_ANLG1, | ||
1585 | RT5670_PWR_HP_R_BIT, 0, NULL, 0), | ||
1586 | SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, | ||
1587 | rt5670_hp_event, SND_SOC_DAPM_PRE_PMD | | ||
1588 | SND_SOC_DAPM_POST_PMU), | ||
1589 | SND_SOC_DAPM_SWITCH("LOUT L Playback", SND_SOC_NOPM, 0, 0, | ||
1590 | &lout_l_enable_control), | ||
1591 | SND_SOC_DAPM_SWITCH("LOUT R Playback", SND_SOC_NOPM, 0, 0, | ||
1592 | &lout_r_enable_control), | ||
1593 | SND_SOC_DAPM_PGA("LOUT Amp", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1594 | |||
1595 | /* PDM */ | ||
1596 | SND_SOC_DAPM_SUPPLY("PDM1 Power", RT5670_PWR_DIG2, | ||
1597 | RT5670_PWR_PDM1_BIT, 0, NULL, 0), | ||
1598 | SND_SOC_DAPM_SUPPLY("PDM2 Power", RT5670_PWR_DIG2, | ||
1599 | RT5670_PWR_PDM2_BIT, 0, NULL, 0), | ||
1600 | |||
1601 | SND_SOC_DAPM_MUX("PDM1 L Mux", RT5670_PDM_OUT_CTRL, | ||
1602 | RT5670_M_PDM1_L_SFT, 1, &rt5670_pdm1_l_mux), | ||
1603 | SND_SOC_DAPM_MUX("PDM1 R Mux", RT5670_PDM_OUT_CTRL, | ||
1604 | RT5670_M_PDM1_R_SFT, 1, &rt5670_pdm1_r_mux), | ||
1605 | SND_SOC_DAPM_MUX("PDM2 L Mux", RT5670_PDM_OUT_CTRL, | ||
1606 | RT5670_M_PDM2_L_SFT, 1, &rt5670_pdm2_l_mux), | ||
1607 | SND_SOC_DAPM_MUX("PDM2 R Mux", RT5670_PDM_OUT_CTRL, | ||
1608 | RT5670_M_PDM2_R_SFT, 1, &rt5670_pdm2_r_mux), | ||
1609 | |||
1610 | /* Output Lines */ | ||
1611 | SND_SOC_DAPM_OUTPUT("HPOL"), | ||
1612 | SND_SOC_DAPM_OUTPUT("HPOR"), | ||
1613 | SND_SOC_DAPM_OUTPUT("LOUTL"), | ||
1614 | SND_SOC_DAPM_OUTPUT("LOUTR"), | ||
1615 | SND_SOC_DAPM_OUTPUT("PDM1L"), | ||
1616 | SND_SOC_DAPM_OUTPUT("PDM1R"), | ||
1617 | SND_SOC_DAPM_OUTPUT("PDM2L"), | ||
1618 | SND_SOC_DAPM_OUTPUT("PDM2R"), | ||
1619 | }; | ||
1620 | |||
1621 | static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { | ||
1622 | { "ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc }, | ||
1623 | { "ADC Stereo2 Filter", NULL, "ADC STO2 ASRC", is_using_asrc }, | ||
1624 | { "ADC Mono Left Filter", NULL, "ADC MONO L ASRC", is_using_asrc }, | ||
1625 | { "ADC Mono Right Filter", NULL, "ADC MONO R ASRC", is_using_asrc }, | ||
1626 | { "DAC Mono Left Filter", NULL, "DAC MONO L ASRC", is_using_asrc }, | ||
1627 | { "DAC Mono Right Filter", NULL, "DAC MONO R ASRC", is_using_asrc }, | ||
1628 | { "DAC Stereo1 Filter", NULL, "DAC STO ASRC", is_using_asrc }, | ||
1629 | |||
1630 | { "I2S1", NULL, "I2S1 ASRC" }, | ||
1631 | { "I2S2", NULL, "I2S2 ASRC" }, | ||
1632 | |||
1633 | { "DMIC1", NULL, "DMIC L1" }, | ||
1634 | { "DMIC1", NULL, "DMIC R1" }, | ||
1635 | { "DMIC2", NULL, "DMIC L2" }, | ||
1636 | { "DMIC2", NULL, "DMIC R2" }, | ||
1637 | { "DMIC3", NULL, "DMIC L3" }, | ||
1638 | { "DMIC3", NULL, "DMIC R3" }, | ||
1639 | |||
1640 | { "BST1", NULL, "IN1P" }, | ||
1641 | { "BST1", NULL, "IN1N" }, | ||
1642 | { "BST1", NULL, "Mic Det Power" }, | ||
1643 | { "BST2", NULL, "IN2P" }, | ||
1644 | { "BST2", NULL, "IN2N" }, | ||
1645 | |||
1646 | { "INL VOL", NULL, "IN2P" }, | ||
1647 | { "INR VOL", NULL, "IN2N" }, | ||
1648 | |||
1649 | { "RECMIXL", "INL Switch", "INL VOL" }, | ||
1650 | { "RECMIXL", "BST2 Switch", "BST2" }, | ||
1651 | { "RECMIXL", "BST1 Switch", "BST1" }, | ||
1652 | |||
1653 | { "RECMIXR", "INR Switch", "INR VOL" }, | ||
1654 | { "RECMIXR", "BST2 Switch", "BST2" }, | ||
1655 | { "RECMIXR", "BST1 Switch", "BST1" }, | ||
1656 | |||
1657 | { "ADC 1", NULL, "RECMIXL" }, | ||
1658 | { "ADC 1", NULL, "ADC 1 power" }, | ||
1659 | { "ADC 1", NULL, "ADC clock" }, | ||
1660 | { "ADC 2", NULL, "RECMIXR" }, | ||
1661 | { "ADC 2", NULL, "ADC 2 power" }, | ||
1662 | { "ADC 2", NULL, "ADC clock" }, | ||
1663 | |||
1664 | { "DMIC L1", NULL, "DMIC CLK" }, | ||
1665 | { "DMIC L1", NULL, "DMIC1 Power" }, | ||
1666 | { "DMIC R1", NULL, "DMIC CLK" }, | ||
1667 | { "DMIC R1", NULL, "DMIC1 Power" }, | ||
1668 | { "DMIC L2", NULL, "DMIC CLK" }, | ||
1669 | { "DMIC L2", NULL, "DMIC2 Power" }, | ||
1670 | { "DMIC R2", NULL, "DMIC CLK" }, | ||
1671 | { "DMIC R2", NULL, "DMIC2 Power" }, | ||
1672 | { "DMIC L3", NULL, "DMIC CLK" }, | ||
1673 | { "DMIC L3", NULL, "DMIC3 Power" }, | ||
1674 | { "DMIC R3", NULL, "DMIC CLK" }, | ||
1675 | { "DMIC R3", NULL, "DMIC3 Power" }, | ||
1676 | |||
1677 | { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" }, | ||
1678 | { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" }, | ||
1679 | { "Stereo1 DMIC Mux", "DMIC3", "DMIC3" }, | ||
1680 | |||
1681 | { "Stereo2 DMIC Mux", "DMIC1", "DMIC1" }, | ||
1682 | { "Stereo2 DMIC Mux", "DMIC2", "DMIC2" }, | ||
1683 | { "Stereo2 DMIC Mux", "DMIC3", "DMIC3" }, | ||
1684 | |||
1685 | { "Mono DMIC L Mux", "DMIC1", "DMIC L1" }, | ||
1686 | { "Mono DMIC L Mux", "DMIC2", "DMIC L2" }, | ||
1687 | { "Mono DMIC L Mux", "DMIC3", "DMIC L3" }, | ||
1688 | |||
1689 | { "Mono DMIC R Mux", "DMIC1", "DMIC R1" }, | ||
1690 | { "Mono DMIC R Mux", "DMIC2", "DMIC R2" }, | ||
1691 | { "Mono DMIC R Mux", "DMIC3", "DMIC R3" }, | ||
1692 | |||
1693 | { "ADC 1_2", NULL, "ADC 1" }, | ||
1694 | { "ADC 1_2", NULL, "ADC 2" }, | ||
1695 | |||
1696 | { "Stereo1 ADC L2 Mux", "DMIC", "Stereo1 DMIC Mux" }, | ||
1697 | { "Stereo1 ADC L2 Mux", "DAC MIX", "DAC MIXL" }, | ||
1698 | { "Stereo1 ADC L1 Mux", "ADC", "ADC 1_2" }, | ||
1699 | { "Stereo1 ADC L1 Mux", "DAC MIX", "DAC MIXL" }, | ||
1700 | |||
1701 | { "Stereo1 ADC R1 Mux", "ADC", "ADC 1_2" }, | ||
1702 | { "Stereo1 ADC R1 Mux", "DAC MIX", "DAC MIXR" }, | ||
1703 | { "Stereo1 ADC R2 Mux", "DMIC", "Stereo1 DMIC Mux" }, | ||
1704 | { "Stereo1 ADC R2 Mux", "DAC MIX", "DAC MIXR" }, | ||
1705 | |||
1706 | { "Mono ADC L2 Mux", "DMIC", "Mono DMIC L Mux" }, | ||
1707 | { "Mono ADC L2 Mux", "Mono DAC MIXL", "Mono DAC MIXL" }, | ||
1708 | { "Mono ADC L1 Mux", "Mono DAC MIXL", "Mono DAC MIXL" }, | ||
1709 | { "Mono ADC L1 Mux", "ADC1", "ADC 1" }, | ||
1710 | |||
1711 | { "Mono ADC R1 Mux", "Mono DAC MIXR", "Mono DAC MIXR" }, | ||
1712 | { "Mono ADC R1 Mux", "ADC2", "ADC 2" }, | ||
1713 | { "Mono ADC R2 Mux", "DMIC", "Mono DMIC R Mux" }, | ||
1714 | { "Mono ADC R2 Mux", "Mono DAC MIXR", "Mono DAC MIXR" }, | ||
1715 | |||
1716 | { "Sto1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC L1 Mux" }, | ||
1717 | { "Sto1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC L2 Mux" }, | ||
1718 | { "Sto1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC R1 Mux" }, | ||
1719 | { "Sto1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux" }, | ||
1720 | |||
1721 | { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, | ||
1722 | { "Stereo1 ADC MIXL", NULL, "ADC Stereo1 Filter" }, | ||
1723 | { "ADC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1724 | |||
1725 | { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, | ||
1726 | { "Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter" }, | ||
1727 | { "ADC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1728 | |||
1729 | { "Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux" }, | ||
1730 | { "Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux" }, | ||
1731 | { "Mono ADC MIXL", NULL, "ADC Mono Left Filter" }, | ||
1732 | { "ADC Mono Left Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1733 | |||
1734 | { "Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux" }, | ||
1735 | { "Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux" }, | ||
1736 | { "Mono ADC MIXR", NULL, "ADC Mono Right Filter" }, | ||
1737 | { "ADC Mono Right Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1738 | |||
1739 | { "Stereo2 ADC L2 Mux", "DMIC", "Stereo2 DMIC Mux" }, | ||
1740 | { "Stereo2 ADC L2 Mux", "DAC MIX", "DAC MIXL" }, | ||
1741 | { "Stereo2 ADC L1 Mux", "ADC", "ADC 1_2" }, | ||
1742 | { "Stereo2 ADC L1 Mux", "DAC MIX", "DAC MIXL" }, | ||
1743 | |||
1744 | { "Stereo2 ADC R1 Mux", "ADC", "ADC 1_2" }, | ||
1745 | { "Stereo2 ADC R1 Mux", "DAC MIX", "DAC MIXR" }, | ||
1746 | { "Stereo2 ADC R2 Mux", "DMIC", "Stereo2 DMIC Mux" }, | ||
1747 | { "Stereo2 ADC R2 Mux", "DAC MIX", "DAC MIXR" }, | ||
1748 | |||
1749 | { "Sto2 ADC MIXL", "ADC1 Switch", "Stereo2 ADC L1 Mux" }, | ||
1750 | { "Sto2 ADC MIXL", "ADC2 Switch", "Stereo2 ADC L2 Mux" }, | ||
1751 | { "Sto2 ADC MIXR", "ADC1 Switch", "Stereo2 ADC R1 Mux" }, | ||
1752 | { "Sto2 ADC MIXR", "ADC2 Switch", "Stereo2 ADC R2 Mux" }, | ||
1753 | |||
1754 | { "Sto2 ADC LR MIX", NULL, "Sto2 ADC MIXL" }, | ||
1755 | { "Sto2 ADC LR MIX", NULL, "Sto2 ADC MIXR" }, | ||
1756 | |||
1757 | { "Stereo2 ADC LR Mux", "L", "Sto2 ADC MIXL" }, | ||
1758 | { "Stereo2 ADC LR Mux", "LR", "Sto2 ADC LR MIX" }, | ||
1759 | |||
1760 | { "Stereo2 ADC MIXL", NULL, "Stereo2 ADC LR Mux" }, | ||
1761 | { "Stereo2 ADC MIXL", NULL, "ADC Stereo2 Filter" }, | ||
1762 | { "ADC Stereo2 Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1763 | |||
1764 | { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, | ||
1765 | { "Stereo2 ADC MIXR", NULL, "ADC Stereo2 Filter" }, | ||
1766 | { "ADC Stereo2 Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1767 | |||
1768 | { "VAD ADC Mux", "Sto1 ADC L", "Stereo1 ADC MIXL" }, | ||
1769 | { "VAD ADC Mux", "Mono ADC L", "Mono ADC MIXL" }, | ||
1770 | { "VAD ADC Mux", "Mono ADC R", "Mono ADC MIXR" }, | ||
1771 | { "VAD ADC Mux", "Sto2 ADC L", "Sto2 ADC MIXL" }, | ||
1772 | |||
1773 | { "VAD_ADC", NULL, "VAD ADC Mux" }, | ||
1774 | |||
1775 | { "IF_ADC1", NULL, "Stereo1 ADC MIXL" }, | ||
1776 | { "IF_ADC1", NULL, "Stereo1 ADC MIXR" }, | ||
1777 | { "IF_ADC2", NULL, "Mono ADC MIXL" }, | ||
1778 | { "IF_ADC2", NULL, "Mono ADC MIXR" }, | ||
1779 | { "IF_ADC3", NULL, "Stereo2 ADC MIXL" }, | ||
1780 | { "IF_ADC3", NULL, "Stereo2 ADC MIXR" }, | ||
1781 | |||
1782 | { "IF1 ADC1 IN1 Mux", "IF_ADC1", "IF_ADC1" }, | ||
1783 | { "IF1 ADC1 IN1 Mux", "IF1_ADC3", "IF1_ADC3" }, | ||
1784 | |||
1785 | { "IF1 ADC1 IN2 Mux", "IF1_ADC1_IN1", "IF1 ADC1 IN1 Mux" }, | ||
1786 | { "IF1 ADC1 IN2 Mux", "IF1_ADC4", "IF1_ADC4" }, | ||
1787 | |||
1788 | { "IF1 ADC2 IN Mux", "IF_ADC2", "IF_ADC2" }, | ||
1789 | { "IF1 ADC2 IN Mux", "VAD_ADC", "VAD_ADC" }, | ||
1790 | |||
1791 | { "IF1 ADC2 IN1 Mux", "IF1_ADC2_IN", "IF1 ADC2 IN Mux" }, | ||
1792 | { "IF1 ADC2 IN1 Mux", "IF1_ADC4", "IF1_ADC4" }, | ||
1793 | |||
1794 | { "IF1_ADC1" , NULL, "IF1 ADC1 IN2 Mux" }, | ||
1795 | { "IF1_ADC2" , NULL, "IF1 ADC2 IN1 Mux" }, | ||
1796 | |||
1797 | { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL" }, | ||
1798 | { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR" }, | ||
1799 | { "Stereo2 ADC MIX", NULL, "Sto2 ADC MIXL" }, | ||
1800 | { "Stereo2 ADC MIX", NULL, "Sto2 ADC MIXR" }, | ||
1801 | { "Mono ADC MIX", NULL, "Mono ADC MIXL" }, | ||
1802 | { "Mono ADC MIX", NULL, "Mono ADC MIXR" }, | ||
1803 | |||
1804 | { "RxDP Mux", "IF2 DAC", "IF2 DAC" }, | ||
1805 | { "RxDP Mux", "IF1 DAC", "IF1 DAC2" }, | ||
1806 | { "RxDP Mux", "STO1 ADC Mixer", "Stereo1 ADC MIX" }, | ||
1807 | { "RxDP Mux", "STO2 ADC Mixer", "Stereo2 ADC MIX" }, | ||
1808 | { "RxDP Mux", "Mono ADC Mixer L", "Mono ADC MIXL" }, | ||
1809 | { "RxDP Mux", "Mono ADC Mixer R", "Mono ADC MIXR" }, | ||
1810 | { "RxDP Mux", "DAC1", "DAC MIX" }, | ||
1811 | |||
1812 | { "TDM Data Mux", "Slot 0-1", "Stereo1 ADC MIX" }, | ||
1813 | { "TDM Data Mux", "Slot 2-3", "Mono ADC MIX" }, | ||
1814 | { "TDM Data Mux", "Slot 4-5", "Stereo2 ADC MIX" }, | ||
1815 | { "TDM Data Mux", "Slot 6-7", "IF2 DAC" }, | ||
1816 | |||
1817 | { "DSP UL Mux", "Bypass", "TDM Data Mux" }, | ||
1818 | { "DSP UL Mux", NULL, "I2S DSP" }, | ||
1819 | { "DSP DL Mux", "Bypass", "RxDP Mux" }, | ||
1820 | { "DSP DL Mux", NULL, "I2S DSP" }, | ||
1821 | |||
1822 | { "TxDP_ADC_L", NULL, "DSP UL Mux" }, | ||
1823 | { "TxDP_ADC_R", NULL, "DSP UL Mux" }, | ||
1824 | { "TxDC_DAC", NULL, "DSP DL Mux" }, | ||
1825 | |||
1826 | { "TxDP_ADC", NULL, "TxDP_ADC_L" }, | ||
1827 | { "TxDP_ADC", NULL, "TxDP_ADC_R" }, | ||
1828 | |||
1829 | { "IF1 ADC", NULL, "I2S1" }, | ||
1830 | { "IF1 ADC", NULL, "IF1_ADC1" }, | ||
1831 | { "IF1 ADC", NULL, "IF1_ADC2" }, | ||
1832 | { "IF1 ADC", NULL, "IF_ADC3" }, | ||
1833 | { "IF1 ADC", NULL, "TxDP_ADC" }, | ||
1834 | |||
1835 | { "IF2 ADC Mux", "IF_ADC1", "IF_ADC1" }, | ||
1836 | { "IF2 ADC Mux", "IF_ADC2", "IF_ADC2" }, | ||
1837 | { "IF2 ADC Mux", "IF_ADC3", "IF_ADC3" }, | ||
1838 | { "IF2 ADC Mux", "TxDC_DAC", "TxDC_DAC" }, | ||
1839 | { "IF2 ADC Mux", "TxDP_ADC", "TxDP_ADC" }, | ||
1840 | { "IF2 ADC Mux", "VAD_ADC", "VAD_ADC" }, | ||
1841 | |||
1842 | { "IF2 ADC L", NULL, "IF2 ADC Mux" }, | ||
1843 | { "IF2 ADC R", NULL, "IF2 ADC Mux" }, | ||
1844 | |||
1845 | { "IF2 ADC", NULL, "I2S2" }, | ||
1846 | { "IF2 ADC", NULL, "IF2 ADC L" }, | ||
1847 | { "IF2 ADC", NULL, "IF2 ADC R" }, | ||
1848 | |||
1849 | { "AIF1TX", NULL, "IF1 ADC" }, | ||
1850 | { "AIF2TX", NULL, "IF2 ADC" }, | ||
1851 | |||
1852 | { "IF1 DAC1", NULL, "AIF1RX" }, | ||
1853 | { "IF1 DAC2", NULL, "AIF1RX" }, | ||
1854 | { "IF2 DAC", NULL, "AIF2RX" }, | ||
1855 | |||
1856 | { "IF1 DAC1", NULL, "I2S1" }, | ||
1857 | { "IF1 DAC2", NULL, "I2S1" }, | ||
1858 | { "IF2 DAC", NULL, "I2S2" }, | ||
1859 | |||
1860 | { "IF1 DAC2 L", NULL, "IF1 DAC2" }, | ||
1861 | { "IF1 DAC2 R", NULL, "IF1 DAC2" }, | ||
1862 | { "IF1 DAC1 L", NULL, "IF1 DAC1" }, | ||
1863 | { "IF1 DAC1 R", NULL, "IF1 DAC1" }, | ||
1864 | { "IF2 DAC L", NULL, "IF2 DAC" }, | ||
1865 | { "IF2 DAC R", NULL, "IF2 DAC" }, | ||
1866 | |||
1867 | { "DAC1 L Mux", "IF1 DAC", "IF1 DAC1 L" }, | ||
1868 | { "DAC1 L Mux", "IF2 DAC", "IF2 DAC L" }, | ||
1869 | |||
1870 | { "DAC1 R Mux", "IF1 DAC", "IF1 DAC1 R" }, | ||
1871 | { "DAC1 R Mux", "IF2 DAC", "IF2 DAC R" }, | ||
1872 | |||
1873 | { "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" }, | ||
1874 | { "DAC1 MIXL", "DAC1 Switch", "DAC1 L Mux" }, | ||
1875 | { "DAC1 MIXL", NULL, "DAC Stereo1 Filter" }, | ||
1876 | { "DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR" }, | ||
1877 | { "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" }, | ||
1878 | { "DAC1 MIXR", NULL, "DAC Stereo1 Filter" }, | ||
1879 | |||
1880 | { "DAC MIX", NULL, "DAC1 MIXL" }, | ||
1881 | { "DAC MIX", NULL, "DAC1 MIXR" }, | ||
1882 | |||
1883 | { "Audio DSP", NULL, "DAC1 MIXL" }, | ||
1884 | { "Audio DSP", NULL, "DAC1 MIXR" }, | ||
1885 | |||
1886 | { "DAC L2 Mux", "IF1 DAC", "IF1 DAC2 L" }, | ||
1887 | { "DAC L2 Mux", "IF2 DAC", "IF2 DAC L" }, | ||
1888 | { "DAC L2 Mux", "TxDC DAC", "TxDC_DAC" }, | ||
1889 | { "DAC L2 Mux", "VAD_ADC", "VAD_ADC" }, | ||
1890 | { "DAC L2 Volume", NULL, "DAC L2 Mux" }, | ||
1891 | { "DAC L2 Volume", NULL, "DAC Mono Left Filter" }, | ||
1892 | |||
1893 | { "DAC R2 Mux", "IF1 DAC", "IF1 DAC2 R" }, | ||
1894 | { "DAC R2 Mux", "IF2 DAC", "IF2 DAC R" }, | ||
1895 | { "DAC R2 Mux", "TxDC DAC", "TxDC_DAC" }, | ||
1896 | { "DAC R2 Mux", "TxDP ADC", "TxDP_ADC" }, | ||
1897 | { "DAC R2 Volume", NULL, "DAC R2 Mux" }, | ||
1898 | { "DAC R2 Volume", NULL, "DAC Mono Right Filter" }, | ||
1899 | |||
1900 | { "Stereo DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" }, | ||
1901 | { "Stereo DAC MIXL", "DAC R1 Switch", "DAC1 MIXR" }, | ||
1902 | { "Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" }, | ||
1903 | { "Stereo DAC MIXL", NULL, "DAC Stereo1 Filter" }, | ||
1904 | { "Stereo DAC MIXL", NULL, "DAC L1 Power" }, | ||
1905 | { "Stereo DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" }, | ||
1906 | { "Stereo DAC MIXR", "DAC L1 Switch", "DAC1 MIXL" }, | ||
1907 | { "Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" }, | ||
1908 | { "Stereo DAC MIXR", NULL, "DAC Stereo1 Filter" }, | ||
1909 | { "Stereo DAC MIXR", NULL, "DAC R1 Power" }, | ||
1910 | |||
1911 | { "Mono DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" }, | ||
1912 | { "Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" }, | ||
1913 | { "Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Volume" }, | ||
1914 | { "Mono DAC MIXL", NULL, "DAC Mono Left Filter" }, | ||
1915 | { "Mono DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" }, | ||
1916 | { "Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" }, | ||
1917 | { "Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" }, | ||
1918 | { "Mono DAC MIXR", NULL, "DAC Mono Right Filter" }, | ||
1919 | |||
1920 | { "DAC MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" }, | ||
1921 | { "DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" }, | ||
1922 | { "DAC MIXL", "DAC R2 Switch", "DAC R2 Volume" }, | ||
1923 | { "DAC MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" }, | ||
1924 | { "DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" }, | ||
1925 | { "DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" }, | ||
1926 | |||
1927 | { "DAC L1", NULL, "DAC L1 Power" }, | ||
1928 | { "DAC L1", NULL, "Stereo DAC MIXL" }, | ||
1929 | { "DAC L1", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1930 | { "DAC R1", NULL, "DAC R1 Power" }, | ||
1931 | { "DAC R1", NULL, "Stereo DAC MIXR" }, | ||
1932 | { "DAC R1", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1933 | { "DAC L2", NULL, "Mono DAC MIXL" }, | ||
1934 | { "DAC L2", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1935 | { "DAC R2", NULL, "Mono DAC MIXR" }, | ||
1936 | { "DAC R2", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1937 | |||
1938 | { "OUT MIXL", "BST1 Switch", "BST1" }, | ||
1939 | { "OUT MIXL", "INL Switch", "INL VOL" }, | ||
1940 | { "OUT MIXL", "DAC L2 Switch", "DAC L2" }, | ||
1941 | { "OUT MIXL", "DAC L1 Switch", "DAC L1" }, | ||
1942 | |||
1943 | { "OUT MIXR", "BST2 Switch", "BST2" }, | ||
1944 | { "OUT MIXR", "INR Switch", "INR VOL" }, | ||
1945 | { "OUT MIXR", "DAC R2 Switch", "DAC R2" }, | ||
1946 | { "OUT MIXR", "DAC R1 Switch", "DAC R1" }, | ||
1947 | |||
1948 | { "HPOVOL MIXL", "DAC1 Switch", "DAC L1" }, | ||
1949 | { "HPOVOL MIXL", "INL Switch", "INL VOL" }, | ||
1950 | { "HPOVOL MIXR", "DAC1 Switch", "DAC R1" }, | ||
1951 | { "HPOVOL MIXR", "INR Switch", "INR VOL" }, | ||
1952 | |||
1953 | { "DAC 2", NULL, "DAC L2" }, | ||
1954 | { "DAC 2", NULL, "DAC R2" }, | ||
1955 | { "DAC 1", NULL, "DAC L1" }, | ||
1956 | { "DAC 1", NULL, "DAC R1" }, | ||
1957 | { "HPOVOL", NULL, "HPOVOL MIXL" }, | ||
1958 | { "HPOVOL", NULL, "HPOVOL MIXR" }, | ||
1959 | { "HPO MIX", "DAC1 Switch", "DAC 1" }, | ||
1960 | { "HPO MIX", "HPVOL Switch", "HPOVOL" }, | ||
1961 | |||
1962 | { "LOUT MIX", "DAC L1 Switch", "DAC L1" }, | ||
1963 | { "LOUT MIX", "DAC R1 Switch", "DAC R1" }, | ||
1964 | { "LOUT MIX", "OUTMIX L Switch", "OUT MIXL" }, | ||
1965 | { "LOUT MIX", "OUTMIX R Switch", "OUT MIXR" }, | ||
1966 | |||
1967 | { "PDM1 L Mux", "Stereo DAC", "Stereo DAC MIXL" }, | ||
1968 | { "PDM1 L Mux", "Mono DAC", "Mono DAC MIXL" }, | ||
1969 | { "PDM1 L Mux", NULL, "PDM1 Power" }, | ||
1970 | { "PDM1 R Mux", "Stereo DAC", "Stereo DAC MIXR" }, | ||
1971 | { "PDM1 R Mux", "Mono DAC", "Mono DAC MIXR" }, | ||
1972 | { "PDM1 R Mux", NULL, "PDM1 Power" }, | ||
1973 | { "PDM2 L Mux", "Stereo DAC", "Stereo DAC MIXL" }, | ||
1974 | { "PDM2 L Mux", "Mono DAC", "Mono DAC MIXL" }, | ||
1975 | { "PDM2 L Mux", NULL, "PDM2 Power" }, | ||
1976 | { "PDM2 R Mux", "Stereo DAC", "Stereo DAC MIXR" }, | ||
1977 | { "PDM2 R Mux", "Mono DAC", "Mono DAC MIXR" }, | ||
1978 | { "PDM2 R Mux", NULL, "PDM2 Power" }, | ||
1979 | |||
1980 | { "HP Amp", NULL, "HPO MIX" }, | ||
1981 | { "HP Amp", NULL, "Mic Det Power" }, | ||
1982 | { "HPOL", NULL, "HP Amp" }, | ||
1983 | { "HPOL", NULL, "HP L Amp" }, | ||
1984 | { "HPOL", NULL, "Improve HP Amp Drv" }, | ||
1985 | { "HPOR", NULL, "HP Amp" }, | ||
1986 | { "HPOR", NULL, "HP R Amp" }, | ||
1987 | { "HPOR", NULL, "Improve HP Amp Drv" }, | ||
1988 | |||
1989 | { "LOUT Amp", NULL, "LOUT MIX" }, | ||
1990 | { "LOUT L Playback", "Switch", "LOUT Amp" }, | ||
1991 | { "LOUT R Playback", "Switch", "LOUT Amp" }, | ||
1992 | { "LOUTL", NULL, "LOUT L Playback" }, | ||
1993 | { "LOUTR", NULL, "LOUT R Playback" }, | ||
1994 | { "LOUTL", NULL, "Improve HP Amp Drv" }, | ||
1995 | { "LOUTR", NULL, "Improve HP Amp Drv" }, | ||
1996 | |||
1997 | { "PDM1L", NULL, "PDM1 L Mux" }, | ||
1998 | { "PDM1R", NULL, "PDM1 R Mux" }, | ||
1999 | { "PDM2L", NULL, "PDM2 L Mux" }, | ||
2000 | { "PDM2R", NULL, "PDM2 R Mux" }, | ||
2001 | }; | ||
2002 | |||
2003 | static int rt5670_hw_params(struct snd_pcm_substream *substream, | ||
2004 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
2005 | { | ||
2006 | struct snd_soc_codec *codec = dai->codec; | ||
2007 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2008 | unsigned int val_len = 0, val_clk, mask_clk; | ||
2009 | int pre_div, bclk_ms, frame_size; | ||
2010 | |||
2011 | rt5670->lrck[dai->id] = params_rate(params); | ||
2012 | pre_div = rl6231_get_clk_info(rt5670->sysclk, rt5670->lrck[dai->id]); | ||
2013 | if (pre_div < 0) { | ||
2014 | dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n", | ||
2015 | rt5670->lrck[dai->id], dai->id); | ||
2016 | return -EINVAL; | ||
2017 | } | ||
2018 | frame_size = snd_soc_params_to_frame_size(params); | ||
2019 | if (frame_size < 0) { | ||
2020 | dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size); | ||
2021 | return -EINVAL; | ||
2022 | } | ||
2023 | bclk_ms = frame_size > 32; | ||
2024 | rt5670->bclk[dai->id] = rt5670->lrck[dai->id] * (32 << bclk_ms); | ||
2025 | |||
2026 | dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", | ||
2027 | rt5670->bclk[dai->id], rt5670->lrck[dai->id]); | ||
2028 | dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", | ||
2029 | bclk_ms, pre_div, dai->id); | ||
2030 | |||
2031 | switch (params_width(params)) { | ||
2032 | case 16: | ||
2033 | break; | ||
2034 | case 20: | ||
2035 | val_len |= RT5670_I2S_DL_20; | ||
2036 | break; | ||
2037 | case 24: | ||
2038 | val_len |= RT5670_I2S_DL_24; | ||
2039 | break; | ||
2040 | case 8: | ||
2041 | val_len |= RT5670_I2S_DL_8; | ||
2042 | break; | ||
2043 | default: | ||
2044 | return -EINVAL; | ||
2045 | } | ||
2046 | |||
2047 | switch (dai->id) { | ||
2048 | case RT5670_AIF1: | ||
2049 | mask_clk = RT5670_I2S_BCLK_MS1_MASK | RT5670_I2S_PD1_MASK; | ||
2050 | val_clk = bclk_ms << RT5670_I2S_BCLK_MS1_SFT | | ||
2051 | pre_div << RT5670_I2S_PD1_SFT; | ||
2052 | snd_soc_update_bits(codec, RT5670_I2S1_SDP, | ||
2053 | RT5670_I2S_DL_MASK, val_len); | ||
2054 | snd_soc_update_bits(codec, RT5670_ADDA_CLK1, mask_clk, val_clk); | ||
2055 | break; | ||
2056 | case RT5670_AIF2: | ||
2057 | mask_clk = RT5670_I2S_BCLK_MS2_MASK | RT5670_I2S_PD2_MASK; | ||
2058 | val_clk = bclk_ms << RT5670_I2S_BCLK_MS2_SFT | | ||
2059 | pre_div << RT5670_I2S_PD2_SFT; | ||
2060 | snd_soc_update_bits(codec, RT5670_I2S2_SDP, | ||
2061 | RT5670_I2S_DL_MASK, val_len); | ||
2062 | snd_soc_update_bits(codec, RT5670_ADDA_CLK1, mask_clk, val_clk); | ||
2063 | break; | ||
2064 | default: | ||
2065 | dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id); | ||
2066 | return -EINVAL; | ||
2067 | } | ||
2068 | |||
2069 | return 0; | ||
2070 | } | ||
2071 | |||
2072 | static int rt5670_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
2073 | { | ||
2074 | struct snd_soc_codec *codec = dai->codec; | ||
2075 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2076 | unsigned int reg_val = 0; | ||
2077 | |||
2078 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
2079 | case SND_SOC_DAIFMT_CBM_CFM: | ||
2080 | rt5670->master[dai->id] = 1; | ||
2081 | break; | ||
2082 | case SND_SOC_DAIFMT_CBS_CFS: | ||
2083 | reg_val |= RT5670_I2S_MS_S; | ||
2084 | rt5670->master[dai->id] = 0; | ||
2085 | break; | ||
2086 | default: | ||
2087 | return -EINVAL; | ||
2088 | } | ||
2089 | |||
2090 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
2091 | case SND_SOC_DAIFMT_NB_NF: | ||
2092 | break; | ||
2093 | case SND_SOC_DAIFMT_IB_NF: | ||
2094 | reg_val |= RT5670_I2S_BP_INV; | ||
2095 | break; | ||
2096 | default: | ||
2097 | return -EINVAL; | ||
2098 | } | ||
2099 | |||
2100 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
2101 | case SND_SOC_DAIFMT_I2S: | ||
2102 | break; | ||
2103 | case SND_SOC_DAIFMT_LEFT_J: | ||
2104 | reg_val |= RT5670_I2S_DF_LEFT; | ||
2105 | break; | ||
2106 | case SND_SOC_DAIFMT_DSP_A: | ||
2107 | reg_val |= RT5670_I2S_DF_PCM_A; | ||
2108 | break; | ||
2109 | case SND_SOC_DAIFMT_DSP_B: | ||
2110 | reg_val |= RT5670_I2S_DF_PCM_B; | ||
2111 | break; | ||
2112 | default: | ||
2113 | return -EINVAL; | ||
2114 | } | ||
2115 | |||
2116 | switch (dai->id) { | ||
2117 | case RT5670_AIF1: | ||
2118 | snd_soc_update_bits(codec, RT5670_I2S1_SDP, | ||
2119 | RT5670_I2S_MS_MASK | RT5670_I2S_BP_MASK | | ||
2120 | RT5670_I2S_DF_MASK, reg_val); | ||
2121 | break; | ||
2122 | case RT5670_AIF2: | ||
2123 | snd_soc_update_bits(codec, RT5670_I2S2_SDP, | ||
2124 | RT5670_I2S_MS_MASK | RT5670_I2S_BP_MASK | | ||
2125 | RT5670_I2S_DF_MASK, reg_val); | ||
2126 | break; | ||
2127 | default: | ||
2128 | dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id); | ||
2129 | return -EINVAL; | ||
2130 | } | ||
2131 | return 0; | ||
2132 | } | ||
2133 | |||
2134 | static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai, | ||
2135 | int clk_id, unsigned int freq, int dir) | ||
2136 | { | ||
2137 | struct snd_soc_codec *codec = dai->codec; | ||
2138 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2139 | unsigned int reg_val = 0; | ||
2140 | |||
2141 | if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src) | ||
2142 | return 0; | ||
2143 | |||
2144 | switch (clk_id) { | ||
2145 | case RT5670_SCLK_S_MCLK: | ||
2146 | reg_val |= RT5670_SCLK_SRC_MCLK; | ||
2147 | break; | ||
2148 | case RT5670_SCLK_S_PLL1: | ||
2149 | reg_val |= RT5670_SCLK_SRC_PLL1; | ||
2150 | break; | ||
2151 | case RT5670_SCLK_S_RCCLK: | ||
2152 | reg_val |= RT5670_SCLK_SRC_RCCLK; | ||
2153 | break; | ||
2154 | default: | ||
2155 | dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); | ||
2156 | return -EINVAL; | ||
2157 | } | ||
2158 | snd_soc_update_bits(codec, RT5670_GLB_CLK, | ||
2159 | RT5670_SCLK_SRC_MASK, reg_val); | ||
2160 | rt5670->sysclk = freq; | ||
2161 | rt5670->sysclk_src = clk_id; | ||
2162 | |||
2163 | dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); | ||
2164 | |||
2165 | return 0; | ||
2166 | } | ||
2167 | |||
2168 | static int rt5670_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | ||
2169 | unsigned int freq_in, unsigned int freq_out) | ||
2170 | { | ||
2171 | struct snd_soc_codec *codec = dai->codec; | ||
2172 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2173 | struct rl6231_pll_code pll_code; | ||
2174 | int ret; | ||
2175 | |||
2176 | if (source == rt5670->pll_src && freq_in == rt5670->pll_in && | ||
2177 | freq_out == rt5670->pll_out) | ||
2178 | return 0; | ||
2179 | |||
2180 | if (!freq_in || !freq_out) { | ||
2181 | dev_dbg(codec->dev, "PLL disabled\n"); | ||
2182 | |||
2183 | rt5670->pll_in = 0; | ||
2184 | rt5670->pll_out = 0; | ||
2185 | snd_soc_update_bits(codec, RT5670_GLB_CLK, | ||
2186 | RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_MCLK); | ||
2187 | return 0; | ||
2188 | } | ||
2189 | |||
2190 | switch (source) { | ||
2191 | case RT5670_PLL1_S_MCLK: | ||
2192 | snd_soc_update_bits(codec, RT5670_GLB_CLK, | ||
2193 | RT5670_PLL1_SRC_MASK, RT5670_PLL1_SRC_MCLK); | ||
2194 | break; | ||
2195 | case RT5670_PLL1_S_BCLK1: | ||
2196 | case RT5670_PLL1_S_BCLK2: | ||
2197 | case RT5670_PLL1_S_BCLK3: | ||
2198 | case RT5670_PLL1_S_BCLK4: | ||
2199 | switch (dai->id) { | ||
2200 | case RT5670_AIF1: | ||
2201 | snd_soc_update_bits(codec, RT5670_GLB_CLK, | ||
2202 | RT5670_PLL1_SRC_MASK, RT5670_PLL1_SRC_BCLK1); | ||
2203 | break; | ||
2204 | case RT5670_AIF2: | ||
2205 | snd_soc_update_bits(codec, RT5670_GLB_CLK, | ||
2206 | RT5670_PLL1_SRC_MASK, RT5670_PLL1_SRC_BCLK2); | ||
2207 | break; | ||
2208 | default: | ||
2209 | dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id); | ||
2210 | return -EINVAL; | ||
2211 | } | ||
2212 | break; | ||
2213 | default: | ||
2214 | dev_err(codec->dev, "Unknown PLL source %d\n", source); | ||
2215 | return -EINVAL; | ||
2216 | } | ||
2217 | |||
2218 | ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); | ||
2219 | if (ret < 0) { | ||
2220 | dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); | ||
2221 | return ret; | ||
2222 | } | ||
2223 | |||
2224 | dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", | ||
2225 | pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), | ||
2226 | pll_code.n_code, pll_code.k_code); | ||
2227 | |||
2228 | snd_soc_write(codec, RT5670_PLL_CTRL1, | ||
2229 | pll_code.n_code << RT5670_PLL_N_SFT | pll_code.k_code); | ||
2230 | snd_soc_write(codec, RT5670_PLL_CTRL2, | ||
2231 | (pll_code.m_bp ? 0 : pll_code.m_code) << RT5670_PLL_M_SFT | | ||
2232 | pll_code.m_bp << RT5670_PLL_M_BP_SFT); | ||
2233 | |||
2234 | rt5670->pll_in = freq_in; | ||
2235 | rt5670->pll_out = freq_out; | ||
2236 | rt5670->pll_src = source; | ||
2237 | |||
2238 | return 0; | ||
2239 | } | ||
2240 | |||
2241 | static int rt5670_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
2242 | unsigned int rx_mask, int slots, int slot_width) | ||
2243 | { | ||
2244 | struct snd_soc_codec *codec = dai->codec; | ||
2245 | unsigned int val = 0; | ||
2246 | |||
2247 | if (rx_mask || tx_mask) | ||
2248 | val |= (1 << 14); | ||
2249 | |||
2250 | switch (slots) { | ||
2251 | case 4: | ||
2252 | val |= (1 << 12); | ||
2253 | break; | ||
2254 | case 6: | ||
2255 | val |= (2 << 12); | ||
2256 | break; | ||
2257 | case 8: | ||
2258 | val |= (3 << 12); | ||
2259 | break; | ||
2260 | case 2: | ||
2261 | break; | ||
2262 | default: | ||
2263 | return -EINVAL; | ||
2264 | } | ||
2265 | |||
2266 | switch (slot_width) { | ||
2267 | case 20: | ||
2268 | val |= (1 << 10); | ||
2269 | break; | ||
2270 | case 24: | ||
2271 | val |= (2 << 10); | ||
2272 | break; | ||
2273 | case 32: | ||
2274 | val |= (3 << 10); | ||
2275 | break; | ||
2276 | case 16: | ||
2277 | break; | ||
2278 | default: | ||
2279 | return -EINVAL; | ||
2280 | } | ||
2281 | |||
2282 | snd_soc_update_bits(codec, RT5670_TDM_CTRL_1, 0x7c00, val); | ||
2283 | |||
2284 | return 0; | ||
2285 | } | ||
2286 | |||
2287 | static int rt5670_set_bias_level(struct snd_soc_codec *codec, | ||
2288 | enum snd_soc_bias_level level) | ||
2289 | { | ||
2290 | switch (level) { | ||
2291 | case SND_SOC_BIAS_PREPARE: | ||
2292 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { | ||
2293 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | ||
2294 | RT5670_PWR_VREF1 | RT5670_PWR_MB | | ||
2295 | RT5670_PWR_BG | RT5670_PWR_VREF2, | ||
2296 | RT5670_PWR_VREF1 | RT5670_PWR_MB | | ||
2297 | RT5670_PWR_BG | RT5670_PWR_VREF2); | ||
2298 | mdelay(10); | ||
2299 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | ||
2300 | RT5670_PWR_FV1 | RT5670_PWR_FV2, | ||
2301 | RT5670_PWR_FV1 | RT5670_PWR_FV2); | ||
2302 | snd_soc_update_bits(codec, RT5670_CHARGE_PUMP, | ||
2303 | RT5670_OSW_L_MASK | RT5670_OSW_R_MASK, | ||
2304 | RT5670_OSW_L_DIS | RT5670_OSW_R_DIS); | ||
2305 | snd_soc_update_bits(codec, RT5670_DIG_MISC, 0x1, 0x1); | ||
2306 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | ||
2307 | RT5670_LDO_SEL_MASK, 0x3); | ||
2308 | } | ||
2309 | break; | ||
2310 | case SND_SOC_BIAS_STANDBY: | ||
2311 | snd_soc_write(codec, RT5670_PWR_DIG1, 0x0000); | ||
2312 | snd_soc_write(codec, RT5670_PWR_DIG2, 0x0001); | ||
2313 | snd_soc_write(codec, RT5670_PWR_VOL, 0x0000); | ||
2314 | snd_soc_write(codec, RT5670_PWR_MIXER, 0x0001); | ||
2315 | snd_soc_write(codec, RT5670_PWR_ANLG1, 0x2800); | ||
2316 | snd_soc_write(codec, RT5670_PWR_ANLG2, 0x0004); | ||
2317 | snd_soc_update_bits(codec, RT5670_DIG_MISC, 0x1, 0x0); | ||
2318 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | ||
2319 | RT5670_LDO_SEL_MASK, 0x1); | ||
2320 | break; | ||
2321 | |||
2322 | default: | ||
2323 | break; | ||
2324 | } | ||
2325 | codec->dapm.bias_level = level; | ||
2326 | |||
2327 | return 0; | ||
2328 | } | ||
2329 | |||
2330 | static int rt5670_probe(struct snd_soc_codec *codec) | ||
2331 | { | ||
2332 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2333 | |||
2334 | rt5670->codec = codec; | ||
2335 | |||
2336 | return 0; | ||
2337 | } | ||
2338 | |||
2339 | static int rt5670_remove(struct snd_soc_codec *codec) | ||
2340 | { | ||
2341 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2342 | |||
2343 | regmap_write(rt5670->regmap, RT5670_RESET, 0); | ||
2344 | return 0; | ||
2345 | } | ||
2346 | |||
2347 | #ifdef CONFIG_PM | ||
2348 | static int rt5670_suspend(struct snd_soc_codec *codec) | ||
2349 | { | ||
2350 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2351 | |||
2352 | regcache_cache_only(rt5670->regmap, true); | ||
2353 | regcache_mark_dirty(rt5670->regmap); | ||
2354 | return 0; | ||
2355 | } | ||
2356 | |||
2357 | static int rt5670_resume(struct snd_soc_codec *codec) | ||
2358 | { | ||
2359 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2360 | |||
2361 | regcache_cache_only(rt5670->regmap, false); | ||
2362 | regcache_sync(rt5670->regmap); | ||
2363 | |||
2364 | return 0; | ||
2365 | } | ||
2366 | #else | ||
2367 | #define rt5670_suspend NULL | ||
2368 | #define rt5670_resume NULL | ||
2369 | #endif | ||
2370 | |||
2371 | #define RT5670_STEREO_RATES SNDRV_PCM_RATE_8000_96000 | ||
2372 | #define RT5670_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
2373 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | ||
2374 | |||
2375 | static struct snd_soc_dai_ops rt5670_aif_dai_ops = { | ||
2376 | .hw_params = rt5670_hw_params, | ||
2377 | .set_fmt = rt5670_set_dai_fmt, | ||
2378 | .set_sysclk = rt5670_set_dai_sysclk, | ||
2379 | .set_tdm_slot = rt5670_set_tdm_slot, | ||
2380 | .set_pll = rt5670_set_dai_pll, | ||
2381 | }; | ||
2382 | |||
2383 | static struct snd_soc_dai_driver rt5670_dai[] = { | ||
2384 | { | ||
2385 | .name = "rt5670-aif1", | ||
2386 | .id = RT5670_AIF1, | ||
2387 | .playback = { | ||
2388 | .stream_name = "AIF1 Playback", | ||
2389 | .channels_min = 1, | ||
2390 | .channels_max = 2, | ||
2391 | .rates = RT5670_STEREO_RATES, | ||
2392 | .formats = RT5670_FORMATS, | ||
2393 | }, | ||
2394 | .capture = { | ||
2395 | .stream_name = "AIF1 Capture", | ||
2396 | .channels_min = 1, | ||
2397 | .channels_max = 2, | ||
2398 | .rates = RT5670_STEREO_RATES, | ||
2399 | .formats = RT5670_FORMATS, | ||
2400 | }, | ||
2401 | .ops = &rt5670_aif_dai_ops, | ||
2402 | }, | ||
2403 | { | ||
2404 | .name = "rt5670-aif2", | ||
2405 | .id = RT5670_AIF2, | ||
2406 | .playback = { | ||
2407 | .stream_name = "AIF2 Playback", | ||
2408 | .channels_min = 1, | ||
2409 | .channels_max = 2, | ||
2410 | .rates = RT5670_STEREO_RATES, | ||
2411 | .formats = RT5670_FORMATS, | ||
2412 | }, | ||
2413 | .capture = { | ||
2414 | .stream_name = "AIF2 Capture", | ||
2415 | .channels_min = 1, | ||
2416 | .channels_max = 2, | ||
2417 | .rates = RT5670_STEREO_RATES, | ||
2418 | .formats = RT5670_FORMATS, | ||
2419 | }, | ||
2420 | .ops = &rt5670_aif_dai_ops, | ||
2421 | }, | ||
2422 | }; | ||
2423 | |||
2424 | static struct snd_soc_codec_driver soc_codec_dev_rt5670 = { | ||
2425 | .probe = rt5670_probe, | ||
2426 | .remove = rt5670_remove, | ||
2427 | .suspend = rt5670_suspend, | ||
2428 | .resume = rt5670_resume, | ||
2429 | .set_bias_level = rt5670_set_bias_level, | ||
2430 | .idle_bias_off = true, | ||
2431 | .controls = rt5670_snd_controls, | ||
2432 | .num_controls = ARRAY_SIZE(rt5670_snd_controls), | ||
2433 | .dapm_widgets = rt5670_dapm_widgets, | ||
2434 | .num_dapm_widgets = ARRAY_SIZE(rt5670_dapm_widgets), | ||
2435 | .dapm_routes = rt5670_dapm_routes, | ||
2436 | .num_dapm_routes = ARRAY_SIZE(rt5670_dapm_routes), | ||
2437 | }; | ||
2438 | |||
2439 | static const struct regmap_config rt5670_regmap = { | ||
2440 | .reg_bits = 8, | ||
2441 | .val_bits = 16, | ||
2442 | .max_register = RT5670_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5670_ranges) * | ||
2443 | RT5670_PR_SPACING), | ||
2444 | .volatile_reg = rt5670_volatile_register, | ||
2445 | .readable_reg = rt5670_readable_register, | ||
2446 | .cache_type = REGCACHE_RBTREE, | ||
2447 | .reg_defaults = rt5670_reg, | ||
2448 | .num_reg_defaults = ARRAY_SIZE(rt5670_reg), | ||
2449 | .ranges = rt5670_ranges, | ||
2450 | .num_ranges = ARRAY_SIZE(rt5670_ranges), | ||
2451 | }; | ||
2452 | |||
2453 | static const struct i2c_device_id rt5670_i2c_id[] = { | ||
2454 | { "rt5670", 0 }, | ||
2455 | { } | ||
2456 | }; | ||
2457 | MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); | ||
2458 | |||
2459 | static int rt5670_i2c_probe(struct i2c_client *i2c, | ||
2460 | const struct i2c_device_id *id) | ||
2461 | { | ||
2462 | struct rt5670_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
2463 | struct rt5670_priv *rt5670; | ||
2464 | int ret; | ||
2465 | unsigned int val; | ||
2466 | |||
2467 | rt5670 = devm_kzalloc(&i2c->dev, | ||
2468 | sizeof(struct rt5670_priv), | ||
2469 | GFP_KERNEL); | ||
2470 | if (NULL == rt5670) | ||
2471 | return -ENOMEM; | ||
2472 | |||
2473 | i2c_set_clientdata(i2c, rt5670); | ||
2474 | |||
2475 | if (pdata) | ||
2476 | rt5670->pdata = *pdata; | ||
2477 | |||
2478 | rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); | ||
2479 | if (IS_ERR(rt5670->regmap)) { | ||
2480 | ret = PTR_ERR(rt5670->regmap); | ||
2481 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
2482 | ret); | ||
2483 | return ret; | ||
2484 | } | ||
2485 | |||
2486 | regmap_read(rt5670->regmap, RT5670_VENDOR_ID2, &val); | ||
2487 | if (val != RT5670_DEVICE_ID) { | ||
2488 | dev_err(&i2c->dev, | ||
2489 | "Device with ID register %x is not rt5670/72\n", val); | ||
2490 | return -ENODEV; | ||
2491 | } | ||
2492 | |||
2493 | regmap_write(rt5670->regmap, RT5670_RESET, 0); | ||
2494 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1, | ||
2495 | RT5670_PWR_HP_L | RT5670_PWR_HP_R | | ||
2496 | RT5670_PWR_VREF2, RT5670_PWR_VREF2); | ||
2497 | msleep(100); | ||
2498 | |||
2499 | regmap_write(rt5670->regmap, RT5670_RESET, 0); | ||
2500 | |||
2501 | ret = regmap_register_patch(rt5670->regmap, init_list, | ||
2502 | ARRAY_SIZE(init_list)); | ||
2503 | if (ret != 0) | ||
2504 | dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); | ||
2505 | |||
2506 | if (rt5670->pdata.in2_diff) | ||
2507 | regmap_update_bits(rt5670->regmap, RT5670_IN2, | ||
2508 | RT5670_IN_DF2, RT5670_IN_DF2); | ||
2509 | |||
2510 | if (i2c->irq) { | ||
2511 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2512 | RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ); | ||
2513 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, | ||
2514 | RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); | ||
2515 | |||
2516 | } | ||
2517 | |||
2518 | if (rt5670->pdata.jd_mode) { | ||
2519 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1, | ||
2520 | RT5670_PWR_MB, RT5670_PWR_MB); | ||
2521 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG2, | ||
2522 | RT5670_PWR_JD1, RT5670_PWR_JD1); | ||
2523 | regmap_update_bits(rt5670->regmap, RT5670_IRQ_CTRL1, | ||
2524 | RT5670_JD1_1_EN_MASK, RT5670_JD1_1_EN); | ||
2525 | regmap_update_bits(rt5670->regmap, RT5670_JD_CTRL3, | ||
2526 | RT5670_JD_TRI_CBJ_SEL_MASK | | ||
2527 | RT5670_JD_TRI_HPO_SEL_MASK, | ||
2528 | RT5670_JD_CBJ_JD1_1 | RT5670_JD_HPO_JD1_1); | ||
2529 | switch (rt5670->pdata.jd_mode) { | ||
2530 | case 1: | ||
2531 | regmap_update_bits(rt5670->regmap, RT5670_A_JD_CTRL1, | ||
2532 | RT5670_JD1_MODE_MASK, | ||
2533 | RT5670_JD1_MODE_0); | ||
2534 | break; | ||
2535 | case 2: | ||
2536 | regmap_update_bits(rt5670->regmap, RT5670_A_JD_CTRL1, | ||
2537 | RT5670_JD1_MODE_MASK, | ||
2538 | RT5670_JD1_MODE_1); | ||
2539 | break; | ||
2540 | case 3: | ||
2541 | regmap_update_bits(rt5670->regmap, RT5670_A_JD_CTRL1, | ||
2542 | RT5670_JD1_MODE_MASK, | ||
2543 | RT5670_JD1_MODE_2); | ||
2544 | break; | ||
2545 | default: | ||
2546 | break; | ||
2547 | } | ||
2548 | } | ||
2549 | |||
2550 | if (rt5670->pdata.dmic_en) { | ||
2551 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2552 | RT5670_GP2_PIN_MASK, | ||
2553 | RT5670_GP2_PIN_DMIC1_SCL); | ||
2554 | |||
2555 | switch (rt5670->pdata.dmic1_data_pin) { | ||
2556 | case RT5670_DMIC_DATA_IN2P: | ||
2557 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, | ||
2558 | RT5670_DMIC_1_DP_MASK, | ||
2559 | RT5670_DMIC_1_DP_IN2P); | ||
2560 | break; | ||
2561 | |||
2562 | case RT5670_DMIC_DATA_GPIO6: | ||
2563 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, | ||
2564 | RT5670_DMIC_1_DP_MASK, | ||
2565 | RT5670_DMIC_1_DP_GPIO6); | ||
2566 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2567 | RT5670_GP6_PIN_MASK, | ||
2568 | RT5670_GP6_PIN_DMIC1_SDA); | ||
2569 | break; | ||
2570 | |||
2571 | case RT5670_DMIC_DATA_GPIO7: | ||
2572 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, | ||
2573 | RT5670_DMIC_1_DP_MASK, | ||
2574 | RT5670_DMIC_1_DP_GPIO7); | ||
2575 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2576 | RT5670_GP7_PIN_MASK, | ||
2577 | RT5670_GP7_PIN_DMIC1_SDA); | ||
2578 | break; | ||
2579 | |||
2580 | default: | ||
2581 | break; | ||
2582 | } | ||
2583 | |||
2584 | switch (rt5670->pdata.dmic2_data_pin) { | ||
2585 | case RT5670_DMIC_DATA_IN3N: | ||
2586 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, | ||
2587 | RT5670_DMIC_2_DP_MASK, | ||
2588 | RT5670_DMIC_2_DP_IN3N); | ||
2589 | break; | ||
2590 | |||
2591 | case RT5670_DMIC_DATA_GPIO8: | ||
2592 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, | ||
2593 | RT5670_DMIC_2_DP_MASK, | ||
2594 | RT5670_DMIC_2_DP_GPIO8); | ||
2595 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2596 | RT5670_GP8_PIN_MASK, | ||
2597 | RT5670_GP8_PIN_DMIC2_SDA); | ||
2598 | break; | ||
2599 | |||
2600 | default: | ||
2601 | break; | ||
2602 | } | ||
2603 | |||
2604 | switch (rt5670->pdata.dmic3_data_pin) { | ||
2605 | case RT5670_DMIC_DATA_GPIO5: | ||
2606 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL2, | ||
2607 | RT5670_DMIC_3_DP_MASK, | ||
2608 | RT5670_DMIC_3_DP_GPIO5); | ||
2609 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2610 | RT5670_GP5_PIN_MASK, | ||
2611 | RT5670_GP5_PIN_DMIC3_SDA); | ||
2612 | break; | ||
2613 | |||
2614 | case RT5670_DMIC_DATA_GPIO9: | ||
2615 | case RT5670_DMIC_DATA_GPIO10: | ||
2616 | dev_err(&i2c->dev, | ||
2617 | "Always use GPIO5 as DMIC3 data pin\n"); | ||
2618 | break; | ||
2619 | |||
2620 | default: | ||
2621 | break; | ||
2622 | } | ||
2623 | |||
2624 | } | ||
2625 | |||
2626 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5670, | ||
2627 | rt5670_dai, ARRAY_SIZE(rt5670_dai)); | ||
2628 | if (ret < 0) | ||
2629 | goto err; | ||
2630 | |||
2631 | return 0; | ||
2632 | err: | ||
2633 | return ret; | ||
2634 | } | ||
2635 | |||
2636 | static int rt5670_i2c_remove(struct i2c_client *i2c) | ||
2637 | { | ||
2638 | snd_soc_unregister_codec(&i2c->dev); | ||
2639 | |||
2640 | return 0; | ||
2641 | } | ||
2642 | |||
2643 | static struct i2c_driver rt5670_i2c_driver = { | ||
2644 | .driver = { | ||
2645 | .name = "rt5670", | ||
2646 | .owner = THIS_MODULE, | ||
2647 | }, | ||
2648 | .probe = rt5670_i2c_probe, | ||
2649 | .remove = rt5670_i2c_remove, | ||
2650 | .id_table = rt5670_i2c_id, | ||
2651 | }; | ||
2652 | |||
2653 | module_i2c_driver(rt5670_i2c_driver); | ||
2654 | |||
2655 | MODULE_DESCRIPTION("ASoC RT5670 driver"); | ||
2656 | MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>"); | ||
2657 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h new file mode 100644 index 000000000000..a0b5c855b492 --- /dev/null +++ b/sound/soc/codecs/rt5670.h | |||
@@ -0,0 +1,2000 @@ | |||
1 | /* | ||
2 | * rt5670.h -- RT5670 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2014 Realtek Microelectronics | ||
5 | * Author: Bard Liao <bardliao@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __RT5670_H__ | ||
13 | #define __RT5670_H__ | ||
14 | |||
15 | #include <sound/rt5670.h> | ||
16 | |||
17 | /* Info */ | ||
18 | #define RT5670_RESET 0x00 | ||
19 | #define RT5670_VENDOR_ID 0xfd | ||
20 | #define RT5670_VENDOR_ID1 0xfe | ||
21 | #define RT5670_VENDOR_ID2 0xff | ||
22 | /* I/O - Output */ | ||
23 | #define RT5670_HP_VOL 0x02 | ||
24 | #define RT5670_LOUT1 0x03 | ||
25 | /* I/O - Input */ | ||
26 | #define RT5670_CJ_CTRL1 0x0a | ||
27 | #define RT5670_CJ_CTRL2 0x0b | ||
28 | #define RT5670_CJ_CTRL3 0x0c | ||
29 | #define RT5670_IN2 0x0e | ||
30 | #define RT5670_INL1_INR1_VOL 0x0f | ||
31 | /* I/O - ADC/DAC/DMIC */ | ||
32 | #define RT5670_DAC1_DIG_VOL 0x19 | ||
33 | #define RT5670_DAC2_DIG_VOL 0x1a | ||
34 | #define RT5670_DAC_CTRL 0x1b | ||
35 | #define RT5670_STO1_ADC_DIG_VOL 0x1c | ||
36 | #define RT5670_MONO_ADC_DIG_VOL 0x1d | ||
37 | #define RT5670_ADC_BST_VOL1 0x1e | ||
38 | #define RT5670_STO2_ADC_DIG_VOL 0x1f | ||
39 | /* Mixer - D-D */ | ||
40 | #define RT5670_ADC_BST_VOL2 0x20 | ||
41 | #define RT5670_STO2_ADC_MIXER 0x26 | ||
42 | #define RT5670_STO1_ADC_MIXER 0x27 | ||
43 | #define RT5670_MONO_ADC_MIXER 0x28 | ||
44 | #define RT5670_AD_DA_MIXER 0x29 | ||
45 | #define RT5670_STO_DAC_MIXER 0x2a | ||
46 | #define RT5670_DD_MIXER 0x2b | ||
47 | #define RT5670_DIG_MIXER 0x2c | ||
48 | #define RT5670_DSP_PATH1 0x2d | ||
49 | #define RT5670_DSP_PATH2 0x2e | ||
50 | #define RT5670_DIG_INF1_DATA 0x2f | ||
51 | #define RT5670_DIG_INF2_DATA 0x30 | ||
52 | /* Mixer - PDM */ | ||
53 | #define RT5670_PDM_OUT_CTRL 0x31 | ||
54 | #define RT5670_PDM_DATA_CTRL1 0x32 | ||
55 | #define RT5670_PDM1_DATA_CTRL2 0x33 | ||
56 | #define RT5670_PDM1_DATA_CTRL3 0x34 | ||
57 | #define RT5670_PDM1_DATA_CTRL4 0x35 | ||
58 | #define RT5670_PDM2_DATA_CTRL2 0x36 | ||
59 | #define RT5670_PDM2_DATA_CTRL3 0x37 | ||
60 | #define RT5670_PDM2_DATA_CTRL4 0x38 | ||
61 | /* Mixer - ADC */ | ||
62 | #define RT5670_REC_L1_MIXER 0x3b | ||
63 | #define RT5670_REC_L2_MIXER 0x3c | ||
64 | #define RT5670_REC_R1_MIXER 0x3d | ||
65 | #define RT5670_REC_R2_MIXER 0x3e | ||
66 | /* Mixer - DAC */ | ||
67 | #define RT5670_HPO_MIXER 0x45 | ||
68 | #define RT5670_MONO_MIXER 0x4c | ||
69 | #define RT5670_OUT_L1_MIXER 0x4f | ||
70 | #define RT5670_OUT_R1_MIXER 0x52 | ||
71 | #define RT5670_LOUT_MIXER 0x53 | ||
72 | /* Power */ | ||
73 | #define RT5670_PWR_DIG1 0x61 | ||
74 | #define RT5670_PWR_DIG2 0x62 | ||
75 | #define RT5670_PWR_ANLG1 0x63 | ||
76 | #define RT5670_PWR_ANLG2 0x64 | ||
77 | #define RT5670_PWR_MIXER 0x65 | ||
78 | #define RT5670_PWR_VOL 0x66 | ||
79 | /* Private Register Control */ | ||
80 | #define RT5670_PRIV_INDEX 0x6a | ||
81 | #define RT5670_PRIV_DATA 0x6c | ||
82 | /* Format - ADC/DAC */ | ||
83 | #define RT5670_I2S4_SDP 0x6f | ||
84 | #define RT5670_I2S1_SDP 0x70 | ||
85 | #define RT5670_I2S2_SDP 0x71 | ||
86 | #define RT5670_I2S3_SDP 0x72 | ||
87 | #define RT5670_ADDA_CLK1 0x73 | ||
88 | #define RT5670_ADDA_CLK2 0x74 | ||
89 | #define RT5670_DMIC_CTRL1 0x75 | ||
90 | #define RT5670_DMIC_CTRL2 0x76 | ||
91 | /* Format - TDM Control */ | ||
92 | #define RT5670_TDM_CTRL_1 0x77 | ||
93 | #define RT5670_TDM_CTRL_2 0x78 | ||
94 | #define RT5670_TDM_CTRL_3 0x79 | ||
95 | |||
96 | /* Function - Analog */ | ||
97 | #define RT5670_DSP_CLK 0x7f | ||
98 | #define RT5670_GLB_CLK 0x80 | ||
99 | #define RT5670_PLL_CTRL1 0x81 | ||
100 | #define RT5670_PLL_CTRL2 0x82 | ||
101 | #define RT5670_ASRC_1 0x83 | ||
102 | #define RT5670_ASRC_2 0x84 | ||
103 | #define RT5670_ASRC_3 0x85 | ||
104 | #define RT5670_ASRC_4 0x86 | ||
105 | #define RT5670_ASRC_5 0x87 | ||
106 | #define RT5670_ASRC_7 0x89 | ||
107 | #define RT5670_ASRC_8 0x8a | ||
108 | #define RT5670_ASRC_9 0x8b | ||
109 | #define RT5670_ASRC_10 0x8c | ||
110 | #define RT5670_ASRC_11 0x8d | ||
111 | #define RT5670_DEPOP_M1 0x8e | ||
112 | #define RT5670_DEPOP_M2 0x8f | ||
113 | #define RT5670_DEPOP_M3 0x90 | ||
114 | #define RT5670_CHARGE_PUMP 0x91 | ||
115 | #define RT5670_MICBIAS 0x93 | ||
116 | #define RT5670_A_JD_CTRL1 0x94 | ||
117 | #define RT5670_A_JD_CTRL2 0x95 | ||
118 | #define RT5670_ASRC_12 0x97 | ||
119 | #define RT5670_ASRC_13 0x98 | ||
120 | #define RT5670_ASRC_14 0x99 | ||
121 | #define RT5670_VAD_CTRL1 0x9a | ||
122 | #define RT5670_VAD_CTRL2 0x9b | ||
123 | #define RT5670_VAD_CTRL3 0x9c | ||
124 | #define RT5670_VAD_CTRL4 0x9d | ||
125 | #define RT5670_VAD_CTRL5 0x9e | ||
126 | /* Function - Digital */ | ||
127 | #define RT5670_ADC_EQ_CTRL1 0xae | ||
128 | #define RT5670_ADC_EQ_CTRL2 0xaf | ||
129 | #define RT5670_EQ_CTRL1 0xb0 | ||
130 | #define RT5670_EQ_CTRL2 0xb1 | ||
131 | #define RT5670_ALC_DRC_CTRL1 0xb2 | ||
132 | #define RT5670_ALC_DRC_CTRL2 0xb3 | ||
133 | #define RT5670_ALC_CTRL_1 0xb4 | ||
134 | #define RT5670_ALC_CTRL_2 0xb5 | ||
135 | #define RT5670_ALC_CTRL_3 0xb6 | ||
136 | #define RT5670_ALC_CTRL_4 0xb7 | ||
137 | #define RT5670_JD_CTRL 0xbb | ||
138 | #define RT5670_IRQ_CTRL1 0xbd | ||
139 | #define RT5670_IRQ_CTRL2 0xbe | ||
140 | #define RT5670_INT_IRQ_ST 0xbf | ||
141 | #define RT5670_GPIO_CTRL1 0xc0 | ||
142 | #define RT5670_GPIO_CTRL2 0xc1 | ||
143 | #define RT5670_GPIO_CTRL3 0xc2 | ||
144 | #define RT5670_SCRABBLE_FUN 0xcd | ||
145 | #define RT5670_SCRABBLE_CTRL 0xce | ||
146 | #define RT5670_BASE_BACK 0xcf | ||
147 | #define RT5670_MP3_PLUS1 0xd0 | ||
148 | #define RT5670_MP3_PLUS2 0xd1 | ||
149 | #define RT5670_ADJ_HPF1 0xd3 | ||
150 | #define RT5670_ADJ_HPF2 0xd4 | ||
151 | #define RT5670_HP_CALIB_AMP_DET 0xd6 | ||
152 | #define RT5670_SV_ZCD1 0xd9 | ||
153 | #define RT5670_SV_ZCD2 0xda | ||
154 | #define RT5670_IL_CMD 0xdb | ||
155 | #define RT5670_IL_CMD2 0xdc | ||
156 | #define RT5670_IL_CMD3 0xdd | ||
157 | #define RT5670_DRC_HL_CTRL1 0xe6 | ||
158 | #define RT5670_DRC_HL_CTRL2 0xe7 | ||
159 | #define RT5670_ADC_MONO_HP_CTRL1 0xec | ||
160 | #define RT5670_ADC_MONO_HP_CTRL2 0xed | ||
161 | #define RT5670_ADC_STO2_HP_CTRL1 0xee | ||
162 | #define RT5670_ADC_STO2_HP_CTRL2 0xef | ||
163 | #define RT5670_JD_CTRL3 0xf8 | ||
164 | #define RT5670_JD_CTRL4 0xf9 | ||
165 | /* General Control */ | ||
166 | #define RT5670_DIG_MISC 0xfa | ||
167 | #define RT5670_GEN_CTRL2 0xfb | ||
168 | #define RT5670_GEN_CTRL3 0xfc | ||
169 | |||
170 | |||
171 | /* Index of Codec Private Register definition */ | ||
172 | #define RT5670_DIG_VOL 0x00 | ||
173 | #define RT5670_PR_ALC_CTRL_1 0x01 | ||
174 | #define RT5670_PR_ALC_CTRL_2 0x02 | ||
175 | #define RT5670_PR_ALC_CTRL_3 0x03 | ||
176 | #define RT5670_PR_ALC_CTRL_4 0x04 | ||
177 | #define RT5670_PR_ALC_CTRL_5 0x05 | ||
178 | #define RT5670_PR_ALC_CTRL_6 0x06 | ||
179 | #define RT5670_BIAS_CUR1 0x12 | ||
180 | #define RT5670_BIAS_CUR3 0x14 | ||
181 | #define RT5670_CLSD_INT_REG1 0x1c | ||
182 | #define RT5670_MAMP_INT_REG2 0x37 | ||
183 | #define RT5670_CHOP_DAC_ADC 0x3d | ||
184 | #define RT5670_MIXER_INT_REG 0x3f | ||
185 | #define RT5670_3D_SPK 0x63 | ||
186 | #define RT5670_WND_1 0x6c | ||
187 | #define RT5670_WND_2 0x6d | ||
188 | #define RT5670_WND_3 0x6e | ||
189 | #define RT5670_WND_4 0x6f | ||
190 | #define RT5670_WND_5 0x70 | ||
191 | #define RT5670_WND_8 0x73 | ||
192 | #define RT5670_DIP_SPK_INF 0x75 | ||
193 | #define RT5670_HP_DCC_INT1 0x77 | ||
194 | #define RT5670_EQ_BW_LOP 0xa0 | ||
195 | #define RT5670_EQ_GN_LOP 0xa1 | ||
196 | #define RT5670_EQ_FC_BP1 0xa2 | ||
197 | #define RT5670_EQ_BW_BP1 0xa3 | ||
198 | #define RT5670_EQ_GN_BP1 0xa4 | ||
199 | #define RT5670_EQ_FC_BP2 0xa5 | ||
200 | #define RT5670_EQ_BW_BP2 0xa6 | ||
201 | #define RT5670_EQ_GN_BP2 0xa7 | ||
202 | #define RT5670_EQ_FC_BP3 0xa8 | ||
203 | #define RT5670_EQ_BW_BP3 0xa9 | ||
204 | #define RT5670_EQ_GN_BP3 0xaa | ||
205 | #define RT5670_EQ_FC_BP4 0xab | ||
206 | #define RT5670_EQ_BW_BP4 0xac | ||
207 | #define RT5670_EQ_GN_BP4 0xad | ||
208 | #define RT5670_EQ_FC_HIP1 0xae | ||
209 | #define RT5670_EQ_GN_HIP1 0xaf | ||
210 | #define RT5670_EQ_FC_HIP2 0xb0 | ||
211 | #define RT5670_EQ_BW_HIP2 0xb1 | ||
212 | #define RT5670_EQ_GN_HIP2 0xb2 | ||
213 | #define RT5670_EQ_PRE_VOL 0xb3 | ||
214 | #define RT5670_EQ_PST_VOL 0xb4 | ||
215 | |||
216 | |||
217 | /* global definition */ | ||
218 | #define RT5670_L_MUTE (0x1 << 15) | ||
219 | #define RT5670_L_MUTE_SFT 15 | ||
220 | #define RT5670_VOL_L_MUTE (0x1 << 14) | ||
221 | #define RT5670_VOL_L_SFT 14 | ||
222 | #define RT5670_R_MUTE (0x1 << 7) | ||
223 | #define RT5670_R_MUTE_SFT 7 | ||
224 | #define RT5670_VOL_R_MUTE (0x1 << 6) | ||
225 | #define RT5670_VOL_R_SFT 6 | ||
226 | #define RT5670_L_VOL_MASK (0x3f << 8) | ||
227 | #define RT5670_L_VOL_SFT 8 | ||
228 | #define RT5670_R_VOL_MASK (0x3f) | ||
229 | #define RT5670_R_VOL_SFT 0 | ||
230 | |||
231 | /* Combo Jack Control 1 (0x0a) */ | ||
232 | #define RT5670_CBJ_BST1_MASK (0xf << 12) | ||
233 | #define RT5670_CBJ_BST1_SFT (12) | ||
234 | #define RT5670_CBJ_JD_HP_EN (0x1 << 9) | ||
235 | #define RT5670_CBJ_JD_MIC_EN (0x1 << 8) | ||
236 | #define RT5670_CBJ_BST1_EN (0x1 << 2) | ||
237 | |||
238 | /* Combo Jack Control 1 (0x0b) */ | ||
239 | #define RT5670_CBJ_MN_JD (0x1 << 12) | ||
240 | #define RT5670_CAPLESS_EN (0x1 << 11) | ||
241 | #define RT5670_CBJ_DET_MODE (0x1 << 7) | ||
242 | |||
243 | /* IN2 Control (0x0e) */ | ||
244 | #define RT5670_BST_MASK1 (0xf<<12) | ||
245 | #define RT5670_BST_SFT1 12 | ||
246 | #define RT5670_BST_MASK2 (0xf<<8) | ||
247 | #define RT5670_BST_SFT2 8 | ||
248 | #define RT5670_IN_DF1 (0x1 << 7) | ||
249 | #define RT5670_IN_SFT1 7 | ||
250 | #define RT5670_IN_DF2 (0x1 << 6) | ||
251 | #define RT5670_IN_SFT2 6 | ||
252 | |||
253 | /* INL and INR Volume Control (0x0f) */ | ||
254 | #define RT5670_INL_SEL_MASK (0x1 << 15) | ||
255 | #define RT5670_INL_SEL_SFT 15 | ||
256 | #define RT5670_INL_SEL_IN4P (0x0 << 15) | ||
257 | #define RT5670_INL_SEL_MONOP (0x1 << 15) | ||
258 | #define RT5670_INL_VOL_MASK (0x1f << 8) | ||
259 | #define RT5670_INL_VOL_SFT 8 | ||
260 | #define RT5670_INR_SEL_MASK (0x1 << 7) | ||
261 | #define RT5670_INR_SEL_SFT 7 | ||
262 | #define RT5670_INR_SEL_IN4N (0x0 << 7) | ||
263 | #define RT5670_INR_SEL_MONON (0x1 << 7) | ||
264 | #define RT5670_INR_VOL_MASK (0x1f) | ||
265 | #define RT5670_INR_VOL_SFT 0 | ||
266 | |||
267 | /* Sidetone Control (0x18) */ | ||
268 | #define RT5670_ST_SEL_MASK (0x7 << 9) | ||
269 | #define RT5670_ST_SEL_SFT 9 | ||
270 | #define RT5670_M_ST_DACR2 (0x1 << 8) | ||
271 | #define RT5670_M_ST_DACR2_SFT 8 | ||
272 | #define RT5670_M_ST_DACL2 (0x1 << 7) | ||
273 | #define RT5670_M_ST_DACL2_SFT 7 | ||
274 | #define RT5670_ST_EN (0x1 << 6) | ||
275 | #define RT5670_ST_EN_SFT 6 | ||
276 | |||
277 | /* DAC1 Digital Volume (0x19) */ | ||
278 | #define RT5670_DAC_L1_VOL_MASK (0xff << 8) | ||
279 | #define RT5670_DAC_L1_VOL_SFT 8 | ||
280 | #define RT5670_DAC_R1_VOL_MASK (0xff) | ||
281 | #define RT5670_DAC_R1_VOL_SFT 0 | ||
282 | |||
283 | /* DAC2 Digital Volume (0x1a) */ | ||
284 | #define RT5670_DAC_L2_VOL_MASK (0xff << 8) | ||
285 | #define RT5670_DAC_L2_VOL_SFT 8 | ||
286 | #define RT5670_DAC_R2_VOL_MASK (0xff) | ||
287 | #define RT5670_DAC_R2_VOL_SFT 0 | ||
288 | |||
289 | /* DAC2 Control (0x1b) */ | ||
290 | #define RT5670_M_DAC_L2_VOL (0x1 << 13) | ||
291 | #define RT5670_M_DAC_L2_VOL_SFT 13 | ||
292 | #define RT5670_M_DAC_R2_VOL (0x1 << 12) | ||
293 | #define RT5670_M_DAC_R2_VOL_SFT 12 | ||
294 | #define RT5670_DAC2_L_SEL_MASK (0x7 << 4) | ||
295 | #define RT5670_DAC2_L_SEL_SFT 4 | ||
296 | #define RT5670_DAC2_R_SEL_MASK (0x7 << 0) | ||
297 | #define RT5670_DAC2_R_SEL_SFT 0 | ||
298 | |||
299 | /* ADC Digital Volume Control (0x1c) */ | ||
300 | #define RT5670_ADC_L_VOL_MASK (0x7f << 8) | ||
301 | #define RT5670_ADC_L_VOL_SFT 8 | ||
302 | #define RT5670_ADC_R_VOL_MASK (0x7f) | ||
303 | #define RT5670_ADC_R_VOL_SFT 0 | ||
304 | |||
305 | /* Mono ADC Digital Volume Control (0x1d) */ | ||
306 | #define RT5670_MONO_ADC_L_VOL_MASK (0x7f << 8) | ||
307 | #define RT5670_MONO_ADC_L_VOL_SFT 8 | ||
308 | #define RT5670_MONO_ADC_R_VOL_MASK (0x7f) | ||
309 | #define RT5670_MONO_ADC_R_VOL_SFT 0 | ||
310 | |||
311 | /* ADC Boost Volume Control (0x1e) */ | ||
312 | #define RT5670_STO1_ADC_L_BST_MASK (0x3 << 14) | ||
313 | #define RT5670_STO1_ADC_L_BST_SFT 14 | ||
314 | #define RT5670_STO1_ADC_R_BST_MASK (0x3 << 12) | ||
315 | #define RT5670_STO1_ADC_R_BST_SFT 12 | ||
316 | #define RT5670_STO1_ADC_COMP_MASK (0x3 << 10) | ||
317 | #define RT5670_STO1_ADC_COMP_SFT 10 | ||
318 | #define RT5670_STO2_ADC_L_BST_MASK (0x3 << 8) | ||
319 | #define RT5670_STO2_ADC_L_BST_SFT 8 | ||
320 | #define RT5670_STO2_ADC_R_BST_MASK (0x3 << 6) | ||
321 | #define RT5670_STO2_ADC_R_BST_SFT 6 | ||
322 | #define RT5670_STO2_ADC_COMP_MASK (0x3 << 4) | ||
323 | #define RT5670_STO2_ADC_COMP_SFT 4 | ||
324 | |||
325 | /* Stereo2 ADC Mixer Control (0x26) */ | ||
326 | #define RT5670_STO2_ADC_SRC_MASK (0x1 << 15) | ||
327 | #define RT5670_STO2_ADC_SRC_SFT 15 | ||
328 | |||
329 | /* Stereo ADC Mixer Control (0x26 0x27) */ | ||
330 | #define RT5670_M_ADC_L1 (0x1 << 14) | ||
331 | #define RT5670_M_ADC_L1_SFT 14 | ||
332 | #define RT5670_M_ADC_L2 (0x1 << 13) | ||
333 | #define RT5670_M_ADC_L2_SFT 13 | ||
334 | #define RT5670_ADC_1_SRC_MASK (0x1 << 12) | ||
335 | #define RT5670_ADC_1_SRC_SFT 12 | ||
336 | #define RT5670_ADC_1_SRC_ADC (0x1 << 12) | ||
337 | #define RT5670_ADC_1_SRC_DACMIX (0x0 << 12) | ||
338 | #define RT5670_ADC_2_SRC_MASK (0x1 << 11) | ||
339 | #define RT5670_ADC_2_SRC_SFT 11 | ||
340 | #define RT5670_ADC_SRC_MASK (0x1 << 10) | ||
341 | #define RT5670_ADC_SRC_SFT 10 | ||
342 | #define RT5670_DMIC_SRC_MASK (0x3 << 8) | ||
343 | #define RT5670_DMIC_SRC_SFT 8 | ||
344 | #define RT5670_M_ADC_R1 (0x1 << 6) | ||
345 | #define RT5670_M_ADC_R1_SFT 6 | ||
346 | #define RT5670_M_ADC_R2 (0x1 << 5) | ||
347 | #define RT5670_M_ADC_R2_SFT 5 | ||
348 | #define RT5670_DMIC3_SRC_MASK (0x1 << 1) | ||
349 | #define RT5670_DMIC3_SRC_SFT 0 | ||
350 | |||
351 | /* Mono ADC Mixer Control (0x28) */ | ||
352 | #define RT5670_M_MONO_ADC_L1 (0x1 << 14) | ||
353 | #define RT5670_M_MONO_ADC_L1_SFT 14 | ||
354 | #define RT5670_M_MONO_ADC_L2 (0x1 << 13) | ||
355 | #define RT5670_M_MONO_ADC_L2_SFT 13 | ||
356 | #define RT5670_MONO_ADC_L1_SRC_MASK (0x1 << 12) | ||
357 | #define RT5670_MONO_ADC_L1_SRC_SFT 12 | ||
358 | #define RT5670_MONO_ADC_L1_SRC_DACMIXL (0x0 << 12) | ||
359 | #define RT5670_MONO_ADC_L1_SRC_ADCL (0x1 << 12) | ||
360 | #define RT5670_MONO_ADC_L2_SRC_MASK (0x1 << 11) | ||
361 | #define RT5670_MONO_ADC_L2_SRC_SFT 11 | ||
362 | #define RT5670_MONO_ADC_L_SRC_MASK (0x1 << 10) | ||
363 | #define RT5670_MONO_ADC_L_SRC_SFT 10 | ||
364 | #define RT5670_MONO_DMIC_L_SRC_MASK (0x3 << 8) | ||
365 | #define RT5670_MONO_DMIC_L_SRC_SFT 8 | ||
366 | #define RT5670_M_MONO_ADC_R1 (0x1 << 6) | ||
367 | #define RT5670_M_MONO_ADC_R1_SFT 6 | ||
368 | #define RT5670_M_MONO_ADC_R2 (0x1 << 5) | ||
369 | #define RT5670_M_MONO_ADC_R2_SFT 5 | ||
370 | #define RT5670_MONO_ADC_R1_SRC_MASK (0x1 << 4) | ||
371 | #define RT5670_MONO_ADC_R1_SRC_SFT 4 | ||
372 | #define RT5670_MONO_ADC_R1_SRC_ADCR (0x1 << 4) | ||
373 | #define RT5670_MONO_ADC_R1_SRC_DACMIXR (0x0 << 4) | ||
374 | #define RT5670_MONO_ADC_R2_SRC_MASK (0x1 << 3) | ||
375 | #define RT5670_MONO_ADC_R2_SRC_SFT 3 | ||
376 | #define RT5670_MONO_DMIC_R_SRC_MASK (0x3) | ||
377 | #define RT5670_MONO_DMIC_R_SRC_SFT 0 | ||
378 | |||
379 | /* ADC Mixer to DAC Mixer Control (0x29) */ | ||
380 | #define RT5670_M_ADCMIX_L (0x1 << 15) | ||
381 | #define RT5670_M_ADCMIX_L_SFT 15 | ||
382 | #define RT5670_M_DAC1_L (0x1 << 14) | ||
383 | #define RT5670_M_DAC1_L_SFT 14 | ||
384 | #define RT5670_DAC1_R_SEL_MASK (0x3 << 10) | ||
385 | #define RT5670_DAC1_R_SEL_SFT 10 | ||
386 | #define RT5670_DAC1_R_SEL_IF1 (0x0 << 10) | ||
387 | #define RT5670_DAC1_R_SEL_IF2 (0x1 << 10) | ||
388 | #define RT5670_DAC1_R_SEL_IF3 (0x2 << 10) | ||
389 | #define RT5670_DAC1_R_SEL_IF4 (0x3 << 10) | ||
390 | #define RT5670_DAC1_L_SEL_MASK (0x3 << 8) | ||
391 | #define RT5670_DAC1_L_SEL_SFT 8 | ||
392 | #define RT5670_DAC1_L_SEL_IF1 (0x0 << 8) | ||
393 | #define RT5670_DAC1_L_SEL_IF2 (0x1 << 8) | ||
394 | #define RT5670_DAC1_L_SEL_IF3 (0x2 << 8) | ||
395 | #define RT5670_DAC1_L_SEL_IF4 (0x3 << 8) | ||
396 | #define RT5670_M_ADCMIX_R (0x1 << 7) | ||
397 | #define RT5670_M_ADCMIX_R_SFT 7 | ||
398 | #define RT5670_M_DAC1_R (0x1 << 6) | ||
399 | #define RT5670_M_DAC1_R_SFT 6 | ||
400 | |||
401 | /* Stereo DAC Mixer Control (0x2a) */ | ||
402 | #define RT5670_M_DAC_L1 (0x1 << 14) | ||
403 | #define RT5670_M_DAC_L1_SFT 14 | ||
404 | #define RT5670_DAC_L1_STO_L_VOL_MASK (0x1 << 13) | ||
405 | #define RT5670_DAC_L1_STO_L_VOL_SFT 13 | ||
406 | #define RT5670_M_DAC_L2 (0x1 << 12) | ||
407 | #define RT5670_M_DAC_L2_SFT 12 | ||
408 | #define RT5670_DAC_L2_STO_L_VOL_MASK (0x1 << 11) | ||
409 | #define RT5670_DAC_L2_STO_L_VOL_SFT 11 | ||
410 | #define RT5670_M_DAC_R1_STO_L (0x1 << 9) | ||
411 | #define RT5670_M_DAC_R1_STO_L_SFT 9 | ||
412 | #define RT5670_DAC_R1_STO_L_VOL_MASK (0x1 << 8) | ||
413 | #define RT5670_DAC_R1_STO_L_VOL_SFT 8 | ||
414 | #define RT5670_M_DAC_R1 (0x1 << 6) | ||
415 | #define RT5670_M_DAC_R1_SFT 6 | ||
416 | #define RT5670_DAC_R1_STO_R_VOL_MASK (0x1 << 5) | ||
417 | #define RT5670_DAC_R1_STO_R_VOL_SFT 5 | ||
418 | #define RT5670_M_DAC_R2 (0x1 << 4) | ||
419 | #define RT5670_M_DAC_R2_SFT 4 | ||
420 | #define RT5670_DAC_R2_STO_R_VOL_MASK (0x1 << 3) | ||
421 | #define RT5670_DAC_R2_STO_R_VOL_SFT 3 | ||
422 | #define RT5670_M_DAC_L1_STO_R (0x1 << 1) | ||
423 | #define RT5670_M_DAC_L1_STO_R_SFT 1 | ||
424 | #define RT5670_DAC_L1_STO_R_VOL_MASK (0x1) | ||
425 | #define RT5670_DAC_L1_STO_R_VOL_SFT 0 | ||
426 | |||
427 | /* Mono DAC Mixer Control (0x2b) */ | ||
428 | #define RT5670_M_DAC_L1_MONO_L (0x1 << 14) | ||
429 | #define RT5670_M_DAC_L1_MONO_L_SFT 14 | ||
430 | #define RT5670_DAC_L1_MONO_L_VOL_MASK (0x1 << 13) | ||
431 | #define RT5670_DAC_L1_MONO_L_VOL_SFT 13 | ||
432 | #define RT5670_M_DAC_L2_MONO_L (0x1 << 12) | ||
433 | #define RT5670_M_DAC_L2_MONO_L_SFT 12 | ||
434 | #define RT5670_DAC_L2_MONO_L_VOL_MASK (0x1 << 11) | ||
435 | #define RT5670_DAC_L2_MONO_L_VOL_SFT 11 | ||
436 | #define RT5670_M_DAC_R2_MONO_L (0x1 << 10) | ||
437 | #define RT5670_M_DAC_R2_MONO_L_SFT 10 | ||
438 | #define RT5670_DAC_R2_MONO_L_VOL_MASK (0x1 << 9) | ||
439 | #define RT5670_DAC_R2_MONO_L_VOL_SFT 9 | ||
440 | #define RT5670_M_DAC_R1_MONO_R (0x1 << 6) | ||
441 | #define RT5670_M_DAC_R1_MONO_R_SFT 6 | ||
442 | #define RT5670_DAC_R1_MONO_R_VOL_MASK (0x1 << 5) | ||
443 | #define RT5670_DAC_R1_MONO_R_VOL_SFT 5 | ||
444 | #define RT5670_M_DAC_R2_MONO_R (0x1 << 4) | ||
445 | #define RT5670_M_DAC_R2_MONO_R_SFT 4 | ||
446 | #define RT5670_DAC_R2_MONO_R_VOL_MASK (0x1 << 3) | ||
447 | #define RT5670_DAC_R2_MONO_R_VOL_SFT 3 | ||
448 | #define RT5670_M_DAC_L2_MONO_R (0x1 << 2) | ||
449 | #define RT5670_M_DAC_L2_MONO_R_SFT 2 | ||
450 | #define RT5670_DAC_L2_MONO_R_VOL_MASK (0x1 << 1) | ||
451 | #define RT5670_DAC_L2_MONO_R_VOL_SFT 1 | ||
452 | |||
453 | /* Digital Mixer Control (0x2c) */ | ||
454 | #define RT5670_M_STO_L_DAC_L (0x1 << 15) | ||
455 | #define RT5670_M_STO_L_DAC_L_SFT 15 | ||
456 | #define RT5670_STO_L_DAC_L_VOL_MASK (0x1 << 14) | ||
457 | #define RT5670_STO_L_DAC_L_VOL_SFT 14 | ||
458 | #define RT5670_M_DAC_L2_DAC_L (0x1 << 13) | ||
459 | #define RT5670_M_DAC_L2_DAC_L_SFT 13 | ||
460 | #define RT5670_DAC_L2_DAC_L_VOL_MASK (0x1 << 12) | ||
461 | #define RT5670_DAC_L2_DAC_L_VOL_SFT 12 | ||
462 | #define RT5670_M_STO_R_DAC_R (0x1 << 11) | ||
463 | #define RT5670_M_STO_R_DAC_R_SFT 11 | ||
464 | #define RT5670_STO_R_DAC_R_VOL_MASK (0x1 << 10) | ||
465 | #define RT5670_STO_R_DAC_R_VOL_SFT 10 | ||
466 | #define RT5670_M_DAC_R2_DAC_R (0x1 << 9) | ||
467 | #define RT5670_M_DAC_R2_DAC_R_SFT 9 | ||
468 | #define RT5670_DAC_R2_DAC_R_VOL_MASK (0x1 << 8) | ||
469 | #define RT5670_DAC_R2_DAC_R_VOL_SFT 8 | ||
470 | #define RT5670_M_DAC_R2_DAC_L (0x1 << 7) | ||
471 | #define RT5670_M_DAC_R2_DAC_L_SFT 7 | ||
472 | #define RT5670_DAC_R2_DAC_L_VOL_MASK (0x1 << 6) | ||
473 | #define RT5670_DAC_R2_DAC_L_VOL_SFT 6 | ||
474 | #define RT5670_M_DAC_L2_DAC_R (0x1 << 5) | ||
475 | #define RT5670_M_DAC_L2_DAC_R_SFT 5 | ||
476 | #define RT5670_DAC_L2_DAC_R_VOL_MASK (0x1 << 4) | ||
477 | #define RT5670_DAC_L2_DAC_R_VOL_SFT 4 | ||
478 | |||
479 | /* DSP Path Control 1 (0x2d) */ | ||
480 | #define RT5670_RXDP_SEL_MASK (0x7 << 13) | ||
481 | #define RT5670_RXDP_SEL_SFT 13 | ||
482 | #define RT5670_RXDP_SRC_MASK (0x3 << 11) | ||
483 | #define RT5670_RXDP_SRC_SFT 11 | ||
484 | #define RT5670_RXDP_SRC_NOR (0x0 << 11) | ||
485 | #define RT5670_RXDP_SRC_DIV2 (0x1 << 11) | ||
486 | #define RT5670_RXDP_SRC_DIV3 (0x2 << 11) | ||
487 | #define RT5670_TXDP_SRC_MASK (0x3 << 4) | ||
488 | #define RT5670_TXDP_SRC_SFT 4 | ||
489 | #define RT5670_TXDP_SRC_NOR (0x0 << 4) | ||
490 | #define RT5670_TXDP_SRC_DIV2 (0x1 << 4) | ||
491 | #define RT5670_TXDP_SRC_DIV3 (0x2 << 4) | ||
492 | #define RT5670_TXDP_SLOT_SEL_MASK (0x3 << 2) | ||
493 | #define RT5670_TXDP_SLOT_SEL_SFT 2 | ||
494 | #define RT5670_DSP_UL_SEL (0x1 << 1) | ||
495 | #define RT5670_DSP_UL_SFT 1 | ||
496 | #define RT5670_DSP_DL_SEL 0x1 | ||
497 | #define RT5670_DSP_DL_SFT 0 | ||
498 | |||
499 | /* DSP Path Control 2 (0x2e) */ | ||
500 | #define RT5670_TXDP_L_VOL_MASK (0x7f << 8) | ||
501 | #define RT5670_TXDP_L_VOL_SFT 8 | ||
502 | #define RT5670_TXDP_R_VOL_MASK (0x7f) | ||
503 | #define RT5670_TXDP_R_VOL_SFT 0 | ||
504 | |||
505 | /* Digital Interface Data Control (0x2f) */ | ||
506 | #define RT5670_IF1_ADC2_IN_SEL (0x1 << 15) | ||
507 | #define RT5670_IF1_ADC2_IN_SFT 15 | ||
508 | #define RT5670_IF2_ADC_IN_MASK (0x7 << 12) | ||
509 | #define RT5670_IF2_ADC_IN_SFT 12 | ||
510 | #define RT5670_IF2_DAC_SEL_MASK (0x3 << 10) | ||
511 | #define RT5670_IF2_DAC_SEL_SFT 10 | ||
512 | #define RT5670_IF2_ADC_SEL_MASK (0x3 << 8) | ||
513 | #define RT5670_IF2_ADC_SEL_SFT 8 | ||
514 | |||
515 | /* Digital Interface Data Control (0x30) */ | ||
516 | #define RT5670_IF4_ADC_IN_MASK (0x3 << 4) | ||
517 | #define RT5670_IF4_ADC_IN_SFT 4 | ||
518 | |||
519 | /* PDM Output Control (0x31) */ | ||
520 | #define RT5670_PDM1_L_MASK (0x1 << 15) | ||
521 | #define RT5670_PDM1_L_SFT 15 | ||
522 | #define RT5670_M_PDM1_L (0x1 << 14) | ||
523 | #define RT5670_M_PDM1_L_SFT 14 | ||
524 | #define RT5670_PDM1_R_MASK (0x1 << 13) | ||
525 | #define RT5670_PDM1_R_SFT 13 | ||
526 | #define RT5670_M_PDM1_R (0x1 << 12) | ||
527 | #define RT5670_M_PDM1_R_SFT 12 | ||
528 | #define RT5670_PDM2_L_MASK (0x1 << 11) | ||
529 | #define RT5670_PDM2_L_SFT 11 | ||
530 | #define RT5670_M_PDM2_L (0x1 << 10) | ||
531 | #define RT5670_M_PDM2_L_SFT 10 | ||
532 | #define RT5670_PDM2_R_MASK (0x1 << 9) | ||
533 | #define RT5670_PDM2_R_SFT 9 | ||
534 | #define RT5670_M_PDM2_R (0x1 << 8) | ||
535 | #define RT5670_M_PDM2_R_SFT 8 | ||
536 | #define RT5670_PDM2_BUSY (0x1 << 7) | ||
537 | #define RT5670_PDM1_BUSY (0x1 << 6) | ||
538 | #define RT5670_PDM_PATTERN (0x1 << 5) | ||
539 | #define RT5670_PDM_GAIN (0x1 << 4) | ||
540 | #define RT5670_PDM_DIV_MASK (0x3) | ||
541 | |||
542 | /* REC Left Mixer Control 1 (0x3b) */ | ||
543 | #define RT5670_G_HP_L_RM_L_MASK (0x7 << 13) | ||
544 | #define RT5670_G_HP_L_RM_L_SFT 13 | ||
545 | #define RT5670_G_IN_L_RM_L_MASK (0x7 << 10) | ||
546 | #define RT5670_G_IN_L_RM_L_SFT 10 | ||
547 | #define RT5670_G_BST4_RM_L_MASK (0x7 << 7) | ||
548 | #define RT5670_G_BST4_RM_L_SFT 7 | ||
549 | #define RT5670_G_BST3_RM_L_MASK (0x7 << 4) | ||
550 | #define RT5670_G_BST3_RM_L_SFT 4 | ||
551 | #define RT5670_G_BST2_RM_L_MASK (0x7 << 1) | ||
552 | #define RT5670_G_BST2_RM_L_SFT 1 | ||
553 | |||
554 | /* REC Left Mixer Control 2 (0x3c) */ | ||
555 | #define RT5670_G_BST1_RM_L_MASK (0x7 << 13) | ||
556 | #define RT5670_G_BST1_RM_L_SFT 13 | ||
557 | #define RT5670_M_IN_L_RM_L (0x1 << 5) | ||
558 | #define RT5670_M_IN_L_RM_L_SFT 5 | ||
559 | #define RT5670_M_BST2_RM_L (0x1 << 3) | ||
560 | #define RT5670_M_BST2_RM_L_SFT 3 | ||
561 | #define RT5670_M_BST1_RM_L (0x1 << 1) | ||
562 | #define RT5670_M_BST1_RM_L_SFT 1 | ||
563 | |||
564 | /* REC Right Mixer Control 1 (0x3d) */ | ||
565 | #define RT5670_G_HP_R_RM_R_MASK (0x7 << 13) | ||
566 | #define RT5670_G_HP_R_RM_R_SFT 13 | ||
567 | #define RT5670_G_IN_R_RM_R_MASK (0x7 << 10) | ||
568 | #define RT5670_G_IN_R_RM_R_SFT 10 | ||
569 | #define RT5670_G_BST4_RM_R_MASK (0x7 << 7) | ||
570 | #define RT5670_G_BST4_RM_R_SFT 7 | ||
571 | #define RT5670_G_BST3_RM_R_MASK (0x7 << 4) | ||
572 | #define RT5670_G_BST3_RM_R_SFT 4 | ||
573 | #define RT5670_G_BST2_RM_R_MASK (0x7 << 1) | ||
574 | #define RT5670_G_BST2_RM_R_SFT 1 | ||
575 | |||
576 | /* REC Right Mixer Control 2 (0x3e) */ | ||
577 | #define RT5670_G_BST1_RM_R_MASK (0x7 << 13) | ||
578 | #define RT5670_G_BST1_RM_R_SFT 13 | ||
579 | #define RT5670_M_IN_R_RM_R (0x1 << 5) | ||
580 | #define RT5670_M_IN_R_RM_R_SFT 5 | ||
581 | #define RT5670_M_BST2_RM_R (0x1 << 3) | ||
582 | #define RT5670_M_BST2_RM_R_SFT 3 | ||
583 | #define RT5670_M_BST1_RM_R (0x1 << 1) | ||
584 | #define RT5670_M_BST1_RM_R_SFT 1 | ||
585 | |||
586 | /* HPMIX Control (0x45) */ | ||
587 | #define RT5670_M_DAC2_HM (0x1 << 15) | ||
588 | #define RT5670_M_DAC2_HM_SFT 15 | ||
589 | #define RT5670_M_HPVOL_HM (0x1 << 14) | ||
590 | #define RT5670_M_HPVOL_HM_SFT 14 | ||
591 | #define RT5670_M_DAC1_HM (0x1 << 13) | ||
592 | #define RT5670_M_DAC1_HM_SFT 13 | ||
593 | #define RT5670_G_HPOMIX_MASK (0x1 << 12) | ||
594 | #define RT5670_G_HPOMIX_SFT 12 | ||
595 | #define RT5670_M_INR1_HMR (0x1 << 3) | ||
596 | #define RT5670_M_INR1_HMR_SFT 3 | ||
597 | #define RT5670_M_DACR1_HMR (0x1 << 2) | ||
598 | #define RT5670_M_DACR1_HMR_SFT 2 | ||
599 | #define RT5670_M_INL1_HML (0x1 << 1) | ||
600 | #define RT5670_M_INL1_HML_SFT 1 | ||
601 | #define RT5670_M_DACL1_HML (0x1) | ||
602 | #define RT5670_M_DACL1_HML_SFT 0 | ||
603 | |||
604 | /* Mono Output Mixer Control (0x4c) */ | ||
605 | #define RT5670_M_DAC_R2_MA (0x1 << 15) | ||
606 | #define RT5670_M_DAC_R2_MA_SFT 15 | ||
607 | #define RT5670_M_DAC_L2_MA (0x1 << 14) | ||
608 | #define RT5670_M_DAC_L2_MA_SFT 14 | ||
609 | #define RT5670_M_OV_R_MM (0x1 << 13) | ||
610 | #define RT5670_M_OV_R_MM_SFT 13 | ||
611 | #define RT5670_M_OV_L_MM (0x1 << 12) | ||
612 | #define RT5670_M_OV_L_MM_SFT 12 | ||
613 | #define RT5670_G_MONOMIX_MASK (0x1 << 10) | ||
614 | #define RT5670_G_MONOMIX_SFT 10 | ||
615 | #define RT5670_M_DAC_R2_MM (0x1 << 9) | ||
616 | #define RT5670_M_DAC_R2_MM_SFT 9 | ||
617 | #define RT5670_M_DAC_L2_MM (0x1 << 8) | ||
618 | #define RT5670_M_DAC_L2_MM_SFT 8 | ||
619 | #define RT5670_M_BST4_MM (0x1 << 7) | ||
620 | #define RT5670_M_BST4_MM_SFT 7 | ||
621 | |||
622 | /* Output Left Mixer Control 1 (0x4d) */ | ||
623 | #define RT5670_G_BST3_OM_L_MASK (0x7 << 13) | ||
624 | #define RT5670_G_BST3_OM_L_SFT 13 | ||
625 | #define RT5670_G_BST2_OM_L_MASK (0x7 << 10) | ||
626 | #define RT5670_G_BST2_OM_L_SFT 10 | ||
627 | #define RT5670_G_BST1_OM_L_MASK (0x7 << 7) | ||
628 | #define RT5670_G_BST1_OM_L_SFT 7 | ||
629 | #define RT5670_G_IN_L_OM_L_MASK (0x7 << 4) | ||
630 | #define RT5670_G_IN_L_OM_L_SFT 4 | ||
631 | #define RT5670_G_RM_L_OM_L_MASK (0x7 << 1) | ||
632 | #define RT5670_G_RM_L_OM_L_SFT 1 | ||
633 | |||
634 | /* Output Left Mixer Control 2 (0x4e) */ | ||
635 | #define RT5670_G_DAC_R2_OM_L_MASK (0x7 << 13) | ||
636 | #define RT5670_G_DAC_R2_OM_L_SFT 13 | ||
637 | #define RT5670_G_DAC_L2_OM_L_MASK (0x7 << 10) | ||
638 | #define RT5670_G_DAC_L2_OM_L_SFT 10 | ||
639 | #define RT5670_G_DAC_L1_OM_L_MASK (0x7 << 7) | ||
640 | #define RT5670_G_DAC_L1_OM_L_SFT 7 | ||
641 | |||
642 | /* Output Left Mixer Control 3 (0x4f) */ | ||
643 | #define RT5670_M_BST1_OM_L (0x1 << 5) | ||
644 | #define RT5670_M_BST1_OM_L_SFT 5 | ||
645 | #define RT5670_M_IN_L_OM_L (0x1 << 4) | ||
646 | #define RT5670_M_IN_L_OM_L_SFT 4 | ||
647 | #define RT5670_M_DAC_L2_OM_L (0x1 << 1) | ||
648 | #define RT5670_M_DAC_L2_OM_L_SFT 1 | ||
649 | #define RT5670_M_DAC_L1_OM_L (0x1) | ||
650 | #define RT5670_M_DAC_L1_OM_L_SFT 0 | ||
651 | |||
652 | /* Output Right Mixer Control 1 (0x50) */ | ||
653 | #define RT5670_G_BST4_OM_R_MASK (0x7 << 13) | ||
654 | #define RT5670_G_BST4_OM_R_SFT 13 | ||
655 | #define RT5670_G_BST2_OM_R_MASK (0x7 << 10) | ||
656 | #define RT5670_G_BST2_OM_R_SFT 10 | ||
657 | #define RT5670_G_BST1_OM_R_MASK (0x7 << 7) | ||
658 | #define RT5670_G_BST1_OM_R_SFT 7 | ||
659 | #define RT5670_G_IN_R_OM_R_MASK (0x7 << 4) | ||
660 | #define RT5670_G_IN_R_OM_R_SFT 4 | ||
661 | #define RT5670_G_RM_R_OM_R_MASK (0x7 << 1) | ||
662 | #define RT5670_G_RM_R_OM_R_SFT 1 | ||
663 | |||
664 | /* Output Right Mixer Control 2 (0x51) */ | ||
665 | #define RT5670_G_DAC_L2_OM_R_MASK (0x7 << 13) | ||
666 | #define RT5670_G_DAC_L2_OM_R_SFT 13 | ||
667 | #define RT5670_G_DAC_R2_OM_R_MASK (0x7 << 10) | ||
668 | #define RT5670_G_DAC_R2_OM_R_SFT 10 | ||
669 | #define RT5670_G_DAC_R1_OM_R_MASK (0x7 << 7) | ||
670 | #define RT5670_G_DAC_R1_OM_R_SFT 7 | ||
671 | |||
672 | /* Output Right Mixer Control 3 (0x52) */ | ||
673 | #define RT5670_M_BST2_OM_R (0x1 << 6) | ||
674 | #define RT5670_M_BST2_OM_R_SFT 6 | ||
675 | #define RT5670_M_IN_R_OM_R (0x1 << 4) | ||
676 | #define RT5670_M_IN_R_OM_R_SFT 4 | ||
677 | #define RT5670_M_DAC_R2_OM_R (0x1 << 1) | ||
678 | #define RT5670_M_DAC_R2_OM_R_SFT 1 | ||
679 | #define RT5670_M_DAC_R1_OM_R (0x1) | ||
680 | #define RT5670_M_DAC_R1_OM_R_SFT 0 | ||
681 | |||
682 | /* LOUT Mixer Control (0x53) */ | ||
683 | #define RT5670_M_DAC_L1_LM (0x1 << 15) | ||
684 | #define RT5670_M_DAC_L1_LM_SFT 15 | ||
685 | #define RT5670_M_DAC_R1_LM (0x1 << 14) | ||
686 | #define RT5670_M_DAC_R1_LM_SFT 14 | ||
687 | #define RT5670_M_OV_L_LM (0x1 << 13) | ||
688 | #define RT5670_M_OV_L_LM_SFT 13 | ||
689 | #define RT5670_M_OV_R_LM (0x1 << 12) | ||
690 | #define RT5670_M_OV_R_LM_SFT 12 | ||
691 | #define RT5670_G_LOUTMIX_MASK (0x1 << 11) | ||
692 | #define RT5670_G_LOUTMIX_SFT 11 | ||
693 | |||
694 | /* Power Management for Digital 1 (0x61) */ | ||
695 | #define RT5670_PWR_I2S1 (0x1 << 15) | ||
696 | #define RT5670_PWR_I2S1_BIT 15 | ||
697 | #define RT5670_PWR_I2S2 (0x1 << 14) | ||
698 | #define RT5670_PWR_I2S2_BIT 14 | ||
699 | #define RT5670_PWR_DAC_L1 (0x1 << 12) | ||
700 | #define RT5670_PWR_DAC_L1_BIT 12 | ||
701 | #define RT5670_PWR_DAC_R1 (0x1 << 11) | ||
702 | #define RT5670_PWR_DAC_R1_BIT 11 | ||
703 | #define RT5670_PWR_DAC_L2 (0x1 << 7) | ||
704 | #define RT5670_PWR_DAC_L2_BIT 7 | ||
705 | #define RT5670_PWR_DAC_R2 (0x1 << 6) | ||
706 | #define RT5670_PWR_DAC_R2_BIT 6 | ||
707 | #define RT5670_PWR_ADC_L (0x1 << 2) | ||
708 | #define RT5670_PWR_ADC_L_BIT 2 | ||
709 | #define RT5670_PWR_ADC_R (0x1 << 1) | ||
710 | #define RT5670_PWR_ADC_R_BIT 1 | ||
711 | #define RT5670_PWR_CLS_D (0x1) | ||
712 | #define RT5670_PWR_CLS_D_BIT 0 | ||
713 | |||
714 | /* Power Management for Digital 2 (0x62) */ | ||
715 | #define RT5670_PWR_ADC_S1F (0x1 << 15) | ||
716 | #define RT5670_PWR_ADC_S1F_BIT 15 | ||
717 | #define RT5670_PWR_ADC_MF_L (0x1 << 14) | ||
718 | #define RT5670_PWR_ADC_MF_L_BIT 14 | ||
719 | #define RT5670_PWR_ADC_MF_R (0x1 << 13) | ||
720 | #define RT5670_PWR_ADC_MF_R_BIT 13 | ||
721 | #define RT5670_PWR_I2S_DSP (0x1 << 12) | ||
722 | #define RT5670_PWR_I2S_DSP_BIT 12 | ||
723 | #define RT5670_PWR_DAC_S1F (0x1 << 11) | ||
724 | #define RT5670_PWR_DAC_S1F_BIT 11 | ||
725 | #define RT5670_PWR_DAC_MF_L (0x1 << 10) | ||
726 | #define RT5670_PWR_DAC_MF_L_BIT 10 | ||
727 | #define RT5670_PWR_DAC_MF_R (0x1 << 9) | ||
728 | #define RT5670_PWR_DAC_MF_R_BIT 9 | ||
729 | #define RT5670_PWR_ADC_S2F (0x1 << 8) | ||
730 | #define RT5670_PWR_ADC_S2F_BIT 8 | ||
731 | #define RT5670_PWR_PDM1 (0x1 << 7) | ||
732 | #define RT5670_PWR_PDM1_BIT 7 | ||
733 | #define RT5670_PWR_PDM2 (0x1 << 6) | ||
734 | #define RT5670_PWR_PDM2_BIT 6 | ||
735 | |||
736 | /* Power Management for Analog 1 (0x63) */ | ||
737 | #define RT5670_PWR_VREF1 (0x1 << 15) | ||
738 | #define RT5670_PWR_VREF1_BIT 15 | ||
739 | #define RT5670_PWR_FV1 (0x1 << 14) | ||
740 | #define RT5670_PWR_FV1_BIT 14 | ||
741 | #define RT5670_PWR_MB (0x1 << 13) | ||
742 | #define RT5670_PWR_MB_BIT 13 | ||
743 | #define RT5670_PWR_LM (0x1 << 12) | ||
744 | #define RT5670_PWR_LM_BIT 12 | ||
745 | #define RT5670_PWR_BG (0x1 << 11) | ||
746 | #define RT5670_PWR_BG_BIT 11 | ||
747 | #define RT5670_PWR_HP_L (0x1 << 7) | ||
748 | #define RT5670_PWR_HP_L_BIT 7 | ||
749 | #define RT5670_PWR_HP_R (0x1 << 6) | ||
750 | #define RT5670_PWR_HP_R_BIT 6 | ||
751 | #define RT5670_PWR_HA (0x1 << 5) | ||
752 | #define RT5670_PWR_HA_BIT 5 | ||
753 | #define RT5670_PWR_VREF2 (0x1 << 4) | ||
754 | #define RT5670_PWR_VREF2_BIT 4 | ||
755 | #define RT5670_PWR_FV2 (0x1 << 3) | ||
756 | #define RT5670_PWR_FV2_BIT 3 | ||
757 | #define RT5670_LDO_SEL_MASK (0x3) | ||
758 | #define RT5670_LDO_SEL_SFT 0 | ||
759 | |||
760 | /* Power Management for Analog 2 (0x64) */ | ||
761 | #define RT5670_PWR_BST1 (0x1 << 15) | ||
762 | #define RT5670_PWR_BST1_BIT 15 | ||
763 | #define RT5670_PWR_BST2 (0x1 << 13) | ||
764 | #define RT5670_PWR_BST2_BIT 13 | ||
765 | #define RT5670_PWR_MB1 (0x1 << 11) | ||
766 | #define RT5670_PWR_MB1_BIT 11 | ||
767 | #define RT5670_PWR_MB2 (0x1 << 10) | ||
768 | #define RT5670_PWR_MB2_BIT 10 | ||
769 | #define RT5670_PWR_PLL (0x1 << 9) | ||
770 | #define RT5670_PWR_PLL_BIT 9 | ||
771 | #define RT5670_PWR_BST1_P (0x1 << 6) | ||
772 | #define RT5670_PWR_BST1_P_BIT 6 | ||
773 | #define RT5670_PWR_BST2_P (0x1 << 4) | ||
774 | #define RT5670_PWR_BST2_P_BIT 4 | ||
775 | #define RT5670_PWR_JD1 (0x1 << 2) | ||
776 | #define RT5670_PWR_JD1_BIT 2 | ||
777 | #define RT5670_PWR_JD (0x1 << 1) | ||
778 | #define RT5670_PWR_JD_BIT 1 | ||
779 | |||
780 | /* Power Management for Mixer (0x65) */ | ||
781 | #define RT5670_PWR_OM_L (0x1 << 15) | ||
782 | #define RT5670_PWR_OM_L_BIT 15 | ||
783 | #define RT5670_PWR_OM_R (0x1 << 14) | ||
784 | #define RT5670_PWR_OM_R_BIT 14 | ||
785 | #define RT5670_PWR_RM_L (0x1 << 11) | ||
786 | #define RT5670_PWR_RM_L_BIT 11 | ||
787 | #define RT5670_PWR_RM_R (0x1 << 10) | ||
788 | #define RT5670_PWR_RM_R_BIT 10 | ||
789 | |||
790 | /* Power Management for Volume (0x66) */ | ||
791 | #define RT5670_PWR_HV_L (0x1 << 11) | ||
792 | #define RT5670_PWR_HV_L_BIT 11 | ||
793 | #define RT5670_PWR_HV_R (0x1 << 10) | ||
794 | #define RT5670_PWR_HV_R_BIT 10 | ||
795 | #define RT5670_PWR_IN_L (0x1 << 9) | ||
796 | #define RT5670_PWR_IN_L_BIT 9 | ||
797 | #define RT5670_PWR_IN_R (0x1 << 8) | ||
798 | #define RT5670_PWR_IN_R_BIT 8 | ||
799 | #define RT5670_PWR_MIC_DET (0x1 << 5) | ||
800 | #define RT5670_PWR_MIC_DET_BIT 5 | ||
801 | |||
802 | /* I2S1/2/3 Audio Serial Data Port Control (0x70 0x71 0x72) */ | ||
803 | #define RT5670_I2S_MS_MASK (0x1 << 15) | ||
804 | #define RT5670_I2S_MS_SFT 15 | ||
805 | #define RT5670_I2S_MS_M (0x0 << 15) | ||
806 | #define RT5670_I2S_MS_S (0x1 << 15) | ||
807 | #define RT5670_I2S_IF_MASK (0x7 << 12) | ||
808 | #define RT5670_I2S_IF_SFT 12 | ||
809 | #define RT5670_I2S_O_CP_MASK (0x3 << 10) | ||
810 | #define RT5670_I2S_O_CP_SFT 10 | ||
811 | #define RT5670_I2S_O_CP_OFF (0x0 << 10) | ||
812 | #define RT5670_I2S_O_CP_U_LAW (0x1 << 10) | ||
813 | #define RT5670_I2S_O_CP_A_LAW (0x2 << 10) | ||
814 | #define RT5670_I2S_I_CP_MASK (0x3 << 8) | ||
815 | #define RT5670_I2S_I_CP_SFT 8 | ||
816 | #define RT5670_I2S_I_CP_OFF (0x0 << 8) | ||
817 | #define RT5670_I2S_I_CP_U_LAW (0x1 << 8) | ||
818 | #define RT5670_I2S_I_CP_A_LAW (0x2 << 8) | ||
819 | #define RT5670_I2S_BP_MASK (0x1 << 7) | ||
820 | #define RT5670_I2S_BP_SFT 7 | ||
821 | #define RT5670_I2S_BP_NOR (0x0 << 7) | ||
822 | #define RT5670_I2S_BP_INV (0x1 << 7) | ||
823 | #define RT5670_I2S_DL_MASK (0x3 << 2) | ||
824 | #define RT5670_I2S_DL_SFT 2 | ||
825 | #define RT5670_I2S_DL_16 (0x0 << 2) | ||
826 | #define RT5670_I2S_DL_20 (0x1 << 2) | ||
827 | #define RT5670_I2S_DL_24 (0x2 << 2) | ||
828 | #define RT5670_I2S_DL_8 (0x3 << 2) | ||
829 | #define RT5670_I2S_DF_MASK (0x3) | ||
830 | #define RT5670_I2S_DF_SFT 0 | ||
831 | #define RT5670_I2S_DF_I2S (0x0) | ||
832 | #define RT5670_I2S_DF_LEFT (0x1) | ||
833 | #define RT5670_I2S_DF_PCM_A (0x2) | ||
834 | #define RT5670_I2S_DF_PCM_B (0x3) | ||
835 | |||
836 | /* I2S2 Audio Serial Data Port Control (0x71) */ | ||
837 | #define RT5670_I2S2_SDI_MASK (0x1 << 6) | ||
838 | #define RT5670_I2S2_SDI_SFT 6 | ||
839 | #define RT5670_I2S2_SDI_I2S1 (0x0 << 6) | ||
840 | #define RT5670_I2S2_SDI_I2S2 (0x1 << 6) | ||
841 | |||
842 | /* ADC/DAC Clock Control 1 (0x73) */ | ||
843 | #define RT5670_I2S_BCLK_MS1_MASK (0x1 << 15) | ||
844 | #define RT5670_I2S_BCLK_MS1_SFT 15 | ||
845 | #define RT5670_I2S_BCLK_MS1_32 (0x0 << 15) | ||
846 | #define RT5670_I2S_BCLK_MS1_64 (0x1 << 15) | ||
847 | #define RT5670_I2S_PD1_MASK (0x7 << 12) | ||
848 | #define RT5670_I2S_PD1_SFT 12 | ||
849 | #define RT5670_I2S_PD1_1 (0x0 << 12) | ||
850 | #define RT5670_I2S_PD1_2 (0x1 << 12) | ||
851 | #define RT5670_I2S_PD1_3 (0x2 << 12) | ||
852 | #define RT5670_I2S_PD1_4 (0x3 << 12) | ||
853 | #define RT5670_I2S_PD1_6 (0x4 << 12) | ||
854 | #define RT5670_I2S_PD1_8 (0x5 << 12) | ||
855 | #define RT5670_I2S_PD1_12 (0x6 << 12) | ||
856 | #define RT5670_I2S_PD1_16 (0x7 << 12) | ||
857 | #define RT5670_I2S_BCLK_MS2_MASK (0x1 << 11) | ||
858 | #define RT5670_I2S_BCLK_MS2_SFT 11 | ||
859 | #define RT5670_I2S_BCLK_MS2_32 (0x0 << 11) | ||
860 | #define RT5670_I2S_BCLK_MS2_64 (0x1 << 11) | ||
861 | #define RT5670_I2S_PD2_MASK (0x7 << 8) | ||
862 | #define RT5670_I2S_PD2_SFT 8 | ||
863 | #define RT5670_I2S_PD2_1 (0x0 << 8) | ||
864 | #define RT5670_I2S_PD2_2 (0x1 << 8) | ||
865 | #define RT5670_I2S_PD2_3 (0x2 << 8) | ||
866 | #define RT5670_I2S_PD2_4 (0x3 << 8) | ||
867 | #define RT5670_I2S_PD2_6 (0x4 << 8) | ||
868 | #define RT5670_I2S_PD2_8 (0x5 << 8) | ||
869 | #define RT5670_I2S_PD2_12 (0x6 << 8) | ||
870 | #define RT5670_I2S_PD2_16 (0x7 << 8) | ||
871 | #define RT5670_I2S_BCLK_MS3_MASK (0x1 << 7) | ||
872 | #define RT5670_I2S_BCLK_MS3_SFT 7 | ||
873 | #define RT5670_I2S_BCLK_MS3_32 (0x0 << 7) | ||
874 | #define RT5670_I2S_BCLK_MS3_64 (0x1 << 7) | ||
875 | #define RT5670_I2S_PD3_MASK (0x7 << 4) | ||
876 | #define RT5670_I2S_PD3_SFT 4 | ||
877 | #define RT5670_I2S_PD3_1 (0x0 << 4) | ||
878 | #define RT5670_I2S_PD3_2 (0x1 << 4) | ||
879 | #define RT5670_I2S_PD3_3 (0x2 << 4) | ||
880 | #define RT5670_I2S_PD3_4 (0x3 << 4) | ||
881 | #define RT5670_I2S_PD3_6 (0x4 << 4) | ||
882 | #define RT5670_I2S_PD3_8 (0x5 << 4) | ||
883 | #define RT5670_I2S_PD3_12 (0x6 << 4) | ||
884 | #define RT5670_I2S_PD3_16 (0x7 << 4) | ||
885 | #define RT5670_DAC_OSR_MASK (0x3 << 2) | ||
886 | #define RT5670_DAC_OSR_SFT 2 | ||
887 | #define RT5670_DAC_OSR_128 (0x0 << 2) | ||
888 | #define RT5670_DAC_OSR_64 (0x1 << 2) | ||
889 | #define RT5670_DAC_OSR_32 (0x2 << 2) | ||
890 | #define RT5670_DAC_OSR_16 (0x3 << 2) | ||
891 | #define RT5670_ADC_OSR_MASK (0x3) | ||
892 | #define RT5670_ADC_OSR_SFT 0 | ||
893 | #define RT5670_ADC_OSR_128 (0x0) | ||
894 | #define RT5670_ADC_OSR_64 (0x1) | ||
895 | #define RT5670_ADC_OSR_32 (0x2) | ||
896 | #define RT5670_ADC_OSR_16 (0x3) | ||
897 | |||
898 | /* ADC/DAC Clock Control 2 (0x74) */ | ||
899 | #define RT5670_DAC_L_OSR_MASK (0x3 << 14) | ||
900 | #define RT5670_DAC_L_OSR_SFT 14 | ||
901 | #define RT5670_DAC_L_OSR_128 (0x0 << 14) | ||
902 | #define RT5670_DAC_L_OSR_64 (0x1 << 14) | ||
903 | #define RT5670_DAC_L_OSR_32 (0x2 << 14) | ||
904 | #define RT5670_DAC_L_OSR_16 (0x3 << 14) | ||
905 | #define RT5670_ADC_R_OSR_MASK (0x3 << 12) | ||
906 | #define RT5670_ADC_R_OSR_SFT 12 | ||
907 | #define RT5670_ADC_R_OSR_128 (0x0 << 12) | ||
908 | #define RT5670_ADC_R_OSR_64 (0x1 << 12) | ||
909 | #define RT5670_ADC_R_OSR_32 (0x2 << 12) | ||
910 | #define RT5670_ADC_R_OSR_16 (0x3 << 12) | ||
911 | #define RT5670_DAHPF_EN (0x1 << 11) | ||
912 | #define RT5670_DAHPF_EN_SFT 11 | ||
913 | #define RT5670_ADHPF_EN (0x1 << 10) | ||
914 | #define RT5670_ADHPF_EN_SFT 10 | ||
915 | |||
916 | /* Digital Microphone Control (0x75) */ | ||
917 | #define RT5670_DMIC_1_EN_MASK (0x1 << 15) | ||
918 | #define RT5670_DMIC_1_EN_SFT 15 | ||
919 | #define RT5670_DMIC_1_DIS (0x0 << 15) | ||
920 | #define RT5670_DMIC_1_EN (0x1 << 15) | ||
921 | #define RT5670_DMIC_2_EN_MASK (0x1 << 14) | ||
922 | #define RT5670_DMIC_2_EN_SFT 14 | ||
923 | #define RT5670_DMIC_2_DIS (0x0 << 14) | ||
924 | #define RT5670_DMIC_2_EN (0x1 << 14) | ||
925 | #define RT5670_DMIC_1L_LH_MASK (0x1 << 13) | ||
926 | #define RT5670_DMIC_1L_LH_SFT 13 | ||
927 | #define RT5670_DMIC_1L_LH_FALLING (0x0 << 13) | ||
928 | #define RT5670_DMIC_1L_LH_RISING (0x1 << 13) | ||
929 | #define RT5670_DMIC_1R_LH_MASK (0x1 << 12) | ||
930 | #define RT5670_DMIC_1R_LH_SFT 12 | ||
931 | #define RT5670_DMIC_1R_LH_FALLING (0x0 << 12) | ||
932 | #define RT5670_DMIC_1R_LH_RISING (0x1 << 12) | ||
933 | #define RT5670_DMIC_2_DP_MASK (0x1 << 10) | ||
934 | #define RT5670_DMIC_2_DP_SFT 10 | ||
935 | #define RT5670_DMIC_2_DP_GPIO8 (0x0 << 10) | ||
936 | #define RT5670_DMIC_2_DP_IN3N (0x1 << 10) | ||
937 | #define RT5670_DMIC_2L_LH_MASK (0x1 << 9) | ||
938 | #define RT5670_DMIC_2L_LH_SFT 9 | ||
939 | #define RT5670_DMIC_2L_LH_FALLING (0x0 << 9) | ||
940 | #define RT5670_DMIC_2L_LH_RISING (0x1 << 9) | ||
941 | #define RT5670_DMIC_2R_LH_MASK (0x1 << 8) | ||
942 | #define RT5670_DMIC_2R_LH_SFT 8 | ||
943 | #define RT5670_DMIC_2R_LH_FALLING (0x0 << 8) | ||
944 | #define RT5670_DMIC_2R_LH_RISING (0x1 << 8) | ||
945 | #define RT5670_DMIC_CLK_MASK (0x7 << 5) | ||
946 | #define RT5670_DMIC_CLK_SFT 5 | ||
947 | #define RT5670_DMIC_3_EN_MASK (0x1 << 4) | ||
948 | #define RT5670_DMIC_3_EN_SFT 4 | ||
949 | #define RT5670_DMIC_3_DIS (0x0 << 4) | ||
950 | #define RT5670_DMIC_3_EN (0x1 << 4) | ||
951 | #define RT5670_DMIC_1_DP_MASK (0x3 << 0) | ||
952 | #define RT5670_DMIC_1_DP_SFT 0 | ||
953 | #define RT5670_DMIC_1_DP_GPIO6 (0x0 << 0) | ||
954 | #define RT5670_DMIC_1_DP_IN2P (0x1 << 0) | ||
955 | #define RT5670_DMIC_1_DP_GPIO7 (0x2 << 0) | ||
956 | |||
957 | /* Digital Microphone Control2 (0x76) */ | ||
958 | #define RT5670_DMIC_3_DP_MASK (0x3 << 6) | ||
959 | #define RT5670_DMIC_3_DP_SFT 6 | ||
960 | #define RT5670_DMIC_3_DP_GPIO9 (0x0 << 6) | ||
961 | #define RT5670_DMIC_3_DP_GPIO10 (0x1 << 6) | ||
962 | #define RT5670_DMIC_3_DP_GPIO5 (0x2 << 6) | ||
963 | |||
964 | /* Global Clock Control (0x80) */ | ||
965 | #define RT5670_SCLK_SRC_MASK (0x3 << 14) | ||
966 | #define RT5670_SCLK_SRC_SFT 14 | ||
967 | #define RT5670_SCLK_SRC_MCLK (0x0 << 14) | ||
968 | #define RT5670_SCLK_SRC_PLL1 (0x1 << 14) | ||
969 | #define RT5670_SCLK_SRC_RCCLK (0x2 << 14) /* 15MHz */ | ||
970 | #define RT5670_PLL1_SRC_MASK (0x3 << 12) | ||
971 | #define RT5670_PLL1_SRC_SFT 12 | ||
972 | #define RT5670_PLL1_SRC_MCLK (0x0 << 12) | ||
973 | #define RT5670_PLL1_SRC_BCLK1 (0x1 << 12) | ||
974 | #define RT5670_PLL1_SRC_BCLK2 (0x2 << 12) | ||
975 | #define RT5670_PLL1_SRC_BCLK3 (0x3 << 12) | ||
976 | #define RT5670_PLL1_PD_MASK (0x1 << 3) | ||
977 | #define RT5670_PLL1_PD_SFT 3 | ||
978 | #define RT5670_PLL1_PD_1 (0x0 << 3) | ||
979 | #define RT5670_PLL1_PD_2 (0x1 << 3) | ||
980 | |||
981 | #define RT5670_PLL_INP_MAX 40000000 | ||
982 | #define RT5670_PLL_INP_MIN 256000 | ||
983 | /* PLL M/N/K Code Control 1 (0x81) */ | ||
984 | #define RT5670_PLL_N_MAX 0x1ff | ||
985 | #define RT5670_PLL_N_MASK (RT5670_PLL_N_MAX << 7) | ||
986 | #define RT5670_PLL_N_SFT 7 | ||
987 | #define RT5670_PLL_K_MAX 0x1f | ||
988 | #define RT5670_PLL_K_MASK (RT5670_PLL_K_MAX) | ||
989 | #define RT5670_PLL_K_SFT 0 | ||
990 | |||
991 | /* PLL M/N/K Code Control 2 (0x82) */ | ||
992 | #define RT5670_PLL_M_MAX 0xf | ||
993 | #define RT5670_PLL_M_MASK (RT5670_PLL_M_MAX << 12) | ||
994 | #define RT5670_PLL_M_SFT 12 | ||
995 | #define RT5670_PLL_M_BP (0x1 << 11) | ||
996 | #define RT5670_PLL_M_BP_SFT 11 | ||
997 | |||
998 | /* ASRC Control 1 (0x83) */ | ||
999 | #define RT5670_STO_T_MASK (0x1 << 15) | ||
1000 | #define RT5670_STO_T_SFT 15 | ||
1001 | #define RT5670_STO_T_SCLK (0x0 << 15) | ||
1002 | #define RT5670_STO_T_LRCK1 (0x1 << 15) | ||
1003 | #define RT5670_M1_T_MASK (0x1 << 14) | ||
1004 | #define RT5670_M1_T_SFT 14 | ||
1005 | #define RT5670_M1_T_I2S2 (0x0 << 14) | ||
1006 | #define RT5670_M1_T_I2S2_D3 (0x1 << 14) | ||
1007 | #define RT5670_I2S2_F_MASK (0x1 << 12) | ||
1008 | #define RT5670_I2S2_F_SFT 12 | ||
1009 | #define RT5670_I2S2_F_I2S2_D2 (0x0 << 12) | ||
1010 | #define RT5670_I2S2_F_I2S1_TCLK (0x1 << 12) | ||
1011 | #define RT5670_DMIC_1_M_MASK (0x1 << 9) | ||
1012 | #define RT5670_DMIC_1_M_SFT 9 | ||
1013 | #define RT5670_DMIC_1_M_NOR (0x0 << 9) | ||
1014 | #define RT5670_DMIC_1_M_ASYN (0x1 << 9) | ||
1015 | #define RT5670_DMIC_2_M_MASK (0x1 << 8) | ||
1016 | #define RT5670_DMIC_2_M_SFT 8 | ||
1017 | #define RT5670_DMIC_2_M_NOR (0x0 << 8) | ||
1018 | #define RT5670_DMIC_2_M_ASYN (0x1 << 8) | ||
1019 | |||
1020 | /* ASRC Control 2 (0x84) */ | ||
1021 | #define RT5670_MDA_L_M_MASK (0x1 << 15) | ||
1022 | #define RT5670_MDA_L_M_SFT 15 | ||
1023 | #define RT5670_MDA_L_M_NOR (0x0 << 15) | ||
1024 | #define RT5670_MDA_L_M_ASYN (0x1 << 15) | ||
1025 | #define RT5670_MDA_R_M_MASK (0x1 << 14) | ||
1026 | #define RT5670_MDA_R_M_SFT 14 | ||
1027 | #define RT5670_MDA_R_M_NOR (0x0 << 14) | ||
1028 | #define RT5670_MDA_R_M_ASYN (0x1 << 14) | ||
1029 | #define RT5670_MAD_L_M_MASK (0x1 << 13) | ||
1030 | #define RT5670_MAD_L_M_SFT 13 | ||
1031 | #define RT5670_MAD_L_M_NOR (0x0 << 13) | ||
1032 | #define RT5670_MAD_L_M_ASYN (0x1 << 13) | ||
1033 | #define RT5670_MAD_R_M_MASK (0x1 << 12) | ||
1034 | #define RT5670_MAD_R_M_SFT 12 | ||
1035 | #define RT5670_MAD_R_M_NOR (0x0 << 12) | ||
1036 | #define RT5670_MAD_R_M_ASYN (0x1 << 12) | ||
1037 | #define RT5670_ADC_M_MASK (0x1 << 11) | ||
1038 | #define RT5670_ADC_M_SFT 11 | ||
1039 | #define RT5670_ADC_M_NOR (0x0 << 11) | ||
1040 | #define RT5670_ADC_M_ASYN (0x1 << 11) | ||
1041 | #define RT5670_STO_DAC_M_MASK (0x1 << 5) | ||
1042 | #define RT5670_STO_DAC_M_SFT 5 | ||
1043 | #define RT5670_STO_DAC_M_NOR (0x0 << 5) | ||
1044 | #define RT5670_STO_DAC_M_ASYN (0x1 << 5) | ||
1045 | #define RT5670_I2S1_R_D_MASK (0x1 << 4) | ||
1046 | #define RT5670_I2S1_R_D_SFT 4 | ||
1047 | #define RT5670_I2S1_R_D_DIS (0x0 << 4) | ||
1048 | #define RT5670_I2S1_R_D_EN (0x1 << 4) | ||
1049 | #define RT5670_I2S2_R_D_MASK (0x1 << 3) | ||
1050 | #define RT5670_I2S2_R_D_SFT 3 | ||
1051 | #define RT5670_I2S2_R_D_DIS (0x0 << 3) | ||
1052 | #define RT5670_I2S2_R_D_EN (0x1 << 3) | ||
1053 | #define RT5670_PRE_SCLK_MASK (0x3) | ||
1054 | #define RT5670_PRE_SCLK_SFT 0 | ||
1055 | #define RT5670_PRE_SCLK_512 (0x0) | ||
1056 | #define RT5670_PRE_SCLK_1024 (0x1) | ||
1057 | #define RT5670_PRE_SCLK_2048 (0x2) | ||
1058 | |||
1059 | /* ASRC Control 3 (0x85) */ | ||
1060 | #define RT5670_I2S1_RATE_MASK (0xf << 12) | ||
1061 | #define RT5670_I2S1_RATE_SFT 12 | ||
1062 | #define RT5670_I2S2_RATE_MASK (0xf << 8) | ||
1063 | #define RT5670_I2S2_RATE_SFT 8 | ||
1064 | |||
1065 | /* ASRC Control 4 (0x89) */ | ||
1066 | #define RT5670_I2S1_PD_MASK (0x7 << 12) | ||
1067 | #define RT5670_I2S1_PD_SFT 12 | ||
1068 | #define RT5670_I2S2_PD_MASK (0x7 << 8) | ||
1069 | #define RT5670_I2S2_PD_SFT 8 | ||
1070 | |||
1071 | /* HPOUT Over Current Detection (0x8b) */ | ||
1072 | #define RT5670_HP_OVCD_MASK (0x1 << 10) | ||
1073 | #define RT5670_HP_OVCD_SFT 10 | ||
1074 | #define RT5670_HP_OVCD_DIS (0x0 << 10) | ||
1075 | #define RT5670_HP_OVCD_EN (0x1 << 10) | ||
1076 | #define RT5670_HP_OC_TH_MASK (0x3 << 8) | ||
1077 | #define RT5670_HP_OC_TH_SFT 8 | ||
1078 | #define RT5670_HP_OC_TH_90 (0x0 << 8) | ||
1079 | #define RT5670_HP_OC_TH_105 (0x1 << 8) | ||
1080 | #define RT5670_HP_OC_TH_120 (0x2 << 8) | ||
1081 | #define RT5670_HP_OC_TH_135 (0x3 << 8) | ||
1082 | |||
1083 | /* Class D Over Current Control (0x8c) */ | ||
1084 | #define RT5670_CLSD_OC_MASK (0x1 << 9) | ||
1085 | #define RT5670_CLSD_OC_SFT 9 | ||
1086 | #define RT5670_CLSD_OC_PU (0x0 << 9) | ||
1087 | #define RT5670_CLSD_OC_PD (0x1 << 9) | ||
1088 | #define RT5670_AUTO_PD_MASK (0x1 << 8) | ||
1089 | #define RT5670_AUTO_PD_SFT 8 | ||
1090 | #define RT5670_AUTO_PD_DIS (0x0 << 8) | ||
1091 | #define RT5670_AUTO_PD_EN (0x1 << 8) | ||
1092 | #define RT5670_CLSD_OC_TH_MASK (0x3f) | ||
1093 | #define RT5670_CLSD_OC_TH_SFT 0 | ||
1094 | |||
1095 | /* Class D Output Control (0x8d) */ | ||
1096 | #define RT5670_CLSD_RATIO_MASK (0xf << 12) | ||
1097 | #define RT5670_CLSD_RATIO_SFT 12 | ||
1098 | #define RT5670_CLSD_OM_MASK (0x1 << 11) | ||
1099 | #define RT5670_CLSD_OM_SFT 11 | ||
1100 | #define RT5670_CLSD_OM_MONO (0x0 << 11) | ||
1101 | #define RT5670_CLSD_OM_STO (0x1 << 11) | ||
1102 | #define RT5670_CLSD_SCH_MASK (0x1 << 10) | ||
1103 | #define RT5670_CLSD_SCH_SFT 10 | ||
1104 | #define RT5670_CLSD_SCH_L (0x0 << 10) | ||
1105 | #define RT5670_CLSD_SCH_S (0x1 << 10) | ||
1106 | |||
1107 | /* Depop Mode Control 1 (0x8e) */ | ||
1108 | #define RT5670_SMT_TRIG_MASK (0x1 << 15) | ||
1109 | #define RT5670_SMT_TRIG_SFT 15 | ||
1110 | #define RT5670_SMT_TRIG_DIS (0x0 << 15) | ||
1111 | #define RT5670_SMT_TRIG_EN (0x1 << 15) | ||
1112 | #define RT5670_HP_L_SMT_MASK (0x1 << 9) | ||
1113 | #define RT5670_HP_L_SMT_SFT 9 | ||
1114 | #define RT5670_HP_L_SMT_DIS (0x0 << 9) | ||
1115 | #define RT5670_HP_L_SMT_EN (0x1 << 9) | ||
1116 | #define RT5670_HP_R_SMT_MASK (0x1 << 8) | ||
1117 | #define RT5670_HP_R_SMT_SFT 8 | ||
1118 | #define RT5670_HP_R_SMT_DIS (0x0 << 8) | ||
1119 | #define RT5670_HP_R_SMT_EN (0x1 << 8) | ||
1120 | #define RT5670_HP_CD_PD_MASK (0x1 << 7) | ||
1121 | #define RT5670_HP_CD_PD_SFT 7 | ||
1122 | #define RT5670_HP_CD_PD_DIS (0x0 << 7) | ||
1123 | #define RT5670_HP_CD_PD_EN (0x1 << 7) | ||
1124 | #define RT5670_RSTN_MASK (0x1 << 6) | ||
1125 | #define RT5670_RSTN_SFT 6 | ||
1126 | #define RT5670_RSTN_DIS (0x0 << 6) | ||
1127 | #define RT5670_RSTN_EN (0x1 << 6) | ||
1128 | #define RT5670_RSTP_MASK (0x1 << 5) | ||
1129 | #define RT5670_RSTP_SFT 5 | ||
1130 | #define RT5670_RSTP_DIS (0x0 << 5) | ||
1131 | #define RT5670_RSTP_EN (0x1 << 5) | ||
1132 | #define RT5670_HP_CO_MASK (0x1 << 4) | ||
1133 | #define RT5670_HP_CO_SFT 4 | ||
1134 | #define RT5670_HP_CO_DIS (0x0 << 4) | ||
1135 | #define RT5670_HP_CO_EN (0x1 << 4) | ||
1136 | #define RT5670_HP_CP_MASK (0x1 << 3) | ||
1137 | #define RT5670_HP_CP_SFT 3 | ||
1138 | #define RT5670_HP_CP_PD (0x0 << 3) | ||
1139 | #define RT5670_HP_CP_PU (0x1 << 3) | ||
1140 | #define RT5670_HP_SG_MASK (0x1 << 2) | ||
1141 | #define RT5670_HP_SG_SFT 2 | ||
1142 | #define RT5670_HP_SG_DIS (0x0 << 2) | ||
1143 | #define RT5670_HP_SG_EN (0x1 << 2) | ||
1144 | #define RT5670_HP_DP_MASK (0x1 << 1) | ||
1145 | #define RT5670_HP_DP_SFT 1 | ||
1146 | #define RT5670_HP_DP_PD (0x0 << 1) | ||
1147 | #define RT5670_HP_DP_PU (0x1 << 1) | ||
1148 | #define RT5670_HP_CB_MASK (0x1) | ||
1149 | #define RT5670_HP_CB_SFT 0 | ||
1150 | #define RT5670_HP_CB_PD (0x0) | ||
1151 | #define RT5670_HP_CB_PU (0x1) | ||
1152 | |||
1153 | /* Depop Mode Control 2 (0x8f) */ | ||
1154 | #define RT5670_DEPOP_MASK (0x1 << 13) | ||
1155 | #define RT5670_DEPOP_SFT 13 | ||
1156 | #define RT5670_DEPOP_AUTO (0x0 << 13) | ||
1157 | #define RT5670_DEPOP_MAN (0x1 << 13) | ||
1158 | #define RT5670_RAMP_MASK (0x1 << 12) | ||
1159 | #define RT5670_RAMP_SFT 12 | ||
1160 | #define RT5670_RAMP_DIS (0x0 << 12) | ||
1161 | #define RT5670_RAMP_EN (0x1 << 12) | ||
1162 | #define RT5670_BPS_MASK (0x1 << 11) | ||
1163 | #define RT5670_BPS_SFT 11 | ||
1164 | #define RT5670_BPS_DIS (0x0 << 11) | ||
1165 | #define RT5670_BPS_EN (0x1 << 11) | ||
1166 | #define RT5670_FAST_UPDN_MASK (0x1 << 10) | ||
1167 | #define RT5670_FAST_UPDN_SFT 10 | ||
1168 | #define RT5670_FAST_UPDN_DIS (0x0 << 10) | ||
1169 | #define RT5670_FAST_UPDN_EN (0x1 << 10) | ||
1170 | #define RT5670_MRES_MASK (0x3 << 8) | ||
1171 | #define RT5670_MRES_SFT 8 | ||
1172 | #define RT5670_MRES_15MO (0x0 << 8) | ||
1173 | #define RT5670_MRES_25MO (0x1 << 8) | ||
1174 | #define RT5670_MRES_35MO (0x2 << 8) | ||
1175 | #define RT5670_MRES_45MO (0x3 << 8) | ||
1176 | #define RT5670_VLO_MASK (0x1 << 7) | ||
1177 | #define RT5670_VLO_SFT 7 | ||
1178 | #define RT5670_VLO_3V (0x0 << 7) | ||
1179 | #define RT5670_VLO_32V (0x1 << 7) | ||
1180 | #define RT5670_DIG_DP_MASK (0x1 << 6) | ||
1181 | #define RT5670_DIG_DP_SFT 6 | ||
1182 | #define RT5670_DIG_DP_DIS (0x0 << 6) | ||
1183 | #define RT5670_DIG_DP_EN (0x1 << 6) | ||
1184 | #define RT5670_DP_TH_MASK (0x3 << 4) | ||
1185 | #define RT5670_DP_TH_SFT 4 | ||
1186 | |||
1187 | /* Depop Mode Control 3 (0x90) */ | ||
1188 | #define RT5670_CP_SYS_MASK (0x7 << 12) | ||
1189 | #define RT5670_CP_SYS_SFT 12 | ||
1190 | #define RT5670_CP_FQ1_MASK (0x7 << 8) | ||
1191 | #define RT5670_CP_FQ1_SFT 8 | ||
1192 | #define RT5670_CP_FQ2_MASK (0x7 << 4) | ||
1193 | #define RT5670_CP_FQ2_SFT 4 | ||
1194 | #define RT5670_CP_FQ3_MASK (0x7) | ||
1195 | #define RT5670_CP_FQ3_SFT 0 | ||
1196 | #define RT5670_CP_FQ_1_5_KHZ 0 | ||
1197 | #define RT5670_CP_FQ_3_KHZ 1 | ||
1198 | #define RT5670_CP_FQ_6_KHZ 2 | ||
1199 | #define RT5670_CP_FQ_12_KHZ 3 | ||
1200 | #define RT5670_CP_FQ_24_KHZ 4 | ||
1201 | #define RT5670_CP_FQ_48_KHZ 5 | ||
1202 | #define RT5670_CP_FQ_96_KHZ 6 | ||
1203 | #define RT5670_CP_FQ_192_KHZ 7 | ||
1204 | |||
1205 | /* HPOUT charge pump (0x91) */ | ||
1206 | #define RT5670_OSW_L_MASK (0x1 << 11) | ||
1207 | #define RT5670_OSW_L_SFT 11 | ||
1208 | #define RT5670_OSW_L_DIS (0x0 << 11) | ||
1209 | #define RT5670_OSW_L_EN (0x1 << 11) | ||
1210 | #define RT5670_OSW_R_MASK (0x1 << 10) | ||
1211 | #define RT5670_OSW_R_SFT 10 | ||
1212 | #define RT5670_OSW_R_DIS (0x0 << 10) | ||
1213 | #define RT5670_OSW_R_EN (0x1 << 10) | ||
1214 | #define RT5670_PM_HP_MASK (0x3 << 8) | ||
1215 | #define RT5670_PM_HP_SFT 8 | ||
1216 | #define RT5670_PM_HP_LV (0x0 << 8) | ||
1217 | #define RT5670_PM_HP_MV (0x1 << 8) | ||
1218 | #define RT5670_PM_HP_HV (0x2 << 8) | ||
1219 | #define RT5670_IB_HP_MASK (0x3 << 6) | ||
1220 | #define RT5670_IB_HP_SFT 6 | ||
1221 | #define RT5670_IB_HP_125IL (0x0 << 6) | ||
1222 | #define RT5670_IB_HP_25IL (0x1 << 6) | ||
1223 | #define RT5670_IB_HP_5IL (0x2 << 6) | ||
1224 | #define RT5670_IB_HP_1IL (0x3 << 6) | ||
1225 | |||
1226 | /* PV detection and SPK gain control (0x92) */ | ||
1227 | #define RT5670_PVDD_DET_MASK (0x1 << 15) | ||
1228 | #define RT5670_PVDD_DET_SFT 15 | ||
1229 | #define RT5670_PVDD_DET_DIS (0x0 << 15) | ||
1230 | #define RT5670_PVDD_DET_EN (0x1 << 15) | ||
1231 | #define RT5670_SPK_AG_MASK (0x1 << 14) | ||
1232 | #define RT5670_SPK_AG_SFT 14 | ||
1233 | #define RT5670_SPK_AG_DIS (0x0 << 14) | ||
1234 | #define RT5670_SPK_AG_EN (0x1 << 14) | ||
1235 | |||
1236 | /* Micbias Control (0x93) */ | ||
1237 | #define RT5670_MIC1_BS_MASK (0x1 << 15) | ||
1238 | #define RT5670_MIC1_BS_SFT 15 | ||
1239 | #define RT5670_MIC1_BS_9AV (0x0 << 15) | ||
1240 | #define RT5670_MIC1_BS_75AV (0x1 << 15) | ||
1241 | #define RT5670_MIC2_BS_MASK (0x1 << 14) | ||
1242 | #define RT5670_MIC2_BS_SFT 14 | ||
1243 | #define RT5670_MIC2_BS_9AV (0x0 << 14) | ||
1244 | #define RT5670_MIC2_BS_75AV (0x1 << 14) | ||
1245 | #define RT5670_MIC1_CLK_MASK (0x1 << 13) | ||
1246 | #define RT5670_MIC1_CLK_SFT 13 | ||
1247 | #define RT5670_MIC1_CLK_DIS (0x0 << 13) | ||
1248 | #define RT5670_MIC1_CLK_EN (0x1 << 13) | ||
1249 | #define RT5670_MIC2_CLK_MASK (0x1 << 12) | ||
1250 | #define RT5670_MIC2_CLK_SFT 12 | ||
1251 | #define RT5670_MIC2_CLK_DIS (0x0 << 12) | ||
1252 | #define RT5670_MIC2_CLK_EN (0x1 << 12) | ||
1253 | #define RT5670_MIC1_OVCD_MASK (0x1 << 11) | ||
1254 | #define RT5670_MIC1_OVCD_SFT 11 | ||
1255 | #define RT5670_MIC1_OVCD_DIS (0x0 << 11) | ||
1256 | #define RT5670_MIC1_OVCD_EN (0x1 << 11) | ||
1257 | #define RT5670_MIC1_OVTH_MASK (0x3 << 9) | ||
1258 | #define RT5670_MIC1_OVTH_SFT 9 | ||
1259 | #define RT5670_MIC1_OVTH_600UA (0x0 << 9) | ||
1260 | #define RT5670_MIC1_OVTH_1500UA (0x1 << 9) | ||
1261 | #define RT5670_MIC1_OVTH_2000UA (0x2 << 9) | ||
1262 | #define RT5670_MIC2_OVCD_MASK (0x1 << 8) | ||
1263 | #define RT5670_MIC2_OVCD_SFT 8 | ||
1264 | #define RT5670_MIC2_OVCD_DIS (0x0 << 8) | ||
1265 | #define RT5670_MIC2_OVCD_EN (0x1 << 8) | ||
1266 | #define RT5670_MIC2_OVTH_MASK (0x3 << 6) | ||
1267 | #define RT5670_MIC2_OVTH_SFT 6 | ||
1268 | #define RT5670_MIC2_OVTH_600UA (0x0 << 6) | ||
1269 | #define RT5670_MIC2_OVTH_1500UA (0x1 << 6) | ||
1270 | #define RT5670_MIC2_OVTH_2000UA (0x2 << 6) | ||
1271 | #define RT5670_PWR_MB_MASK (0x1 << 5) | ||
1272 | #define RT5670_PWR_MB_SFT 5 | ||
1273 | #define RT5670_PWR_MB_PD (0x0 << 5) | ||
1274 | #define RT5670_PWR_MB_PU (0x1 << 5) | ||
1275 | #define RT5670_PWR_CLK25M_MASK (0x1 << 4) | ||
1276 | #define RT5670_PWR_CLK25M_SFT 4 | ||
1277 | #define RT5670_PWR_CLK25M_PD (0x0 << 4) | ||
1278 | #define RT5670_PWR_CLK25M_PU (0x1 << 4) | ||
1279 | |||
1280 | /* Analog JD Control 1 (0x94) */ | ||
1281 | #define RT5670_JD1_MODE_MASK (0x3 << 0) | ||
1282 | #define RT5670_JD1_MODE_0 (0x0 << 0) | ||
1283 | #define RT5670_JD1_MODE_1 (0x1 << 0) | ||
1284 | #define RT5670_JD1_MODE_2 (0x2 << 0) | ||
1285 | |||
1286 | /* VAD Control 4 (0x9d) */ | ||
1287 | #define RT5670_VAD_SEL_MASK (0x3 << 8) | ||
1288 | #define RT5670_VAD_SEL_SFT 8 | ||
1289 | |||
1290 | /* EQ Control 1 (0xb0) */ | ||
1291 | #define RT5670_EQ_SRC_MASK (0x1 << 15) | ||
1292 | #define RT5670_EQ_SRC_SFT 15 | ||
1293 | #define RT5670_EQ_SRC_DAC (0x0 << 15) | ||
1294 | #define RT5670_EQ_SRC_ADC (0x1 << 15) | ||
1295 | #define RT5670_EQ_UPD (0x1 << 14) | ||
1296 | #define RT5670_EQ_UPD_BIT 14 | ||
1297 | #define RT5670_EQ_CD_MASK (0x1 << 13) | ||
1298 | #define RT5670_EQ_CD_SFT 13 | ||
1299 | #define RT5670_EQ_CD_DIS (0x0 << 13) | ||
1300 | #define RT5670_EQ_CD_EN (0x1 << 13) | ||
1301 | #define RT5670_EQ_DITH_MASK (0x3 << 8) | ||
1302 | #define RT5670_EQ_DITH_SFT 8 | ||
1303 | #define RT5670_EQ_DITH_NOR (0x0 << 8) | ||
1304 | #define RT5670_EQ_DITH_LSB (0x1 << 8) | ||
1305 | #define RT5670_EQ_DITH_LSB_1 (0x2 << 8) | ||
1306 | #define RT5670_EQ_DITH_LSB_2 (0x3 << 8) | ||
1307 | |||
1308 | /* EQ Control 2 (0xb1) */ | ||
1309 | #define RT5670_EQ_HPF1_M_MASK (0x1 << 8) | ||
1310 | #define RT5670_EQ_HPF1_M_SFT 8 | ||
1311 | #define RT5670_EQ_HPF1_M_HI (0x0 << 8) | ||
1312 | #define RT5670_EQ_HPF1_M_1ST (0x1 << 8) | ||
1313 | #define RT5670_EQ_LPF1_M_MASK (0x1 << 7) | ||
1314 | #define RT5670_EQ_LPF1_M_SFT 7 | ||
1315 | #define RT5670_EQ_LPF1_M_LO (0x0 << 7) | ||
1316 | #define RT5670_EQ_LPF1_M_1ST (0x1 << 7) | ||
1317 | #define RT5670_EQ_HPF2_MASK (0x1 << 6) | ||
1318 | #define RT5670_EQ_HPF2_SFT 6 | ||
1319 | #define RT5670_EQ_HPF2_DIS (0x0 << 6) | ||
1320 | #define RT5670_EQ_HPF2_EN (0x1 << 6) | ||
1321 | #define RT5670_EQ_HPF1_MASK (0x1 << 5) | ||
1322 | #define RT5670_EQ_HPF1_SFT 5 | ||
1323 | #define RT5670_EQ_HPF1_DIS (0x0 << 5) | ||
1324 | #define RT5670_EQ_HPF1_EN (0x1 << 5) | ||
1325 | #define RT5670_EQ_BPF4_MASK (0x1 << 4) | ||
1326 | #define RT5670_EQ_BPF4_SFT 4 | ||
1327 | #define RT5670_EQ_BPF4_DIS (0x0 << 4) | ||
1328 | #define RT5670_EQ_BPF4_EN (0x1 << 4) | ||
1329 | #define RT5670_EQ_BPF3_MASK (0x1 << 3) | ||
1330 | #define RT5670_EQ_BPF3_SFT 3 | ||
1331 | #define RT5670_EQ_BPF3_DIS (0x0 << 3) | ||
1332 | #define RT5670_EQ_BPF3_EN (0x1 << 3) | ||
1333 | #define RT5670_EQ_BPF2_MASK (0x1 << 2) | ||
1334 | #define RT5670_EQ_BPF2_SFT 2 | ||
1335 | #define RT5670_EQ_BPF2_DIS (0x0 << 2) | ||
1336 | #define RT5670_EQ_BPF2_EN (0x1 << 2) | ||
1337 | #define RT5670_EQ_BPF1_MASK (0x1 << 1) | ||
1338 | #define RT5670_EQ_BPF1_SFT 1 | ||
1339 | #define RT5670_EQ_BPF1_DIS (0x0 << 1) | ||
1340 | #define RT5670_EQ_BPF1_EN (0x1 << 1) | ||
1341 | #define RT5670_EQ_LPF_MASK (0x1) | ||
1342 | #define RT5670_EQ_LPF_SFT 0 | ||
1343 | #define RT5670_EQ_LPF_DIS (0x0) | ||
1344 | #define RT5670_EQ_LPF_EN (0x1) | ||
1345 | #define RT5670_EQ_CTRL_MASK (0x7f) | ||
1346 | |||
1347 | /* Memory Test (0xb2) */ | ||
1348 | #define RT5670_MT_MASK (0x1 << 15) | ||
1349 | #define RT5670_MT_SFT 15 | ||
1350 | #define RT5670_MT_DIS (0x0 << 15) | ||
1351 | #define RT5670_MT_EN (0x1 << 15) | ||
1352 | |||
1353 | /* DRC/AGC Control 1 (0xb4) */ | ||
1354 | #define RT5670_DRC_AGC_P_MASK (0x1 << 15) | ||
1355 | #define RT5670_DRC_AGC_P_SFT 15 | ||
1356 | #define RT5670_DRC_AGC_P_DAC (0x0 << 15) | ||
1357 | #define RT5670_DRC_AGC_P_ADC (0x1 << 15) | ||
1358 | #define RT5670_DRC_AGC_MASK (0x1 << 14) | ||
1359 | #define RT5670_DRC_AGC_SFT 14 | ||
1360 | #define RT5670_DRC_AGC_DIS (0x0 << 14) | ||
1361 | #define RT5670_DRC_AGC_EN (0x1 << 14) | ||
1362 | #define RT5670_DRC_AGC_UPD (0x1 << 13) | ||
1363 | #define RT5670_DRC_AGC_UPD_BIT 13 | ||
1364 | #define RT5670_DRC_AGC_AR_MASK (0x1f << 8) | ||
1365 | #define RT5670_DRC_AGC_AR_SFT 8 | ||
1366 | #define RT5670_DRC_AGC_R_MASK (0x7 << 5) | ||
1367 | #define RT5670_DRC_AGC_R_SFT 5 | ||
1368 | #define RT5670_DRC_AGC_R_48K (0x1 << 5) | ||
1369 | #define RT5670_DRC_AGC_R_96K (0x2 << 5) | ||
1370 | #define RT5670_DRC_AGC_R_192K (0x3 << 5) | ||
1371 | #define RT5670_DRC_AGC_R_441K (0x5 << 5) | ||
1372 | #define RT5670_DRC_AGC_R_882K (0x6 << 5) | ||
1373 | #define RT5670_DRC_AGC_R_1764K (0x7 << 5) | ||
1374 | #define RT5670_DRC_AGC_RC_MASK (0x1f) | ||
1375 | #define RT5670_DRC_AGC_RC_SFT 0 | ||
1376 | |||
1377 | /* DRC/AGC Control 2 (0xb5) */ | ||
1378 | #define RT5670_DRC_AGC_POB_MASK (0x3f << 8) | ||
1379 | #define RT5670_DRC_AGC_POB_SFT 8 | ||
1380 | #define RT5670_DRC_AGC_CP_MASK (0x1 << 7) | ||
1381 | #define RT5670_DRC_AGC_CP_SFT 7 | ||
1382 | #define RT5670_DRC_AGC_CP_DIS (0x0 << 7) | ||
1383 | #define RT5670_DRC_AGC_CP_EN (0x1 << 7) | ||
1384 | #define RT5670_DRC_AGC_CPR_MASK (0x3 << 5) | ||
1385 | #define RT5670_DRC_AGC_CPR_SFT 5 | ||
1386 | #define RT5670_DRC_AGC_CPR_1_1 (0x0 << 5) | ||
1387 | #define RT5670_DRC_AGC_CPR_1_2 (0x1 << 5) | ||
1388 | #define RT5670_DRC_AGC_CPR_1_3 (0x2 << 5) | ||
1389 | #define RT5670_DRC_AGC_CPR_1_4 (0x3 << 5) | ||
1390 | #define RT5670_DRC_AGC_PRB_MASK (0x1f) | ||
1391 | #define RT5670_DRC_AGC_PRB_SFT 0 | ||
1392 | |||
1393 | /* DRC/AGC Control 3 (0xb6) */ | ||
1394 | #define RT5670_DRC_AGC_NGB_MASK (0xf << 12) | ||
1395 | #define RT5670_DRC_AGC_NGB_SFT 12 | ||
1396 | #define RT5670_DRC_AGC_TAR_MASK (0x1f << 7) | ||
1397 | #define RT5670_DRC_AGC_TAR_SFT 7 | ||
1398 | #define RT5670_DRC_AGC_NG_MASK (0x1 << 6) | ||
1399 | #define RT5670_DRC_AGC_NG_SFT 6 | ||
1400 | #define RT5670_DRC_AGC_NG_DIS (0x0 << 6) | ||
1401 | #define RT5670_DRC_AGC_NG_EN (0x1 << 6) | ||
1402 | #define RT5670_DRC_AGC_NGH_MASK (0x1 << 5) | ||
1403 | #define RT5670_DRC_AGC_NGH_SFT 5 | ||
1404 | #define RT5670_DRC_AGC_NGH_DIS (0x0 << 5) | ||
1405 | #define RT5670_DRC_AGC_NGH_EN (0x1 << 5) | ||
1406 | #define RT5670_DRC_AGC_NGT_MASK (0x1f) | ||
1407 | #define RT5670_DRC_AGC_NGT_SFT 0 | ||
1408 | |||
1409 | /* Jack Detect Control (0xbb) */ | ||
1410 | #define RT5670_JD_MASK (0x7 << 13) | ||
1411 | #define RT5670_JD_SFT 13 | ||
1412 | #define RT5670_JD_DIS (0x0 << 13) | ||
1413 | #define RT5670_JD_GPIO1 (0x1 << 13) | ||
1414 | #define RT5670_JD_JD1_IN4P (0x2 << 13) | ||
1415 | #define RT5670_JD_JD2_IN4N (0x3 << 13) | ||
1416 | #define RT5670_JD_GPIO2 (0x4 << 13) | ||
1417 | #define RT5670_JD_GPIO3 (0x5 << 13) | ||
1418 | #define RT5670_JD_GPIO4 (0x6 << 13) | ||
1419 | #define RT5670_JD_HP_MASK (0x1 << 11) | ||
1420 | #define RT5670_JD_HP_SFT 11 | ||
1421 | #define RT5670_JD_HP_DIS (0x0 << 11) | ||
1422 | #define RT5670_JD_HP_EN (0x1 << 11) | ||
1423 | #define RT5670_JD_HP_TRG_MASK (0x1 << 10) | ||
1424 | #define RT5670_JD_HP_TRG_SFT 10 | ||
1425 | #define RT5670_JD_HP_TRG_LO (0x0 << 10) | ||
1426 | #define RT5670_JD_HP_TRG_HI (0x1 << 10) | ||
1427 | #define RT5670_JD_SPL_MASK (0x1 << 9) | ||
1428 | #define RT5670_JD_SPL_SFT 9 | ||
1429 | #define RT5670_JD_SPL_DIS (0x0 << 9) | ||
1430 | #define RT5670_JD_SPL_EN (0x1 << 9) | ||
1431 | #define RT5670_JD_SPL_TRG_MASK (0x1 << 8) | ||
1432 | #define RT5670_JD_SPL_TRG_SFT 8 | ||
1433 | #define RT5670_JD_SPL_TRG_LO (0x0 << 8) | ||
1434 | #define RT5670_JD_SPL_TRG_HI (0x1 << 8) | ||
1435 | #define RT5670_JD_SPR_MASK (0x1 << 7) | ||
1436 | #define RT5670_JD_SPR_SFT 7 | ||
1437 | #define RT5670_JD_SPR_DIS (0x0 << 7) | ||
1438 | #define RT5670_JD_SPR_EN (0x1 << 7) | ||
1439 | #define RT5670_JD_SPR_TRG_MASK (0x1 << 6) | ||
1440 | #define RT5670_JD_SPR_TRG_SFT 6 | ||
1441 | #define RT5670_JD_SPR_TRG_LO (0x0 << 6) | ||
1442 | #define RT5670_JD_SPR_TRG_HI (0x1 << 6) | ||
1443 | #define RT5670_JD_MO_MASK (0x1 << 5) | ||
1444 | #define RT5670_JD_MO_SFT 5 | ||
1445 | #define RT5670_JD_MO_DIS (0x0 << 5) | ||
1446 | #define RT5670_JD_MO_EN (0x1 << 5) | ||
1447 | #define RT5670_JD_MO_TRG_MASK (0x1 << 4) | ||
1448 | #define RT5670_JD_MO_TRG_SFT 4 | ||
1449 | #define RT5670_JD_MO_TRG_LO (0x0 << 4) | ||
1450 | #define RT5670_JD_MO_TRG_HI (0x1 << 4) | ||
1451 | #define RT5670_JD_LO_MASK (0x1 << 3) | ||
1452 | #define RT5670_JD_LO_SFT 3 | ||
1453 | #define RT5670_JD_LO_DIS (0x0 << 3) | ||
1454 | #define RT5670_JD_LO_EN (0x1 << 3) | ||
1455 | #define RT5670_JD_LO_TRG_MASK (0x1 << 2) | ||
1456 | #define RT5670_JD_LO_TRG_SFT 2 | ||
1457 | #define RT5670_JD_LO_TRG_LO (0x0 << 2) | ||
1458 | #define RT5670_JD_LO_TRG_HI (0x1 << 2) | ||
1459 | #define RT5670_JD1_IN4P_MASK (0x1 << 1) | ||
1460 | #define RT5670_JD1_IN4P_SFT 1 | ||
1461 | #define RT5670_JD1_IN4P_DIS (0x0 << 1) | ||
1462 | #define RT5670_JD1_IN4P_EN (0x1 << 1) | ||
1463 | #define RT5670_JD2_IN4N_MASK (0x1) | ||
1464 | #define RT5670_JD2_IN4N_SFT 0 | ||
1465 | #define RT5670_JD2_IN4N_DIS (0x0) | ||
1466 | #define RT5670_JD2_IN4N_EN (0x1) | ||
1467 | |||
1468 | /* IRQ Control 1 (0xbd) */ | ||
1469 | #define RT5670_IRQ_JD_MASK (0x1 << 15) | ||
1470 | #define RT5670_IRQ_JD_SFT 15 | ||
1471 | #define RT5670_IRQ_JD_BP (0x0 << 15) | ||
1472 | #define RT5670_IRQ_JD_NOR (0x1 << 15) | ||
1473 | #define RT5670_IRQ_OT_MASK (0x1 << 14) | ||
1474 | #define RT5670_IRQ_OT_SFT 14 | ||
1475 | #define RT5670_IRQ_OT_BP (0x0 << 14) | ||
1476 | #define RT5670_IRQ_OT_NOR (0x1 << 14) | ||
1477 | #define RT5670_JD_STKY_MASK (0x1 << 13) | ||
1478 | #define RT5670_JD_STKY_SFT 13 | ||
1479 | #define RT5670_JD_STKY_DIS (0x0 << 13) | ||
1480 | #define RT5670_JD_STKY_EN (0x1 << 13) | ||
1481 | #define RT5670_OT_STKY_MASK (0x1 << 12) | ||
1482 | #define RT5670_OT_STKY_SFT 12 | ||
1483 | #define RT5670_OT_STKY_DIS (0x0 << 12) | ||
1484 | #define RT5670_OT_STKY_EN (0x1 << 12) | ||
1485 | #define RT5670_JD_P_MASK (0x1 << 11) | ||
1486 | #define RT5670_JD_P_SFT 11 | ||
1487 | #define RT5670_JD_P_NOR (0x0 << 11) | ||
1488 | #define RT5670_JD_P_INV (0x1 << 11) | ||
1489 | #define RT5670_OT_P_MASK (0x1 << 10) | ||
1490 | #define RT5670_OT_P_SFT 10 | ||
1491 | #define RT5670_OT_P_NOR (0x0 << 10) | ||
1492 | #define RT5670_OT_P_INV (0x1 << 10) | ||
1493 | #define RT5670_JD1_1_EN_MASK (0x1 << 9) | ||
1494 | #define RT5670_JD1_1_EN_SFT 9 | ||
1495 | #define RT5670_JD1_1_DIS (0x0 << 9) | ||
1496 | #define RT5670_JD1_1_EN (0x1 << 9) | ||
1497 | |||
1498 | /* IRQ Control 2 (0xbe) */ | ||
1499 | #define RT5670_IRQ_MB1_OC_MASK (0x1 << 15) | ||
1500 | #define RT5670_IRQ_MB1_OC_SFT 15 | ||
1501 | #define RT5670_IRQ_MB1_OC_BP (0x0 << 15) | ||
1502 | #define RT5670_IRQ_MB1_OC_NOR (0x1 << 15) | ||
1503 | #define RT5670_IRQ_MB2_OC_MASK (0x1 << 14) | ||
1504 | #define RT5670_IRQ_MB2_OC_SFT 14 | ||
1505 | #define RT5670_IRQ_MB2_OC_BP (0x0 << 14) | ||
1506 | #define RT5670_IRQ_MB2_OC_NOR (0x1 << 14) | ||
1507 | #define RT5670_MB1_OC_STKY_MASK (0x1 << 11) | ||
1508 | #define RT5670_MB1_OC_STKY_SFT 11 | ||
1509 | #define RT5670_MB1_OC_STKY_DIS (0x0 << 11) | ||
1510 | #define RT5670_MB1_OC_STKY_EN (0x1 << 11) | ||
1511 | #define RT5670_MB2_OC_STKY_MASK (0x1 << 10) | ||
1512 | #define RT5670_MB2_OC_STKY_SFT 10 | ||
1513 | #define RT5670_MB2_OC_STKY_DIS (0x0 << 10) | ||
1514 | #define RT5670_MB2_OC_STKY_EN (0x1 << 10) | ||
1515 | #define RT5670_MB1_OC_P_MASK (0x1 << 7) | ||
1516 | #define RT5670_MB1_OC_P_SFT 7 | ||
1517 | #define RT5670_MB1_OC_P_NOR (0x0 << 7) | ||
1518 | #define RT5670_MB1_OC_P_INV (0x1 << 7) | ||
1519 | #define RT5670_MB2_OC_P_MASK (0x1 << 6) | ||
1520 | #define RT5670_MB2_OC_P_SFT 6 | ||
1521 | #define RT5670_MB2_OC_P_NOR (0x0 << 6) | ||
1522 | #define RT5670_MB2_OC_P_INV (0x1 << 6) | ||
1523 | #define RT5670_MB1_OC_CLR (0x1 << 3) | ||
1524 | #define RT5670_MB1_OC_CLR_SFT 3 | ||
1525 | #define RT5670_MB2_OC_CLR (0x1 << 2) | ||
1526 | #define RT5670_MB2_OC_CLR_SFT 2 | ||
1527 | |||
1528 | /* GPIO Control 1 (0xc0) */ | ||
1529 | #define RT5670_GP1_PIN_MASK (0x1 << 15) | ||
1530 | #define RT5670_GP1_PIN_SFT 15 | ||
1531 | #define RT5670_GP1_PIN_GPIO1 (0x0 << 15) | ||
1532 | #define RT5670_GP1_PIN_IRQ (0x1 << 15) | ||
1533 | #define RT5670_GP2_PIN_MASK (0x1 << 14) | ||
1534 | #define RT5670_GP2_PIN_SFT 14 | ||
1535 | #define RT5670_GP2_PIN_GPIO2 (0x0 << 14) | ||
1536 | #define RT5670_GP2_PIN_DMIC1_SCL (0x1 << 14) | ||
1537 | #define RT5670_GP3_PIN_MASK (0x3 << 12) | ||
1538 | #define RT5670_GP3_PIN_SFT 12 | ||
1539 | #define RT5670_GP3_PIN_GPIO3 (0x0 << 12) | ||
1540 | #define RT5670_GP3_PIN_DMIC1_SDA (0x1 << 12) | ||
1541 | #define RT5670_GP3_PIN_IRQ (0x2 << 12) | ||
1542 | #define RT5670_GP4_PIN_MASK (0x1 << 11) | ||
1543 | #define RT5670_GP4_PIN_SFT 11 | ||
1544 | #define RT5670_GP4_PIN_GPIO4 (0x0 << 11) | ||
1545 | #define RT5670_GP4_PIN_DMIC2_SDA (0x1 << 11) | ||
1546 | #define RT5670_DP_SIG_MASK (0x1 << 10) | ||
1547 | #define RT5670_DP_SIG_SFT 10 | ||
1548 | #define RT5670_DP_SIG_TEST (0x0 << 10) | ||
1549 | #define RT5670_DP_SIG_AP (0x1 << 10) | ||
1550 | #define RT5670_GPIO_M_MASK (0x1 << 9) | ||
1551 | #define RT5670_GPIO_M_SFT 9 | ||
1552 | #define RT5670_GPIO_M_FLT (0x0 << 9) | ||
1553 | #define RT5670_GPIO_M_PH (0x1 << 9) | ||
1554 | #define RT5670_I2S2_PIN_MASK (0x1 << 8) | ||
1555 | #define RT5670_I2S2_PIN_SFT 8 | ||
1556 | #define RT5670_I2S2_PIN_I2S (0x0 << 8) | ||
1557 | #define RT5670_I2S2_PIN_GPIO (0x1 << 8) | ||
1558 | #define RT5670_GP5_PIN_MASK (0x1 << 7) | ||
1559 | #define RT5670_GP5_PIN_SFT 7 | ||
1560 | #define RT5670_GP5_PIN_GPIO5 (0x0 << 7) | ||
1561 | #define RT5670_GP5_PIN_DMIC3_SDA (0x1 << 7) | ||
1562 | #define RT5670_GP6_PIN_MASK (0x1 << 6) | ||
1563 | #define RT5670_GP6_PIN_SFT 6 | ||
1564 | #define RT5670_GP6_PIN_GPIO6 (0x0 << 6) | ||
1565 | #define RT5670_GP6_PIN_DMIC1_SDA (0x1 << 6) | ||
1566 | #define RT5670_GP7_PIN_MASK (0x3 << 4) | ||
1567 | #define RT5670_GP7_PIN_SFT 4 | ||
1568 | #define RT5670_GP7_PIN_GPIO7 (0x0 << 4) | ||
1569 | #define RT5670_GP7_PIN_DMIC1_SDA (0x1 << 4) | ||
1570 | #define RT5670_GP7_PIN_PDM_SCL2 (0x2 << 4) | ||
1571 | #define RT5670_GP8_PIN_MASK (0x1 << 3) | ||
1572 | #define RT5670_GP8_PIN_SFT 3 | ||
1573 | #define RT5670_GP8_PIN_GPIO8 (0x0 << 3) | ||
1574 | #define RT5670_GP8_PIN_DMIC2_SDA (0x1 << 3) | ||
1575 | #define RT5670_GP9_PIN_MASK (0x1 << 2) | ||
1576 | #define RT5670_GP9_PIN_SFT 2 | ||
1577 | #define RT5670_GP9_PIN_GPIO9 (0x0 << 2) | ||
1578 | #define RT5670_GP9_PIN_DMIC3_SDA (0x1 << 2) | ||
1579 | #define RT5670_GP10_PIN_MASK (0x3) | ||
1580 | #define RT5670_GP10_PIN_SFT 0 | ||
1581 | #define RT5670_GP10_PIN_GPIO9 (0x0) | ||
1582 | #define RT5670_GP10_PIN_DMIC3_SDA (0x1) | ||
1583 | #define RT5670_GP10_PIN_PDM_ADT2 (0x2) | ||
1584 | |||
1585 | /* GPIO Control 2 (0xc1) */ | ||
1586 | #define RT5670_GP4_PF_MASK (0x1 << 11) | ||
1587 | #define RT5670_GP4_PF_SFT 11 | ||
1588 | #define RT5670_GP4_PF_IN (0x0 << 11) | ||
1589 | #define RT5670_GP4_PF_OUT (0x1 << 11) | ||
1590 | #define RT5670_GP4_OUT_MASK (0x1 << 10) | ||
1591 | #define RT5670_GP4_OUT_SFT 10 | ||
1592 | #define RT5670_GP4_OUT_LO (0x0 << 10) | ||
1593 | #define RT5670_GP4_OUT_HI (0x1 << 10) | ||
1594 | #define RT5670_GP4_P_MASK (0x1 << 9) | ||
1595 | #define RT5670_GP4_P_SFT 9 | ||
1596 | #define RT5670_GP4_P_NOR (0x0 << 9) | ||
1597 | #define RT5670_GP4_P_INV (0x1 << 9) | ||
1598 | #define RT5670_GP3_PF_MASK (0x1 << 8) | ||
1599 | #define RT5670_GP3_PF_SFT 8 | ||
1600 | #define RT5670_GP3_PF_IN (0x0 << 8) | ||
1601 | #define RT5670_GP3_PF_OUT (0x1 << 8) | ||
1602 | #define RT5670_GP3_OUT_MASK (0x1 << 7) | ||
1603 | #define RT5670_GP3_OUT_SFT 7 | ||
1604 | #define RT5670_GP3_OUT_LO (0x0 << 7) | ||
1605 | #define RT5670_GP3_OUT_HI (0x1 << 7) | ||
1606 | #define RT5670_GP3_P_MASK (0x1 << 6) | ||
1607 | #define RT5670_GP3_P_SFT 6 | ||
1608 | #define RT5670_GP3_P_NOR (0x0 << 6) | ||
1609 | #define RT5670_GP3_P_INV (0x1 << 6) | ||
1610 | #define RT5670_GP2_PF_MASK (0x1 << 5) | ||
1611 | #define RT5670_GP2_PF_SFT 5 | ||
1612 | #define RT5670_GP2_PF_IN (0x0 << 5) | ||
1613 | #define RT5670_GP2_PF_OUT (0x1 << 5) | ||
1614 | #define RT5670_GP2_OUT_MASK (0x1 << 4) | ||
1615 | #define RT5670_GP2_OUT_SFT 4 | ||
1616 | #define RT5670_GP2_OUT_LO (0x0 << 4) | ||
1617 | #define RT5670_GP2_OUT_HI (0x1 << 4) | ||
1618 | #define RT5670_GP2_P_MASK (0x1 << 3) | ||
1619 | #define RT5670_GP2_P_SFT 3 | ||
1620 | #define RT5670_GP2_P_NOR (0x0 << 3) | ||
1621 | #define RT5670_GP2_P_INV (0x1 << 3) | ||
1622 | #define RT5670_GP1_PF_MASK (0x1 << 2) | ||
1623 | #define RT5670_GP1_PF_SFT 2 | ||
1624 | #define RT5670_GP1_PF_IN (0x0 << 2) | ||
1625 | #define RT5670_GP1_PF_OUT (0x1 << 2) | ||
1626 | #define RT5670_GP1_OUT_MASK (0x1 << 1) | ||
1627 | #define RT5670_GP1_OUT_SFT 1 | ||
1628 | #define RT5670_GP1_OUT_LO (0x0 << 1) | ||
1629 | #define RT5670_GP1_OUT_HI (0x1 << 1) | ||
1630 | #define RT5670_GP1_P_MASK (0x1) | ||
1631 | #define RT5670_GP1_P_SFT 0 | ||
1632 | #define RT5670_GP1_P_NOR (0x0) | ||
1633 | #define RT5670_GP1_P_INV (0x1) | ||
1634 | |||
1635 | /* Scramble Function (0xcd) */ | ||
1636 | #define RT5670_SCB_KEY_MASK (0xff) | ||
1637 | #define RT5670_SCB_KEY_SFT 0 | ||
1638 | |||
1639 | /* Scramble Control (0xce) */ | ||
1640 | #define RT5670_SCB_SWAP_MASK (0x1 << 15) | ||
1641 | #define RT5670_SCB_SWAP_SFT 15 | ||
1642 | #define RT5670_SCB_SWAP_DIS (0x0 << 15) | ||
1643 | #define RT5670_SCB_SWAP_EN (0x1 << 15) | ||
1644 | #define RT5670_SCB_MASK (0x1 << 14) | ||
1645 | #define RT5670_SCB_SFT 14 | ||
1646 | #define RT5670_SCB_DIS (0x0 << 14) | ||
1647 | #define RT5670_SCB_EN (0x1 << 14) | ||
1648 | |||
1649 | /* Baseback Control (0xcf) */ | ||
1650 | #define RT5670_BB_MASK (0x1 << 15) | ||
1651 | #define RT5670_BB_SFT 15 | ||
1652 | #define RT5670_BB_DIS (0x0 << 15) | ||
1653 | #define RT5670_BB_EN (0x1 << 15) | ||
1654 | #define RT5670_BB_CT_MASK (0x7 << 12) | ||
1655 | #define RT5670_BB_CT_SFT 12 | ||
1656 | #define RT5670_BB_CT_A (0x0 << 12) | ||
1657 | #define RT5670_BB_CT_B (0x1 << 12) | ||
1658 | #define RT5670_BB_CT_C (0x2 << 12) | ||
1659 | #define RT5670_BB_CT_D (0x3 << 12) | ||
1660 | #define RT5670_M_BB_L_MASK (0x1 << 9) | ||
1661 | #define RT5670_M_BB_L_SFT 9 | ||
1662 | #define RT5670_M_BB_R_MASK (0x1 << 8) | ||
1663 | #define RT5670_M_BB_R_SFT 8 | ||
1664 | #define RT5670_M_BB_HPF_L_MASK (0x1 << 7) | ||
1665 | #define RT5670_M_BB_HPF_L_SFT 7 | ||
1666 | #define RT5670_M_BB_HPF_R_MASK (0x1 << 6) | ||
1667 | #define RT5670_M_BB_HPF_R_SFT 6 | ||
1668 | #define RT5670_G_BB_BST_MASK (0x3f) | ||
1669 | #define RT5670_G_BB_BST_SFT 0 | ||
1670 | |||
1671 | /* MP3 Plus Control 1 (0xd0) */ | ||
1672 | #define RT5670_M_MP3_L_MASK (0x1 << 15) | ||
1673 | #define RT5670_M_MP3_L_SFT 15 | ||
1674 | #define RT5670_M_MP3_R_MASK (0x1 << 14) | ||
1675 | #define RT5670_M_MP3_R_SFT 14 | ||
1676 | #define RT5670_M_MP3_MASK (0x1 << 13) | ||
1677 | #define RT5670_M_MP3_SFT 13 | ||
1678 | #define RT5670_M_MP3_DIS (0x0 << 13) | ||
1679 | #define RT5670_M_MP3_EN (0x1 << 13) | ||
1680 | #define RT5670_EG_MP3_MASK (0x1f << 8) | ||
1681 | #define RT5670_EG_MP3_SFT 8 | ||
1682 | #define RT5670_MP3_HLP_MASK (0x1 << 7) | ||
1683 | #define RT5670_MP3_HLP_SFT 7 | ||
1684 | #define RT5670_MP3_HLP_DIS (0x0 << 7) | ||
1685 | #define RT5670_MP3_HLP_EN (0x1 << 7) | ||
1686 | #define RT5670_M_MP3_ORG_L_MASK (0x1 << 6) | ||
1687 | #define RT5670_M_MP3_ORG_L_SFT 6 | ||
1688 | #define RT5670_M_MP3_ORG_R_MASK (0x1 << 5) | ||
1689 | #define RT5670_M_MP3_ORG_R_SFT 5 | ||
1690 | |||
1691 | /* MP3 Plus Control 2 (0xd1) */ | ||
1692 | #define RT5670_MP3_WT_MASK (0x1 << 13) | ||
1693 | #define RT5670_MP3_WT_SFT 13 | ||
1694 | #define RT5670_MP3_WT_1_4 (0x0 << 13) | ||
1695 | #define RT5670_MP3_WT_1_2 (0x1 << 13) | ||
1696 | #define RT5670_OG_MP3_MASK (0x1f << 8) | ||
1697 | #define RT5670_OG_MP3_SFT 8 | ||
1698 | #define RT5670_HG_MP3_MASK (0x3f) | ||
1699 | #define RT5670_HG_MP3_SFT 0 | ||
1700 | |||
1701 | /* 3D HP Control 1 (0xd2) */ | ||
1702 | #define RT5670_3D_CF_MASK (0x1 << 15) | ||
1703 | #define RT5670_3D_CF_SFT 15 | ||
1704 | #define RT5670_3D_CF_DIS (0x0 << 15) | ||
1705 | #define RT5670_3D_CF_EN (0x1 << 15) | ||
1706 | #define RT5670_3D_HP_MASK (0x1 << 14) | ||
1707 | #define RT5670_3D_HP_SFT 14 | ||
1708 | #define RT5670_3D_HP_DIS (0x0 << 14) | ||
1709 | #define RT5670_3D_HP_EN (0x1 << 14) | ||
1710 | #define RT5670_3D_BT_MASK (0x1 << 13) | ||
1711 | #define RT5670_3D_BT_SFT 13 | ||
1712 | #define RT5670_3D_BT_DIS (0x0 << 13) | ||
1713 | #define RT5670_3D_BT_EN (0x1 << 13) | ||
1714 | #define RT5670_3D_1F_MIX_MASK (0x3 << 11) | ||
1715 | #define RT5670_3D_1F_MIX_SFT 11 | ||
1716 | #define RT5670_3D_HP_M_MASK (0x1 << 10) | ||
1717 | #define RT5670_3D_HP_M_SFT 10 | ||
1718 | #define RT5670_3D_HP_M_SUR (0x0 << 10) | ||
1719 | #define RT5670_3D_HP_M_FRO (0x1 << 10) | ||
1720 | #define RT5670_M_3D_HRTF_MASK (0x1 << 9) | ||
1721 | #define RT5670_M_3D_HRTF_SFT 9 | ||
1722 | #define RT5670_M_3D_D2H_MASK (0x1 << 8) | ||
1723 | #define RT5670_M_3D_D2H_SFT 8 | ||
1724 | #define RT5670_M_3D_D2R_MASK (0x1 << 7) | ||
1725 | #define RT5670_M_3D_D2R_SFT 7 | ||
1726 | #define RT5670_M_3D_REVB_MASK (0x1 << 6) | ||
1727 | #define RT5670_M_3D_REVB_SFT 6 | ||
1728 | |||
1729 | /* Adjustable high pass filter control 1 (0xd3) */ | ||
1730 | #define RT5670_2ND_HPF_MASK (0x1 << 15) | ||
1731 | #define RT5670_2ND_HPF_SFT 15 | ||
1732 | #define RT5670_2ND_HPF_DIS (0x0 << 15) | ||
1733 | #define RT5670_2ND_HPF_EN (0x1 << 15) | ||
1734 | #define RT5670_HPF_CF_L_MASK (0x7 << 12) | ||
1735 | #define RT5670_HPF_CF_L_SFT 12 | ||
1736 | #define RT5670_1ST_HPF_MASK (0x1 << 11) | ||
1737 | #define RT5670_1ST_HPF_SFT 11 | ||
1738 | #define RT5670_1ST_HPF_DIS (0x0 << 11) | ||
1739 | #define RT5670_1ST_HPF_EN (0x1 << 11) | ||
1740 | #define RT5670_HPF_CF_R_MASK (0x7 << 8) | ||
1741 | #define RT5670_HPF_CF_R_SFT 8 | ||
1742 | #define RT5670_ZD_T_MASK (0x3 << 6) | ||
1743 | #define RT5670_ZD_T_SFT 6 | ||
1744 | #define RT5670_ZD_F_MASK (0x3 << 4) | ||
1745 | #define RT5670_ZD_F_SFT 4 | ||
1746 | #define RT5670_ZD_F_IM (0x0 << 4) | ||
1747 | #define RT5670_ZD_F_ZC_IM (0x1 << 4) | ||
1748 | #define RT5670_ZD_F_ZC_IOD (0x2 << 4) | ||
1749 | #define RT5670_ZD_F_UN (0x3 << 4) | ||
1750 | |||
1751 | /* HP calibration control and Amp detection (0xd6) */ | ||
1752 | #define RT5670_SI_DAC_MASK (0x1 << 11) | ||
1753 | #define RT5670_SI_DAC_SFT 11 | ||
1754 | #define RT5670_SI_DAC_AUTO (0x0 << 11) | ||
1755 | #define RT5670_SI_DAC_TEST (0x1 << 11) | ||
1756 | #define RT5670_DC_CAL_M_MASK (0x1 << 10) | ||
1757 | #define RT5670_DC_CAL_M_SFT 10 | ||
1758 | #define RT5670_DC_CAL_M_CAL (0x0 << 10) | ||
1759 | #define RT5670_DC_CAL_M_NOR (0x1 << 10) | ||
1760 | #define RT5670_DC_CAL_MASK (0x1 << 9) | ||
1761 | #define RT5670_DC_CAL_SFT 9 | ||
1762 | #define RT5670_DC_CAL_DIS (0x0 << 9) | ||
1763 | #define RT5670_DC_CAL_EN (0x1 << 9) | ||
1764 | #define RT5670_HPD_RCV_MASK (0x7 << 6) | ||
1765 | #define RT5670_HPD_RCV_SFT 6 | ||
1766 | #define RT5670_HPD_PS_MASK (0x1 << 5) | ||
1767 | #define RT5670_HPD_PS_SFT 5 | ||
1768 | #define RT5670_HPD_PS_DIS (0x0 << 5) | ||
1769 | #define RT5670_HPD_PS_EN (0x1 << 5) | ||
1770 | #define RT5670_CAL_M_MASK (0x1 << 4) | ||
1771 | #define RT5670_CAL_M_SFT 4 | ||
1772 | #define RT5670_CAL_M_DEP (0x0 << 4) | ||
1773 | #define RT5670_CAL_M_CAL (0x1 << 4) | ||
1774 | #define RT5670_CAL_MASK (0x1 << 3) | ||
1775 | #define RT5670_CAL_SFT 3 | ||
1776 | #define RT5670_CAL_DIS (0x0 << 3) | ||
1777 | #define RT5670_CAL_EN (0x1 << 3) | ||
1778 | #define RT5670_CAL_TEST_MASK (0x1 << 2) | ||
1779 | #define RT5670_CAL_TEST_SFT 2 | ||
1780 | #define RT5670_CAL_TEST_DIS (0x0 << 2) | ||
1781 | #define RT5670_CAL_TEST_EN (0x1 << 2) | ||
1782 | #define RT5670_CAL_P_MASK (0x3) | ||
1783 | #define RT5670_CAL_P_SFT 0 | ||
1784 | #define RT5670_CAL_P_NONE (0x0) | ||
1785 | #define RT5670_CAL_P_CAL (0x1) | ||
1786 | #define RT5670_CAL_P_DAC_CAL (0x2) | ||
1787 | |||
1788 | /* Soft volume and zero cross control 1 (0xd9) */ | ||
1789 | #define RT5670_SV_MASK (0x1 << 15) | ||
1790 | #define RT5670_SV_SFT 15 | ||
1791 | #define RT5670_SV_DIS (0x0 << 15) | ||
1792 | #define RT5670_SV_EN (0x1 << 15) | ||
1793 | #define RT5670_SPO_SV_MASK (0x1 << 14) | ||
1794 | #define RT5670_SPO_SV_SFT 14 | ||
1795 | #define RT5670_SPO_SV_DIS (0x0 << 14) | ||
1796 | #define RT5670_SPO_SV_EN (0x1 << 14) | ||
1797 | #define RT5670_OUT_SV_MASK (0x1 << 13) | ||
1798 | #define RT5670_OUT_SV_SFT 13 | ||
1799 | #define RT5670_OUT_SV_DIS (0x0 << 13) | ||
1800 | #define RT5670_OUT_SV_EN (0x1 << 13) | ||
1801 | #define RT5670_HP_SV_MASK (0x1 << 12) | ||
1802 | #define RT5670_HP_SV_SFT 12 | ||
1803 | #define RT5670_HP_SV_DIS (0x0 << 12) | ||
1804 | #define RT5670_HP_SV_EN (0x1 << 12) | ||
1805 | #define RT5670_ZCD_DIG_MASK (0x1 << 11) | ||
1806 | #define RT5670_ZCD_DIG_SFT 11 | ||
1807 | #define RT5670_ZCD_DIG_DIS (0x0 << 11) | ||
1808 | #define RT5670_ZCD_DIG_EN (0x1 << 11) | ||
1809 | #define RT5670_ZCD_MASK (0x1 << 10) | ||
1810 | #define RT5670_ZCD_SFT 10 | ||
1811 | #define RT5670_ZCD_PD (0x0 << 10) | ||
1812 | #define RT5670_ZCD_PU (0x1 << 10) | ||
1813 | #define RT5670_M_ZCD_MASK (0x3f << 4) | ||
1814 | #define RT5670_M_ZCD_SFT 4 | ||
1815 | #define RT5670_M_ZCD_RM_L (0x1 << 9) | ||
1816 | #define RT5670_M_ZCD_RM_R (0x1 << 8) | ||
1817 | #define RT5670_M_ZCD_SM_L (0x1 << 7) | ||
1818 | #define RT5670_M_ZCD_SM_R (0x1 << 6) | ||
1819 | #define RT5670_M_ZCD_OM_L (0x1 << 5) | ||
1820 | #define RT5670_M_ZCD_OM_R (0x1 << 4) | ||
1821 | #define RT5670_SV_DLY_MASK (0xf) | ||
1822 | #define RT5670_SV_DLY_SFT 0 | ||
1823 | |||
1824 | /* Soft volume and zero cross control 2 (0xda) */ | ||
1825 | #define RT5670_ZCD_HP_MASK (0x1 << 15) | ||
1826 | #define RT5670_ZCD_HP_SFT 15 | ||
1827 | #define RT5670_ZCD_HP_DIS (0x0 << 15) | ||
1828 | #define RT5670_ZCD_HP_EN (0x1 << 15) | ||
1829 | |||
1830 | |||
1831 | /* Codec Private Register definition */ | ||
1832 | /* 3D Speaker Control (0x63) */ | ||
1833 | #define RT5670_3D_SPK_MASK (0x1 << 15) | ||
1834 | #define RT5670_3D_SPK_SFT 15 | ||
1835 | #define RT5670_3D_SPK_DIS (0x0 << 15) | ||
1836 | #define RT5670_3D_SPK_EN (0x1 << 15) | ||
1837 | #define RT5670_3D_SPK_M_MASK (0x3 << 13) | ||
1838 | #define RT5670_3D_SPK_M_SFT 13 | ||
1839 | #define RT5670_3D_SPK_CG_MASK (0x1f << 8) | ||
1840 | #define RT5670_3D_SPK_CG_SFT 8 | ||
1841 | #define RT5670_3D_SPK_SG_MASK (0x1f) | ||
1842 | #define RT5670_3D_SPK_SG_SFT 0 | ||
1843 | |||
1844 | /* Wind Noise Detection Control 1 (0x6c) */ | ||
1845 | #define RT5670_WND_MASK (0x1 << 15) | ||
1846 | #define RT5670_WND_SFT 15 | ||
1847 | #define RT5670_WND_DIS (0x0 << 15) | ||
1848 | #define RT5670_WND_EN (0x1 << 15) | ||
1849 | |||
1850 | /* Wind Noise Detection Control 2 (0x6d) */ | ||
1851 | #define RT5670_WND_FC_NW_MASK (0x3f << 10) | ||
1852 | #define RT5670_WND_FC_NW_SFT 10 | ||
1853 | #define RT5670_WND_FC_WK_MASK (0x3f << 4) | ||
1854 | #define RT5670_WND_FC_WK_SFT 4 | ||
1855 | |||
1856 | /* Wind Noise Detection Control 3 (0x6e) */ | ||
1857 | #define RT5670_HPF_FC_MASK (0x3f << 6) | ||
1858 | #define RT5670_HPF_FC_SFT 6 | ||
1859 | #define RT5670_WND_FC_ST_MASK (0x3f) | ||
1860 | #define RT5670_WND_FC_ST_SFT 0 | ||
1861 | |||
1862 | /* Wind Noise Detection Control 4 (0x6f) */ | ||
1863 | #define RT5670_WND_TH_LO_MASK (0x3ff) | ||
1864 | #define RT5670_WND_TH_LO_SFT 0 | ||
1865 | |||
1866 | /* Wind Noise Detection Control 5 (0x70) */ | ||
1867 | #define RT5670_WND_TH_HI_MASK (0x3ff) | ||
1868 | #define RT5670_WND_TH_HI_SFT 0 | ||
1869 | |||
1870 | /* Wind Noise Detection Control 8 (0x73) */ | ||
1871 | #define RT5670_WND_WIND_MASK (0x1 << 13) /* Read-Only */ | ||
1872 | #define RT5670_WND_WIND_SFT 13 | ||
1873 | #define RT5670_WND_STRONG_MASK (0x1 << 12) /* Read-Only */ | ||
1874 | #define RT5670_WND_STRONG_SFT 12 | ||
1875 | enum { | ||
1876 | RT5670_NO_WIND, | ||
1877 | RT5670_BREEZE, | ||
1878 | RT5670_STORM, | ||
1879 | }; | ||
1880 | |||
1881 | /* Dipole Speaker Interface (0x75) */ | ||
1882 | #define RT5670_DP_ATT_MASK (0x3 << 14) | ||
1883 | #define RT5670_DP_ATT_SFT 14 | ||
1884 | #define RT5670_DP_SPK_MASK (0x1 << 10) | ||
1885 | #define RT5670_DP_SPK_SFT 10 | ||
1886 | #define RT5670_DP_SPK_DIS (0x0 << 10) | ||
1887 | #define RT5670_DP_SPK_EN (0x1 << 10) | ||
1888 | |||
1889 | /* EQ Pre Volume Control (0xb3) */ | ||
1890 | #define RT5670_EQ_PRE_VOL_MASK (0xffff) | ||
1891 | #define RT5670_EQ_PRE_VOL_SFT 0 | ||
1892 | |||
1893 | /* EQ Post Volume Control (0xb4) */ | ||
1894 | #define RT5670_EQ_PST_VOL_MASK (0xffff) | ||
1895 | #define RT5670_EQ_PST_VOL_SFT 0 | ||
1896 | |||
1897 | /* Jack Detect Control 3 (0xf8) */ | ||
1898 | #define RT5670_CMP_MIC_IN_DET_MASK (0x7 << 12) | ||
1899 | #define RT5670_JD_CBJ_EN (0x1 << 7) | ||
1900 | #define RT5670_JD_CBJ_POL (0x1 << 6) | ||
1901 | #define RT5670_JD_TRI_CBJ_SEL_MASK (0x7 << 3) | ||
1902 | #define RT5670_JD_TRI_CBJ_SEL_SFT (3) | ||
1903 | #define RT5670_JD_CBJ_GPIO_JD1 (0x0 << 3) | ||
1904 | #define RT5670_JD_CBJ_JD1_1 (0x1 << 3) | ||
1905 | #define RT5670_JD_CBJ_JD1_2 (0x2 << 3) | ||
1906 | #define RT5670_JD_CBJ_JD2 (0x3 << 3) | ||
1907 | #define RT5670_JD_CBJ_JD3 (0x4 << 3) | ||
1908 | #define RT5670_JD_CBJ_GPIO_JD2 (0x5 << 3) | ||
1909 | #define RT5670_JD_CBJ_MX0B_12 (0x6 << 3) | ||
1910 | #define RT5670_JD_TRI_HPO_SEL_MASK (0x7 << 3) | ||
1911 | #define RT5670_JD_TRI_HPO_SEL_SFT (0) | ||
1912 | #define RT5670_JD_HPO_GPIO_JD1 (0x0) | ||
1913 | #define RT5670_JD_HPO_JD1_1 (0x1) | ||
1914 | #define RT5670_JD_HPO_JD1_2 (0x2) | ||
1915 | #define RT5670_JD_HPO_JD2 (0x3) | ||
1916 | #define RT5670_JD_HPO_JD3 (0x4) | ||
1917 | #define RT5670_JD_HPO_GPIO_JD2 (0x5) | ||
1918 | #define RT5670_JD_HPO_MX0B_12 (0x6) | ||
1919 | |||
1920 | /* Digital Misc Control (0xfa) */ | ||
1921 | #define RT5670_RST_DSP (0x1 << 13) | ||
1922 | #define RT5670_IF1_ADC1_IN1_SEL (0x1 << 12) | ||
1923 | #define RT5670_IF1_ADC1_IN1_SFT 12 | ||
1924 | #define RT5670_IF1_ADC1_IN2_SEL (0x1 << 11) | ||
1925 | #define RT5670_IF1_ADC1_IN2_SFT 11 | ||
1926 | #define RT5670_IF1_ADC2_IN1_SEL (0x1 << 10) | ||
1927 | #define RT5670_IF1_ADC2_IN1_SFT 10 | ||
1928 | |||
1929 | /* General Control2 (0xfb) */ | ||
1930 | #define RT5670_RXDC_SRC_MASK (0x1 << 7) | ||
1931 | #define RT5670_RXDC_SRC_STO (0x0 << 7) | ||
1932 | #define RT5670_RXDC_SRC_MONO (0x1 << 7) | ||
1933 | #define RT5670_RXDC_SRC_SFT (7) | ||
1934 | #define RT5670_RXDP2_SEL_MASK (0x1 << 3) | ||
1935 | #define RT5670_RXDP2_SEL_IF2 (0x0 << 3) | ||
1936 | #define RT5670_RXDP2_SEL_ADC (0x1 << 3) | ||
1937 | #define RT5670_RXDP2_SEL_SFT (3) | ||
1938 | |||
1939 | /* System Clock Source */ | ||
1940 | enum { | ||
1941 | RT5670_SCLK_S_MCLK, | ||
1942 | RT5670_SCLK_S_PLL1, | ||
1943 | RT5670_SCLK_S_RCCLK, | ||
1944 | }; | ||
1945 | |||
1946 | /* PLL1 Source */ | ||
1947 | enum { | ||
1948 | RT5670_PLL1_S_MCLK, | ||
1949 | RT5670_PLL1_S_BCLK1, | ||
1950 | RT5670_PLL1_S_BCLK2, | ||
1951 | RT5670_PLL1_S_BCLK3, | ||
1952 | RT5670_PLL1_S_BCLK4, | ||
1953 | }; | ||
1954 | |||
1955 | enum { | ||
1956 | RT5670_AIF1, | ||
1957 | RT5670_AIF2, | ||
1958 | RT5670_AIF3, | ||
1959 | RT5670_AIF4, | ||
1960 | RT5670_AIFS, | ||
1961 | }; | ||
1962 | |||
1963 | enum { | ||
1964 | RT5670_DMIC_DATA_GPIO6, | ||
1965 | RT5670_DMIC_DATA_IN2P, | ||
1966 | RT5670_DMIC_DATA_GPIO7, | ||
1967 | }; | ||
1968 | |||
1969 | enum { | ||
1970 | RT5670_DMIC_DATA_GPIO8, | ||
1971 | RT5670_DMIC_DATA_IN3N, | ||
1972 | }; | ||
1973 | |||
1974 | enum { | ||
1975 | RT5670_DMIC_DATA_GPIO9, | ||
1976 | RT5670_DMIC_DATA_GPIO10, | ||
1977 | RT5670_DMIC_DATA_GPIO5, | ||
1978 | }; | ||
1979 | |||
1980 | struct rt5670_priv { | ||
1981 | struct snd_soc_codec *codec; | ||
1982 | struct rt5670_platform_data pdata; | ||
1983 | struct regmap *regmap; | ||
1984 | |||
1985 | int sysclk; | ||
1986 | int sysclk_src; | ||
1987 | int lrck[RT5670_AIFS]; | ||
1988 | int bclk[RT5670_AIFS]; | ||
1989 | int master[RT5670_AIFS]; | ||
1990 | |||
1991 | int pll_src; | ||
1992 | int pll_in; | ||
1993 | int pll_out; | ||
1994 | |||
1995 | int dsp_sw; /* expected parameter setting */ | ||
1996 | int dsp_rate; | ||
1997 | int jack_type; | ||
1998 | }; | ||
1999 | |||
2000 | #endif /* __RT5670_H__ */ | ||
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 833231e27340..67f14556462f 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <sound/initval.h> | 27 | #include <sound/initval.h> |
28 | #include <sound/tlv.h> | 28 | #include <sound/tlv.h> |
29 | 29 | ||
30 | #include "rl6231.h" | ||
30 | #include "rt5677.h" | 31 | #include "rt5677.h" |
31 | 32 | ||
32 | #define RT5677_DEVICE_ID 0x6327 | 33 | #define RT5677_DEVICE_ID 0x6327 |
@@ -604,19 +605,19 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = { | |||
604 | adc_vol_tlv), | 605 | adc_vol_tlv), |
605 | 606 | ||
606 | /* ADC Boost Volume Control */ | 607 | /* ADC Boost Volume Control */ |
607 | SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5677_STO1_2_ADC_BST, | 608 | SOC_DOUBLE_TLV("STO1 ADC Boost Volume", RT5677_STO1_2_ADC_BST, |
608 | RT5677_STO1_ADC_L_BST_SFT, RT5677_STO1_ADC_R_BST_SFT, 3, 0, | 609 | RT5677_STO1_ADC_L_BST_SFT, RT5677_STO1_ADC_R_BST_SFT, 3, 0, |
609 | adc_bst_tlv), | 610 | adc_bst_tlv), |
610 | SOC_DOUBLE_TLV("STO2 ADC Boost Gain", RT5677_STO1_2_ADC_BST, | 611 | SOC_DOUBLE_TLV("STO2 ADC Boost Volume", RT5677_STO1_2_ADC_BST, |
611 | RT5677_STO2_ADC_L_BST_SFT, RT5677_STO2_ADC_R_BST_SFT, 3, 0, | 612 | RT5677_STO2_ADC_L_BST_SFT, RT5677_STO2_ADC_R_BST_SFT, 3, 0, |
612 | adc_bst_tlv), | 613 | adc_bst_tlv), |
613 | SOC_DOUBLE_TLV("STO3 ADC Boost Gain", RT5677_STO3_4_ADC_BST, | 614 | SOC_DOUBLE_TLV("STO3 ADC Boost Volume", RT5677_STO3_4_ADC_BST, |
614 | RT5677_STO3_ADC_L_BST_SFT, RT5677_STO3_ADC_R_BST_SFT, 3, 0, | 615 | RT5677_STO3_ADC_L_BST_SFT, RT5677_STO3_ADC_R_BST_SFT, 3, 0, |
615 | adc_bst_tlv), | 616 | adc_bst_tlv), |
616 | SOC_DOUBLE_TLV("STO4 ADC Boost Gain", RT5677_STO3_4_ADC_BST, | 617 | SOC_DOUBLE_TLV("STO4 ADC Boost Volume", RT5677_STO3_4_ADC_BST, |
617 | RT5677_STO4_ADC_L_BST_SFT, RT5677_STO4_ADC_R_BST_SFT, 3, 0, | 618 | RT5677_STO4_ADC_L_BST_SFT, RT5677_STO4_ADC_R_BST_SFT, 3, 0, |
618 | adc_bst_tlv), | 619 | adc_bst_tlv), |
619 | SOC_DOUBLE_TLV("Mono ADC Boost Gain", RT5677_ADC_BST_CTRL2, | 620 | SOC_DOUBLE_TLV("Mono ADC Boost Volume", RT5677_ADC_BST_CTRL2, |
620 | RT5677_MONO_ADC_L_BST_SFT, RT5677_MONO_ADC_R_BST_SFT, 3, 0, | 621 | RT5677_MONO_ADC_L_BST_SFT, RT5677_MONO_ADC_R_BST_SFT, 3, 0, |
621 | adc_bst_tlv), | 622 | adc_bst_tlv), |
622 | }; | 623 | }; |
@@ -636,21 +637,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
636 | { | 637 | { |
637 | struct snd_soc_codec *codec = w->codec; | 638 | struct snd_soc_codec *codec = w->codec; |
638 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 639 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
639 | int div[] = {2, 3, 4, 6, 8, 12}, idx = -EINVAL, i; | 640 | int idx = rl6231_calc_dmic_clk(rt5677->sysclk); |
640 | int rate, red, bound, temp; | ||
641 | |||
642 | rate = rt5677->sysclk; | ||
643 | red = 3000000 * 12; | ||
644 | for (i = 0; i < ARRAY_SIZE(div); i++) { | ||
645 | bound = div[i] * 3000000; | ||
646 | if (rate > bound) | ||
647 | continue; | ||
648 | temp = bound - rate; | ||
649 | if (temp < red) { | ||
650 | red = temp; | ||
651 | idx = i; | ||
652 | } | ||
653 | } | ||
654 | 641 | ||
655 | if (idx < 0) | 642 | if (idx < 0) |
656 | dev_err(codec->dev, "Failed to set DMIC clock\n"); | 643 | dev_err(codec->dev, "Failed to set DMIC clock\n"); |
@@ -951,7 +938,7 @@ static const struct snd_kcontrol_new rt5677_ob_7_mix[] = { | |||
951 | 938 | ||
952 | 939 | ||
953 | /* Mux */ | 940 | /* Mux */ |
954 | /* DAC1 L/R source */ /* MX-29 [10:8] */ | 941 | /* DAC1 L/R Source */ /* MX-29 [10:8] */ |
955 | static const char * const rt5677_dac1_src[] = { | 942 | static const char * const rt5677_dac1_src[] = { |
956 | "IF1 DAC 01", "IF2 DAC 01", "IF3 DAC LR", "IF4 DAC LR", "SLB DAC 01", | 943 | "IF1 DAC 01", "IF2 DAC 01", "IF3 DAC LR", "IF4 DAC LR", "SLB DAC 01", |
957 | "OB 01" | 944 | "OB 01" |
@@ -962,9 +949,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
962 | RT5677_DAC1_L_SEL_SFT, rt5677_dac1_src); | 949 | RT5677_DAC1_L_SEL_SFT, rt5677_dac1_src); |
963 | 950 | ||
964 | static const struct snd_kcontrol_new rt5677_dac1_mux = | 951 | static const struct snd_kcontrol_new rt5677_dac1_mux = |
965 | SOC_DAPM_ENUM("DAC1 source", rt5677_dac1_enum); | 952 | SOC_DAPM_ENUM("DAC1 Source", rt5677_dac1_enum); |
966 | 953 | ||
967 | /* ADDA1 L/R source */ /* MX-29 [1:0] */ | 954 | /* ADDA1 L/R Source */ /* MX-29 [1:0] */ |
968 | static const char * const rt5677_adda1_src[] = { | 955 | static const char * const rt5677_adda1_src[] = { |
969 | "STO1 ADC MIX", "STO2 ADC MIX", "OB 67", | 956 | "STO1 ADC MIX", "STO2 ADC MIX", "OB 67", |
970 | }; | 957 | }; |
@@ -974,10 +961,10 @@ static SOC_ENUM_SINGLE_DECL( | |||
974 | RT5677_ADDA1_SEL_SFT, rt5677_adda1_src); | 961 | RT5677_ADDA1_SEL_SFT, rt5677_adda1_src); |
975 | 962 | ||
976 | static const struct snd_kcontrol_new rt5677_adda1_mux = | 963 | static const struct snd_kcontrol_new rt5677_adda1_mux = |
977 | SOC_DAPM_ENUM("ADDA1 source", rt5677_adda1_enum); | 964 | SOC_DAPM_ENUM("ADDA1 Source", rt5677_adda1_enum); |
978 | 965 | ||
979 | 966 | ||
980 | /*DAC2 L/R source*/ /* MX-1B [6:4] [2:0] */ | 967 | /*DAC2 L/R Source*/ /* MX-1B [6:4] [2:0] */ |
981 | static const char * const rt5677_dac2l_src[] = { | 968 | static const char * const rt5677_dac2l_src[] = { |
982 | "IF1 DAC 2", "IF2 DAC 2", "IF3 DAC L", "IF4 DAC L", "SLB DAC 2", | 969 | "IF1 DAC 2", "IF2 DAC 2", "IF3 DAC L", "IF4 DAC L", "SLB DAC 2", |
983 | "OB 2", | 970 | "OB 2", |
@@ -988,7 +975,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
988 | RT5677_SEL_DAC2_L_SRC_SFT, rt5677_dac2l_src); | 975 | RT5677_SEL_DAC2_L_SRC_SFT, rt5677_dac2l_src); |
989 | 976 | ||
990 | static const struct snd_kcontrol_new rt5677_dac2_l_mux = | 977 | static const struct snd_kcontrol_new rt5677_dac2_l_mux = |
991 | SOC_DAPM_ENUM("DAC2 L source", rt5677_dac2l_enum); | 978 | SOC_DAPM_ENUM("DAC2 L Source", rt5677_dac2l_enum); |
992 | 979 | ||
993 | static const char * const rt5677_dac2r_src[] = { | 980 | static const char * const rt5677_dac2r_src[] = { |
994 | "IF1 DAC 3", "IF2 DAC 3", "IF3 DAC R", "IF4 DAC R", "SLB DAC 3", | 981 | "IF1 DAC 3", "IF2 DAC 3", "IF3 DAC R", "IF4 DAC R", "SLB DAC 3", |
@@ -1000,9 +987,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
1000 | RT5677_SEL_DAC2_R_SRC_SFT, rt5677_dac2r_src); | 987 | RT5677_SEL_DAC2_R_SRC_SFT, rt5677_dac2r_src); |
1001 | 988 | ||
1002 | static const struct snd_kcontrol_new rt5677_dac2_r_mux = | 989 | static const struct snd_kcontrol_new rt5677_dac2_r_mux = |
1003 | SOC_DAPM_ENUM("DAC2 R source", rt5677_dac2r_enum); | 990 | SOC_DAPM_ENUM("DAC2 R Source", rt5677_dac2r_enum); |
1004 | 991 | ||
1005 | /*DAC3 L/R source*/ /* MX-16 [6:4] [2:0] */ | 992 | /*DAC3 L/R Source*/ /* MX-16 [6:4] [2:0] */ |
1006 | static const char * const rt5677_dac3l_src[] = { | 993 | static const char * const rt5677_dac3l_src[] = { |
1007 | "IF1 DAC 4", "IF2 DAC 4", "IF3 DAC L", "IF4 DAC L", | 994 | "IF1 DAC 4", "IF2 DAC 4", "IF3 DAC L", "IF4 DAC L", |
1008 | "SLB DAC 4", "OB 4" | 995 | "SLB DAC 4", "OB 4" |
@@ -1013,7 +1000,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1013 | RT5677_SEL_DAC3_L_SRC_SFT, rt5677_dac3l_src); | 1000 | RT5677_SEL_DAC3_L_SRC_SFT, rt5677_dac3l_src); |
1014 | 1001 | ||
1015 | static const struct snd_kcontrol_new rt5677_dac3_l_mux = | 1002 | static const struct snd_kcontrol_new rt5677_dac3_l_mux = |
1016 | SOC_DAPM_ENUM("DAC3 L source", rt5677_dac3l_enum); | 1003 | SOC_DAPM_ENUM("DAC3 L Source", rt5677_dac3l_enum); |
1017 | 1004 | ||
1018 | static const char * const rt5677_dac3r_src[] = { | 1005 | static const char * const rt5677_dac3r_src[] = { |
1019 | "IF1 DAC 5", "IF2 DAC 5", "IF3 DAC R", "IF4 DAC R", | 1006 | "IF1 DAC 5", "IF2 DAC 5", "IF3 DAC R", "IF4 DAC R", |
@@ -1025,9 +1012,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
1025 | RT5677_SEL_DAC3_R_SRC_SFT, rt5677_dac3r_src); | 1012 | RT5677_SEL_DAC3_R_SRC_SFT, rt5677_dac3r_src); |
1026 | 1013 | ||
1027 | static const struct snd_kcontrol_new rt5677_dac3_r_mux = | 1014 | static const struct snd_kcontrol_new rt5677_dac3_r_mux = |
1028 | SOC_DAPM_ENUM("DAC3 R source", rt5677_dac3r_enum); | 1015 | SOC_DAPM_ENUM("DAC3 R Source", rt5677_dac3r_enum); |
1029 | 1016 | ||
1030 | /*DAC4 L/R source*/ /* MX-16 [14:12] [10:8] */ | 1017 | /*DAC4 L/R Source*/ /* MX-16 [14:12] [10:8] */ |
1031 | static const char * const rt5677_dac4l_src[] = { | 1018 | static const char * const rt5677_dac4l_src[] = { |
1032 | "IF1 DAC 6", "IF2 DAC 6", "IF3 DAC L", "IF4 DAC L", | 1019 | "IF1 DAC 6", "IF2 DAC 6", "IF3 DAC L", "IF4 DAC L", |
1033 | "SLB DAC 6", "OB 6" | 1020 | "SLB DAC 6", "OB 6" |
@@ -1038,7 +1025,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1038 | RT5677_SEL_DAC4_L_SRC_SFT, rt5677_dac4l_src); | 1025 | RT5677_SEL_DAC4_L_SRC_SFT, rt5677_dac4l_src); |
1039 | 1026 | ||
1040 | static const struct snd_kcontrol_new rt5677_dac4_l_mux = | 1027 | static const struct snd_kcontrol_new rt5677_dac4_l_mux = |
1041 | SOC_DAPM_ENUM("DAC4 L source", rt5677_dac4l_enum); | 1028 | SOC_DAPM_ENUM("DAC4 L Source", rt5677_dac4l_enum); |
1042 | 1029 | ||
1043 | static const char * const rt5677_dac4r_src[] = { | 1030 | static const char * const rt5677_dac4r_src[] = { |
1044 | "IF1 DAC 7", "IF2 DAC 7", "IF3 DAC R", "IF4 DAC R", | 1031 | "IF1 DAC 7", "IF2 DAC 7", "IF3 DAC R", "IF4 DAC R", |
@@ -1050,7 +1037,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1050 | RT5677_SEL_DAC4_R_SRC_SFT, rt5677_dac4r_src); | 1037 | RT5677_SEL_DAC4_R_SRC_SFT, rt5677_dac4r_src); |
1051 | 1038 | ||
1052 | static const struct snd_kcontrol_new rt5677_dac4_r_mux = | 1039 | static const struct snd_kcontrol_new rt5677_dac4_r_mux = |
1053 | SOC_DAPM_ENUM("DAC4 R source", rt5677_dac4r_enum); | 1040 | SOC_DAPM_ENUM("DAC4 R Source", rt5677_dac4r_enum); |
1054 | 1041 | ||
1055 | /* In/OutBound Source Pass SRC */ /* MX-A5 [3] [4] [0] [1] [2] */ | 1042 | /* In/OutBound Source Pass SRC */ /* MX-A5 [3] [4] [0] [1] [2] */ |
1056 | static const char * const rt5677_iob_bypass_src[] = { | 1043 | static const char * const rt5677_iob_bypass_src[] = { |
@@ -1062,35 +1049,35 @@ static SOC_ENUM_SINGLE_DECL( | |||
1062 | RT5677_SEL_SRC_OB01_SFT, rt5677_iob_bypass_src); | 1049 | RT5677_SEL_SRC_OB01_SFT, rt5677_iob_bypass_src); |
1063 | 1050 | ||
1064 | static const struct snd_kcontrol_new rt5677_ob01_bypass_src_mux = | 1051 | static const struct snd_kcontrol_new rt5677_ob01_bypass_src_mux = |
1065 | SOC_DAPM_ENUM("OB01 Bypass source", rt5677_ob01_bypass_src_enum); | 1052 | SOC_DAPM_ENUM("OB01 Bypass Source", rt5677_ob01_bypass_src_enum); |
1066 | 1053 | ||
1067 | static SOC_ENUM_SINGLE_DECL( | 1054 | static SOC_ENUM_SINGLE_DECL( |
1068 | rt5677_ob23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, | 1055 | rt5677_ob23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, |
1069 | RT5677_SEL_SRC_OB23_SFT, rt5677_iob_bypass_src); | 1056 | RT5677_SEL_SRC_OB23_SFT, rt5677_iob_bypass_src); |
1070 | 1057 | ||
1071 | static const struct snd_kcontrol_new rt5677_ob23_bypass_src_mux = | 1058 | static const struct snd_kcontrol_new rt5677_ob23_bypass_src_mux = |
1072 | SOC_DAPM_ENUM("OB23 Bypass source", rt5677_ob23_bypass_src_enum); | 1059 | SOC_DAPM_ENUM("OB23 Bypass Source", rt5677_ob23_bypass_src_enum); |
1073 | 1060 | ||
1074 | static SOC_ENUM_SINGLE_DECL( | 1061 | static SOC_ENUM_SINGLE_DECL( |
1075 | rt5677_ib01_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, | 1062 | rt5677_ib01_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, |
1076 | RT5677_SEL_SRC_IB01_SFT, rt5677_iob_bypass_src); | 1063 | RT5677_SEL_SRC_IB01_SFT, rt5677_iob_bypass_src); |
1077 | 1064 | ||
1078 | static const struct snd_kcontrol_new rt5677_ib01_bypass_src_mux = | 1065 | static const struct snd_kcontrol_new rt5677_ib01_bypass_src_mux = |
1079 | SOC_DAPM_ENUM("IB01 Bypass source", rt5677_ib01_bypass_src_enum); | 1066 | SOC_DAPM_ENUM("IB01 Bypass Source", rt5677_ib01_bypass_src_enum); |
1080 | 1067 | ||
1081 | static SOC_ENUM_SINGLE_DECL( | 1068 | static SOC_ENUM_SINGLE_DECL( |
1082 | rt5677_ib23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, | 1069 | rt5677_ib23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, |
1083 | RT5677_SEL_SRC_IB23_SFT, rt5677_iob_bypass_src); | 1070 | RT5677_SEL_SRC_IB23_SFT, rt5677_iob_bypass_src); |
1084 | 1071 | ||
1085 | static const struct snd_kcontrol_new rt5677_ib23_bypass_src_mux = | 1072 | static const struct snd_kcontrol_new rt5677_ib23_bypass_src_mux = |
1086 | SOC_DAPM_ENUM("IB23 Bypass source", rt5677_ib23_bypass_src_enum); | 1073 | SOC_DAPM_ENUM("IB23 Bypass Source", rt5677_ib23_bypass_src_enum); |
1087 | 1074 | ||
1088 | static SOC_ENUM_SINGLE_DECL( | 1075 | static SOC_ENUM_SINGLE_DECL( |
1089 | rt5677_ib45_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, | 1076 | rt5677_ib45_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, |
1090 | RT5677_SEL_SRC_IB45_SFT, rt5677_iob_bypass_src); | 1077 | RT5677_SEL_SRC_IB45_SFT, rt5677_iob_bypass_src); |
1091 | 1078 | ||
1092 | static const struct snd_kcontrol_new rt5677_ib45_bypass_src_mux = | 1079 | static const struct snd_kcontrol_new rt5677_ib45_bypass_src_mux = |
1093 | SOC_DAPM_ENUM("IB45 Bypass source", rt5677_ib45_bypass_src_enum); | 1080 | SOC_DAPM_ENUM("IB45 Bypass Source", rt5677_ib45_bypass_src_enum); |
1094 | 1081 | ||
1095 | /* Stereo ADC Source 2 */ /* MX-27 MX26 MX25 [11:10] */ | 1082 | /* Stereo ADC Source 2 */ /* MX-27 MX26 MX25 [11:10] */ |
1096 | static const char * const rt5677_stereo_adc2_src[] = { | 1083 | static const char * const rt5677_stereo_adc2_src[] = { |
@@ -1102,21 +1089,21 @@ static SOC_ENUM_SINGLE_DECL( | |||
1102 | RT5677_SEL_STO1_ADC2_SFT, rt5677_stereo_adc2_src); | 1089 | RT5677_SEL_STO1_ADC2_SFT, rt5677_stereo_adc2_src); |
1103 | 1090 | ||
1104 | static const struct snd_kcontrol_new rt5677_sto1_adc2_mux = | 1091 | static const struct snd_kcontrol_new rt5677_sto1_adc2_mux = |
1105 | SOC_DAPM_ENUM("Stereo1 ADC2 source", rt5677_stereo1_adc2_enum); | 1092 | SOC_DAPM_ENUM("Stereo1 ADC2 Source", rt5677_stereo1_adc2_enum); |
1106 | 1093 | ||
1107 | static SOC_ENUM_SINGLE_DECL( | 1094 | static SOC_ENUM_SINGLE_DECL( |
1108 | rt5677_stereo2_adc2_enum, RT5677_STO2_ADC_MIXER, | 1095 | rt5677_stereo2_adc2_enum, RT5677_STO2_ADC_MIXER, |
1109 | RT5677_SEL_STO2_ADC2_SFT, rt5677_stereo_adc2_src); | 1096 | RT5677_SEL_STO2_ADC2_SFT, rt5677_stereo_adc2_src); |
1110 | 1097 | ||
1111 | static const struct snd_kcontrol_new rt5677_sto2_adc2_mux = | 1098 | static const struct snd_kcontrol_new rt5677_sto2_adc2_mux = |
1112 | SOC_DAPM_ENUM("Stereo2 ADC2 source", rt5677_stereo2_adc2_enum); | 1099 | SOC_DAPM_ENUM("Stereo2 ADC2 Source", rt5677_stereo2_adc2_enum); |
1113 | 1100 | ||
1114 | static SOC_ENUM_SINGLE_DECL( | 1101 | static SOC_ENUM_SINGLE_DECL( |
1115 | rt5677_stereo3_adc2_enum, RT5677_STO3_ADC_MIXER, | 1102 | rt5677_stereo3_adc2_enum, RT5677_STO3_ADC_MIXER, |
1116 | RT5677_SEL_STO3_ADC2_SFT, rt5677_stereo_adc2_src); | 1103 | RT5677_SEL_STO3_ADC2_SFT, rt5677_stereo_adc2_src); |
1117 | 1104 | ||
1118 | static const struct snd_kcontrol_new rt5677_sto3_adc2_mux = | 1105 | static const struct snd_kcontrol_new rt5677_sto3_adc2_mux = |
1119 | SOC_DAPM_ENUM("Stereo3 ADC2 source", rt5677_stereo3_adc2_enum); | 1106 | SOC_DAPM_ENUM("Stereo3 ADC2 Source", rt5677_stereo3_adc2_enum); |
1120 | 1107 | ||
1121 | /* DMIC Source */ /* MX-28 [9:8][1:0] MX-27 MX-26 MX-25 MX-24 [9:8] */ | 1108 | /* DMIC Source */ /* MX-28 [9:8][1:0] MX-27 MX-26 MX-25 MX-24 [9:8] */ |
1122 | static const char * const rt5677_dmic_src[] = { | 1109 | static const char * const rt5677_dmic_src[] = { |
@@ -1128,44 +1115,44 @@ static SOC_ENUM_SINGLE_DECL( | |||
1128 | RT5677_SEL_MONO_DMIC_L_SFT, rt5677_dmic_src); | 1115 | RT5677_SEL_MONO_DMIC_L_SFT, rt5677_dmic_src); |
1129 | 1116 | ||
1130 | static const struct snd_kcontrol_new rt5677_mono_dmic_l_mux = | 1117 | static const struct snd_kcontrol_new rt5677_mono_dmic_l_mux = |
1131 | SOC_DAPM_ENUM("Mono DMIC L source", rt5677_mono_dmic_l_enum); | 1118 | SOC_DAPM_ENUM("Mono DMIC L Source", rt5677_mono_dmic_l_enum); |
1132 | 1119 | ||
1133 | static SOC_ENUM_SINGLE_DECL( | 1120 | static SOC_ENUM_SINGLE_DECL( |
1134 | rt5677_mono_dmic_r_enum, RT5677_MONO_ADC_MIXER, | 1121 | rt5677_mono_dmic_r_enum, RT5677_MONO_ADC_MIXER, |
1135 | RT5677_SEL_MONO_DMIC_R_SFT, rt5677_dmic_src); | 1122 | RT5677_SEL_MONO_DMIC_R_SFT, rt5677_dmic_src); |
1136 | 1123 | ||
1137 | static const struct snd_kcontrol_new rt5677_mono_dmic_r_mux = | 1124 | static const struct snd_kcontrol_new rt5677_mono_dmic_r_mux = |
1138 | SOC_DAPM_ENUM("Mono DMIC R source", rt5677_mono_dmic_r_enum); | 1125 | SOC_DAPM_ENUM("Mono DMIC R Source", rt5677_mono_dmic_r_enum); |
1139 | 1126 | ||
1140 | static SOC_ENUM_SINGLE_DECL( | 1127 | static SOC_ENUM_SINGLE_DECL( |
1141 | rt5677_stereo1_dmic_enum, RT5677_STO1_ADC_MIXER, | 1128 | rt5677_stereo1_dmic_enum, RT5677_STO1_ADC_MIXER, |
1142 | RT5677_SEL_STO1_DMIC_SFT, rt5677_dmic_src); | 1129 | RT5677_SEL_STO1_DMIC_SFT, rt5677_dmic_src); |
1143 | 1130 | ||
1144 | static const struct snd_kcontrol_new rt5677_sto1_dmic_mux = | 1131 | static const struct snd_kcontrol_new rt5677_sto1_dmic_mux = |
1145 | SOC_DAPM_ENUM("Stereo1 DMIC source", rt5677_stereo1_dmic_enum); | 1132 | SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5677_stereo1_dmic_enum); |
1146 | 1133 | ||
1147 | static SOC_ENUM_SINGLE_DECL( | 1134 | static SOC_ENUM_SINGLE_DECL( |
1148 | rt5677_stereo2_dmic_enum, RT5677_STO2_ADC_MIXER, | 1135 | rt5677_stereo2_dmic_enum, RT5677_STO2_ADC_MIXER, |
1149 | RT5677_SEL_STO2_DMIC_SFT, rt5677_dmic_src); | 1136 | RT5677_SEL_STO2_DMIC_SFT, rt5677_dmic_src); |
1150 | 1137 | ||
1151 | static const struct snd_kcontrol_new rt5677_sto2_dmic_mux = | 1138 | static const struct snd_kcontrol_new rt5677_sto2_dmic_mux = |
1152 | SOC_DAPM_ENUM("Stereo2 DMIC source", rt5677_stereo2_dmic_enum); | 1139 | SOC_DAPM_ENUM("Stereo2 DMIC Source", rt5677_stereo2_dmic_enum); |
1153 | 1140 | ||
1154 | static SOC_ENUM_SINGLE_DECL( | 1141 | static SOC_ENUM_SINGLE_DECL( |
1155 | rt5677_stereo3_dmic_enum, RT5677_STO3_ADC_MIXER, | 1142 | rt5677_stereo3_dmic_enum, RT5677_STO3_ADC_MIXER, |
1156 | RT5677_SEL_STO3_DMIC_SFT, rt5677_dmic_src); | 1143 | RT5677_SEL_STO3_DMIC_SFT, rt5677_dmic_src); |
1157 | 1144 | ||
1158 | static const struct snd_kcontrol_new rt5677_sto3_dmic_mux = | 1145 | static const struct snd_kcontrol_new rt5677_sto3_dmic_mux = |
1159 | SOC_DAPM_ENUM("Stereo3 DMIC source", rt5677_stereo3_dmic_enum); | 1146 | SOC_DAPM_ENUM("Stereo3 DMIC Source", rt5677_stereo3_dmic_enum); |
1160 | 1147 | ||
1161 | static SOC_ENUM_SINGLE_DECL( | 1148 | static SOC_ENUM_SINGLE_DECL( |
1162 | rt5677_stereo4_dmic_enum, RT5677_STO4_ADC_MIXER, | 1149 | rt5677_stereo4_dmic_enum, RT5677_STO4_ADC_MIXER, |
1163 | RT5677_SEL_STO4_DMIC_SFT, rt5677_dmic_src); | 1150 | RT5677_SEL_STO4_DMIC_SFT, rt5677_dmic_src); |
1164 | 1151 | ||
1165 | static const struct snd_kcontrol_new rt5677_sto4_dmic_mux = | 1152 | static const struct snd_kcontrol_new rt5677_sto4_dmic_mux = |
1166 | SOC_DAPM_ENUM("Stereo4 DMIC source", rt5677_stereo4_dmic_enum); | 1153 | SOC_DAPM_ENUM("Stereo4 DMIC Source", rt5677_stereo4_dmic_enum); |
1167 | 1154 | ||
1168 | /* Stereo2 ADC source */ /* MX-26 [0] */ | 1155 | /* Stereo2 ADC Source */ /* MX-26 [0] */ |
1169 | static const char * const rt5677_stereo2_adc_lr_src[] = { | 1156 | static const char * const rt5677_stereo2_adc_lr_src[] = { |
1170 | "L", "LR" | 1157 | "L", "LR" |
1171 | }; | 1158 | }; |
@@ -1175,7 +1162,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1175 | RT5677_SEL_STO2_LR_MIX_SFT, rt5677_stereo2_adc_lr_src); | 1162 | RT5677_SEL_STO2_LR_MIX_SFT, rt5677_stereo2_adc_lr_src); |
1176 | 1163 | ||
1177 | static const struct snd_kcontrol_new rt5677_sto2_adc_lr_mux = | 1164 | static const struct snd_kcontrol_new rt5677_sto2_adc_lr_mux = |
1178 | SOC_DAPM_ENUM("Stereo2 ADC LR source", rt5677_stereo2_adc_lr_enum); | 1165 | SOC_DAPM_ENUM("Stereo2 ADC LR Source", rt5677_stereo2_adc_lr_enum); |
1179 | 1166 | ||
1180 | /* Stereo1 ADC Source 1 */ /* MX-27 MX26 MX25 [13:12] */ | 1167 | /* Stereo1 ADC Source 1 */ /* MX-27 MX26 MX25 [13:12] */ |
1181 | static const char * const rt5677_stereo_adc1_src[] = { | 1168 | static const char * const rt5677_stereo_adc1_src[] = { |
@@ -1187,23 +1174,23 @@ static SOC_ENUM_SINGLE_DECL( | |||
1187 | RT5677_SEL_STO1_ADC1_SFT, rt5677_stereo_adc1_src); | 1174 | RT5677_SEL_STO1_ADC1_SFT, rt5677_stereo_adc1_src); |
1188 | 1175 | ||
1189 | static const struct snd_kcontrol_new rt5677_sto1_adc1_mux = | 1176 | static const struct snd_kcontrol_new rt5677_sto1_adc1_mux = |
1190 | SOC_DAPM_ENUM("Stereo1 ADC1 source", rt5677_stereo1_adc1_enum); | 1177 | SOC_DAPM_ENUM("Stereo1 ADC1 Source", rt5677_stereo1_adc1_enum); |
1191 | 1178 | ||
1192 | static SOC_ENUM_SINGLE_DECL( | 1179 | static SOC_ENUM_SINGLE_DECL( |
1193 | rt5677_stereo2_adc1_enum, RT5677_STO2_ADC_MIXER, | 1180 | rt5677_stereo2_adc1_enum, RT5677_STO2_ADC_MIXER, |
1194 | RT5677_SEL_STO2_ADC1_SFT, rt5677_stereo_adc1_src); | 1181 | RT5677_SEL_STO2_ADC1_SFT, rt5677_stereo_adc1_src); |
1195 | 1182 | ||
1196 | static const struct snd_kcontrol_new rt5677_sto2_adc1_mux = | 1183 | static const struct snd_kcontrol_new rt5677_sto2_adc1_mux = |
1197 | SOC_DAPM_ENUM("Stereo2 ADC1 source", rt5677_stereo2_adc1_enum); | 1184 | SOC_DAPM_ENUM("Stereo2 ADC1 Source", rt5677_stereo2_adc1_enum); |
1198 | 1185 | ||
1199 | static SOC_ENUM_SINGLE_DECL( | 1186 | static SOC_ENUM_SINGLE_DECL( |
1200 | rt5677_stereo3_adc1_enum, RT5677_STO3_ADC_MIXER, | 1187 | rt5677_stereo3_adc1_enum, RT5677_STO3_ADC_MIXER, |
1201 | RT5677_SEL_STO3_ADC1_SFT, rt5677_stereo_adc1_src); | 1188 | RT5677_SEL_STO3_ADC1_SFT, rt5677_stereo_adc1_src); |
1202 | 1189 | ||
1203 | static const struct snd_kcontrol_new rt5677_sto3_adc1_mux = | 1190 | static const struct snd_kcontrol_new rt5677_sto3_adc1_mux = |
1204 | SOC_DAPM_ENUM("Stereo3 ADC1 source", rt5677_stereo3_adc1_enum); | 1191 | SOC_DAPM_ENUM("Stereo3 ADC1 Source", rt5677_stereo3_adc1_enum); |
1205 | 1192 | ||
1206 | /* Mono ADC Left source 2 */ /* MX-28 [11:10] */ | 1193 | /* Mono ADC Left Source 2 */ /* MX-28 [11:10] */ |
1207 | static const char * const rt5677_mono_adc2_l_src[] = { | 1194 | static const char * const rt5677_mono_adc2_l_src[] = { |
1208 | "DD MIX1L", "DMIC", "MONO DAC MIXL" | 1195 | "DD MIX1L", "DMIC", "MONO DAC MIXL" |
1209 | }; | 1196 | }; |
@@ -1213,9 +1200,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
1213 | RT5677_SEL_MONO_ADC_L2_SFT, rt5677_mono_adc2_l_src); | 1200 | RT5677_SEL_MONO_ADC_L2_SFT, rt5677_mono_adc2_l_src); |
1214 | 1201 | ||
1215 | static const struct snd_kcontrol_new rt5677_mono_adc2_l_mux = | 1202 | static const struct snd_kcontrol_new rt5677_mono_adc2_l_mux = |
1216 | SOC_DAPM_ENUM("Mono ADC2 L source", rt5677_mono_adc2_l_enum); | 1203 | SOC_DAPM_ENUM("Mono ADC2 L Source", rt5677_mono_adc2_l_enum); |
1217 | 1204 | ||
1218 | /* Mono ADC Left source 1 */ /* MX-28 [13:12] */ | 1205 | /* Mono ADC Left Source 1 */ /* MX-28 [13:12] */ |
1219 | static const char * const rt5677_mono_adc1_l_src[] = { | 1206 | static const char * const rt5677_mono_adc1_l_src[] = { |
1220 | "DD MIX1L", "ADC1", "MONO DAC MIXL" | 1207 | "DD MIX1L", "ADC1", "MONO DAC MIXL" |
1221 | }; | 1208 | }; |
@@ -1225,9 +1212,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
1225 | RT5677_SEL_MONO_ADC_L1_SFT, rt5677_mono_adc1_l_src); | 1212 | RT5677_SEL_MONO_ADC_L1_SFT, rt5677_mono_adc1_l_src); |
1226 | 1213 | ||
1227 | static const struct snd_kcontrol_new rt5677_mono_adc1_l_mux = | 1214 | static const struct snd_kcontrol_new rt5677_mono_adc1_l_mux = |
1228 | SOC_DAPM_ENUM("Mono ADC1 L source", rt5677_mono_adc1_l_enum); | 1215 | SOC_DAPM_ENUM("Mono ADC1 L Source", rt5677_mono_adc1_l_enum); |
1229 | 1216 | ||
1230 | /* Mono ADC Right source 2 */ /* MX-28 [3:2] */ | 1217 | /* Mono ADC Right Source 2 */ /* MX-28 [3:2] */ |
1231 | static const char * const rt5677_mono_adc2_r_src[] = { | 1218 | static const char * const rt5677_mono_adc2_r_src[] = { |
1232 | "DD MIX1R", "DMIC", "MONO DAC MIXR" | 1219 | "DD MIX1R", "DMIC", "MONO DAC MIXR" |
1233 | }; | 1220 | }; |
@@ -1237,9 +1224,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
1237 | RT5677_SEL_MONO_ADC_R2_SFT, rt5677_mono_adc2_r_src); | 1224 | RT5677_SEL_MONO_ADC_R2_SFT, rt5677_mono_adc2_r_src); |
1238 | 1225 | ||
1239 | static const struct snd_kcontrol_new rt5677_mono_adc2_r_mux = | 1226 | static const struct snd_kcontrol_new rt5677_mono_adc2_r_mux = |
1240 | SOC_DAPM_ENUM("Mono ADC2 R source", rt5677_mono_adc2_r_enum); | 1227 | SOC_DAPM_ENUM("Mono ADC2 R Source", rt5677_mono_adc2_r_enum); |
1241 | 1228 | ||
1242 | /* Mono ADC Right source 1 */ /* MX-28 [5:4] */ | 1229 | /* Mono ADC Right Source 1 */ /* MX-28 [5:4] */ |
1243 | static const char * const rt5677_mono_adc1_r_src[] = { | 1230 | static const char * const rt5677_mono_adc1_r_src[] = { |
1244 | "DD MIX1R", "ADC2", "MONO DAC MIXR" | 1231 | "DD MIX1R", "ADC2", "MONO DAC MIXR" |
1245 | }; | 1232 | }; |
@@ -1249,7 +1236,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1249 | RT5677_SEL_MONO_ADC_R1_SFT, rt5677_mono_adc1_r_src); | 1236 | RT5677_SEL_MONO_ADC_R1_SFT, rt5677_mono_adc1_r_src); |
1250 | 1237 | ||
1251 | static const struct snd_kcontrol_new rt5677_mono_adc1_r_mux = | 1238 | static const struct snd_kcontrol_new rt5677_mono_adc1_r_mux = |
1252 | SOC_DAPM_ENUM("Mono ADC1 R source", rt5677_mono_adc1_r_enum); | 1239 | SOC_DAPM_ENUM("Mono ADC1 R Source", rt5677_mono_adc1_r_enum); |
1253 | 1240 | ||
1254 | /* Stereo4 ADC Source 2 */ /* MX-24 [11:10] */ | 1241 | /* Stereo4 ADC Source 2 */ /* MX-24 [11:10] */ |
1255 | static const char * const rt5677_stereo4_adc2_src[] = { | 1242 | static const char * const rt5677_stereo4_adc2_src[] = { |
@@ -1261,7 +1248,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1261 | RT5677_SEL_STO4_ADC2_SFT, rt5677_stereo4_adc2_src); | 1248 | RT5677_SEL_STO4_ADC2_SFT, rt5677_stereo4_adc2_src); |
1262 | 1249 | ||
1263 | static const struct snd_kcontrol_new rt5677_sto4_adc2_mux = | 1250 | static const struct snd_kcontrol_new rt5677_sto4_adc2_mux = |
1264 | SOC_DAPM_ENUM("Stereo4 ADC2 source", rt5677_stereo4_adc2_enum); | 1251 | SOC_DAPM_ENUM("Stereo4 ADC2 Source", rt5677_stereo4_adc2_enum); |
1265 | 1252 | ||
1266 | 1253 | ||
1267 | /* Stereo4 ADC Source 1 */ /* MX-24 [13:12] */ | 1254 | /* Stereo4 ADC Source 1 */ /* MX-24 [13:12] */ |
@@ -1274,7 +1261,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1274 | RT5677_SEL_STO4_ADC1_SFT, rt5677_stereo4_adc1_src); | 1261 | RT5677_SEL_STO4_ADC1_SFT, rt5677_stereo4_adc1_src); |
1275 | 1262 | ||
1276 | static const struct snd_kcontrol_new rt5677_sto4_adc1_mux = | 1263 | static const struct snd_kcontrol_new rt5677_sto4_adc1_mux = |
1277 | SOC_DAPM_ENUM("Stereo4 ADC1 source", rt5677_stereo4_adc1_enum); | 1264 | SOC_DAPM_ENUM("Stereo4 ADC1 Source", rt5677_stereo4_adc1_enum); |
1278 | 1265 | ||
1279 | /* InBound0/1 Source */ /* MX-A3 [14:12] */ | 1266 | /* InBound0/1 Source */ /* MX-A3 [14:12] */ |
1280 | static const char * const rt5677_inbound01_src[] = { | 1267 | static const char * const rt5677_inbound01_src[] = { |
@@ -1416,7 +1403,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1416 | static const struct snd_kcontrol_new rt5677_dac3_mux = | 1403 | static const struct snd_kcontrol_new rt5677_dac3_mux = |
1417 | SOC_DAPM_ENUM("Analog DAC3 Source", rt5677_dac3_enum); | 1404 | SOC_DAPM_ENUM("Analog DAC3 Source", rt5677_dac3_enum); |
1418 | 1405 | ||
1419 | /* PDM channel source */ /* MX-31 [13:12][9:8][5:4][1:0] */ | 1406 | /* PDM channel Source */ /* MX-31 [13:12][9:8][5:4][1:0] */ |
1420 | static const char * const rt5677_pdm_src[] = { | 1407 | static const char * const rt5677_pdm_src[] = { |
1421 | "STO1 DAC MIX", "MONO DAC MIX", "DD MIX1", "DD MIX2" | 1408 | "STO1 DAC MIX", "MONO DAC MIX", "DD MIX1", "DD MIX2" |
1422 | }; | 1409 | }; |
@@ -1426,28 +1413,28 @@ static SOC_ENUM_SINGLE_DECL( | |||
1426 | RT5677_SEL_PDM1_L_SFT, rt5677_pdm_src); | 1413 | RT5677_SEL_PDM1_L_SFT, rt5677_pdm_src); |
1427 | 1414 | ||
1428 | static const struct snd_kcontrol_new rt5677_pdm1_l_mux = | 1415 | static const struct snd_kcontrol_new rt5677_pdm1_l_mux = |
1429 | SOC_DAPM_ENUM("PDM1 source", rt5677_pdm1_l_enum); | 1416 | SOC_DAPM_ENUM("PDM1 Source", rt5677_pdm1_l_enum); |
1430 | 1417 | ||
1431 | static SOC_ENUM_SINGLE_DECL( | 1418 | static SOC_ENUM_SINGLE_DECL( |
1432 | rt5677_pdm2_l_enum, RT5677_PDM_OUT_CTRL, | 1419 | rt5677_pdm2_l_enum, RT5677_PDM_OUT_CTRL, |
1433 | RT5677_SEL_PDM2_L_SFT, rt5677_pdm_src); | 1420 | RT5677_SEL_PDM2_L_SFT, rt5677_pdm_src); |
1434 | 1421 | ||
1435 | static const struct snd_kcontrol_new rt5677_pdm2_l_mux = | 1422 | static const struct snd_kcontrol_new rt5677_pdm2_l_mux = |
1436 | SOC_DAPM_ENUM("PDM2 source", rt5677_pdm2_l_enum); | 1423 | SOC_DAPM_ENUM("PDM2 Source", rt5677_pdm2_l_enum); |
1437 | 1424 | ||
1438 | static SOC_ENUM_SINGLE_DECL( | 1425 | static SOC_ENUM_SINGLE_DECL( |
1439 | rt5677_pdm1_r_enum, RT5677_PDM_OUT_CTRL, | 1426 | rt5677_pdm1_r_enum, RT5677_PDM_OUT_CTRL, |
1440 | RT5677_SEL_PDM1_R_SFT, rt5677_pdm_src); | 1427 | RT5677_SEL_PDM1_R_SFT, rt5677_pdm_src); |
1441 | 1428 | ||
1442 | static const struct snd_kcontrol_new rt5677_pdm1_r_mux = | 1429 | static const struct snd_kcontrol_new rt5677_pdm1_r_mux = |
1443 | SOC_DAPM_ENUM("PDM1 source", rt5677_pdm1_r_enum); | 1430 | SOC_DAPM_ENUM("PDM1 Source", rt5677_pdm1_r_enum); |
1444 | 1431 | ||
1445 | static SOC_ENUM_SINGLE_DECL( | 1432 | static SOC_ENUM_SINGLE_DECL( |
1446 | rt5677_pdm2_r_enum, RT5677_PDM_OUT_CTRL, | 1433 | rt5677_pdm2_r_enum, RT5677_PDM_OUT_CTRL, |
1447 | RT5677_SEL_PDM2_R_SFT, rt5677_pdm_src); | 1434 | RT5677_SEL_PDM2_R_SFT, rt5677_pdm_src); |
1448 | 1435 | ||
1449 | static const struct snd_kcontrol_new rt5677_pdm2_r_mux = | 1436 | static const struct snd_kcontrol_new rt5677_pdm2_r_mux = |
1450 | SOC_DAPM_ENUM("PDM2 source", rt5677_pdm2_r_enum); | 1437 | SOC_DAPM_ENUM("PDM2 Source", rt5677_pdm2_r_enum); |
1451 | 1438 | ||
1452 | /* TDM IF1/2 SLB ADC1 Data Selection */ /* MX-3C MX-41 [5:4] MX-08 [1:0]*/ | 1439 | /* TDM IF1/2 SLB ADC1 Data Selection */ /* MX-3C MX-41 [5:4] MX-08 [1:0]*/ |
1453 | static const char * const rt5677_if12_adc1_src[] = { | 1440 | static const char * const rt5677_if12_adc1_src[] = { |
@@ -1459,21 +1446,21 @@ static SOC_ENUM_SINGLE_DECL( | |||
1459 | RT5677_IF1_ADC1_SFT, rt5677_if12_adc1_src); | 1446 | RT5677_IF1_ADC1_SFT, rt5677_if12_adc1_src); |
1460 | 1447 | ||
1461 | static const struct snd_kcontrol_new rt5677_if1_adc1_mux = | 1448 | static const struct snd_kcontrol_new rt5677_if1_adc1_mux = |
1462 | SOC_DAPM_ENUM("IF1 ADC1 source", rt5677_if1_adc1_enum); | 1449 | SOC_DAPM_ENUM("IF1 ADC1 Source", rt5677_if1_adc1_enum); |
1463 | 1450 | ||
1464 | static SOC_ENUM_SINGLE_DECL( | 1451 | static SOC_ENUM_SINGLE_DECL( |
1465 | rt5677_if2_adc1_enum, RT5677_TDM2_CTRL2, | 1452 | rt5677_if2_adc1_enum, RT5677_TDM2_CTRL2, |
1466 | RT5677_IF2_ADC1_SFT, rt5677_if12_adc1_src); | 1453 | RT5677_IF2_ADC1_SFT, rt5677_if12_adc1_src); |
1467 | 1454 | ||
1468 | static const struct snd_kcontrol_new rt5677_if2_adc1_mux = | 1455 | static const struct snd_kcontrol_new rt5677_if2_adc1_mux = |
1469 | SOC_DAPM_ENUM("IF2 ADC1 source", rt5677_if2_adc1_enum); | 1456 | SOC_DAPM_ENUM("IF2 ADC1 Source", rt5677_if2_adc1_enum); |
1470 | 1457 | ||
1471 | static SOC_ENUM_SINGLE_DECL( | 1458 | static SOC_ENUM_SINGLE_DECL( |
1472 | rt5677_slb_adc1_enum, RT5677_SLIMBUS_RX, | 1459 | rt5677_slb_adc1_enum, RT5677_SLIMBUS_RX, |
1473 | RT5677_SLB_ADC1_SFT, rt5677_if12_adc1_src); | 1460 | RT5677_SLB_ADC1_SFT, rt5677_if12_adc1_src); |
1474 | 1461 | ||
1475 | static const struct snd_kcontrol_new rt5677_slb_adc1_mux = | 1462 | static const struct snd_kcontrol_new rt5677_slb_adc1_mux = |
1476 | SOC_DAPM_ENUM("SLB ADC1 source", rt5677_slb_adc1_enum); | 1463 | SOC_DAPM_ENUM("SLB ADC1 Source", rt5677_slb_adc1_enum); |
1477 | 1464 | ||
1478 | /* TDM IF1/2 SLB ADC2 Data Selection */ /* MX-3C MX-41 [7:6] MX-08 [3:2] */ | 1465 | /* TDM IF1/2 SLB ADC2 Data Selection */ /* MX-3C MX-41 [7:6] MX-08 [3:2] */ |
1479 | static const char * const rt5677_if12_adc2_src[] = { | 1466 | static const char * const rt5677_if12_adc2_src[] = { |
@@ -1485,21 +1472,21 @@ static SOC_ENUM_SINGLE_DECL( | |||
1485 | RT5677_IF1_ADC2_SFT, rt5677_if12_adc2_src); | 1472 | RT5677_IF1_ADC2_SFT, rt5677_if12_adc2_src); |
1486 | 1473 | ||
1487 | static const struct snd_kcontrol_new rt5677_if1_adc2_mux = | 1474 | static const struct snd_kcontrol_new rt5677_if1_adc2_mux = |
1488 | SOC_DAPM_ENUM("IF1 ADC2 source", rt5677_if1_adc2_enum); | 1475 | SOC_DAPM_ENUM("IF1 ADC2 Source", rt5677_if1_adc2_enum); |
1489 | 1476 | ||
1490 | static SOC_ENUM_SINGLE_DECL( | 1477 | static SOC_ENUM_SINGLE_DECL( |
1491 | rt5677_if2_adc2_enum, RT5677_TDM2_CTRL2, | 1478 | rt5677_if2_adc2_enum, RT5677_TDM2_CTRL2, |
1492 | RT5677_IF2_ADC2_SFT, rt5677_if12_adc2_src); | 1479 | RT5677_IF2_ADC2_SFT, rt5677_if12_adc2_src); |
1493 | 1480 | ||
1494 | static const struct snd_kcontrol_new rt5677_if2_adc2_mux = | 1481 | static const struct snd_kcontrol_new rt5677_if2_adc2_mux = |
1495 | SOC_DAPM_ENUM("IF2 ADC2 source", rt5677_if2_adc2_enum); | 1482 | SOC_DAPM_ENUM("IF2 ADC2 Source", rt5677_if2_adc2_enum); |
1496 | 1483 | ||
1497 | static SOC_ENUM_SINGLE_DECL( | 1484 | static SOC_ENUM_SINGLE_DECL( |
1498 | rt5677_slb_adc2_enum, RT5677_SLIMBUS_RX, | 1485 | rt5677_slb_adc2_enum, RT5677_SLIMBUS_RX, |
1499 | RT5677_SLB_ADC2_SFT, rt5677_if12_adc2_src); | 1486 | RT5677_SLB_ADC2_SFT, rt5677_if12_adc2_src); |
1500 | 1487 | ||
1501 | static const struct snd_kcontrol_new rt5677_slb_adc2_mux = | 1488 | static const struct snd_kcontrol_new rt5677_slb_adc2_mux = |
1502 | SOC_DAPM_ENUM("SLB ADC2 source", rt5677_slb_adc2_enum); | 1489 | SOC_DAPM_ENUM("SLB ADC2 Source", rt5677_slb_adc2_enum); |
1503 | 1490 | ||
1504 | /* TDM IF1/2 SLB ADC3 Data Selection */ /* MX-3C MX-41 [9:8] MX-08 [5:4] */ | 1491 | /* TDM IF1/2 SLB ADC3 Data Selection */ /* MX-3C MX-41 [9:8] MX-08 [5:4] */ |
1505 | static const char * const rt5677_if12_adc3_src[] = { | 1492 | static const char * const rt5677_if12_adc3_src[] = { |
@@ -1511,21 +1498,21 @@ static SOC_ENUM_SINGLE_DECL( | |||
1511 | RT5677_IF1_ADC3_SFT, rt5677_if12_adc3_src); | 1498 | RT5677_IF1_ADC3_SFT, rt5677_if12_adc3_src); |
1512 | 1499 | ||
1513 | static const struct snd_kcontrol_new rt5677_if1_adc3_mux = | 1500 | static const struct snd_kcontrol_new rt5677_if1_adc3_mux = |
1514 | SOC_DAPM_ENUM("IF1 ADC3 source", rt5677_if1_adc3_enum); | 1501 | SOC_DAPM_ENUM("IF1 ADC3 Source", rt5677_if1_adc3_enum); |
1515 | 1502 | ||
1516 | static SOC_ENUM_SINGLE_DECL( | 1503 | static SOC_ENUM_SINGLE_DECL( |
1517 | rt5677_if2_adc3_enum, RT5677_TDM2_CTRL2, | 1504 | rt5677_if2_adc3_enum, RT5677_TDM2_CTRL2, |
1518 | RT5677_IF2_ADC3_SFT, rt5677_if12_adc3_src); | 1505 | RT5677_IF2_ADC3_SFT, rt5677_if12_adc3_src); |
1519 | 1506 | ||
1520 | static const struct snd_kcontrol_new rt5677_if2_adc3_mux = | 1507 | static const struct snd_kcontrol_new rt5677_if2_adc3_mux = |
1521 | SOC_DAPM_ENUM("IF2 ADC3 source", rt5677_if2_adc3_enum); | 1508 | SOC_DAPM_ENUM("IF2 ADC3 Source", rt5677_if2_adc3_enum); |
1522 | 1509 | ||
1523 | static SOC_ENUM_SINGLE_DECL( | 1510 | static SOC_ENUM_SINGLE_DECL( |
1524 | rt5677_slb_adc3_enum, RT5677_SLIMBUS_RX, | 1511 | rt5677_slb_adc3_enum, RT5677_SLIMBUS_RX, |
1525 | RT5677_SLB_ADC3_SFT, rt5677_if12_adc3_src); | 1512 | RT5677_SLB_ADC3_SFT, rt5677_if12_adc3_src); |
1526 | 1513 | ||
1527 | static const struct snd_kcontrol_new rt5677_slb_adc3_mux = | 1514 | static const struct snd_kcontrol_new rt5677_slb_adc3_mux = |
1528 | SOC_DAPM_ENUM("SLB ADC3 source", rt5677_slb_adc3_enum); | 1515 | SOC_DAPM_ENUM("SLB ADC3 Source", rt5677_slb_adc3_enum); |
1529 | 1516 | ||
1530 | /* TDM IF1/2 SLB ADC4 Data Selection */ /* MX-3C MX-41 [11:10] MX-08 [7:6] */ | 1517 | /* TDM IF1/2 SLB ADC4 Data Selection */ /* MX-3C MX-41 [11:10] MX-08 [7:6] */ |
1531 | static const char * const rt5677_if12_adc4_src[] = { | 1518 | static const char * const rt5677_if12_adc4_src[] = { |
@@ -1537,21 +1524,21 @@ static SOC_ENUM_SINGLE_DECL( | |||
1537 | RT5677_IF1_ADC4_SFT, rt5677_if12_adc4_src); | 1524 | RT5677_IF1_ADC4_SFT, rt5677_if12_adc4_src); |
1538 | 1525 | ||
1539 | static const struct snd_kcontrol_new rt5677_if1_adc4_mux = | 1526 | static const struct snd_kcontrol_new rt5677_if1_adc4_mux = |
1540 | SOC_DAPM_ENUM("IF1 ADC4 source", rt5677_if1_adc4_enum); | 1527 | SOC_DAPM_ENUM("IF1 ADC4 Source", rt5677_if1_adc4_enum); |
1541 | 1528 | ||
1542 | static SOC_ENUM_SINGLE_DECL( | 1529 | static SOC_ENUM_SINGLE_DECL( |
1543 | rt5677_if2_adc4_enum, RT5677_TDM2_CTRL2, | 1530 | rt5677_if2_adc4_enum, RT5677_TDM2_CTRL2, |
1544 | RT5677_IF2_ADC4_SFT, rt5677_if12_adc4_src); | 1531 | RT5677_IF2_ADC4_SFT, rt5677_if12_adc4_src); |
1545 | 1532 | ||
1546 | static const struct snd_kcontrol_new rt5677_if2_adc4_mux = | 1533 | static const struct snd_kcontrol_new rt5677_if2_adc4_mux = |
1547 | SOC_DAPM_ENUM("IF2 ADC4 source", rt5677_if2_adc4_enum); | 1534 | SOC_DAPM_ENUM("IF2 ADC4 Source", rt5677_if2_adc4_enum); |
1548 | 1535 | ||
1549 | static SOC_ENUM_SINGLE_DECL( | 1536 | static SOC_ENUM_SINGLE_DECL( |
1550 | rt5677_slb_adc4_enum, RT5677_SLIMBUS_RX, | 1537 | rt5677_slb_adc4_enum, RT5677_SLIMBUS_RX, |
1551 | RT5677_SLB_ADC4_SFT, rt5677_if12_adc4_src); | 1538 | RT5677_SLB_ADC4_SFT, rt5677_if12_adc4_src); |
1552 | 1539 | ||
1553 | static const struct snd_kcontrol_new rt5677_slb_adc4_mux = | 1540 | static const struct snd_kcontrol_new rt5677_slb_adc4_mux = |
1554 | SOC_DAPM_ENUM("SLB ADC4 source", rt5677_slb_adc4_enum); | 1541 | SOC_DAPM_ENUM("SLB ADC4 Source", rt5677_slb_adc4_enum); |
1555 | 1542 | ||
1556 | /* Interface3/4 ADC Data Input */ /* MX-2F [3:0] MX-30 [7:4]*/ | 1543 | /* Interface3/4 ADC Data Input */ /* MX-2F [3:0] MX-30 [7:4]*/ |
1557 | static const char * const rt5677_if34_adc_src[] = { | 1544 | static const char * const rt5677_if34_adc_src[] = { |
@@ -1564,14 +1551,14 @@ static SOC_ENUM_SINGLE_DECL( | |||
1564 | RT5677_IF3_ADC_IN_SFT, rt5677_if34_adc_src); | 1551 | RT5677_IF3_ADC_IN_SFT, rt5677_if34_adc_src); |
1565 | 1552 | ||
1566 | static const struct snd_kcontrol_new rt5677_if3_adc_mux = | 1553 | static const struct snd_kcontrol_new rt5677_if3_adc_mux = |
1567 | SOC_DAPM_ENUM("IF3 ADC source", rt5677_if3_adc_enum); | 1554 | SOC_DAPM_ENUM("IF3 ADC Source", rt5677_if3_adc_enum); |
1568 | 1555 | ||
1569 | static SOC_ENUM_SINGLE_DECL( | 1556 | static SOC_ENUM_SINGLE_DECL( |
1570 | rt5677_if4_adc_enum, RT5677_IF4_DATA, | 1557 | rt5677_if4_adc_enum, RT5677_IF4_DATA, |
1571 | RT5677_IF4_ADC_IN_SFT, rt5677_if34_adc_src); | 1558 | RT5677_IF4_ADC_IN_SFT, rt5677_if34_adc_src); |
1572 | 1559 | ||
1573 | static const struct snd_kcontrol_new rt5677_if4_adc_mux = | 1560 | static const struct snd_kcontrol_new rt5677_if4_adc_mux = |
1574 | SOC_DAPM_ENUM("IF4 ADC source", rt5677_if4_adc_enum); | 1561 | SOC_DAPM_ENUM("IF4 ADC Source", rt5677_if4_adc_enum); |
1575 | 1562 | ||
1576 | static int rt5677_bst1_event(struct snd_soc_dapm_widget *w, | 1563 | static int rt5677_bst1_event(struct snd_soc_dapm_widget *w, |
1577 | struct snd_kcontrol *kcontrol, int event) | 1564 | struct snd_kcontrol *kcontrol, int event) |
@@ -1670,6 +1657,13 @@ static int rt5677_set_micbias1_event(struct snd_soc_dapm_widget *w, | |||
1670 | RT5677_PWR_CLK_MB, RT5677_PWR_CLK_MB1 | | 1657 | RT5677_PWR_CLK_MB, RT5677_PWR_CLK_MB1 | |
1671 | RT5677_PWR_PP_MB1 | RT5677_PWR_CLK_MB); | 1658 | RT5677_PWR_PP_MB1 | RT5677_PWR_CLK_MB); |
1672 | break; | 1659 | break; |
1660 | |||
1661 | case SND_SOC_DAPM_PRE_PMD: | ||
1662 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2, | ||
1663 | RT5677_PWR_CLK_MB1 | RT5677_PWR_PP_MB1 | | ||
1664 | RT5677_PWR_CLK_MB, 0); | ||
1665 | break; | ||
1666 | |||
1673 | default: | 1667 | default: |
1674 | return 0; | 1668 | return 0; |
1675 | } | 1669 | } |
@@ -1685,8 +1679,9 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
1685 | 1679 | ||
1686 | /* Input Side */ | 1680 | /* Input Side */ |
1687 | /* micbias */ | 1681 | /* micbias */ |
1688 | SND_SOC_DAPM_SUPPLY("micbias1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT, | 1682 | SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT, |
1689 | 0, rt5677_set_micbias1_event, SND_SOC_DAPM_POST_PMU), | 1683 | 0, rt5677_set_micbias1_event, SND_SOC_DAPM_PRE_PMD | |
1684 | SND_SOC_DAPM_POST_PMU), | ||
1690 | 1685 | ||
1691 | /* Input Lines */ | 1686 | /* Input Lines */ |
1692 | SND_SOC_DAPM_INPUT("DMIC L1"), | 1687 | SND_SOC_DAPM_INPUT("DMIC L1"), |
@@ -2798,21 +2793,6 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2798 | { "PDM2R", NULL, "PDM2 R Mux" }, | 2793 | { "PDM2R", NULL, "PDM2 R Mux" }, |
2799 | }; | 2794 | }; |
2800 | 2795 | ||
2801 | static int get_clk_info(int sclk, int rate) | ||
2802 | { | ||
2803 | int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; | ||
2804 | |||
2805 | if (sclk <= 0 || rate <= 0) | ||
2806 | return -EINVAL; | ||
2807 | |||
2808 | rate = rate << 8; | ||
2809 | for (i = 0; i < ARRAY_SIZE(pd); i++) | ||
2810 | if (sclk == rate * pd[i]) | ||
2811 | return i; | ||
2812 | |||
2813 | return -EINVAL; | ||
2814 | } | ||
2815 | |||
2816 | static int rt5677_hw_params(struct snd_pcm_substream *substream, | 2796 | static int rt5677_hw_params(struct snd_pcm_substream *substream, |
2817 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 2797 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
2818 | { | 2798 | { |
@@ -2822,7 +2802,7 @@ static int rt5677_hw_params(struct snd_pcm_substream *substream, | |||
2822 | int pre_div, bclk_ms, frame_size; | 2802 | int pre_div, bclk_ms, frame_size; |
2823 | 2803 | ||
2824 | rt5677->lrck[dai->id] = params_rate(params); | 2804 | rt5677->lrck[dai->id] = params_rate(params); |
2825 | pre_div = get_clk_info(rt5677->sysclk, rt5677->lrck[dai->id]); | 2805 | pre_div = rl6231_get_clk_info(rt5677->sysclk, rt5677->lrck[dai->id]); |
2826 | if (pre_div < 0) { | 2806 | if (pre_div < 0) { |
2827 | dev_err(codec->dev, "Unsupported clock setting\n"); | 2807 | dev_err(codec->dev, "Unsupported clock setting\n"); |
2828 | return -EINVAL; | 2808 | return -EINVAL; |
@@ -3016,62 +2996,12 @@ static int rt5677_set_dai_sysclk(struct snd_soc_dai *dai, | |||
3016 | * Returns 0 for success or negative error code. | 2996 | * Returns 0 for success or negative error code. |
3017 | */ | 2997 | */ |
3018 | static int rt5677_pll_calc(const unsigned int freq_in, | 2998 | static int rt5677_pll_calc(const unsigned int freq_in, |
3019 | const unsigned int freq_out, struct rt5677_pll_code *pll_code) | 2999 | const unsigned int freq_out, struct rl6231_pll_code *pll_code) |
3020 | { | 3000 | { |
3021 | int max_n = RT5677_PLL_N_MAX, max_m = RT5677_PLL_M_MAX; | 3001 | if (RT5677_PLL_INP_MIN > freq_in) |
3022 | int k, red, n_t, pll_out, in_t; | ||
3023 | int n = 0, m = 0, m_t = 0; | ||
3024 | int out_t, red_t = abs(freq_out - freq_in); | ||
3025 | bool m_bp = false, k_bp = false; | ||
3026 | |||
3027 | if (RT5677_PLL_INP_MAX < freq_in || RT5677_PLL_INP_MIN > freq_in) | ||
3028 | return -EINVAL; | 3002 | return -EINVAL; |
3029 | 3003 | ||
3030 | k = 100000000 / freq_out - 2; | 3004 | return rl6231_pll_calc(freq_in, freq_out, pll_code); |
3031 | if (k > RT5677_PLL_K_MAX) | ||
3032 | k = RT5677_PLL_K_MAX; | ||
3033 | for (n_t = 0; n_t <= max_n; n_t++) { | ||
3034 | in_t = freq_in / (k + 2); | ||
3035 | pll_out = freq_out / (n_t + 2); | ||
3036 | if (in_t < 0) | ||
3037 | continue; | ||
3038 | if (in_t == pll_out) { | ||
3039 | m_bp = true; | ||
3040 | n = n_t; | ||
3041 | goto code_find; | ||
3042 | } | ||
3043 | red = abs(in_t - pll_out); | ||
3044 | if (red < red_t) { | ||
3045 | m_bp = true; | ||
3046 | n = n_t; | ||
3047 | m = m_t; | ||
3048 | if (red == 0) | ||
3049 | goto code_find; | ||
3050 | red_t = red; | ||
3051 | } | ||
3052 | for (m_t = 0; m_t <= max_m; m_t++) { | ||
3053 | out_t = in_t / (m_t + 2); | ||
3054 | red = abs(out_t - pll_out); | ||
3055 | if (red < red_t) { | ||
3056 | m_bp = false; | ||
3057 | n = n_t; | ||
3058 | m = m_t; | ||
3059 | if (red == 0) | ||
3060 | goto code_find; | ||
3061 | red_t = red; | ||
3062 | } | ||
3063 | } | ||
3064 | } | ||
3065 | pr_debug("Only get approximation about PLL\n"); | ||
3066 | |||
3067 | code_find: | ||
3068 | |||
3069 | pll_code->m_bp = m_bp; | ||
3070 | pll_code->k_bp = k_bp; | ||
3071 | pll_code->m_code = m; | ||
3072 | pll_code->n_code = n; | ||
3073 | pll_code->k_code = k; | ||
3074 | return 0; | ||
3075 | } | 3005 | } |
3076 | 3006 | ||
3077 | static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | 3007 | static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, |
@@ -3079,7 +3009,7 @@ static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | |||
3079 | { | 3009 | { |
3080 | struct snd_soc_codec *codec = dai->codec; | 3010 | struct snd_soc_codec *codec = dai->codec; |
3081 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 3011 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
3082 | struct rt5677_pll_code pll_code; | 3012 | struct rl6231_pll_code pll_code; |
3083 | int ret; | 3013 | int ret; |
3084 | 3014 | ||
3085 | if (source == rt5677->pll_src && freq_in == rt5677->pll_in && | 3015 | if (source == rt5677->pll_src && freq_in == rt5677->pll_in && |
@@ -3137,15 +3067,12 @@ static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | |||
3137 | return ret; | 3067 | return ret; |
3138 | } | 3068 | } |
3139 | 3069 | ||
3140 | dev_dbg(codec->dev, "m_bypass=%d k_bypass=%d m=%d n=%d k=%d\n", | 3070 | dev_dbg(codec->dev, "m_bypass=%d m=%d n=%d k=%d\n", |
3141 | pll_code.m_bp, pll_code.k_bp, | 3071 | pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), |
3142 | (pll_code.m_bp ? 0 : pll_code.m_code), pll_code.n_code, | 3072 | pll_code.n_code, pll_code.k_code); |
3143 | (pll_code.k_bp ? 0 : pll_code.k_code)); | ||
3144 | 3073 | ||
3145 | regmap_write(rt5677->regmap, RT5677_PLL1_CTRL1, | 3074 | regmap_write(rt5677->regmap, RT5677_PLL1_CTRL1, |
3146 | pll_code.n_code << RT5677_PLL_N_SFT | | 3075 | pll_code.n_code << RT5677_PLL_N_SFT | pll_code.k_code); |
3147 | pll_code.k_bp << RT5677_PLL_K_BP_SFT | | ||
3148 | (pll_code.k_bp ? 0 : pll_code.k_code)); | ||
3149 | regmap_write(rt5677->regmap, RT5677_PLL1_CTRL2, | 3076 | regmap_write(rt5677->regmap, RT5677_PLL1_CTRL2, |
3150 | (pll_code.m_bp ? 0 : pll_code.m_code) << RT5677_PLL_M_SFT | | 3077 | (pll_code.m_bp ? 0 : pll_code.m_code) << RT5677_PLL_M_SFT | |
3151 | pll_code.m_bp << RT5677_PLL_M_BP_SFT); | 3078 | pll_code.m_bp << RT5677_PLL_M_BP_SFT); |
@@ -3197,7 +3124,7 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec, | |||
3197 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0); | 3124 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0); |
3198 | regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000); | 3125 | regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000); |
3199 | regmap_write(rt5677->regmap, RT5677_PWR_DIG2, 0x0000); | 3126 | regmap_write(rt5677->regmap, RT5677_PWR_DIG2, 0x0000); |
3200 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0000); | 3127 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0022); |
3201 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000); | 3128 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000); |
3202 | regmap_update_bits(rt5677->regmap, | 3129 | regmap_update_bits(rt5677->regmap, |
3203 | RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000); | 3130 | RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000); |
@@ -3454,14 +3381,8 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
3454 | regmap_update_bits(rt5677->regmap, RT5677_IN1, | 3381 | regmap_update_bits(rt5677->regmap, RT5677_IN1, |
3455 | RT5677_IN_DF2, RT5677_IN_DF2); | 3382 | RT5677_IN_DF2, RT5677_IN_DF2); |
3456 | 3383 | ||
3457 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, | 3384 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, |
3458 | rt5677_dai, ARRAY_SIZE(rt5677_dai)); | 3385 | rt5677_dai, ARRAY_SIZE(rt5677_dai)); |
3459 | if (ret < 0) | ||
3460 | goto err; | ||
3461 | |||
3462 | return 0; | ||
3463 | err: | ||
3464 | return ret; | ||
3465 | } | 3386 | } |
3466 | 3387 | ||
3467 | static int rt5677_i2c_remove(struct i2c_client *i2c) | 3388 | static int rt5677_i2c_remove(struct i2c_client *i2c) |
@@ -3480,18 +3401,7 @@ static struct i2c_driver rt5677_i2c_driver = { | |||
3480 | .remove = rt5677_i2c_remove, | 3401 | .remove = rt5677_i2c_remove, |
3481 | .id_table = rt5677_i2c_id, | 3402 | .id_table = rt5677_i2c_id, |
3482 | }; | 3403 | }; |
3483 | 3404 | module_i2c_driver(rt5677_i2c_driver); | |
3484 | static int __init rt5677_modinit(void) | ||
3485 | { | ||
3486 | return i2c_add_driver(&rt5677_i2c_driver); | ||
3487 | } | ||
3488 | module_init(rt5677_modinit); | ||
3489 | |||
3490 | static void __exit rt5677_modexit(void) | ||
3491 | { | ||
3492 | i2c_del_driver(&rt5677_i2c_driver); | ||
3493 | } | ||
3494 | module_exit(rt5677_modexit); | ||
3495 | 3405 | ||
3496 | MODULE_DESCRIPTION("ASoC RT5677 driver"); | 3406 | MODULE_DESCRIPTION("ASoC RT5677 driver"); |
3497 | MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); | 3407 | MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); |
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index af4e9c797408..863393e62096 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h | |||
@@ -1393,13 +1393,6 @@ | |||
1393 | #define RT5677_DSP_IB_9_L (0x1 << 1) | 1393 | #define RT5677_DSP_IB_9_L (0x1 << 1) |
1394 | #define RT5677_DSP_IB_9_L_SFT 1 | 1394 | #define RT5677_DSP_IB_9_L_SFT 1 |
1395 | 1395 | ||
1396 | /* Debug String Length */ | ||
1397 | #define RT5677_REG_DISP_LEN 23 | ||
1398 | |||
1399 | #define RT5677_NO_JACK BIT(0) | ||
1400 | #define RT5677_HEADSET_DET BIT(1) | ||
1401 | #define RT5677_HEADPHO_DET BIT(2) | ||
1402 | |||
1403 | /* System Clock Source */ | 1396 | /* System Clock Source */ |
1404 | enum { | 1397 | enum { |
1405 | RT5677_SCLK_S_MCLK, | 1398 | RT5677_SCLK_S_MCLK, |
@@ -1425,14 +1418,6 @@ enum { | |||
1425 | RT5677_AIFS, | 1418 | RT5677_AIFS, |
1426 | }; | 1419 | }; |
1427 | 1420 | ||
1428 | struct rt5677_pll_code { | ||
1429 | bool m_bp; /* Indicates bypass m code or not. */ | ||
1430 | bool k_bp; /* Indicates bypass k code or not. */ | ||
1431 | int m_code; | ||
1432 | int n_code; | ||
1433 | int k_code; | ||
1434 | }; | ||
1435 | |||
1436 | struct rt5677_priv { | 1421 | struct rt5677_priv { |
1437 | struct snd_soc_codec *codec; | 1422 | struct snd_soc_codec *codec; |
1438 | struct rt5677_platform_data pdata; | 1423 | struct rt5677_platform_data pdata; |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 3d39f0b5b4a8..d739f83380a8 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -843,10 +843,8 @@ static int ldo_regulator_register(struct snd_soc_codec *codec, | |||
843 | 843 | ||
844 | ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL); | 844 | ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL); |
845 | 845 | ||
846 | if (!ldo) { | 846 | if (!ldo) |
847 | dev_err(codec->dev, "failed to allocate ldo_regulator\n"); | ||
848 | return -ENOMEM; | 847 | return -ENOMEM; |
849 | } | ||
850 | 848 | ||
851 | ldo->desc.name = kstrdup(dev_name(codec->dev), GFP_KERNEL); | 849 | ldo->desc.name = kstrdup(dev_name(codec->dev), GFP_KERNEL); |
852 | if (!ldo->desc.name) { | 850 | if (!ldo->desc.name) { |
@@ -1277,7 +1275,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | |||
1277 | return ret; | 1275 | return ret; |
1278 | } | 1276 | } |
1279 | 1277 | ||
1280 | ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), | 1278 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), |
1281 | sgtl5000->supplies); | 1279 | sgtl5000->supplies); |
1282 | if (ret) | 1280 | if (ret) |
1283 | goto err_ldo_remove; | 1281 | goto err_ldo_remove; |
@@ -1285,13 +1283,16 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | |||
1285 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), | 1283 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), |
1286 | sgtl5000->supplies); | 1284 | sgtl5000->supplies); |
1287 | if (ret) | 1285 | if (ret) |
1288 | goto err_ldo_remove; | 1286 | goto err_regulator_free; |
1289 | 1287 | ||
1290 | /* wait for all power rails bring up */ | 1288 | /* wait for all power rails bring up */ |
1291 | udelay(10); | 1289 | udelay(10); |
1292 | 1290 | ||
1293 | return 0; | 1291 | return 0; |
1294 | 1292 | ||
1293 | err_regulator_free: | ||
1294 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | ||
1295 | sgtl5000->supplies); | ||
1295 | err_ldo_remove: | 1296 | err_ldo_remove: |
1296 | if (!external_vddd) | 1297 | if (!external_vddd) |
1297 | ldo_regulator_remove(codec); | 1298 | ldo_regulator_remove(codec); |
@@ -1361,6 +1362,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) | |||
1361 | err: | 1362 | err: |
1362 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | 1363 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), |
1363 | sgtl5000->supplies); | 1364 | sgtl5000->supplies); |
1365 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | ||
1366 | sgtl5000->supplies); | ||
1364 | ldo_regulator_remove(codec); | 1367 | ldo_regulator_remove(codec); |
1365 | 1368 | ||
1366 | return ret; | 1369 | return ret; |
@@ -1374,6 +1377,8 @@ static int sgtl5000_remove(struct snd_soc_codec *codec) | |||
1374 | 1377 | ||
1375 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | 1378 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), |
1376 | sgtl5000->supplies); | 1379 | sgtl5000->supplies); |
1380 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | ||
1381 | sgtl5000->supplies); | ||
1377 | ldo_regulator_remove(codec); | 1382 | ldo_regulator_remove(codec); |
1378 | 1383 | ||
1379 | return 0; | 1384 | return 0; |
diff --git a/sound/soc/codecs/sigmadsp-i2c.c b/sound/soc/codecs/sigmadsp-i2c.c new file mode 100644 index 000000000000..246081aae8ca --- /dev/null +++ b/sound/soc/codecs/sigmadsp-i2c.c | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Load Analog Devices SigmaStudio firmware files | ||
3 | * | ||
4 | * Copyright 2009-2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/i2c.h> | ||
10 | #include <linux/export.h> | ||
11 | #include <linux/module.h> | ||
12 | |||
13 | #include "sigmadsp.h" | ||
14 | |||
15 | static int sigma_action_write_i2c(void *control_data, | ||
16 | const struct sigma_action *sa, size_t len) | ||
17 | { | ||
18 | return i2c_master_send(control_data, (const unsigned char *)&sa->addr, | ||
19 | len); | ||
20 | } | ||
21 | |||
22 | int process_sigma_firmware(struct i2c_client *client, const char *name) | ||
23 | { | ||
24 | struct sigma_firmware ssfw; | ||
25 | |||
26 | ssfw.control_data = client; | ||
27 | ssfw.write = sigma_action_write_i2c; | ||
28 | |||
29 | return _process_sigma_firmware(&client->dev, &ssfw, name); | ||
30 | } | ||
31 | EXPORT_SYMBOL(process_sigma_firmware); | ||
32 | |||
33 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
34 | MODULE_DESCRIPTION("SigmaDSP I2C firmware loader"); | ||
35 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/sigmadsp-regmap.c b/sound/soc/codecs/sigmadsp-regmap.c new file mode 100644 index 000000000000..f78ed8d2cfb2 --- /dev/null +++ b/sound/soc/codecs/sigmadsp-regmap.c | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Load Analog Devices SigmaStudio firmware files | ||
3 | * | ||
4 | * Copyright 2009-2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/regmap.h> | ||
10 | #include <linux/export.h> | ||
11 | #include <linux/module.h> | ||
12 | |||
13 | #include "sigmadsp.h" | ||
14 | |||
15 | static int sigma_action_write_regmap(void *control_data, | ||
16 | const struct sigma_action *sa, size_t len) | ||
17 | { | ||
18 | return regmap_raw_write(control_data, be16_to_cpu(sa->addr), | ||
19 | sa->payload, len - 2); | ||
20 | } | ||
21 | |||
22 | int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap, | ||
23 | const char *name) | ||
24 | { | ||
25 | struct sigma_firmware ssfw; | ||
26 | |||
27 | ssfw.control_data = regmap; | ||
28 | ssfw.write = sigma_action_write_regmap; | ||
29 | |||
30 | return _process_sigma_firmware(dev, &ssfw, name); | ||
31 | } | ||
32 | EXPORT_SYMBOL(process_sigma_firmware_regmap); | ||
33 | |||
34 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
35 | MODULE_DESCRIPTION("SigmaDSP regmap firmware loader"); | ||
36 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c index 4068f2491232..f2de7e049bc6 100644 --- a/sound/soc/codecs/sigmadsp.c +++ b/sound/soc/codecs/sigmadsp.c | |||
@@ -34,23 +34,6 @@ enum { | |||
34 | SIGMA_ACTION_END, | 34 | SIGMA_ACTION_END, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | struct sigma_action { | ||
38 | u8 instr; | ||
39 | u8 len_hi; | ||
40 | __le16 len; | ||
41 | __be16 addr; | ||
42 | unsigned char payload[]; | ||
43 | } __packed; | ||
44 | |||
45 | struct sigma_firmware { | ||
46 | const struct firmware *fw; | ||
47 | size_t pos; | ||
48 | |||
49 | void *control_data; | ||
50 | int (*write)(void *control_data, const struct sigma_action *sa, | ||
51 | size_t len); | ||
52 | }; | ||
53 | |||
54 | static inline u32 sigma_action_len(struct sigma_action *sa) | 37 | static inline u32 sigma_action_len(struct sigma_action *sa) |
55 | { | 38 | { |
56 | return (sa->len_hi << 16) | le16_to_cpu(sa->len); | 39 | return (sa->len_hi << 16) | le16_to_cpu(sa->len); |
@@ -138,7 +121,7 @@ process_sigma_actions(struct sigma_firmware *ssfw) | |||
138 | return 0; | 121 | return 0; |
139 | } | 122 | } |
140 | 123 | ||
141 | static int _process_sigma_firmware(struct device *dev, | 124 | int _process_sigma_firmware(struct device *dev, |
142 | struct sigma_firmware *ssfw, const char *name) | 125 | struct sigma_firmware *ssfw, const char *name) |
143 | { | 126 | { |
144 | int ret; | 127 | int ret; |
@@ -197,50 +180,6 @@ static int _process_sigma_firmware(struct device *dev, | |||
197 | 180 | ||
198 | return ret; | 181 | return ret; |
199 | } | 182 | } |
200 | 183 | EXPORT_SYMBOL_GPL(_process_sigma_firmware); | |
201 | #if IS_ENABLED(CONFIG_I2C) | ||
202 | |||
203 | static int sigma_action_write_i2c(void *control_data, | ||
204 | const struct sigma_action *sa, size_t len) | ||
205 | { | ||
206 | return i2c_master_send(control_data, (const unsigned char *)&sa->addr, | ||
207 | len); | ||
208 | } | ||
209 | |||
210 | int process_sigma_firmware(struct i2c_client *client, const char *name) | ||
211 | { | ||
212 | struct sigma_firmware ssfw; | ||
213 | |||
214 | ssfw.control_data = client; | ||
215 | ssfw.write = sigma_action_write_i2c; | ||
216 | |||
217 | return _process_sigma_firmware(&client->dev, &ssfw, name); | ||
218 | } | ||
219 | EXPORT_SYMBOL(process_sigma_firmware); | ||
220 | |||
221 | #endif | ||
222 | |||
223 | #if IS_ENABLED(CONFIG_REGMAP) | ||
224 | |||
225 | static int sigma_action_write_regmap(void *control_data, | ||
226 | const struct sigma_action *sa, size_t len) | ||
227 | { | ||
228 | return regmap_raw_write(control_data, be16_to_cpu(sa->addr), | ||
229 | sa->payload, len - 2); | ||
230 | } | ||
231 | |||
232 | int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap, | ||
233 | const char *name) | ||
234 | { | ||
235 | struct sigma_firmware ssfw; | ||
236 | |||
237 | ssfw.control_data = regmap; | ||
238 | ssfw.write = sigma_action_write_regmap; | ||
239 | |||
240 | return _process_sigma_firmware(dev, &ssfw, name); | ||
241 | } | ||
242 | EXPORT_SYMBOL(process_sigma_firmware_regmap); | ||
243 | |||
244 | #endif | ||
245 | 184 | ||
246 | MODULE_LICENSE("GPL"); | 185 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/sigmadsp.h b/sound/soc/codecs/sigmadsp.h index e439cbd7af7d..c47cd23e9827 100644 --- a/sound/soc/codecs/sigmadsp.h +++ b/sound/soc/codecs/sigmadsp.h | |||
@@ -12,6 +12,26 @@ | |||
12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
13 | #include <linux/regmap.h> | 13 | #include <linux/regmap.h> |
14 | 14 | ||
15 | struct sigma_action { | ||
16 | u8 instr; | ||
17 | u8 len_hi; | ||
18 | __le16 len; | ||
19 | __be16 addr; | ||
20 | unsigned char payload[]; | ||
21 | } __packed; | ||
22 | |||
23 | struct sigma_firmware { | ||
24 | const struct firmware *fw; | ||
25 | size_t pos; | ||
26 | |||
27 | void *control_data; | ||
28 | int (*write)(void *control_data, const struct sigma_action *sa, | ||
29 | size_t len); | ||
30 | }; | ||
31 | |||
32 | int _process_sigma_firmware(struct device *dev, | ||
33 | struct sigma_firmware *ssfw, const char *name); | ||
34 | |||
15 | struct i2c_client; | 35 | struct i2c_client; |
16 | 36 | ||
17 | extern int process_sigma_firmware(struct i2c_client *client, const char *name); | 37 | extern int process_sigma_firmware(struct i2c_client *client, const char *name); |
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index a40c4b0196a3..fcdf11026aff 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c | |||
@@ -380,10 +380,8 @@ static int sta529_i2c_probe(struct i2c_client *i2c, | |||
380 | return -EINVAL; | 380 | return -EINVAL; |
381 | 381 | ||
382 | sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL); | 382 | sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL); |
383 | if (sta529 == NULL) { | 383 | if (!sta529) |
384 | dev_err(&i2c->dev, "Can not allocate memory\n"); | ||
385 | return -ENOMEM; | 384 | return -ENOMEM; |
386 | } | ||
387 | 385 | ||
388 | sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap); | 386 | sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap); |
389 | if (IS_ERR(sta529->regmap)) { | 387 | if (IS_ERR(sta529->regmap)) { |
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 23419109ecac..1cdae8ccc61b 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -1178,7 +1178,7 @@ static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx) | |||
1178 | } | 1178 | } |
1179 | #endif /* CONFIG_OF */ | 1179 | #endif /* CONFIG_OF */ |
1180 | 1180 | ||
1181 | static void aic31xx_device_init(struct aic31xx_priv *aic31xx) | 1181 | static int aic31xx_device_init(struct aic31xx_priv *aic31xx) |
1182 | { | 1182 | { |
1183 | int ret, i; | 1183 | int ret, i; |
1184 | 1184 | ||
@@ -1197,7 +1197,7 @@ static void aic31xx_device_init(struct aic31xx_priv *aic31xx) | |||
1197 | "aic31xx-reset-pin"); | 1197 | "aic31xx-reset-pin"); |
1198 | if (ret < 0) { | 1198 | if (ret < 0) { |
1199 | dev_err(aic31xx->dev, "not able to acquire gpio\n"); | 1199 | dev_err(aic31xx->dev, "not able to acquire gpio\n"); |
1200 | return; | 1200 | return ret; |
1201 | } | 1201 | } |
1202 | } | 1202 | } |
1203 | 1203 | ||
@@ -1210,6 +1210,7 @@ static void aic31xx_device_init(struct aic31xx_priv *aic31xx) | |||
1210 | if (ret != 0) | 1210 | if (ret != 0) |
1211 | dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret); | 1211 | dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret); |
1212 | 1212 | ||
1213 | return ret; | ||
1213 | } | 1214 | } |
1214 | 1215 | ||
1215 | static int aic31xx_i2c_probe(struct i2c_client *i2c, | 1216 | static int aic31xx_i2c_probe(struct i2c_client *i2c, |
@@ -1239,7 +1240,9 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, | |||
1239 | 1240 | ||
1240 | aic31xx->pdata.codec_type = id->driver_data; | 1241 | aic31xx->pdata.codec_type = id->driver_data; |
1241 | 1242 | ||
1242 | aic31xx_device_init(aic31xx); | 1243 | ret = aic31xx_device_init(aic31xx); |
1244 | if (ret) | ||
1245 | return ret; | ||
1243 | 1246 | ||
1244 | return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, | 1247 | return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, |
1245 | aic31xx_dai_driver, | 1248 | aic31xx_dai_driver, |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index e12fafbb1e09..f14b551b729e 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -879,7 +879,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, | |||
879 | case SNDRV_PCM_FORMAT_S20_3LE: | 879 | case SNDRV_PCM_FORMAT_S20_3LE: |
880 | data |= (0x01 << 4); | 880 | data |= (0x01 << 4); |
881 | break; | 881 | break; |
882 | case SNDRV_PCM_FORMAT_S24_LE: | 882 | case SNDRV_PCM_FORMAT_S24_3LE: |
883 | data |= (0x02 << 4); | 883 | data |= (0x02 << 4); |
884 | break; | 884 | break; |
885 | case SNDRV_PCM_FORMAT_S32_LE: | 885 | case SNDRV_PCM_FORMAT_S32_LE: |
@@ -1477,10 +1477,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1477 | u32 value; | 1477 | u32 value; |
1478 | 1478 | ||
1479 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); | 1479 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); |
1480 | if (aic3x == NULL) { | 1480 | if (!aic3x) |
1481 | dev_err(&i2c->dev, "failed to create private data\n"); | ||
1482 | return -ENOMEM; | 1481 | return -ENOMEM; |
1483 | } | ||
1484 | 1482 | ||
1485 | aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap); | 1483 | aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap); |
1486 | if (IS_ERR(aic3x->regmap)) { | 1484 | if (IS_ERR(aic3x->regmap)) { |
@@ -1498,10 +1496,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1498 | } else if (np) { | 1496 | } else if (np) { |
1499 | ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), | 1497 | ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), |
1500 | GFP_KERNEL); | 1498 | GFP_KERNEL); |
1501 | if (ai3x_setup == NULL) { | 1499 | if (!ai3x_setup) |
1502 | dev_err(&i2c->dev, "failed to create private data\n"); | ||
1503 | return -ENOMEM; | 1500 | return -ENOMEM; |
1504 | } | ||
1505 | 1501 | ||
1506 | ret = of_get_named_gpio(np, "gpio-reset", 0); | 1502 | ret = of_get_named_gpio(np, "gpio-reset", 0); |
1507 | if (ret >= 0) | 1503 | if (ret >= 0) |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index df3a7506c023..ff006cc95520 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -1404,7 +1404,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec) | |||
1404 | if (dac33->irq >= 0) { | 1404 | if (dac33->irq >= 0) { |
1405 | ret = request_irq(dac33->irq, dac33_interrupt_handler, | 1405 | ret = request_irq(dac33->irq, dac33_interrupt_handler, |
1406 | IRQF_TRIGGER_RISING, | 1406 | IRQF_TRIGGER_RISING, |
1407 | codec->name, codec); | 1407 | codec->component.name, codec); |
1408 | if (ret < 0) { | 1408 | if (ret < 0) { |
1409 | dev_err(codec->dev, "Could not request IRQ%d (%d)\n", | 1409 | dev_err(codec->dev, "Could not request IRQ%d (%d)\n", |
1410 | dac33->irq, ret); | 1410 | dac33->irq, ret); |
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 8fc5a647453b..6fac9e034c48 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -381,10 +381,8 @@ static int tpa6130a2_probe(struct i2c_client *client, | |||
381 | dev = &client->dev; | 381 | dev = &client->dev; |
382 | 382 | ||
383 | data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); | 383 | data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); |
384 | if (data == NULL) { | 384 | if (!data) |
385 | dev_err(dev, "Can not allocate memory\n"); | ||
386 | return -ENOMEM; | 385 | return -ENOMEM; |
387 | } | ||
388 | 386 | ||
389 | if (pdata) { | 387 | if (pdata) { |
390 | data->power_gpio = pdata->power_gpio; | 388 | data->power_gpio = pdata->power_gpio; |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 69e12a311ba2..cf404505e7d1 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -344,17 +344,16 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
344 | static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) | 344 | static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) |
345 | { | 345 | { |
346 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 346 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
347 | int status = -1; | ||
348 | 347 | ||
349 | if (enable) { | 348 | if (enable) { |
350 | twl4030->apll_enabled++; | 349 | twl4030->apll_enabled++; |
351 | if (twl4030->apll_enabled == 1) | 350 | if (twl4030->apll_enabled == 1) |
352 | status = twl4030_audio_enable_resource( | 351 | twl4030_audio_enable_resource( |
353 | TWL4030_AUDIO_RES_APLL); | 352 | TWL4030_AUDIO_RES_APLL); |
354 | } else { | 353 | } else { |
355 | twl4030->apll_enabled--; | 354 | twl4030->apll_enabled--; |
356 | if (!twl4030->apll_enabled) | 355 | if (!twl4030->apll_enabled) |
357 | status = twl4030_audio_disable_resource( | 356 | twl4030_audio_disable_resource( |
358 | TWL4030_AUDIO_RES_APLL); | 357 | TWL4030_AUDIO_RES_APLL); |
359 | } | 358 | } |
360 | } | 359 | } |
@@ -2162,10 +2161,8 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec) | |||
2162 | 2161 | ||
2163 | twl4030 = devm_kzalloc(codec->dev, sizeof(struct twl4030_priv), | 2162 | twl4030 = devm_kzalloc(codec->dev, sizeof(struct twl4030_priv), |
2164 | GFP_KERNEL); | 2163 | GFP_KERNEL); |
2165 | if (twl4030 == NULL) { | 2164 | if (!twl4030) |
2166 | dev_err(codec->dev, "Can not allocate memory\n"); | ||
2167 | return -ENOMEM; | 2165 | return -ENOMEM; |
2168 | } | ||
2169 | snd_soc_codec_set_drvdata(codec, twl4030); | 2166 | snd_soc_codec_set_drvdata(codec, twl4030); |
2170 | /* Set the defaults, and power up the codec */ | 2167 | /* Set the defaults, and power up the codec */ |
2171 | twl4030->sysclk = twl4030_audio_get_mclk() / 1000; | 2168 | twl4030->sysclk = twl4030_audio_get_mclk() / 1000; |
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index edf27acc1d77..12fc0aed7503 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c | |||
@@ -479,7 +479,7 @@ static struct snd_soc_dai_driver uda134x_dai = { | |||
479 | static int uda134x_soc_probe(struct snd_soc_codec *codec) | 479 | static int uda134x_soc_probe(struct snd_soc_codec *codec) |
480 | { | 480 | { |
481 | struct uda134x_priv *uda134x; | 481 | struct uda134x_priv *uda134x; |
482 | struct uda134x_platform_data *pd = codec->card->dev->platform_data; | 482 | struct uda134x_platform_data *pd = codec->component.card->dev->platform_data; |
483 | const struct snd_soc_dapm_widget *widgets; | 483 | const struct snd_soc_dapm_widget *widgets; |
484 | unsigned num_widgets; | 484 | unsigned num_widgets; |
485 | 485 | ||
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index 4ead0dc02b87..5d8ba779085b 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c | |||
@@ -461,10 +461,8 @@ static int wl1273_probe(struct snd_soc_codec *codec) | |||
461 | } | 461 | } |
462 | 462 | ||
463 | wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL); | 463 | wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL); |
464 | if (wl1273 == NULL) { | 464 | if (!wl1273) |
465 | dev_err(codec->dev, "Cannot allocate memory.\n"); | ||
466 | return -ENOMEM; | 465 | return -ENOMEM; |
467 | } | ||
468 | 466 | ||
469 | wl1273->mode = WL1273_MODE_BT; | 467 | wl1273->mode = WL1273_MODE_BT; |
470 | wl1273->core = *core; | 468 | wl1273->core = *core; |
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 71ce3159a62e..982467c1d56a 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c | |||
@@ -413,7 +413,6 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) | |||
413 | 413 | ||
414 | xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); | 414 | xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); |
415 | if (!xfer) { | 415 | if (!xfer) { |
416 | dev_err(codec->dev, "Failed to allocate xfer\n"); | ||
417 | ret = -ENOMEM; | 416 | ret = -ENOMEM; |
418 | goto abort; | 417 | goto abort; |
419 | } | 418 | } |
@@ -423,8 +422,6 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) | |||
423 | 422 | ||
424 | out = kzalloc(len, GFP_KERNEL | GFP_DMA); | 423 | out = kzalloc(len, GFP_KERNEL | GFP_DMA); |
425 | if (!out) { | 424 | if (!out) { |
426 | dev_err(codec->dev, | ||
427 | "Failed to allocate RX buffer\n"); | ||
428 | ret = -ENOMEM; | 425 | ret = -ENOMEM; |
429 | goto abort1; | 426 | goto abort1; |
430 | } | 427 | } |
@@ -432,8 +429,6 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) | |||
432 | 429 | ||
433 | img = kzalloc(len, GFP_KERNEL | GFP_DMA); | 430 | img = kzalloc(len, GFP_KERNEL | GFP_DMA); |
434 | if (!img) { | 431 | if (!img) { |
435 | dev_err(codec->dev, | ||
436 | "Failed to allocate image buffer\n"); | ||
437 | ret = -ENOMEM; | 432 | ret = -ENOMEM; |
438 | goto abort1; | 433 | goto abort1; |
439 | } | 434 | } |
@@ -526,14 +521,12 @@ static int wm0010_stage2_load(struct snd_soc_codec *codec) | |||
526 | /* Copy to local buffer first as vmalloc causes problems for dma */ | 521 | /* Copy to local buffer first as vmalloc causes problems for dma */ |
527 | img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); | 522 | img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); |
528 | if (!img) { | 523 | if (!img) { |
529 | dev_err(codec->dev, "Failed to allocate image buffer\n"); | ||
530 | ret = -ENOMEM; | 524 | ret = -ENOMEM; |
531 | goto abort2; | 525 | goto abort2; |
532 | } | 526 | } |
533 | 527 | ||
534 | out = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); | 528 | out = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); |
535 | if (!out) { | 529 | if (!out) { |
536 | dev_err(codec->dev, "Failed to allocate output buffer\n"); | ||
537 | ret = -ENOMEM; | 530 | ret = -ENOMEM; |
538 | goto abort1; | 531 | goto abort1; |
539 | } | 532 | } |
@@ -679,11 +672,8 @@ static int wm0010_boot(struct snd_soc_codec *codec) | |||
679 | } | 672 | } |
680 | 673 | ||
681 | img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA); | 674 | img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA); |
682 | if (!img_swap) { | 675 | if (!img_swap) |
683 | dev_err(codec->dev, | ||
684 | "Failed to allocate image buffer\n"); | ||
685 | goto abort; | 676 | goto abort; |
686 | } | ||
687 | 677 | ||
688 | /* We need to re-order for 0010 */ | 678 | /* We need to re-order for 0010 */ |
689 | byte_swap_64((u64 *)&pll_rec, img_swap, len); | 679 | byte_swap_64((u64 *)&pll_rec, img_swap, len); |
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index 6e6b93d4696e..8011f75fb6cb 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c | |||
@@ -164,7 +164,6 @@ static int wm1250_ev1_pdata(struct i2c_client *i2c) | |||
164 | 164 | ||
165 | wm1250 = devm_kzalloc(&i2c->dev, sizeof(*wm1250), GFP_KERNEL); | 165 | wm1250 = devm_kzalloc(&i2c->dev, sizeof(*wm1250), GFP_KERNEL); |
166 | if (!wm1250) { | 166 | if (!wm1250) { |
167 | dev_err(&i2c->dev, "Unable to allocate private data\n"); | ||
168 | ret = -ENOMEM; | 167 | ret = -ENOMEM; |
169 | goto err; | 168 | goto err; |
170 | } | 169 | } |
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index a4c352cc3464..34ef65c52a7d 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -826,10 +826,8 @@ static int wm2000_i2c_probe(struct i2c_client *i2c, | |||
826 | 826 | ||
827 | wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv), | 827 | wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv), |
828 | GFP_KERNEL); | 828 | GFP_KERNEL); |
829 | if (wm2000 == NULL) { | 829 | if (!wm2000) |
830 | dev_err(&i2c->dev, "Unable to allocate private data\n"); | ||
831 | return -ENOMEM; | 830 | return -ENOMEM; |
832 | } | ||
833 | 831 | ||
834 | mutex_init(&wm2000->lock); | 832 | mutex_init(&wm2000->lock); |
835 | 833 | ||
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 91a9ea2a2056..7bb0d36d4c54 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
@@ -735,8 +735,7 @@ WM5100_MIXER_CONTROLS("LHPF4", WM5100_HPLP4MIX_INPUT_1_SOURCE), | |||
735 | static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm, | 735 | static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm, |
736 | enum snd_soc_dapm_type event, int subseq) | 736 | enum snd_soc_dapm_type event, int subseq) |
737 | { | 737 | { |
738 | struct snd_soc_codec *codec = container_of(dapm, | 738 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); |
739 | struct snd_soc_codec, dapm); | ||
740 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | 739 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); |
741 | u16 val, expect, i; | 740 | u16 val, expect, i; |
742 | 741 | ||
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 289b64d89abd..f60234962527 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -612,6 +612,62 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
612 | return 0; | 612 | return 0; |
613 | } | 613 | } |
614 | 614 | ||
615 | static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, | ||
616 | struct snd_ctl_elem_value *ucontrol) | ||
617 | { | ||
618 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
619 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
620 | uint16_t data; | ||
621 | |||
622 | mutex_lock(&codec->mutex); | ||
623 | data = cpu_to_be16(arizona->dac_comp_coeff); | ||
624 | memcpy(ucontrol->value.bytes.data, &data, sizeof(data)); | ||
625 | mutex_unlock(&codec->mutex); | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static int wm5102_out_comp_coeff_put(struct snd_kcontrol *kcontrol, | ||
631 | struct snd_ctl_elem_value *ucontrol) | ||
632 | { | ||
633 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
634 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
635 | |||
636 | mutex_lock(&codec->mutex); | ||
637 | memcpy(&arizona->dac_comp_coeff, ucontrol->value.bytes.data, | ||
638 | sizeof(arizona->dac_comp_coeff)); | ||
639 | arizona->dac_comp_coeff = be16_to_cpu(arizona->dac_comp_coeff); | ||
640 | mutex_unlock(&codec->mutex); | ||
641 | |||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | static int wm5102_out_comp_switch_get(struct snd_kcontrol *kcontrol, | ||
646 | struct snd_ctl_elem_value *ucontrol) | ||
647 | { | ||
648 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
649 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
650 | |||
651 | mutex_lock(&codec->mutex); | ||
652 | ucontrol->value.integer.value[0] = arizona->dac_comp_enabled; | ||
653 | mutex_unlock(&codec->mutex); | ||
654 | |||
655 | return 0; | ||
656 | } | ||
657 | |||
658 | static int wm5102_out_comp_switch_put(struct snd_kcontrol *kcontrol, | ||
659 | struct snd_ctl_elem_value *ucontrol) | ||
660 | { | ||
661 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
662 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
663 | |||
664 | mutex_lock(&codec->mutex); | ||
665 | arizona->dac_comp_enabled = ucontrol->value.integer.value[0]; | ||
666 | mutex_unlock(&codec->mutex); | ||
667 | |||
668 | return 0; | ||
669 | } | ||
670 | |||
615 | static const char *wm5102_osr_text[] = { | 671 | static const char *wm5102_osr_text[] = { |
616 | "Low power", "Normal", "High performance", | 672 | "Low power", "Normal", "High performance", |
617 | }; | 673 | }; |
@@ -843,6 +899,12 @@ SOC_SINGLE_TLV("Noise Gate Threshold Volume", ARIZONA_NOISE_GATE_CONTROL, | |||
843 | ARIZONA_NGATE_THR_SHIFT, 7, 1, ng_tlv), | 899 | ARIZONA_NGATE_THR_SHIFT, 7, 1, ng_tlv), |
844 | SOC_ENUM("Noise Gate Hold", arizona_ng_hold), | 900 | SOC_ENUM("Noise Gate Hold", arizona_ng_hold), |
845 | 901 | ||
902 | SND_SOC_BYTES_EXT("Output Compensation Coefficient", 2, | ||
903 | wm5102_out_comp_coeff_get, wm5102_out_comp_coeff_put), | ||
904 | |||
905 | SOC_SINGLE_EXT("Output Compensation Switch", 0, 0, 1, 0, | ||
906 | wm5102_out_comp_switch_get, wm5102_out_comp_switch_put), | ||
907 | |||
846 | WM5102_NG_SRC("HPOUT1L", ARIZONA_NOISE_GATE_SELECT_1L), | 908 | WM5102_NG_SRC("HPOUT1L", ARIZONA_NOISE_GATE_SELECT_1L), |
847 | WM5102_NG_SRC("HPOUT1R", ARIZONA_NOISE_GATE_SELECT_1R), | 909 | WM5102_NG_SRC("HPOUT1R", ARIZONA_NOISE_GATE_SELECT_1R), |
848 | WM5102_NG_SRC("HPOUT2L", ARIZONA_NOISE_GATE_SELECT_2L), | 910 | WM5102_NG_SRC("HPOUT2L", ARIZONA_NOISE_GATE_SELECT_2L), |
@@ -1653,6 +1715,7 @@ static struct snd_soc_dai_driver wm5102_dai[] = { | |||
1653 | }, | 1715 | }, |
1654 | .ops = &arizona_dai_ops, | 1716 | .ops = &arizona_dai_ops, |
1655 | .symmetric_rates = 1, | 1717 | .symmetric_rates = 1, |
1718 | .symmetric_samplebits = 1, | ||
1656 | }, | 1719 | }, |
1657 | { | 1720 | { |
1658 | .name = "wm5102-aif2", | 1721 | .name = "wm5102-aif2", |
@@ -1674,6 +1737,7 @@ static struct snd_soc_dai_driver wm5102_dai[] = { | |||
1674 | }, | 1737 | }, |
1675 | .ops = &arizona_dai_ops, | 1738 | .ops = &arizona_dai_ops, |
1676 | .symmetric_rates = 1, | 1739 | .symmetric_rates = 1, |
1740 | .symmetric_samplebits = 1, | ||
1677 | }, | 1741 | }, |
1678 | { | 1742 | { |
1679 | .name = "wm5102-aif3", | 1743 | .name = "wm5102-aif3", |
@@ -1695,6 +1759,7 @@ static struct snd_soc_dai_driver wm5102_dai[] = { | |||
1695 | }, | 1759 | }, |
1696 | .ops = &arizona_dai_ops, | 1760 | .ops = &arizona_dai_ops, |
1697 | .symmetric_rates = 1, | 1761 | .symmetric_rates = 1, |
1762 | .symmetric_samplebits = 1, | ||
1698 | }, | 1763 | }, |
1699 | { | 1764 | { |
1700 | .name = "wm5102-slim1", | 1765 | .name = "wm5102-slim1", |
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 2e5fcb559e90..2f2ec26d831c 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -1485,6 +1485,7 @@ static struct snd_soc_dai_driver wm5110_dai[] = { | |||
1485 | }, | 1485 | }, |
1486 | .ops = &arizona_dai_ops, | 1486 | .ops = &arizona_dai_ops, |
1487 | .symmetric_rates = 1, | 1487 | .symmetric_rates = 1, |
1488 | .symmetric_samplebits = 1, | ||
1488 | }, | 1489 | }, |
1489 | { | 1490 | { |
1490 | .name = "wm5110-aif2", | 1491 | .name = "wm5110-aif2", |
@@ -1506,6 +1507,7 @@ static struct snd_soc_dai_driver wm5110_dai[] = { | |||
1506 | }, | 1507 | }, |
1507 | .ops = &arizona_dai_ops, | 1508 | .ops = &arizona_dai_ops, |
1508 | .symmetric_rates = 1, | 1509 | .symmetric_rates = 1, |
1510 | .symmetric_samplebits = 1, | ||
1509 | }, | 1511 | }, |
1510 | { | 1512 | { |
1511 | .name = "wm5110-aif3", | 1513 | .name = "wm5110-aif3", |
@@ -1527,6 +1529,7 @@ static struct snd_soc_dai_driver wm5110_dai[] = { | |||
1527 | }, | 1529 | }, |
1528 | .ops = &arizona_dai_ops, | 1530 | .ops = &arizona_dai_ops, |
1529 | .symmetric_rates = 1, | 1531 | .symmetric_rates = 1, |
1532 | .symmetric_samplebits = 1, | ||
1530 | }, | 1533 | }, |
1531 | { | 1534 | { |
1532 | .name = "wm5110-slim1", | 1535 | .name = "wm5110-slim1", |
@@ -1596,6 +1599,7 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) | |||
1596 | 1599 | ||
1597 | arizona_init_spk(codec); | 1600 | arizona_init_spk(codec); |
1598 | arizona_init_gpio(codec); | 1601 | arizona_init_gpio(codec); |
1602 | arizona_init_mono(codec); | ||
1599 | 1603 | ||
1600 | ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8); | 1604 | ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8); |
1601 | if (ret != 0) | 1605 | if (ret != 0) |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 392285edb595..d9e634c55e81 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -1341,21 +1341,18 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, | |||
1341 | { | 1341 | { |
1342 | struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); | 1342 | struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); |
1343 | struct wm8350 *wm8350 = priv->wm8350; | 1343 | struct wm8350 *wm8350 = priv->wm8350; |
1344 | int irq; | ||
1345 | int ena; | 1344 | int ena; |
1346 | 1345 | ||
1347 | switch (which) { | 1346 | switch (which) { |
1348 | case WM8350_JDL: | 1347 | case WM8350_JDL: |
1349 | priv->hpl.jack = jack; | 1348 | priv->hpl.jack = jack; |
1350 | priv->hpl.report = report; | 1349 | priv->hpl.report = report; |
1351 | irq = WM8350_IRQ_CODEC_JCK_DET_L; | ||
1352 | ena = WM8350_JDL_ENA; | 1350 | ena = WM8350_JDL_ENA; |
1353 | break; | 1351 | break; |
1354 | 1352 | ||
1355 | case WM8350_JDR: | 1353 | case WM8350_JDR: |
1356 | priv->hpr.jack = jack; | 1354 | priv->hpr.jack = jack; |
1357 | priv->hpr.report = report; | 1355 | priv->hpr.report = report; |
1358 | irq = WM8350_IRQ_CODEC_JCK_DET_R; | ||
1359 | ena = WM8350_JDR_ENA; | 1356 | ena = WM8350_JDR_ENA; |
1360 | break; | 1357 | break; |
1361 | 1358 | ||
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index b84940c359a1..ec3250daa93e 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -281,8 +281,7 @@ static int wm8903_dcs_event(struct snd_soc_dapm_widget *w, | |||
281 | static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, | 281 | static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, |
282 | enum snd_soc_dapm_type event, int subseq) | 282 | enum snd_soc_dapm_type event, int subseq) |
283 | { | 283 | { |
284 | struct snd_soc_codec *codec = container_of(dapm, | 284 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); |
285 | struct snd_soc_codec, dapm); | ||
286 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 285 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
287 | int dcs_mode = WM8903_DCS_MODE_WRITE_STOP; | 286 | int dcs_mode = WM8903_DCS_MODE_WRITE_STOP; |
288 | int i, val; | 287 | int i, val; |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index f7c549949c54..e2792980ecf2 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -2013,12 +2013,8 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) | |||
2013 | /* We need an array of texts for the enum API */ | 2013 | /* We need an array of texts for the enum API */ |
2014 | wm8904->drc_texts = kmalloc(sizeof(char *) | 2014 | wm8904->drc_texts = kmalloc(sizeof(char *) |
2015 | * pdata->num_drc_cfgs, GFP_KERNEL); | 2015 | * pdata->num_drc_cfgs, GFP_KERNEL); |
2016 | if (!wm8904->drc_texts) { | 2016 | if (!wm8904->drc_texts) |
2017 | dev_err(codec->dev, | ||
2018 | "Failed to allocate %d DRC config texts\n", | ||
2019 | pdata->num_drc_cfgs); | ||
2020 | return; | 2017 | return; |
2021 | } | ||
2022 | 2018 | ||
2023 | for (i = 0; i < pdata->num_drc_cfgs; i++) | 2019 | for (i = 0; i < pdata->num_drc_cfgs; i++) |
2024 | wm8904->drc_texts[i] = pdata->drc_cfgs[i].name; | 2020 | wm8904->drc_texts[i] = pdata->drc_cfgs[i].name; |
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index b2ebb104d879..0dada7f0105e 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c | |||
@@ -934,12 +934,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
934 | /* We need an array of texts for the enum API */ | 934 | /* We need an array of texts for the enum API */ |
935 | wm8994->mbc_texts = kmalloc(sizeof(char *) | 935 | wm8994->mbc_texts = kmalloc(sizeof(char *) |
936 | * pdata->num_mbc_cfgs, GFP_KERNEL); | 936 | * pdata->num_mbc_cfgs, GFP_KERNEL); |
937 | if (!wm8994->mbc_texts) { | 937 | if (!wm8994->mbc_texts) |
938 | dev_err(wm8994->hubs.codec->dev, | ||
939 | "Failed to allocate %d MBC config texts\n", | ||
940 | pdata->num_mbc_cfgs); | ||
941 | return; | 938 | return; |
942 | } | ||
943 | 939 | ||
944 | for (i = 0; i < pdata->num_mbc_cfgs; i++) | 940 | for (i = 0; i < pdata->num_mbc_cfgs; i++) |
945 | wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; | 941 | wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; |
@@ -963,12 +959,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
963 | /* We need an array of texts for the enum API */ | 959 | /* We need an array of texts for the enum API */ |
964 | wm8994->vss_texts = kmalloc(sizeof(char *) | 960 | wm8994->vss_texts = kmalloc(sizeof(char *) |
965 | * pdata->num_vss_cfgs, GFP_KERNEL); | 961 | * pdata->num_vss_cfgs, GFP_KERNEL); |
966 | if (!wm8994->vss_texts) { | 962 | if (!wm8994->vss_texts) |
967 | dev_err(wm8994->hubs.codec->dev, | ||
968 | "Failed to allocate %d VSS config texts\n", | ||
969 | pdata->num_vss_cfgs); | ||
970 | return; | 963 | return; |
971 | } | ||
972 | 964 | ||
973 | for (i = 0; i < pdata->num_vss_cfgs; i++) | 965 | for (i = 0; i < pdata->num_vss_cfgs; i++) |
974 | wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; | 966 | wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; |
@@ -993,12 +985,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
993 | /* We need an array of texts for the enum API */ | 985 | /* We need an array of texts for the enum API */ |
994 | wm8994->vss_hpf_texts = kmalloc(sizeof(char *) | 986 | wm8994->vss_hpf_texts = kmalloc(sizeof(char *) |
995 | * pdata->num_vss_hpf_cfgs, GFP_KERNEL); | 987 | * pdata->num_vss_hpf_cfgs, GFP_KERNEL); |
996 | if (!wm8994->vss_hpf_texts) { | 988 | if (!wm8994->vss_hpf_texts) |
997 | dev_err(wm8994->hubs.codec->dev, | ||
998 | "Failed to allocate %d VSS HPF config texts\n", | ||
999 | pdata->num_vss_hpf_cfgs); | ||
1000 | return; | 989 | return; |
1001 | } | ||
1002 | 990 | ||
1003 | for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) | 991 | for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) |
1004 | wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; | 992 | wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; |
@@ -1024,12 +1012,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1024 | /* We need an array of texts for the enum API */ | 1012 | /* We need an array of texts for the enum API */ |
1025 | wm8994->enh_eq_texts = kmalloc(sizeof(char *) | 1013 | wm8994->enh_eq_texts = kmalloc(sizeof(char *) |
1026 | * pdata->num_enh_eq_cfgs, GFP_KERNEL); | 1014 | * pdata->num_enh_eq_cfgs, GFP_KERNEL); |
1027 | if (!wm8994->enh_eq_texts) { | 1015 | if (!wm8994->enh_eq_texts) |
1028 | dev_err(wm8994->hubs.codec->dev, | ||
1029 | "Failed to allocate %d enhanced EQ config texts\n", | ||
1030 | pdata->num_enh_eq_cfgs); | ||
1031 | return; | 1016 | return; |
1032 | } | ||
1033 | 1017 | ||
1034 | for (i = 0; i < pdata->num_enh_eq_cfgs; i++) | 1018 | for (i = 0; i < pdata->num_enh_eq_cfgs; i++) |
1035 | wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; | 1019 | wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index a145d0431b63..e96349b04ba6 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -472,7 +472,7 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec) | |||
472 | * list each time to find the desired power state do so now | 472 | * list each time to find the desired power state do so now |
473 | * and save the result. | 473 | * and save the result. |
474 | */ | 474 | */ |
475 | list_for_each_entry(w, &codec->card->widgets, list) { | 475 | list_for_each_entry(w, &codec->component.card->widgets, list) { |
476 | if (w->dapm != &codec->dapm) | 476 | if (w->dapm != &codec->dapm) |
477 | continue; | 477 | continue; |
478 | if (strcmp(w->name, "LOUT1 PGA") == 0) | 478 | if (strcmp(w->name, "LOUT1 PGA") == 0) |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 247b39013fba..39d8df040116 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -3296,12 +3296,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3296 | /* We need an array of texts for the enum API */ | 3296 | /* We need an array of texts for the enum API */ |
3297 | wm8994->drc_texts = devm_kzalloc(wm8994->hubs.codec->dev, | 3297 | wm8994->drc_texts = devm_kzalloc(wm8994->hubs.codec->dev, |
3298 | sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); | 3298 | sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); |
3299 | if (!wm8994->drc_texts) { | 3299 | if (!wm8994->drc_texts) |
3300 | dev_err(wm8994->hubs.codec->dev, | ||
3301 | "Failed to allocate %d DRC config texts\n", | ||
3302 | pdata->num_drc_cfgs); | ||
3303 | return; | 3300 | return; |
3304 | } | ||
3305 | 3301 | ||
3306 | for (i = 0; i < pdata->num_drc_cfgs; i++) | 3302 | for (i = 0; i < pdata->num_drc_cfgs; i++) |
3307 | wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; | 3303 | wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; |
@@ -3505,6 +3501,7 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) | |||
3505 | return IRQ_HANDLED; | 3501 | return IRQ_HANDLED; |
3506 | } | 3502 | } |
3507 | 3503 | ||
3504 | /* Should be called with accdet_lock held */ | ||
3508 | static void wm1811_micd_stop(struct snd_soc_codec *codec) | 3505 | static void wm1811_micd_stop(struct snd_soc_codec *codec) |
3509 | { | 3506 | { |
3510 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3507 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
@@ -3512,14 +3509,10 @@ static void wm1811_micd_stop(struct snd_soc_codec *codec) | |||
3512 | if (!wm8994->jackdet) | 3509 | if (!wm8994->jackdet) |
3513 | return; | 3510 | return; |
3514 | 3511 | ||
3515 | mutex_lock(&wm8994->accdet_lock); | ||
3516 | |||
3517 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0); | 3512 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0); |
3518 | 3513 | ||
3519 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); | 3514 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); |
3520 | 3515 | ||
3521 | mutex_unlock(&wm8994->accdet_lock); | ||
3522 | |||
3523 | if (wm8994->wm8994->pdata.jd_ext_cap) | 3516 | if (wm8994->wm8994->pdata.jd_ext_cap) |
3524 | snd_soc_dapm_disable_pin(&codec->dapm, | 3517 | snd_soc_dapm_disable_pin(&codec->dapm, |
3525 | "MICBIAS2"); | 3518 | "MICBIAS2"); |
@@ -3560,10 +3553,10 @@ static void wm8958_open_circuit_work(struct work_struct *work) | |||
3560 | open_circuit_work.work); | 3553 | open_circuit_work.work); |
3561 | struct device *dev = wm8994->wm8994->dev; | 3554 | struct device *dev = wm8994->wm8994->dev; |
3562 | 3555 | ||
3563 | wm1811_micd_stop(wm8994->hubs.codec); | ||
3564 | |||
3565 | mutex_lock(&wm8994->accdet_lock); | 3556 | mutex_lock(&wm8994->accdet_lock); |
3566 | 3557 | ||
3558 | wm1811_micd_stop(wm8994->hubs.codec); | ||
3559 | |||
3567 | dev_dbg(dev, "Reporting open circuit\n"); | 3560 | dev_dbg(dev, "Reporting open circuit\n"); |
3568 | 3561 | ||
3569 | wm8994->jack_mic = false; | 3562 | wm8994->jack_mic = false; |
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 69266332760e..f16ff4f56923 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -620,15 +620,12 @@ static int bg_event(struct snd_soc_dapm_widget *w, | |||
620 | static int cp_event(struct snd_soc_dapm_widget *w, | 620 | static int cp_event(struct snd_soc_dapm_widget *w, |
621 | struct snd_kcontrol *kcontrol, int event) | 621 | struct snd_kcontrol *kcontrol, int event) |
622 | { | 622 | { |
623 | int ret = 0; | ||
624 | |||
625 | switch (event) { | 623 | switch (event) { |
626 | case SND_SOC_DAPM_POST_PMU: | 624 | case SND_SOC_DAPM_POST_PMU: |
627 | msleep(5); | 625 | msleep(5); |
628 | break; | 626 | break; |
629 | default: | 627 | default: |
630 | WARN(1, "Invalid event %d\n", event); | 628 | WARN(1, "Invalid event %d\n", event); |
631 | ret = -EINVAL; | ||
632 | } | 629 | } |
633 | 630 | ||
634 | return 0; | 631 | return 0; |
@@ -690,8 +687,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask) | |||
690 | static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm, | 687 | static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm, |
691 | enum snd_soc_dapm_type event, int subseq) | 688 | enum snd_soc_dapm_type event, int subseq) |
692 | { | 689 | { |
693 | struct snd_soc_codec *codec = container_of(dapm, | 690 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); |
694 | struct snd_soc_codec, dapm); | ||
695 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 691 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
696 | u16 val, mask; | 692 | u16 val, mask; |
697 | 693 | ||
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index bb9b47b956aa..ab33fe596519 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c | |||
@@ -967,6 +967,7 @@ static struct snd_soc_dai_driver wm8997_dai[] = { | |||
967 | }, | 967 | }, |
968 | .ops = &arizona_dai_ops, | 968 | .ops = &arizona_dai_ops, |
969 | .symmetric_rates = 1, | 969 | .symmetric_rates = 1, |
970 | .symmetric_samplebits = 1, | ||
970 | }, | 971 | }, |
971 | { | 972 | { |
972 | .name = "wm8997-aif2", | 973 | .name = "wm8997-aif2", |
@@ -988,6 +989,7 @@ static struct snd_soc_dai_driver wm8997_dai[] = { | |||
988 | }, | 989 | }, |
989 | .ops = &arizona_dai_ops, | 990 | .ops = &arizona_dai_ops, |
990 | .symmetric_rates = 1, | 991 | .symmetric_rates = 1, |
992 | .symmetric_samplebits = 1, | ||
991 | }, | 993 | }, |
992 | { | 994 | { |
993 | .name = "wm8997-slim1", | 995 | .name = "wm8997-slim1", |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 87934171f063..a13f0725611a 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -613,10 +613,8 @@ static int wm9090_i2c_probe(struct i2c_client *i2c, | |||
613 | int ret; | 613 | int ret; |
614 | 614 | ||
615 | wm9090 = devm_kzalloc(&i2c->dev, sizeof(*wm9090), GFP_KERNEL); | 615 | wm9090 = devm_kzalloc(&i2c->dev, sizeof(*wm9090), GFP_KERNEL); |
616 | if (wm9090 == NULL) { | 616 | if (!wm9090) |
617 | dev_err(&i2c->dev, "Can not allocate memory\n"); | ||
618 | return -ENOMEM; | 617 | return -ENOMEM; |
619 | } | ||
620 | 618 | ||
621 | wm9090->regmap = devm_regmap_init_i2c(i2c, &wm9090_regmap); | 619 | wm9090->regmap = devm_regmap_init_i2c(i2c, &wm9090_regmap); |
622 | if (IS_ERR(wm9090->regmap)) { | 620 | if (IS_ERR(wm9090->regmap)) { |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 060027182dcb..f412a9911a75 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -1382,7 +1382,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
1382 | int ret; | 1382 | int ret; |
1383 | int val; | 1383 | int val; |
1384 | 1384 | ||
1385 | dsp->card = codec->card; | 1385 | dsp->card = codec->component.card; |
1386 | 1386 | ||
1387 | switch (event) { | 1387 | switch (event) { |
1388 | case SND_SOC_DAPM_POST_PMU: | 1388 | case SND_SOC_DAPM_POST_PMU: |
@@ -1617,7 +1617,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, | |||
1617 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | 1617 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); |
1618 | struct wm_adsp *dsp = &dsps[w->shift]; | 1618 | struct wm_adsp *dsp = &dsps[w->shift]; |
1619 | 1619 | ||
1620 | dsp->card = codec->card; | 1620 | dsp->card = codec->component.card; |
1621 | 1621 | ||
1622 | switch (event) { | 1622 | switch (event) { |
1623 | case SND_SOC_DAPM_PRE_PMU: | 1623 | case SND_SOC_DAPM_PRE_PMU: |
@@ -1758,3 +1758,5 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) | |||
1758 | return 0; | 1758 | return 0; |
1759 | } | 1759 | } |
1760 | EXPORT_SYMBOL_GPL(wm_adsp2_init); | 1760 | EXPORT_SYMBOL_GPL(wm_adsp2_init); |
1761 | |||
1762 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 916817fe6632..374537d5e179 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -183,10 +183,8 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg) | |||
183 | return; | 183 | return; |
184 | 184 | ||
185 | cache = devm_kzalloc(codec->dev, sizeof(*cache), GFP_KERNEL); | 185 | cache = devm_kzalloc(codec->dev, sizeof(*cache), GFP_KERNEL); |
186 | if (!cache) { | 186 | if (!cache) |
187 | dev_err(codec->dev, "Failed to allocate DCS cache entry\n"); | ||
188 | return; | 187 | return; |
189 | } | ||
190 | 188 | ||
191 | cache->left = snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME); | 189 | cache->left = snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME); |
192 | cache->left &= WM8993_HPOUT1L_VOL_MASK; | 190 | cache->left &= WM8993_HPOUT1L_VOL_MASK; |
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index 50a098749b9e..d69510c53239 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig | |||
@@ -1,12 +1,29 @@ | |||
1 | config SND_DAVINCI_SOC | 1 | config SND_DAVINCI_SOC |
2 | tristate "SoC Audio for TI DAVINCI or AM33XX/AM43XX chips" | 2 | tristate "SoC Audio for TI DAVINCI" |
3 | depends on ARCH_DAVINCI || SOC_AM33XX || SOC_AM43XX | 3 | depends on ARCH_DAVINCI |
4 | |||
5 | config SND_EDMA_SOC | ||
6 | tristate "SoC Audio for Texas Instruments chips using eDMA (AM33XX/43XX)" | ||
7 | depends on SOC_AM33XX || SOC_AM43XX | ||
8 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
9 | help | ||
10 | Say Y or M here if you want audio support for TI SoC which uses eDMA. | ||
11 | The following line of SoCs are supported by this platform driver: | ||
12 | - AM335x | ||
13 | - AM437x/AM438x | ||
4 | 14 | ||
5 | config SND_DAVINCI_SOC_I2S | 15 | config SND_DAVINCI_SOC_I2S |
6 | tristate | 16 | tristate |
7 | 17 | ||
8 | config SND_DAVINCI_SOC_MCASP | 18 | config SND_DAVINCI_SOC_MCASP |
9 | tristate | 19 | tristate "Multichannel Audio Serial Port (McASP) support" |
20 | depends on SND_DAVINCI_SOC || SND_OMAP_SOC || SND_EDMA_SOC | ||
21 | help | ||
22 | Say Y or M here if you want to have support for McASP IP found in | ||
23 | various Texas Instruments SoCs like: | ||
24 | - daVinci devices | ||
25 | - Sitara line of SoCs (AM335x, AM438x, etc) | ||
26 | - DRA7x devices | ||
10 | 27 | ||
11 | config SND_DAVINCI_SOC_VCIF | 28 | config SND_DAVINCI_SOC_VCIF |
12 | tristate | 29 | tristate |
@@ -18,7 +35,7 @@ config SND_DAVINCI_SOC_GENERIC_EVM | |||
18 | 35 | ||
19 | config SND_AM33XX_SOC_EVM | 36 | config SND_AM33XX_SOC_EVM |
20 | tristate "SoC Audio for the AM33XX chip based boards" | 37 | tristate "SoC Audio for the AM33XX chip based boards" |
21 | depends on SND_DAVINCI_SOC && SOC_AM33XX && I2C | 38 | depends on SND_EDMA_SOC && SOC_AM33XX && I2C |
22 | select SND_DAVINCI_SOC_GENERIC_EVM | 39 | select SND_DAVINCI_SOC_GENERIC_EVM |
23 | help | 40 | help |
24 | Say Y or M if you want to add support for SoC audio on AM33XX | 41 | Say Y or M if you want to add support for SoC audio on AM33XX |
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile index 744d4d9a0184..09bf2ba92d38 100644 --- a/sound/soc/davinci/Makefile +++ b/sound/soc/davinci/Makefile | |||
@@ -1,10 +1,12 @@ | |||
1 | # DAVINCI Platform Support | 1 | # DAVINCI Platform Support |
2 | snd-soc-davinci-objs := davinci-pcm.o | 2 | snd-soc-davinci-objs := davinci-pcm.o |
3 | snd-soc-edma-objs := edma-pcm.o | ||
3 | snd-soc-davinci-i2s-objs := davinci-i2s.o | 4 | snd-soc-davinci-i2s-objs := davinci-i2s.o |
4 | snd-soc-davinci-mcasp-objs:= davinci-mcasp.o | 5 | snd-soc-davinci-mcasp-objs:= davinci-mcasp.o |
5 | snd-soc-davinci-vcif-objs:= davinci-vcif.o | 6 | snd-soc-davinci-vcif-objs:= davinci-vcif.o |
6 | 7 | ||
7 | obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o | 8 | obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o |
9 | obj-$(CONFIG_SND_EDMA_SOC) += snd-soc-edma.o | ||
8 | obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o | 10 | obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o |
9 | obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o | 11 | obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o |
10 | obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o | 12 | obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 9afb14629a17..c28508da34cf 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/of_platform.h> | 27 | #include <linux/of_platform.h> |
28 | #include <linux/of_device.h> | 28 | #include <linux/of_device.h> |
29 | 29 | ||
30 | #include <sound/asoundef.h> | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
32 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
@@ -36,6 +37,7 @@ | |||
36 | #include <sound/omap-pcm.h> | 37 | #include <sound/omap-pcm.h> |
37 | 38 | ||
38 | #include "davinci-pcm.h" | 39 | #include "davinci-pcm.h" |
40 | #include "edma-pcm.h" | ||
39 | #include "davinci-mcasp.h" | 41 | #include "davinci-mcasp.h" |
40 | 42 | ||
41 | #define MCASP_MAX_AFIFO_DEPTH 64 | 43 | #define MCASP_MAX_AFIFO_DEPTH 64 |
@@ -63,6 +65,7 @@ struct davinci_mcasp { | |||
63 | u8 num_serializer; | 65 | u8 num_serializer; |
64 | u8 *serial_dir; | 66 | u8 *serial_dir; |
65 | u8 version; | 67 | u8 version; |
68 | u8 bclk_div; | ||
66 | u16 bclk_lrclk_ratio; | 69 | u16 bclk_lrclk_ratio; |
67 | int streams; | 70 | int streams; |
68 | 71 | ||
@@ -417,6 +420,7 @@ static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div | |||
417 | ACLKXDIV(div - 1), ACLKXDIV_MASK); | 420 | ACLKXDIV(div - 1), ACLKXDIV_MASK); |
418 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, | 421 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, |
419 | ACLKRDIV(div - 1), ACLKRDIV_MASK); | 422 | ACLKRDIV(div - 1), ACLKRDIV_MASK); |
423 | mcasp->bclk_div = div; | ||
420 | break; | 424 | break; |
421 | 425 | ||
422 | case 2: /* BCLK/LRCLK ratio */ | 426 | case 2: /* BCLK/LRCLK ratio */ |
@@ -637,8 +641,12 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream) | |||
637 | } | 641 | } |
638 | 642 | ||
639 | /* S/PDIF */ | 643 | /* S/PDIF */ |
640 | static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp) | 644 | static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, |
645 | unsigned int rate) | ||
641 | { | 646 | { |
647 | u32 cs_value = 0; | ||
648 | u8 *cs_bytes = (u8*) &cs_value; | ||
649 | |||
642 | /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 | 650 | /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 |
643 | and LSB first */ | 651 | and LSB first */ |
644 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15)); | 652 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15)); |
@@ -660,6 +668,46 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp) | |||
660 | /* Enable the DIT */ | 668 | /* Enable the DIT */ |
661 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); | 669 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); |
662 | 670 | ||
671 | /* Set S/PDIF channel status bits */ | ||
672 | cs_bytes[0] = IEC958_AES0_CON_NOT_COPYRIGHT; | ||
673 | cs_bytes[1] = IEC958_AES1_CON_PCM_CODER; | ||
674 | |||
675 | switch (rate) { | ||
676 | case 22050: | ||
677 | cs_bytes[3] |= IEC958_AES3_CON_FS_22050; | ||
678 | break; | ||
679 | case 24000: | ||
680 | cs_bytes[3] |= IEC958_AES3_CON_FS_24000; | ||
681 | break; | ||
682 | case 32000: | ||
683 | cs_bytes[3] |= IEC958_AES3_CON_FS_32000; | ||
684 | break; | ||
685 | case 44100: | ||
686 | cs_bytes[3] |= IEC958_AES3_CON_FS_44100; | ||
687 | break; | ||
688 | case 48000: | ||
689 | cs_bytes[3] |= IEC958_AES3_CON_FS_48000; | ||
690 | break; | ||
691 | case 88200: | ||
692 | cs_bytes[3] |= IEC958_AES3_CON_FS_88200; | ||
693 | break; | ||
694 | case 96000: | ||
695 | cs_bytes[3] |= IEC958_AES3_CON_FS_96000; | ||
696 | break; | ||
697 | case 176400: | ||
698 | cs_bytes[3] |= IEC958_AES3_CON_FS_176400; | ||
699 | break; | ||
700 | case 192000: | ||
701 | cs_bytes[3] |= IEC958_AES3_CON_FS_192000; | ||
702 | break; | ||
703 | default: | ||
704 | printk(KERN_WARNING "unsupported sampling rate: %d\n", rate); | ||
705 | return -EINVAL; | ||
706 | } | ||
707 | |||
708 | mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, cs_value); | ||
709 | mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, cs_value); | ||
710 | |||
663 | return 0; | 711 | return 0; |
664 | } | 712 | } |
665 | 713 | ||
@@ -675,15 +723,22 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
675 | int period_size = params_period_size(params); | 723 | int period_size = params_period_size(params); |
676 | int ret; | 724 | int ret; |
677 | 725 | ||
678 | /* If mcasp is BCLK master we need to set BCLK divider */ | 726 | /* |
679 | if (mcasp->bclk_master) { | 727 | * If mcasp is BCLK master, and a BCLK divider was not provided by |
728 | * the machine driver, we need to calculate the ratio. | ||
729 | */ | ||
730 | if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { | ||
680 | unsigned int bclk_freq = snd_soc_params_to_bclk(params); | 731 | unsigned int bclk_freq = snd_soc_params_to_bclk(params); |
732 | unsigned int div = mcasp->sysclk_freq / bclk_freq; | ||
681 | if (mcasp->sysclk_freq % bclk_freq != 0) { | 733 | if (mcasp->sysclk_freq % bclk_freq != 0) { |
682 | dev_err(mcasp->dev, "Can't produce required BCLK\n"); | 734 | if (((mcasp->sysclk_freq / div) - bclk_freq) > |
683 | return -EINVAL; | 735 | (bclk_freq - (mcasp->sysclk_freq / (div+1)))) |
736 | div++; | ||
737 | dev_warn(mcasp->dev, | ||
738 | "Inaccurate BCLK: %u Hz / %u != %u Hz\n", | ||
739 | mcasp->sysclk_freq, div, bclk_freq); | ||
684 | } | 740 | } |
685 | davinci_mcasp_set_clkdiv( | 741 | davinci_mcasp_set_clkdiv(cpu_dai, 1, div); |
686 | cpu_dai, 1, mcasp->sysclk_freq / bclk_freq); | ||
687 | } | 742 | } |
688 | 743 | ||
689 | ret = mcasp_common_hw_param(mcasp, substream->stream, | 744 | ret = mcasp_common_hw_param(mcasp, substream->stream, |
@@ -692,7 +747,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
692 | return ret; | 747 | return ret; |
693 | 748 | ||
694 | if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) | 749 | if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) |
695 | ret = mcasp_dit_hw_param(mcasp); | 750 | ret = mcasp_dit_hw_param(mcasp, params_rate(params)); |
696 | else | 751 | else |
697 | ret = mcasp_i2s_hw_param(mcasp, substream->stream); | 752 | ret = mcasp_i2s_hw_param(mcasp, substream->stream); |
698 | 753 | ||
@@ -720,6 +775,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
720 | 775 | ||
721 | case SNDRV_PCM_FORMAT_U24_LE: | 776 | case SNDRV_PCM_FORMAT_U24_LE: |
722 | case SNDRV_PCM_FORMAT_S24_LE: | 777 | case SNDRV_PCM_FORMAT_S24_LE: |
778 | dma_params->data_type = 4; | ||
779 | word_length = 24; | ||
780 | break; | ||
781 | |||
723 | case SNDRV_PCM_FORMAT_U32_LE: | 782 | case SNDRV_PCM_FORMAT_U32_LE: |
724 | case SNDRV_PCM_FORMAT_S32_LE: | 783 | case SNDRV_PCM_FORMAT_S32_LE: |
725 | dma_params->data_type = 4; | 784 | dma_params->data_type = 4; |
@@ -778,7 +837,7 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) | |||
778 | { | 837 | { |
779 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); | 838 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); |
780 | 839 | ||
781 | if (mcasp->version == MCASP_VERSION_4) { | 840 | if (mcasp->version >= MCASP_VERSION_3) { |
782 | /* Using dmaengine PCM */ | 841 | /* Using dmaengine PCM */ |
783 | dai->playback_dma_data = | 842 | dai->playback_dma_data = |
784 | &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; | 843 | &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; |
@@ -1223,14 +1282,28 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1223 | goto err; | 1282 | goto err; |
1224 | 1283 | ||
1225 | switch (mcasp->version) { | 1284 | switch (mcasp->version) { |
1285 | #if IS_BUILTIN(CONFIG_SND_DAVINCI_SOC) || \ | ||
1286 | (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ | ||
1287 | IS_MODULE(CONFIG_SND_DAVINCI_SOC)) | ||
1226 | case MCASP_VERSION_1: | 1288 | case MCASP_VERSION_1: |
1227 | case MCASP_VERSION_2: | 1289 | case MCASP_VERSION_2: |
1228 | case MCASP_VERSION_3: | ||
1229 | ret = davinci_soc_platform_register(&pdev->dev); | 1290 | ret = davinci_soc_platform_register(&pdev->dev); |
1230 | break; | 1291 | break; |
1292 | #endif | ||
1293 | #if IS_BUILTIN(CONFIG_SND_EDMA_SOC) || \ | ||
1294 | (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ | ||
1295 | IS_MODULE(CONFIG_SND_EDMA_SOC)) | ||
1296 | case MCASP_VERSION_3: | ||
1297 | ret = edma_pcm_platform_register(&pdev->dev); | ||
1298 | break; | ||
1299 | #endif | ||
1300 | #if IS_BUILTIN(CONFIG_SND_OMAP_SOC) || \ | ||
1301 | (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ | ||
1302 | IS_MODULE(CONFIG_SND_OMAP_SOC)) | ||
1231 | case MCASP_VERSION_4: | 1303 | case MCASP_VERSION_4: |
1232 | ret = omap_pcm_platform_register(&pdev->dev); | 1304 | ret = omap_pcm_platform_register(&pdev->dev); |
1233 | break; | 1305 | break; |
1306 | #endif | ||
1234 | default: | 1307 | default: |
1235 | dev_err(&pdev->dev, "Invalid McASP version: %d\n", | 1308 | dev_err(&pdev->dev, "Invalid McASP version: %d\n", |
1236 | mcasp->version); | 1309 | mcasp->version); |
diff --git a/sound/soc/davinci/edma-pcm.c b/sound/soc/davinci/edma-pcm.c index d38afb1c61ae..605e643133db 100644 --- a/sound/soc/davinci/edma-pcm.c +++ b/sound/soc/davinci/edma-pcm.c | |||
@@ -28,8 +28,8 @@ | |||
28 | static const struct snd_pcm_hardware edma_pcm_hardware = { | 28 | static const struct snd_pcm_hardware edma_pcm_hardware = { |
29 | .info = SNDRV_PCM_INFO_MMAP | | 29 | .info = SNDRV_PCM_INFO_MMAP | |
30 | SNDRV_PCM_INFO_MMAP_VALID | | 30 | SNDRV_PCM_INFO_MMAP_VALID | |
31 | SNDRV_PCM_INFO_BATCH | | ||
32 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | | 31 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | |
32 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP | | ||
33 | SNDRV_PCM_INFO_INTERLEAVED, | 33 | SNDRV_PCM_INFO_INTERLEAVED, |
34 | .buffer_bytes_max = 128 * 1024, | 34 | .buffer_bytes_max = 128 * 1024, |
35 | .period_bytes_min = 32, | 35 | .period_bytes_min = 32, |
diff --git a/sound/soc/davinci/edma-pcm.h b/sound/soc/davinci/edma-pcm.h index 894c378c0f74..b0957744851c 100644 --- a/sound/soc/davinci/edma-pcm.h +++ b/sound/soc/davinci/edma-pcm.h | |||
@@ -20,6 +20,13 @@ | |||
20 | #ifndef __EDMA_PCM_H__ | 20 | #ifndef __EDMA_PCM_H__ |
21 | #define __EDMA_PCM_H__ | 21 | #define __EDMA_PCM_H__ |
22 | 22 | ||
23 | #if IS_ENABLED(CONFIG_SND_EDMA_SOC) | ||
23 | int edma_pcm_platform_register(struct device *dev); | 24 | int edma_pcm_platform_register(struct device *dev); |
25 | #else | ||
26 | static inline int edma_pcm_platform_register(struct device *dev) | ||
27 | { | ||
28 | return 0; | ||
29 | } | ||
30 | #endif /* CONFIG_SND_EDMA_SOC */ | ||
24 | 31 | ||
25 | #endif /* __EDMA_PCM_H__ */ | 32 | #endif /* __EDMA_PCM_H__ */ |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 37933629cbed..f54a8fc99291 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -2,9 +2,20 @@ menu "SoC Audio for Freescale CPUs" | |||
2 | 2 | ||
3 | comment "Common SoC Audio options for Freescale CPUs:" | 3 | comment "Common SoC Audio options for Freescale CPUs:" |
4 | 4 | ||
5 | config SND_SOC_FSL_ASRC | ||
6 | tristate "Asynchronous Sample Rate Converter (ASRC) module support" | ||
7 | select REGMAP_MMIO | ||
8 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
9 | help | ||
10 | Say Y if you want to add Asynchronous Sample Rate Converter (ASRC) | ||
11 | support for the Freescale CPUs. | ||
12 | This option is only useful for out-of-tree drivers since | ||
13 | in-tree drivers select it automatically. | ||
14 | |||
5 | config SND_SOC_FSL_SAI | 15 | config SND_SOC_FSL_SAI |
6 | tristate "Synchronous Audio Interface (SAI) module support" | 16 | tristate "Synchronous Audio Interface (SAI) module support" |
7 | select REGMAP_MMIO | 17 | select REGMAP_MMIO |
18 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n | ||
8 | select SND_SOC_GENERIC_DMAENGINE_PCM | 19 | select SND_SOC_GENERIC_DMAENGINE_PCM |
9 | help | 20 | help |
10 | Say Y if you want to add Synchronous Audio Interface (SAI) | 21 | Say Y if you want to add Synchronous Audio Interface (SAI) |
@@ -15,7 +26,7 @@ config SND_SOC_FSL_SAI | |||
15 | config SND_SOC_FSL_SSI | 26 | config SND_SOC_FSL_SSI |
16 | tristate "Synchronous Serial Interface module support" | 27 | tristate "Synchronous Serial Interface module support" |
17 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n | 28 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n |
18 | select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && ARCH_MXC | 29 | select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && (MXC_TZIC || MXC_AVIC) |
19 | select REGMAP_MMIO | 30 | select REGMAP_MMIO |
20 | help | 31 | help |
21 | Say Y if you want to add Synchronous Serial Interface (SSI) | 32 | Say Y if you want to add Synchronous Serial Interface (SSI) |
@@ -27,7 +38,7 @@ config SND_SOC_FSL_SPDIF | |||
27 | tristate "Sony/Philips Digital Interface module support" | 38 | tristate "Sony/Philips Digital Interface module support" |
28 | select REGMAP_MMIO | 39 | select REGMAP_MMIO |
29 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n | 40 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n |
30 | select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && ARCH_MXC | 41 | select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && (MXC_TZIC || MXC_AVIC) |
31 | help | 42 | help |
32 | Say Y if you want to add Sony/Philips Digital Interface (SPDIF) | 43 | Say Y if you want to add Sony/Philips Digital Interface (SPDIF) |
33 | support for the Freescale CPUs. | 44 | support for the Freescale CPUs. |
@@ -37,6 +48,7 @@ config SND_SOC_FSL_SPDIF | |||
37 | config SND_SOC_FSL_ESAI | 48 | config SND_SOC_FSL_ESAI |
38 | tristate "Enhanced Serial Audio Interface (ESAI) module support" | 49 | tristate "Enhanced Serial Audio Interface (ESAI) module support" |
39 | select REGMAP_MMIO | 50 | select REGMAP_MMIO |
51 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n | ||
40 | select SND_SOC_FSL_UTILS | 52 | select SND_SOC_FSL_UTILS |
41 | help | 53 | help |
42 | Say Y if you want to add Enhanced Synchronous Audio Interface | 54 | Say Y if you want to add Enhanced Synchronous Audio Interface |
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index db254e358c18..9ff59267eac9 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
@@ -11,6 +11,7 @@ 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 SSI/DMA/SAI/SPDIF Support | 13 | # Freescale SSI/DMA/SAI/SPDIF Support |
14 | snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o | ||
14 | snd-soc-fsl-sai-objs := fsl_sai.o | 15 | snd-soc-fsl-sai-objs := fsl_sai.o |
15 | snd-soc-fsl-ssi-y := fsl_ssi.o | 16 | snd-soc-fsl-ssi-y := fsl_ssi.o |
16 | snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o | 17 | snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o |
@@ -18,6 +19,7 @@ snd-soc-fsl-spdif-objs := fsl_spdif.o | |||
18 | snd-soc-fsl-esai-objs := fsl_esai.o | 19 | snd-soc-fsl-esai-objs := fsl_esai.o |
19 | snd-soc-fsl-utils-objs := fsl_utils.o | 20 | snd-soc-fsl-utils-objs := fsl_utils.o |
20 | snd-soc-fsl-dma-objs := fsl_dma.o | 21 | snd-soc-fsl-dma-objs := fsl_dma.o |
22 | obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o | ||
21 | obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o | 23 | obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o |
22 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o | 24 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o |
23 | obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o | 25 | obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o |
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c new file mode 100644 index 000000000000..822110420b71 --- /dev/null +++ b/sound/soc/fsl/fsl_asrc.c | |||
@@ -0,0 +1,995 @@ | |||
1 | /* | ||
2 | * Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Nicolin Chen <nicoleotsuka@gmail.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 | #include <linux/clk.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/dma-mapping.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/of_platform.h> | ||
18 | #include <linux/platform_data/dma-imx.h> | ||
19 | #include <linux/pm_runtime.h> | ||
20 | #include <sound/dmaengine_pcm.h> | ||
21 | #include <sound/pcm_params.h> | ||
22 | |||
23 | #include "fsl_asrc.h" | ||
24 | |||
25 | #define IDEAL_RATIO_DECIMAL_DEPTH 26 | ||
26 | |||
27 | #define pair_err(fmt, ...) \ | ||
28 | dev_err(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) | ||
29 | |||
30 | #define pair_dbg(fmt, ...) \ | ||
31 | dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) | ||
32 | |||
33 | /* Sample rates are aligned with that defined in pcm.h file */ | ||
34 | static const u8 process_option[][8][2] = { | ||
35 | /* 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */ | ||
36 | {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */ | ||
37 | {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */ | ||
38 | {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */ | ||
39 | {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */ | ||
40 | {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */ | ||
41 | {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */ | ||
42 | {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */ | ||
43 | {{0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */ | ||
44 | {{1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */ | ||
45 | {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */ | ||
46 | {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */ | ||
47 | {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */ | ||
48 | {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */ | ||
49 | }; | ||
50 | |||
51 | /* Corresponding to process_option */ | ||
52 | static int supported_input_rate[] = { | ||
53 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, | ||
54 | 96000, 176400, 192000, | ||
55 | }; | ||
56 | |||
57 | static int supported_asrc_rate[] = { | ||
58 | 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000, | ||
59 | }; | ||
60 | |||
61 | /** | ||
62 | * The following tables map the relationship between asrc_inclk/asrc_outclk in | ||
63 | * fsl_asrc.h and the registers of ASRCSR | ||
64 | */ | ||
65 | static unsigned char input_clk_map_imx35[] = { | ||
66 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, | ||
67 | }; | ||
68 | |||
69 | static unsigned char output_clk_map_imx35[] = { | ||
70 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, | ||
71 | }; | ||
72 | |||
73 | /* i.MX53 uses the same map for input and output */ | ||
74 | static unsigned char input_clk_map_imx53[] = { | ||
75 | /* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */ | ||
76 | 0x0, 0x1, 0x2, 0x7, 0x4, 0x5, 0x6, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0xe, 0xd, | ||
77 | }; | ||
78 | |||
79 | static unsigned char output_clk_map_imx53[] = { | ||
80 | /* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */ | ||
81 | 0x8, 0x9, 0xa, 0x7, 0xc, 0x5, 0x6, 0xb, 0x0, 0x1, 0x2, 0x3, 0x4, 0xf, 0xe, 0xd, | ||
82 | }; | ||
83 | |||
84 | static unsigned char *clk_map[2]; | ||
85 | |||
86 | /** | ||
87 | * Request ASRC pair | ||
88 | * | ||
89 | * It assigns pair by the order of A->C->B because allocation of pair B, | ||
90 | * within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A | ||
91 | * while pair A and pair C are comparatively independent. | ||
92 | */ | ||
93 | static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair) | ||
94 | { | ||
95 | enum asrc_pair_index index = ASRC_INVALID_PAIR; | ||
96 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
97 | struct device *dev = &asrc_priv->pdev->dev; | ||
98 | unsigned long lock_flags; | ||
99 | int i, ret = 0; | ||
100 | |||
101 | spin_lock_irqsave(&asrc_priv->lock, lock_flags); | ||
102 | |||
103 | for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) { | ||
104 | if (asrc_priv->pair[i] != NULL) | ||
105 | continue; | ||
106 | |||
107 | index = i; | ||
108 | |||
109 | if (i != ASRC_PAIR_B) | ||
110 | break; | ||
111 | } | ||
112 | |||
113 | if (index == ASRC_INVALID_PAIR) { | ||
114 | dev_err(dev, "all pairs are busy now\n"); | ||
115 | ret = -EBUSY; | ||
116 | } else if (asrc_priv->channel_avail < channels) { | ||
117 | dev_err(dev, "can't afford required channels: %d\n", channels); | ||
118 | ret = -EINVAL; | ||
119 | } else { | ||
120 | asrc_priv->channel_avail -= channels; | ||
121 | asrc_priv->pair[index] = pair; | ||
122 | pair->channels = channels; | ||
123 | pair->index = index; | ||
124 | } | ||
125 | |||
126 | spin_unlock_irqrestore(&asrc_priv->lock, lock_flags); | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * Release ASRC pair | ||
133 | * | ||
134 | * It clears the resource from asrc_priv and releases the occupied channels. | ||
135 | */ | ||
136 | static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair) | ||
137 | { | ||
138 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
139 | enum asrc_pair_index index = pair->index; | ||
140 | unsigned long lock_flags; | ||
141 | |||
142 | /* Make sure the pair is disabled */ | ||
143 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
144 | ASRCTR_ASRCEi_MASK(index), 0); | ||
145 | |||
146 | spin_lock_irqsave(&asrc_priv->lock, lock_flags); | ||
147 | |||
148 | asrc_priv->channel_avail += pair->channels; | ||
149 | asrc_priv->pair[index] = NULL; | ||
150 | pair->error = 0; | ||
151 | |||
152 | spin_unlock_irqrestore(&asrc_priv->lock, lock_flags); | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * Configure input and output thresholds | ||
157 | */ | ||
158 | static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out) | ||
159 | { | ||
160 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
161 | enum asrc_pair_index index = pair->index; | ||
162 | |||
163 | regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index), | ||
164 | ASRMCRi_EXTTHRSHi_MASK | | ||
165 | ASRMCRi_INFIFO_THRESHOLD_MASK | | ||
166 | ASRMCRi_OUTFIFO_THRESHOLD_MASK, | ||
167 | ASRMCRi_EXTTHRSHi | | ||
168 | ASRMCRi_INFIFO_THRESHOLD(in) | | ||
169 | ASRMCRi_OUTFIFO_THRESHOLD(out)); | ||
170 | } | ||
171 | |||
172 | /** | ||
173 | * Calculate the total divisor between asrck clock rate and sample rate | ||
174 | * | ||
175 | * It follows the formula clk_rate = samplerate * (2 ^ prescaler) * divider | ||
176 | */ | ||
177 | static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair *pair, u32 div) | ||
178 | { | ||
179 | u32 ps; | ||
180 | |||
181 | /* Calculate the divisors: prescaler [2^0, 2^7], divder [1, 8] */ | ||
182 | for (ps = 0; div > 8; ps++) | ||
183 | div >>= 1; | ||
184 | |||
185 | return ((div - 1) << ASRCDRi_AxCPi_WIDTH) | ps; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * Calculate and set the ratio for Ideal Ratio mode only | ||
190 | * | ||
191 | * The ratio is a 32-bit fixed point value with 26 fractional bits. | ||
192 | */ | ||
193 | static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair, | ||
194 | int inrate, int outrate) | ||
195 | { | ||
196 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
197 | enum asrc_pair_index index = pair->index; | ||
198 | unsigned long ratio; | ||
199 | int i; | ||
200 | |||
201 | if (!outrate) { | ||
202 | pair_err("output rate should not be zero\n"); | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | |||
206 | /* Calculate the intergal part of the ratio */ | ||
207 | ratio = (inrate / outrate) << IDEAL_RATIO_DECIMAL_DEPTH; | ||
208 | |||
209 | /* ... and then the 26 depth decimal part */ | ||
210 | inrate %= outrate; | ||
211 | |||
212 | for (i = 1; i <= IDEAL_RATIO_DECIMAL_DEPTH; i++) { | ||
213 | inrate <<= 1; | ||
214 | |||
215 | if (inrate < outrate) | ||
216 | continue; | ||
217 | |||
218 | ratio |= 1 << (IDEAL_RATIO_DECIMAL_DEPTH - i); | ||
219 | inrate -= outrate; | ||
220 | |||
221 | if (!inrate) | ||
222 | break; | ||
223 | } | ||
224 | |||
225 | regmap_write(asrc_priv->regmap, REG_ASRIDRL(index), ratio); | ||
226 | regmap_write(asrc_priv->regmap, REG_ASRIDRH(index), ratio >> 24); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | /** | ||
232 | * Configure the assigned ASRC pair | ||
233 | * | ||
234 | * It configures those ASRC registers according to a configuration instance | ||
235 | * of struct asrc_config which includes in/output sample rate, width, channel | ||
236 | * and clock settings. | ||
237 | */ | ||
238 | static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) | ||
239 | { | ||
240 | struct asrc_config *config = pair->config; | ||
241 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
242 | enum asrc_pair_index index = pair->index; | ||
243 | u32 inrate, outrate, indiv, outdiv; | ||
244 | u32 clk_index[2], div[2]; | ||
245 | int in, out, channels; | ||
246 | struct clk *clk; | ||
247 | bool ideal; | ||
248 | |||
249 | if (!config) { | ||
250 | pair_err("invalid pair config\n"); | ||
251 | return -EINVAL; | ||
252 | } | ||
253 | |||
254 | /* Validate channels */ | ||
255 | if (config->channel_num < 1 || config->channel_num > 10) { | ||
256 | pair_err("does not support %d channels\n", config->channel_num); | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
260 | /* Validate output width */ | ||
261 | if (config->output_word_width == ASRC_WIDTH_8_BIT) { | ||
262 | pair_err("does not support 8bit width output\n"); | ||
263 | return -EINVAL; | ||
264 | } | ||
265 | |||
266 | inrate = config->input_sample_rate; | ||
267 | outrate = config->output_sample_rate; | ||
268 | ideal = config->inclk == INCLK_NONE; | ||
269 | |||
270 | /* Validate input and output sample rates */ | ||
271 | for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++) | ||
272 | if (inrate == supported_input_rate[in]) | ||
273 | break; | ||
274 | |||
275 | if (in == ARRAY_SIZE(supported_input_rate)) { | ||
276 | pair_err("unsupported input sample rate: %dHz\n", inrate); | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
280 | for (out = 0; out < ARRAY_SIZE(supported_asrc_rate); out++) | ||
281 | if (outrate == supported_asrc_rate[out]) | ||
282 | break; | ||
283 | |||
284 | if (out == ARRAY_SIZE(supported_asrc_rate)) { | ||
285 | pair_err("unsupported output sample rate: %dHz\n", outrate); | ||
286 | return -EINVAL; | ||
287 | } | ||
288 | |||
289 | /* Validate input and output clock sources */ | ||
290 | clk_index[IN] = clk_map[IN][config->inclk]; | ||
291 | clk_index[OUT] = clk_map[OUT][config->outclk]; | ||
292 | |||
293 | /* We only have output clock for ideal ratio mode */ | ||
294 | clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]]; | ||
295 | |||
296 | div[IN] = clk_get_rate(clk) / inrate; | ||
297 | if (div[IN] == 0) { | ||
298 | pair_err("failed to support input sample rate %dHz by asrck_%x\n", | ||
299 | inrate, clk_index[ideal ? OUT : IN]); | ||
300 | return -EINVAL; | ||
301 | } | ||
302 | |||
303 | clk = asrc_priv->asrck_clk[clk_index[OUT]]; | ||
304 | |||
305 | /* Use fixed output rate for Ideal Ratio mode (INCLK_NONE) */ | ||
306 | if (ideal) | ||
307 | div[OUT] = clk_get_rate(clk) / IDEAL_RATIO_RATE; | ||
308 | else | ||
309 | div[OUT] = clk_get_rate(clk) / outrate; | ||
310 | |||
311 | if (div[OUT] == 0) { | ||
312 | pair_err("failed to support output sample rate %dHz by asrck_%x\n", | ||
313 | outrate, clk_index[OUT]); | ||
314 | return -EINVAL; | ||
315 | } | ||
316 | |||
317 | /* Set the channel number */ | ||
318 | channels = config->channel_num; | ||
319 | |||
320 | if (asrc_priv->channel_bits < 4) | ||
321 | channels /= 2; | ||
322 | |||
323 | /* Update channels for current pair */ | ||
324 | regmap_update_bits(asrc_priv->regmap, REG_ASRCNCR, | ||
325 | ASRCNCR_ANCi_MASK(index, asrc_priv->channel_bits), | ||
326 | ASRCNCR_ANCi(index, channels, asrc_priv->channel_bits)); | ||
327 | |||
328 | /* Default setting: Automatic selection for processing mode */ | ||
329 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
330 | ASRCTR_ATSi_MASK(index), ASRCTR_ATS(index)); | ||
331 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
332 | ASRCTR_USRi_MASK(index), 0); | ||
333 | |||
334 | /* Set the input and output clock sources */ | ||
335 | regmap_update_bits(asrc_priv->regmap, REG_ASRCSR, | ||
336 | ASRCSR_AICSi_MASK(index) | ASRCSR_AOCSi_MASK(index), | ||
337 | ASRCSR_AICS(index, clk_index[IN]) | | ||
338 | ASRCSR_AOCS(index, clk_index[OUT])); | ||
339 | |||
340 | /* Calculate the input clock divisors */ | ||
341 | indiv = fsl_asrc_cal_asrck_divisor(pair, div[IN]); | ||
342 | outdiv = fsl_asrc_cal_asrck_divisor(pair, div[OUT]); | ||
343 | |||
344 | /* Suppose indiv and outdiv includes prescaler, so add its MASK too */ | ||
345 | regmap_update_bits(asrc_priv->regmap, REG_ASRCDR(index), | ||
346 | ASRCDRi_AOCPi_MASK(index) | ASRCDRi_AICPi_MASK(index) | | ||
347 | ASRCDRi_AOCDi_MASK(index) | ASRCDRi_AICDi_MASK(index), | ||
348 | ASRCDRi_AOCP(index, outdiv) | ASRCDRi_AICP(index, indiv)); | ||
349 | |||
350 | /* Implement word_width configurations */ | ||
351 | regmap_update_bits(asrc_priv->regmap, REG_ASRMCR1(index), | ||
352 | ASRMCR1i_OW16_MASK | ASRMCR1i_IWD_MASK, | ||
353 | ASRMCR1i_OW16(config->output_word_width) | | ||
354 | ASRMCR1i_IWD(config->input_word_width)); | ||
355 | |||
356 | /* Enable BUFFER STALL */ | ||
357 | regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index), | ||
358 | ASRMCRi_BUFSTALLi_MASK, ASRMCRi_BUFSTALLi); | ||
359 | |||
360 | /* Set default thresholds for input and output FIFO */ | ||
361 | fsl_asrc_set_watermarks(pair, ASRC_INPUTFIFO_THRESHOLD, | ||
362 | ASRC_INPUTFIFO_THRESHOLD); | ||
363 | |||
364 | /* Configure the followings only for Ideal Ratio mode */ | ||
365 | if (!ideal) | ||
366 | return 0; | ||
367 | |||
368 | /* Clear ASTSx bit to use Ideal Ratio mode */ | ||
369 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
370 | ASRCTR_ATSi_MASK(index), 0); | ||
371 | |||
372 | /* Enable Ideal Ratio mode */ | ||
373 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
374 | ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index), | ||
375 | ASRCTR_IDR(index) | ASRCTR_USR(index)); | ||
376 | |||
377 | /* Apply configurations for pre- and post-processing */ | ||
378 | regmap_update_bits(asrc_priv->regmap, REG_ASRCFG, | ||
379 | ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index), | ||
380 | ASRCFG_PREMOD(index, process_option[in][out][0]) | | ||
381 | ASRCFG_POSTMOD(index, process_option[in][out][1])); | ||
382 | |||
383 | return fsl_asrc_set_ideal_ratio(pair, inrate, outrate); | ||
384 | } | ||
385 | |||
386 | /** | ||
387 | * Start the assigned ASRC pair | ||
388 | * | ||
389 | * It enables the assigned pair and makes it stopped at the stall level. | ||
390 | */ | ||
391 | static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair) | ||
392 | { | ||
393 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
394 | enum asrc_pair_index index = pair->index; | ||
395 | int reg, retry = 10, i; | ||
396 | |||
397 | /* Enable the current pair */ | ||
398 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
399 | ASRCTR_ASRCEi_MASK(index), ASRCTR_ASRCE(index)); | ||
400 | |||
401 | /* Wait for status of initialization */ | ||
402 | do { | ||
403 | udelay(5); | ||
404 | regmap_read(asrc_priv->regmap, REG_ASRCFG, ®); | ||
405 | reg &= ASRCFG_INIRQi_MASK(index); | ||
406 | } while (!reg && --retry); | ||
407 | |||
408 | /* Make the input fifo to ASRC STALL level */ | ||
409 | regmap_read(asrc_priv->regmap, REG_ASRCNCR, ®); | ||
410 | for (i = 0; i < pair->channels * 4; i++) | ||
411 | regmap_write(asrc_priv->regmap, REG_ASRDI(index), 0); | ||
412 | |||
413 | /* Enable overload interrupt */ | ||
414 | regmap_write(asrc_priv->regmap, REG_ASRIER, ASRIER_AOLIE); | ||
415 | } | ||
416 | |||
417 | /** | ||
418 | * Stop the assigned ASRC pair | ||
419 | */ | ||
420 | static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair) | ||
421 | { | ||
422 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
423 | enum asrc_pair_index index = pair->index; | ||
424 | |||
425 | /* Stop the current pair */ | ||
426 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
427 | ASRCTR_ASRCEi_MASK(index), 0); | ||
428 | } | ||
429 | |||
430 | /** | ||
431 | * Get DMA channel according to the pair and direction. | ||
432 | */ | ||
433 | struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir) | ||
434 | { | ||
435 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
436 | enum asrc_pair_index index = pair->index; | ||
437 | char name[4]; | ||
438 | |||
439 | sprintf(name, "%cx%c", dir == IN ? 'r' : 't', index + 'a'); | ||
440 | |||
441 | return dma_request_slave_channel(&asrc_priv->pdev->dev, name); | ||
442 | } | ||
443 | EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel); | ||
444 | |||
445 | static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, | ||
446 | struct snd_pcm_hw_params *params, | ||
447 | struct snd_soc_dai *dai) | ||
448 | { | ||
449 | struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai); | ||
450 | int width = snd_pcm_format_width(params_format(params)); | ||
451 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
452 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
453 | unsigned int channels = params_channels(params); | ||
454 | unsigned int rate = params_rate(params); | ||
455 | struct asrc_config config; | ||
456 | int word_width, ret; | ||
457 | |||
458 | ret = fsl_asrc_request_pair(channels, pair); | ||
459 | if (ret) { | ||
460 | dev_err(dai->dev, "fail to request asrc pair\n"); | ||
461 | return ret; | ||
462 | } | ||
463 | |||
464 | pair->config = &config; | ||
465 | |||
466 | if (width == 16) | ||
467 | width = ASRC_WIDTH_16_BIT; | ||
468 | else | ||
469 | width = ASRC_WIDTH_24_BIT; | ||
470 | |||
471 | if (asrc_priv->asrc_width == 16) | ||
472 | word_width = ASRC_WIDTH_16_BIT; | ||
473 | else | ||
474 | word_width = ASRC_WIDTH_24_BIT; | ||
475 | |||
476 | config.pair = pair->index; | ||
477 | config.channel_num = channels; | ||
478 | config.inclk = INCLK_NONE; | ||
479 | config.outclk = OUTCLK_ASRCK1_CLK; | ||
480 | |||
481 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
482 | config.input_word_width = width; | ||
483 | config.output_word_width = word_width; | ||
484 | config.input_sample_rate = rate; | ||
485 | config.output_sample_rate = asrc_priv->asrc_rate; | ||
486 | } else { | ||
487 | config.input_word_width = word_width; | ||
488 | config.output_word_width = width; | ||
489 | config.input_sample_rate = asrc_priv->asrc_rate; | ||
490 | config.output_sample_rate = rate; | ||
491 | } | ||
492 | |||
493 | ret = fsl_asrc_config_pair(pair); | ||
494 | if (ret) { | ||
495 | dev_err(dai->dev, "fail to config asrc pair\n"); | ||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static int fsl_asrc_dai_hw_free(struct snd_pcm_substream *substream, | ||
503 | struct snd_soc_dai *dai) | ||
504 | { | ||
505 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
506 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
507 | |||
508 | if (pair) | ||
509 | fsl_asrc_release_pair(pair); | ||
510 | |||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static int fsl_asrc_dai_trigger(struct snd_pcm_substream *substream, int cmd, | ||
515 | struct snd_soc_dai *dai) | ||
516 | { | ||
517 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
518 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
519 | |||
520 | switch (cmd) { | ||
521 | case SNDRV_PCM_TRIGGER_START: | ||
522 | case SNDRV_PCM_TRIGGER_RESUME: | ||
523 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
524 | fsl_asrc_start_pair(pair); | ||
525 | break; | ||
526 | case SNDRV_PCM_TRIGGER_STOP: | ||
527 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
528 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
529 | fsl_asrc_stop_pair(pair); | ||
530 | break; | ||
531 | default: | ||
532 | return -EINVAL; | ||
533 | } | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static struct snd_soc_dai_ops fsl_asrc_dai_ops = { | ||
539 | .hw_params = fsl_asrc_dai_hw_params, | ||
540 | .hw_free = fsl_asrc_dai_hw_free, | ||
541 | .trigger = fsl_asrc_dai_trigger, | ||
542 | }; | ||
543 | |||
544 | static int fsl_asrc_dai_probe(struct snd_soc_dai *dai) | ||
545 | { | ||
546 | struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai); | ||
547 | |||
548 | snd_soc_dai_init_dma_data(dai, &asrc_priv->dma_params_tx, | ||
549 | &asrc_priv->dma_params_rx); | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | #define FSL_ASRC_RATES SNDRV_PCM_RATE_8000_192000 | ||
555 | #define FSL_ASRC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \ | ||
556 | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
557 | SNDRV_PCM_FMTBIT_S20_3LE) | ||
558 | |||
559 | static struct snd_soc_dai_driver fsl_asrc_dai = { | ||
560 | .probe = fsl_asrc_dai_probe, | ||
561 | .playback = { | ||
562 | .stream_name = "ASRC-Playback", | ||
563 | .channels_min = 1, | ||
564 | .channels_max = 10, | ||
565 | .rates = FSL_ASRC_RATES, | ||
566 | .formats = FSL_ASRC_FORMATS, | ||
567 | }, | ||
568 | .capture = { | ||
569 | .stream_name = "ASRC-Capture", | ||
570 | .channels_min = 1, | ||
571 | .channels_max = 10, | ||
572 | .rates = FSL_ASRC_RATES, | ||
573 | .formats = FSL_ASRC_FORMATS, | ||
574 | }, | ||
575 | .ops = &fsl_asrc_dai_ops, | ||
576 | }; | ||
577 | |||
578 | static const struct snd_soc_component_driver fsl_asrc_component = { | ||
579 | .name = "fsl-asrc-dai", | ||
580 | }; | ||
581 | |||
582 | static bool fsl_asrc_readable_reg(struct device *dev, unsigned int reg) | ||
583 | { | ||
584 | switch (reg) { | ||
585 | case REG_ASRCTR: | ||
586 | case REG_ASRIER: | ||
587 | case REG_ASRCNCR: | ||
588 | case REG_ASRCFG: | ||
589 | case REG_ASRCSR: | ||
590 | case REG_ASRCDR1: | ||
591 | case REG_ASRCDR2: | ||
592 | case REG_ASRSTR: | ||
593 | case REG_ASRPM1: | ||
594 | case REG_ASRPM2: | ||
595 | case REG_ASRPM3: | ||
596 | case REG_ASRPM4: | ||
597 | case REG_ASRPM5: | ||
598 | case REG_ASRTFR1: | ||
599 | case REG_ASRCCR: | ||
600 | case REG_ASRDOA: | ||
601 | case REG_ASRDOB: | ||
602 | case REG_ASRDOC: | ||
603 | case REG_ASRIDRHA: | ||
604 | case REG_ASRIDRLA: | ||
605 | case REG_ASRIDRHB: | ||
606 | case REG_ASRIDRLB: | ||
607 | case REG_ASRIDRHC: | ||
608 | case REG_ASRIDRLC: | ||
609 | case REG_ASR76K: | ||
610 | case REG_ASR56K: | ||
611 | case REG_ASRMCRA: | ||
612 | case REG_ASRFSTA: | ||
613 | case REG_ASRMCRB: | ||
614 | case REG_ASRFSTB: | ||
615 | case REG_ASRMCRC: | ||
616 | case REG_ASRFSTC: | ||
617 | case REG_ASRMCR1A: | ||
618 | case REG_ASRMCR1B: | ||
619 | case REG_ASRMCR1C: | ||
620 | return true; | ||
621 | default: | ||
622 | return false; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | static bool fsl_asrc_volatile_reg(struct device *dev, unsigned int reg) | ||
627 | { | ||
628 | switch (reg) { | ||
629 | case REG_ASRSTR: | ||
630 | case REG_ASRDIA: | ||
631 | case REG_ASRDIB: | ||
632 | case REG_ASRDIC: | ||
633 | case REG_ASRDOA: | ||
634 | case REG_ASRDOB: | ||
635 | case REG_ASRDOC: | ||
636 | case REG_ASRFSTA: | ||
637 | case REG_ASRFSTB: | ||
638 | case REG_ASRFSTC: | ||
639 | case REG_ASRCFG: | ||
640 | return true; | ||
641 | default: | ||
642 | return false; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg) | ||
647 | { | ||
648 | switch (reg) { | ||
649 | case REG_ASRCTR: | ||
650 | case REG_ASRIER: | ||
651 | case REG_ASRCNCR: | ||
652 | case REG_ASRCFG: | ||
653 | case REG_ASRCSR: | ||
654 | case REG_ASRCDR1: | ||
655 | case REG_ASRCDR2: | ||
656 | case REG_ASRSTR: | ||
657 | case REG_ASRPM1: | ||
658 | case REG_ASRPM2: | ||
659 | case REG_ASRPM3: | ||
660 | case REG_ASRPM4: | ||
661 | case REG_ASRPM5: | ||
662 | case REG_ASRTFR1: | ||
663 | case REG_ASRCCR: | ||
664 | case REG_ASRDIA: | ||
665 | case REG_ASRDIB: | ||
666 | case REG_ASRDIC: | ||
667 | case REG_ASRIDRHA: | ||
668 | case REG_ASRIDRLA: | ||
669 | case REG_ASRIDRHB: | ||
670 | case REG_ASRIDRLB: | ||
671 | case REG_ASRIDRHC: | ||
672 | case REG_ASRIDRLC: | ||
673 | case REG_ASR76K: | ||
674 | case REG_ASR56K: | ||
675 | case REG_ASRMCRA: | ||
676 | case REG_ASRMCRB: | ||
677 | case REG_ASRMCRC: | ||
678 | case REG_ASRMCR1A: | ||
679 | case REG_ASRMCR1B: | ||
680 | case REG_ASRMCR1C: | ||
681 | return true; | ||
682 | default: | ||
683 | return false; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | static struct regmap_config fsl_asrc_regmap_config = { | ||
688 | .reg_bits = 32, | ||
689 | .reg_stride = 4, | ||
690 | .val_bits = 32, | ||
691 | |||
692 | .max_register = REG_ASRMCR1C, | ||
693 | .readable_reg = fsl_asrc_readable_reg, | ||
694 | .volatile_reg = fsl_asrc_volatile_reg, | ||
695 | .writeable_reg = fsl_asrc_writeable_reg, | ||
696 | .cache_type = REGCACHE_RBTREE, | ||
697 | }; | ||
698 | |||
699 | /** | ||
700 | * Initialize ASRC registers with a default configurations | ||
701 | */ | ||
702 | static int fsl_asrc_init(struct fsl_asrc *asrc_priv) | ||
703 | { | ||
704 | /* Halt ASRC internal FP when input FIFO needs data for pair A, B, C */ | ||
705 | regmap_write(asrc_priv->regmap, REG_ASRCTR, ASRCTR_ASRCEN); | ||
706 | |||
707 | /* Disable interrupt by default */ | ||
708 | regmap_write(asrc_priv->regmap, REG_ASRIER, 0x0); | ||
709 | |||
710 | /* Apply recommended settings for parameters from Reference Manual */ | ||
711 | regmap_write(asrc_priv->regmap, REG_ASRPM1, 0x7fffff); | ||
712 | regmap_write(asrc_priv->regmap, REG_ASRPM2, 0x255555); | ||
713 | regmap_write(asrc_priv->regmap, REG_ASRPM3, 0xff7280); | ||
714 | regmap_write(asrc_priv->regmap, REG_ASRPM4, 0xff7280); | ||
715 | regmap_write(asrc_priv->regmap, REG_ASRPM5, 0xff7280); | ||
716 | |||
717 | /* Base address for task queue FIFO. Set to 0x7C */ | ||
718 | regmap_update_bits(asrc_priv->regmap, REG_ASRTFR1, | ||
719 | ASRTFR1_TF_BASE_MASK, ASRTFR1_TF_BASE(0xfc)); | ||
720 | |||
721 | /* Set the processing clock for 76KHz to 133M */ | ||
722 | regmap_write(asrc_priv->regmap, REG_ASR76K, 0x06D6); | ||
723 | |||
724 | /* Set the processing clock for 56KHz to 133M */ | ||
725 | return regmap_write(asrc_priv->regmap, REG_ASR56K, 0x0947); | ||
726 | } | ||
727 | |||
728 | /** | ||
729 | * Interrupt handler for ASRC | ||
730 | */ | ||
731 | static irqreturn_t fsl_asrc_isr(int irq, void *dev_id) | ||
732 | { | ||
733 | struct fsl_asrc *asrc_priv = (struct fsl_asrc *)dev_id; | ||
734 | struct device *dev = &asrc_priv->pdev->dev; | ||
735 | enum asrc_pair_index index; | ||
736 | u32 status; | ||
737 | |||
738 | regmap_read(asrc_priv->regmap, REG_ASRSTR, &status); | ||
739 | |||
740 | /* Clean overload error */ | ||
741 | regmap_write(asrc_priv->regmap, REG_ASRSTR, ASRSTR_AOLE); | ||
742 | |||
743 | /* | ||
744 | * We here use dev_dbg() for all exceptions because ASRC itself does | ||
745 | * not care if FIFO overflowed or underrun while a warning in the | ||
746 | * interrupt would result a ridged conversion. | ||
747 | */ | ||
748 | for (index = ASRC_PAIR_A; index < ASRC_PAIR_MAX_NUM; index++) { | ||
749 | if (!asrc_priv->pair[index]) | ||
750 | continue; | ||
751 | |||
752 | if (status & ASRSTR_ATQOL) { | ||
753 | asrc_priv->pair[index]->error |= ASRC_TASK_Q_OVERLOAD; | ||
754 | dev_dbg(dev, "ASRC Task Queue FIFO overload\n"); | ||
755 | } | ||
756 | |||
757 | if (status & ASRSTR_AOOL(index)) { | ||
758 | asrc_priv->pair[index]->error |= ASRC_OUTPUT_TASK_OVERLOAD; | ||
759 | pair_dbg("Output Task Overload\n"); | ||
760 | } | ||
761 | |||
762 | if (status & ASRSTR_AIOL(index)) { | ||
763 | asrc_priv->pair[index]->error |= ASRC_INPUT_TASK_OVERLOAD; | ||
764 | pair_dbg("Input Task Overload\n"); | ||
765 | } | ||
766 | |||
767 | if (status & ASRSTR_AODO(index)) { | ||
768 | asrc_priv->pair[index]->error |= ASRC_OUTPUT_BUFFER_OVERFLOW; | ||
769 | pair_dbg("Output Data Buffer has overflowed\n"); | ||
770 | } | ||
771 | |||
772 | if (status & ASRSTR_AIDU(index)) { | ||
773 | asrc_priv->pair[index]->error |= ASRC_INPUT_BUFFER_UNDERRUN; | ||
774 | pair_dbg("Input Data Buffer has underflowed\n"); | ||
775 | } | ||
776 | } | ||
777 | |||
778 | return IRQ_HANDLED; | ||
779 | } | ||
780 | |||
781 | static int fsl_asrc_probe(struct platform_device *pdev) | ||
782 | { | ||
783 | struct device_node *np = pdev->dev.of_node; | ||
784 | struct fsl_asrc *asrc_priv; | ||
785 | struct resource *res; | ||
786 | void __iomem *regs; | ||
787 | int irq, ret, i; | ||
788 | char tmp[16]; | ||
789 | |||
790 | asrc_priv = devm_kzalloc(&pdev->dev, sizeof(*asrc_priv), GFP_KERNEL); | ||
791 | if (!asrc_priv) | ||
792 | return -ENOMEM; | ||
793 | |||
794 | asrc_priv->pdev = pdev; | ||
795 | strcpy(asrc_priv->name, np->name); | ||
796 | |||
797 | /* Get the addresses and IRQ */ | ||
798 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
799 | regs = devm_ioremap_resource(&pdev->dev, res); | ||
800 | if (IS_ERR(regs)) | ||
801 | return PTR_ERR(regs); | ||
802 | |||
803 | asrc_priv->paddr = res->start; | ||
804 | |||
805 | /* Register regmap and let it prepare core clock */ | ||
806 | if (of_property_read_bool(np, "big-endian")) | ||
807 | fsl_asrc_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; | ||
808 | |||
809 | asrc_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs, | ||
810 | &fsl_asrc_regmap_config); | ||
811 | if (IS_ERR(asrc_priv->regmap)) { | ||
812 | dev_err(&pdev->dev, "failed to init regmap\n"); | ||
813 | return PTR_ERR(asrc_priv->regmap); | ||
814 | } | ||
815 | |||
816 | irq = platform_get_irq(pdev, 0); | ||
817 | if (irq < 0) { | ||
818 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | ||
819 | return irq; | ||
820 | } | ||
821 | |||
822 | ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0, | ||
823 | asrc_priv->name, asrc_priv); | ||
824 | if (ret) { | ||
825 | dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret); | ||
826 | return ret; | ||
827 | } | ||
828 | |||
829 | asrc_priv->mem_clk = devm_clk_get(&pdev->dev, "mem"); | ||
830 | if (IS_ERR(asrc_priv->mem_clk)) { | ||
831 | dev_err(&pdev->dev, "failed to get mem clock\n"); | ||
832 | return PTR_ERR(asrc_priv->mem_clk); | ||
833 | } | ||
834 | |||
835 | asrc_priv->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); | ||
836 | if (IS_ERR(asrc_priv->ipg_clk)) { | ||
837 | dev_err(&pdev->dev, "failed to get ipg clock\n"); | ||
838 | return PTR_ERR(asrc_priv->ipg_clk); | ||
839 | } | ||
840 | |||
841 | for (i = 0; i < ASRC_CLK_MAX_NUM; i++) { | ||
842 | sprintf(tmp, "asrck_%x", i); | ||
843 | asrc_priv->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp); | ||
844 | if (IS_ERR(asrc_priv->asrck_clk[i])) { | ||
845 | dev_err(&pdev->dev, "failed to get %s clock\n", tmp); | ||
846 | return PTR_ERR(asrc_priv->asrck_clk[i]); | ||
847 | } | ||
848 | } | ||
849 | |||
850 | if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx35-asrc")) { | ||
851 | asrc_priv->channel_bits = 3; | ||
852 | clk_map[IN] = input_clk_map_imx35; | ||
853 | clk_map[OUT] = output_clk_map_imx35; | ||
854 | } else { | ||
855 | asrc_priv->channel_bits = 4; | ||
856 | clk_map[IN] = input_clk_map_imx53; | ||
857 | clk_map[OUT] = output_clk_map_imx53; | ||
858 | } | ||
859 | |||
860 | ret = fsl_asrc_init(asrc_priv); | ||
861 | if (ret) { | ||
862 | dev_err(&pdev->dev, "failed to init asrc %d\n", ret); | ||
863 | return -EINVAL; | ||
864 | } | ||
865 | |||
866 | asrc_priv->channel_avail = 10; | ||
867 | |||
868 | ret = of_property_read_u32(np, "fsl,asrc-rate", | ||
869 | &asrc_priv->asrc_rate); | ||
870 | if (ret) { | ||
871 | dev_err(&pdev->dev, "failed to get output rate\n"); | ||
872 | return -EINVAL; | ||
873 | } | ||
874 | |||
875 | ret = of_property_read_u32(np, "fsl,asrc-width", | ||
876 | &asrc_priv->asrc_width); | ||
877 | if (ret) { | ||
878 | dev_err(&pdev->dev, "failed to get output width\n"); | ||
879 | return -EINVAL; | ||
880 | } | ||
881 | |||
882 | if (asrc_priv->asrc_width != 16 && asrc_priv->asrc_width != 24) { | ||
883 | dev_warn(&pdev->dev, "unsupported width, switching to 24bit\n"); | ||
884 | asrc_priv->asrc_width = 24; | ||
885 | } | ||
886 | |||
887 | platform_set_drvdata(pdev, asrc_priv); | ||
888 | pm_runtime_enable(&pdev->dev); | ||
889 | spin_lock_init(&asrc_priv->lock); | ||
890 | |||
891 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component, | ||
892 | &fsl_asrc_dai, 1); | ||
893 | if (ret) { | ||
894 | dev_err(&pdev->dev, "failed to register ASoC DAI\n"); | ||
895 | return ret; | ||
896 | } | ||
897 | |||
898 | ret = devm_snd_soc_register_platform(&pdev->dev, &fsl_asrc_platform); | ||
899 | if (ret) { | ||
900 | dev_err(&pdev->dev, "failed to register ASoC platform\n"); | ||
901 | return ret; | ||
902 | } | ||
903 | |||
904 | dev_info(&pdev->dev, "driver registered\n"); | ||
905 | |||
906 | return 0; | ||
907 | } | ||
908 | |||
909 | #ifdef CONFIG_PM_RUNTIME | ||
910 | static int fsl_asrc_runtime_resume(struct device *dev) | ||
911 | { | ||
912 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); | ||
913 | int i; | ||
914 | |||
915 | clk_prepare_enable(asrc_priv->mem_clk); | ||
916 | clk_prepare_enable(asrc_priv->ipg_clk); | ||
917 | for (i = 0; i < ASRC_CLK_MAX_NUM; i++) | ||
918 | clk_prepare_enable(asrc_priv->asrck_clk[i]); | ||
919 | |||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | static int fsl_asrc_runtime_suspend(struct device *dev) | ||
924 | { | ||
925 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); | ||
926 | int i; | ||
927 | |||
928 | for (i = 0; i < ASRC_CLK_MAX_NUM; i++) | ||
929 | clk_disable_unprepare(asrc_priv->asrck_clk[i]); | ||
930 | clk_disable_unprepare(asrc_priv->ipg_clk); | ||
931 | clk_disable_unprepare(asrc_priv->mem_clk); | ||
932 | |||
933 | return 0; | ||
934 | } | ||
935 | #endif /* CONFIG_PM_RUNTIME */ | ||
936 | |||
937 | #ifdef CONFIG_PM_SLEEP | ||
938 | static int fsl_asrc_suspend(struct device *dev) | ||
939 | { | ||
940 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); | ||
941 | |||
942 | regcache_cache_only(asrc_priv->regmap, true); | ||
943 | regcache_mark_dirty(asrc_priv->regmap); | ||
944 | |||
945 | return 0; | ||
946 | } | ||
947 | |||
948 | static int fsl_asrc_resume(struct device *dev) | ||
949 | { | ||
950 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); | ||
951 | u32 asrctr; | ||
952 | |||
953 | /* Stop all pairs provisionally */ | ||
954 | regmap_read(asrc_priv->regmap, REG_ASRCTR, &asrctr); | ||
955 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
956 | ASRCTR_ASRCEi_ALL_MASK, 0); | ||
957 | |||
958 | /* Restore all registers */ | ||
959 | regcache_cache_only(asrc_priv->regmap, false); | ||
960 | regcache_sync(asrc_priv->regmap); | ||
961 | |||
962 | /* Restart enabled pairs */ | ||
963 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
964 | ASRCTR_ASRCEi_ALL_MASK, asrctr); | ||
965 | |||
966 | return 0; | ||
967 | } | ||
968 | #endif /* CONFIG_PM_SLEEP */ | ||
969 | |||
970 | static const struct dev_pm_ops fsl_asrc_pm = { | ||
971 | SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL) | ||
972 | SET_SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend, fsl_asrc_resume) | ||
973 | }; | ||
974 | |||
975 | static const struct of_device_id fsl_asrc_ids[] = { | ||
976 | { .compatible = "fsl,imx35-asrc", }, | ||
977 | { .compatible = "fsl,imx53-asrc", }, | ||
978 | {} | ||
979 | }; | ||
980 | MODULE_DEVICE_TABLE(of, fsl_asrc_ids); | ||
981 | |||
982 | static struct platform_driver fsl_asrc_driver = { | ||
983 | .probe = fsl_asrc_probe, | ||
984 | .driver = { | ||
985 | .name = "fsl-asrc", | ||
986 | .of_match_table = fsl_asrc_ids, | ||
987 | .pm = &fsl_asrc_pm, | ||
988 | }, | ||
989 | }; | ||
990 | module_platform_driver(fsl_asrc_driver); | ||
991 | |||
992 | MODULE_DESCRIPTION("Freescale ASRC ASoC driver"); | ||
993 | MODULE_AUTHOR("Nicolin Chen <nicoleotsuka@gmail.com>"); | ||
994 | MODULE_ALIAS("platform:fsl-asrc"); | ||
995 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h new file mode 100644 index 000000000000..a3f211f53c23 --- /dev/null +++ b/sound/soc/fsl/fsl_asrc.h | |||
@@ -0,0 +1,461 @@ | |||
1 | /* | ||
2 | * fsl_asrc.h - Freescale ASRC ALSA SoC header file | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Nicolin Chen <nicoleotsuka@gmail.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_ASRC_H | ||
14 | #define _FSL_ASRC_H | ||
15 | |||
16 | #define IN 0 | ||
17 | #define OUT 1 | ||
18 | |||
19 | #define ASRC_DMA_BUFFER_NUM 2 | ||
20 | #define ASRC_INPUTFIFO_THRESHOLD 32 | ||
21 | #define ASRC_OUTPUTFIFO_THRESHOLD 32 | ||
22 | #define ASRC_FIFO_THRESHOLD_MIN 0 | ||
23 | #define ASRC_FIFO_THRESHOLD_MAX 63 | ||
24 | #define ASRC_DMA_BUFFER_SIZE (1024 * 48 * 4) | ||
25 | #define ASRC_MAX_BUFFER_SIZE (1024 * 48) | ||
26 | #define ASRC_OUTPUT_LAST_SAMPLE 8 | ||
27 | |||
28 | #define IDEAL_RATIO_RATE 1000000 | ||
29 | |||
30 | #define REG_ASRCTR 0x00 | ||
31 | #define REG_ASRIER 0x04 | ||
32 | #define REG_ASRCNCR 0x0C | ||
33 | #define REG_ASRCFG 0x10 | ||
34 | #define REG_ASRCSR 0x14 | ||
35 | |||
36 | #define REG_ASRCDR1 0x18 | ||
37 | #define REG_ASRCDR2 0x1C | ||
38 | #define REG_ASRCDR(i) ((i < 2) ? REG_ASRCDR1 : REG_ASRCDR2) | ||
39 | |||
40 | #define REG_ASRSTR 0x20 | ||
41 | #define REG_ASRRA 0x24 | ||
42 | #define REG_ASRRB 0x28 | ||
43 | #define REG_ASRRC 0x2C | ||
44 | #define REG_ASRPM1 0x40 | ||
45 | #define REG_ASRPM2 0x44 | ||
46 | #define REG_ASRPM3 0x48 | ||
47 | #define REG_ASRPM4 0x4C | ||
48 | #define REG_ASRPM5 0x50 | ||
49 | #define REG_ASRTFR1 0x54 | ||
50 | #define REG_ASRCCR 0x5C | ||
51 | |||
52 | #define REG_ASRDIA 0x60 | ||
53 | #define REG_ASRDOA 0x64 | ||
54 | #define REG_ASRDIB 0x68 | ||
55 | #define REG_ASRDOB 0x6C | ||
56 | #define REG_ASRDIC 0x70 | ||
57 | #define REG_ASRDOC 0x74 | ||
58 | #define REG_ASRDI(i) (REG_ASRDIA + (i << 3)) | ||
59 | #define REG_ASRDO(i) (REG_ASRDOA + (i << 3)) | ||
60 | #define REG_ASRDx(x, i) (x == IN ? REG_ASRDI(i) : REG_ASRDO(i)) | ||
61 | |||
62 | #define REG_ASRIDRHA 0x80 | ||
63 | #define REG_ASRIDRLA 0x84 | ||
64 | #define REG_ASRIDRHB 0x88 | ||
65 | #define REG_ASRIDRLB 0x8C | ||
66 | #define REG_ASRIDRHC 0x90 | ||
67 | #define REG_ASRIDRLC 0x94 | ||
68 | #define REG_ASRIDRH(i) (REG_ASRIDRHA + (i << 3)) | ||
69 | #define REG_ASRIDRL(i) (REG_ASRIDRLA + (i << 3)) | ||
70 | |||
71 | #define REG_ASR76K 0x98 | ||
72 | #define REG_ASR56K 0x9C | ||
73 | |||
74 | #define REG_ASRMCRA 0xA0 | ||
75 | #define REG_ASRFSTA 0xA4 | ||
76 | #define REG_ASRMCRB 0xA8 | ||
77 | #define REG_ASRFSTB 0xAC | ||
78 | #define REG_ASRMCRC 0xB0 | ||
79 | #define REG_ASRFSTC 0xB4 | ||
80 | #define REG_ASRMCR(i) (REG_ASRMCRA + (i << 3)) | ||
81 | #define REG_ASRFST(i) (REG_ASRFSTA + (i << 3)) | ||
82 | |||
83 | #define REG_ASRMCR1A 0xC0 | ||
84 | #define REG_ASRMCR1B 0xC4 | ||
85 | #define REG_ASRMCR1C 0xC8 | ||
86 | #define REG_ASRMCR1(i) (REG_ASRMCR1A + (i << 2)) | ||
87 | |||
88 | |||
89 | /* REG0 0x00 REG_ASRCTR */ | ||
90 | #define ASRCTR_ATSi_SHIFT(i) (20 + i) | ||
91 | #define ASRCTR_ATSi_MASK(i) (1 << ASRCTR_ATSi_SHIFT(i)) | ||
92 | #define ASRCTR_ATS(i) (1 << ASRCTR_ATSi_SHIFT(i)) | ||
93 | #define ASRCTR_USRi_SHIFT(i) (14 + (i << 1)) | ||
94 | #define ASRCTR_USRi_MASK(i) (1 << ASRCTR_USRi_SHIFT(i)) | ||
95 | #define ASRCTR_USR(i) (1 << ASRCTR_USRi_SHIFT(i)) | ||
96 | #define ASRCTR_IDRi_SHIFT(i) (13 + (i << 1)) | ||
97 | #define ASRCTR_IDRi_MASK(i) (1 << ASRCTR_IDRi_SHIFT(i)) | ||
98 | #define ASRCTR_IDR(i) (1 << ASRCTR_IDRi_SHIFT(i)) | ||
99 | #define ASRCTR_SRST_SHIFT 4 | ||
100 | #define ASRCTR_SRST_MASK (1 << ASRCTR_SRST_SHIFT) | ||
101 | #define ASRCTR_SRST (1 << ASRCTR_SRST_SHIFT) | ||
102 | #define ASRCTR_ASRCEi_SHIFT(i) (1 + i) | ||
103 | #define ASRCTR_ASRCEi_MASK(i) (1 << ASRCTR_ASRCEi_SHIFT(i)) | ||
104 | #define ASRCTR_ASRCE(i) (1 << ASRCTR_ASRCEi_SHIFT(i)) | ||
105 | #define ASRCTR_ASRCEi_ALL_MASK (0x7 << ASRCTR_ASRCEi_SHIFT(0)) | ||
106 | #define ASRCTR_ASRCEN_SHIFT 0 | ||
107 | #define ASRCTR_ASRCEN_MASK (1 << ASRCTR_ASRCEN_SHIFT) | ||
108 | #define ASRCTR_ASRCEN (1 << ASRCTR_ASRCEN_SHIFT) | ||
109 | |||
110 | /* REG1 0x04 REG_ASRIER */ | ||
111 | #define ASRIER_AFPWE_SHIFT 7 | ||
112 | #define ASRIER_AFPWE_MASK (1 << ASRIER_AFPWE_SHIFT) | ||
113 | #define ASRIER_AFPWE (1 << ASRIER_AFPWE_SHIFT) | ||
114 | #define ASRIER_AOLIE_SHIFT 6 | ||
115 | #define ASRIER_AOLIE_MASK (1 << ASRIER_AOLIE_SHIFT) | ||
116 | #define ASRIER_AOLIE (1 << ASRIER_AOLIE_SHIFT) | ||
117 | #define ASRIER_ADOEi_SHIFT(i) (3 + i) | ||
118 | #define ASRIER_ADOEi_MASK(i) (1 << ASRIER_ADOEi_SHIFT(i)) | ||
119 | #define ASRIER_ADOE(i) (1 << ASRIER_ADOEi_SHIFT(i)) | ||
120 | #define ASRIER_ADIEi_SHIFT(i) (0 + i) | ||
121 | #define ASRIER_ADIEi_MASK(i) (1 << ASRIER_ADIEi_SHIFT(i)) | ||
122 | #define ASRIER_ADIE(i) (1 << ASRIER_ADIEi_SHIFT(i)) | ||
123 | |||
124 | /* REG2 0x0C REG_ASRCNCR */ | ||
125 | #define ASRCNCR_ANCi_SHIFT(i, b) (b * i) | ||
126 | #define ASRCNCR_ANCi_MASK(i, b) (((1 << b) - 1) << ASRCNCR_ANCi_SHIFT(i, b)) | ||
127 | #define ASRCNCR_ANCi(i, v, b) ((v << ASRCNCR_ANCi_SHIFT(i, b)) & ASRCNCR_ANCi_MASK(i, b)) | ||
128 | |||
129 | /* REG3 0x10 REG_ASRCFG */ | ||
130 | #define ASRCFG_INIRQi_SHIFT(i) (21 + i) | ||
131 | #define ASRCFG_INIRQi_MASK(i) (1 << ASRCFG_INIRQi_SHIFT(i)) | ||
132 | #define ASRCFG_INIRQi (1 << ASRCFG_INIRQi_SHIFT(i)) | ||
133 | #define ASRCFG_NDPRi_SHIFT(i) (18 + i) | ||
134 | #define ASRCFG_NDPRi_MASK(i) (1 << ASRCFG_NDPRi_SHIFT(i)) | ||
135 | #define ASRCFG_NDPRi (1 << ASRCFG_NDPRi_SHIFT(i)) | ||
136 | #define ASRCFG_POSTMODi_SHIFT(i) (8 + (i << 2)) | ||
137 | #define ASRCFG_POSTMODi_WIDTH 2 | ||
138 | #define ASRCFG_POSTMODi_MASK(i) (((1 << ASRCFG_POSTMODi_WIDTH) - 1) << ASRCFG_POSTMODi_SHIFT(i)) | ||
139 | #define ASRCFG_POSTMOD(i, v) ((v) << ASRCFG_POSTMODi_SHIFT(i)) | ||
140 | #define ASRCFG_POSTMODi_UP(i) (0 << ASRCFG_POSTMODi_SHIFT(i)) | ||
141 | #define ASRCFG_POSTMODi_DCON(i) (1 << ASRCFG_POSTMODi_SHIFT(i)) | ||
142 | #define ASRCFG_POSTMODi_DOWN(i) (2 << ASRCFG_POSTMODi_SHIFT(i)) | ||
143 | #define ASRCFG_PREMODi_SHIFT(i) (6 + (i << 2)) | ||
144 | #define ASRCFG_PREMODi_WIDTH 2 | ||
145 | #define ASRCFG_PREMODi_MASK(i) (((1 << ASRCFG_PREMODi_WIDTH) - 1) << ASRCFG_PREMODi_SHIFT(i)) | ||
146 | #define ASRCFG_PREMOD(i, v) ((v) << ASRCFG_PREMODi_SHIFT(i)) | ||
147 | #define ASRCFG_PREMODi_UP(i) (0 << ASRCFG_PREMODi_SHIFT(i)) | ||
148 | #define ASRCFG_PREMODi_DCON(i) (1 << ASRCFG_PREMODi_SHIFT(i)) | ||
149 | #define ASRCFG_PREMODi_DOWN(i) (2 << ASRCFG_PREMODi_SHIFT(i)) | ||
150 | #define ASRCFG_PREMODi_BYPASS(i) (3 << ASRCFG_PREMODi_SHIFT(i)) | ||
151 | |||
152 | /* REG4 0x14 REG_ASRCSR */ | ||
153 | #define ASRCSR_AxCSi_WIDTH 4 | ||
154 | #define ASRCSR_AxCSi_MASK ((1 << ASRCSR_AxCSi_WIDTH) - 1) | ||
155 | #define ASRCSR_AOCSi_SHIFT(i) (12 + (i << 2)) | ||
156 | #define ASRCSR_AOCSi_MASK(i) (((1 << ASRCSR_AxCSi_WIDTH) - 1) << ASRCSR_AOCSi_SHIFT(i)) | ||
157 | #define ASRCSR_AOCS(i, v) ((v) << ASRCSR_AOCSi_SHIFT(i)) | ||
158 | #define ASRCSR_AICSi_SHIFT(i) (i << 2) | ||
159 | #define ASRCSR_AICSi_MASK(i) (((1 << ASRCSR_AxCSi_WIDTH) - 1) << ASRCSR_AICSi_SHIFT(i)) | ||
160 | #define ASRCSR_AICS(i, v) ((v) << ASRCSR_AICSi_SHIFT(i)) | ||
161 | |||
162 | /* REG5&6 0x18 & 0x1C REG_ASRCDR1 & ASRCDR2 */ | ||
163 | #define ASRCDRi_AxCPi_WIDTH 3 | ||
164 | #define ASRCDRi_AICPi_SHIFT(i) (0 + (i % 2) * 6) | ||
165 | #define ASRCDRi_AICPi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AICPi_SHIFT(i)) | ||
166 | #define ASRCDRi_AICP(i, v) ((v) << ASRCDRi_AICPi_SHIFT(i)) | ||
167 | #define ASRCDRi_AICDi_SHIFT(i) (3 + (i % 2) * 6) | ||
168 | #define ASRCDRi_AICDi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AICDi_SHIFT(i)) | ||
169 | #define ASRCDRi_AICD(i, v) ((v) << ASRCDRi_AICDi_SHIFT(i)) | ||
170 | #define ASRCDRi_AOCPi_SHIFT(i) ((i < 2) ? 12 + i * 6 : 6) | ||
171 | #define ASRCDRi_AOCPi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AOCPi_SHIFT(i)) | ||
172 | #define ASRCDRi_AOCP(i, v) ((v) << ASRCDRi_AOCPi_SHIFT(i)) | ||
173 | #define ASRCDRi_AOCDi_SHIFT(i) ((i < 2) ? 15 + i * 6 : 9) | ||
174 | #define ASRCDRi_AOCDi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AOCDi_SHIFT(i)) | ||
175 | #define ASRCDRi_AOCD(i, v) ((v) << ASRCDRi_AOCDi_SHIFT(i)) | ||
176 | |||
177 | /* REG7 0x20 REG_ASRSTR */ | ||
178 | #define ASRSTR_DSLCNT_SHIFT 21 | ||
179 | #define ASRSTR_DSLCNT_MASK (1 << ASRSTR_DSLCNT_SHIFT) | ||
180 | #define ASRSTR_DSLCNT (1 << ASRSTR_DSLCNT_SHIFT) | ||
181 | #define ASRSTR_ATQOL_SHIFT 20 | ||
182 | #define ASRSTR_ATQOL_MASK (1 << ASRSTR_ATQOL_SHIFT) | ||
183 | #define ASRSTR_ATQOL (1 << ASRSTR_ATQOL_SHIFT) | ||
184 | #define ASRSTR_AOOLi_SHIFT(i) (17 + i) | ||
185 | #define ASRSTR_AOOLi_MASK(i) (1 << ASRSTR_AOOLi_SHIFT(i)) | ||
186 | #define ASRSTR_AOOL(i) (1 << ASRSTR_AOOLi_SHIFT(i)) | ||
187 | #define ASRSTR_AIOLi_SHIFT(i) (14 + i) | ||
188 | #define ASRSTR_AIOLi_MASK(i) (1 << ASRSTR_AIOLi_SHIFT(i)) | ||
189 | #define ASRSTR_AIOL(i) (1 << ASRSTR_AIOLi_SHIFT(i)) | ||
190 | #define ASRSTR_AODOi_SHIFT(i) (11 + i) | ||
191 | #define ASRSTR_AODOi_MASK(i) (1 << ASRSTR_AODOi_SHIFT(i)) | ||
192 | #define ASRSTR_AODO(i) (1 << ASRSTR_AODOi_SHIFT(i)) | ||
193 | #define ASRSTR_AIDUi_SHIFT(i) (8 + i) | ||
194 | #define ASRSTR_AIDUi_MASK(i) (1 << ASRSTR_AIDUi_SHIFT(i)) | ||
195 | #define ASRSTR_AIDU(i) (1 << ASRSTR_AIDUi_SHIFT(i)) | ||
196 | #define ASRSTR_FPWT_SHIFT 7 | ||
197 | #define ASRSTR_FPWT_MASK (1 << ASRSTR_FPWT_SHIFT) | ||
198 | #define ASRSTR_FPWT (1 << ASRSTR_FPWT_SHIFT) | ||
199 | #define ASRSTR_AOLE_SHIFT 6 | ||
200 | #define ASRSTR_AOLE_MASK (1 << ASRSTR_AOLE_SHIFT) | ||
201 | #define ASRSTR_AOLE (1 << ASRSTR_AOLE_SHIFT) | ||
202 | #define ASRSTR_AODEi_SHIFT(i) (3 + i) | ||
203 | #define ASRSTR_AODFi_MASK(i) (1 << ASRSTR_AODEi_SHIFT(i)) | ||
204 | #define ASRSTR_AODF(i) (1 << ASRSTR_AODEi_SHIFT(i)) | ||
205 | #define ASRSTR_AIDEi_SHIFT(i) (0 + i) | ||
206 | #define ASRSTR_AIDEi_MASK(i) (1 << ASRSTR_AIDEi_SHIFT(i)) | ||
207 | #define ASRSTR_AIDE(i) (1 << ASRSTR_AIDEi_SHIFT(i)) | ||
208 | |||
209 | /* REG10 0x54 REG_ASRTFR1 */ | ||
210 | #define ASRTFR1_TF_BASE_WIDTH 7 | ||
211 | #define ASRTFR1_TF_BASE_SHIFT 6 | ||
212 | #define ASRTFR1_TF_BASE_MASK (((1 << ASRTFR1_TF_BASE_WIDTH) - 1) << ASRTFR1_TF_BASE_SHIFT) | ||
213 | #define ASRTFR1_TF_BASE(i) ((i) << ASRTFR1_TF_BASE_SHIFT) | ||
214 | |||
215 | /* | ||
216 | * REG22 0xA0 REG_ASRMCRA | ||
217 | * REG24 0xA8 REG_ASRMCRB | ||
218 | * REG26 0xB0 REG_ASRMCRC | ||
219 | */ | ||
220 | #define ASRMCRi_ZEROBUFi_SHIFT 23 | ||
221 | #define ASRMCRi_ZEROBUFi_MASK (1 << ASRMCRi_ZEROBUFi_SHIFT) | ||
222 | #define ASRMCRi_ZEROBUFi (1 << ASRMCRi_ZEROBUFi_SHIFT) | ||
223 | #define ASRMCRi_EXTTHRSHi_SHIFT 22 | ||
224 | #define ASRMCRi_EXTTHRSHi_MASK (1 << ASRMCRi_EXTTHRSHi_SHIFT) | ||
225 | #define ASRMCRi_EXTTHRSHi (1 << ASRMCRi_EXTTHRSHi_SHIFT) | ||
226 | #define ASRMCRi_BUFSTALLi_SHIFT 21 | ||
227 | #define ASRMCRi_BUFSTALLi_MASK (1 << ASRMCRi_BUFSTALLi_SHIFT) | ||
228 | #define ASRMCRi_BUFSTALLi (1 << ASRMCRi_BUFSTALLi_SHIFT) | ||
229 | #define ASRMCRi_BYPASSPOLYi_SHIFT 20 | ||
230 | #define ASRMCRi_BYPASSPOLYi_MASK (1 << ASRMCRi_BYPASSPOLYi_SHIFT) | ||
231 | #define ASRMCRi_BYPASSPOLYi (1 << ASRMCRi_BYPASSPOLYi_SHIFT) | ||
232 | #define ASRMCRi_OUTFIFO_THRESHOLD_WIDTH 6 | ||
233 | #define ASRMCRi_OUTFIFO_THRESHOLD_SHIFT 12 | ||
234 | #define ASRMCRi_OUTFIFO_THRESHOLD_MASK (((1 << ASRMCRi_OUTFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRi_OUTFIFO_THRESHOLD_SHIFT) | ||
235 | #define ASRMCRi_OUTFIFO_THRESHOLD(v) (((v) << ASRMCRi_OUTFIFO_THRESHOLD_SHIFT) & ASRMCRi_OUTFIFO_THRESHOLD_MASK) | ||
236 | #define ASRMCRi_RSYNIFi_SHIFT 11 | ||
237 | #define ASRMCRi_RSYNIFi_MASK (1 << ASRMCRi_RSYNIFi_SHIFT) | ||
238 | #define ASRMCRi_RSYNIFi (1 << ASRMCRi_RSYNIFi_SHIFT) | ||
239 | #define ASRMCRi_RSYNOFi_SHIFT 10 | ||
240 | #define ASRMCRi_RSYNOFi_MASK (1 << ASRMCRi_RSYNOFi_SHIFT) | ||
241 | #define ASRMCRi_RSYNOFi (1 << ASRMCRi_RSYNOFi_SHIFT) | ||
242 | #define ASRMCRi_INFIFO_THRESHOLD_WIDTH 6 | ||
243 | #define ASRMCRi_INFIFO_THRESHOLD_SHIFT 0 | ||
244 | #define ASRMCRi_INFIFO_THRESHOLD_MASK (((1 << ASRMCRi_INFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRi_INFIFO_THRESHOLD_SHIFT) | ||
245 | #define ASRMCRi_INFIFO_THRESHOLD(v) (((v) << ASRMCRi_INFIFO_THRESHOLD_SHIFT) & ASRMCRi_INFIFO_THRESHOLD_MASK) | ||
246 | |||
247 | /* | ||
248 | * REG23 0xA4 REG_ASRFSTA | ||
249 | * REG25 0xAC REG_ASRFSTB | ||
250 | * REG27 0xB4 REG_ASRFSTC | ||
251 | */ | ||
252 | #define ASRFSTi_OAFi_SHIFT 23 | ||
253 | #define ASRFSTi_OAFi_MASK (1 << ASRFSTi_OAFi_SHIFT) | ||
254 | #define ASRFSTi_OAFi (1 << ASRFSTi_OAFi_SHIFT) | ||
255 | #define ASRFSTi_OUTPUT_FIFO_WIDTH 7 | ||
256 | #define ASRFSTi_OUTPUT_FIFO_SHIFT 12 | ||
257 | #define ASRFSTi_OUTPUT_FIFO_MASK (((1 << ASRFSTi_OUTPUT_FIFO_WIDTH) - 1) << ASRFSTi_OUTPUT_FIFO_SHIFT) | ||
258 | #define ASRFSTi_IAEi_SHIFT 11 | ||
259 | #define ASRFSTi_IAEi_MASK (1 << ASRFSTi_OAFi_SHIFT) | ||
260 | #define ASRFSTi_IAEi (1 << ASRFSTi_OAFi_SHIFT) | ||
261 | #define ASRFSTi_INPUT_FIFO_WIDTH 7 | ||
262 | #define ASRFSTi_INPUT_FIFO_SHIFT 0 | ||
263 | #define ASRFSTi_INPUT_FIFO_MASK ((1 << ASRFSTi_INPUT_FIFO_WIDTH) - 1) | ||
264 | |||
265 | /* REG28 0xC0 & 0xC4 & 0xC8 REG_ASRMCR1i */ | ||
266 | #define ASRMCR1i_IWD_WIDTH 3 | ||
267 | #define ASRMCR1i_IWD_SHIFT 9 | ||
268 | #define ASRMCR1i_IWD_MASK (((1 << ASRMCR1i_IWD_WIDTH) - 1) << ASRMCR1i_IWD_SHIFT) | ||
269 | #define ASRMCR1i_IWD(v) ((v) << ASRMCR1i_IWD_SHIFT) | ||
270 | #define ASRMCR1i_IMSB_SHIFT 8 | ||
271 | #define ASRMCR1i_IMSB_MASK (1 << ASRMCR1i_IMSB_SHIFT) | ||
272 | #define ASRMCR1i_IMSB_MSB (1 << ASRMCR1i_IMSB_SHIFT) | ||
273 | #define ASRMCR1i_IMSB_LSB (0 << ASRMCR1i_IMSB_SHIFT) | ||
274 | #define ASRMCR1i_OMSB_SHIFT 2 | ||
275 | #define ASRMCR1i_OMSB_MASK (1 << ASRMCR1i_OMSB_SHIFT) | ||
276 | #define ASRMCR1i_OMSB_MSB (1 << ASRMCR1i_OMSB_SHIFT) | ||
277 | #define ASRMCR1i_OMSB_LSB (0 << ASRMCR1i_OMSB_SHIFT) | ||
278 | #define ASRMCR1i_OSGN_SHIFT 1 | ||
279 | #define ASRMCR1i_OSGN_MASK (1 << ASRMCR1i_OSGN_SHIFT) | ||
280 | #define ASRMCR1i_OSGN (1 << ASRMCR1i_OSGN_SHIFT) | ||
281 | #define ASRMCR1i_OW16_SHIFT 0 | ||
282 | #define ASRMCR1i_OW16_MASK (1 << ASRMCR1i_OW16_SHIFT) | ||
283 | #define ASRMCR1i_OW16(v) ((v) << ASRMCR1i_OW16_SHIFT) | ||
284 | |||
285 | |||
286 | enum asrc_pair_index { | ||
287 | ASRC_INVALID_PAIR = -1, | ||
288 | ASRC_PAIR_A = 0, | ||
289 | ASRC_PAIR_B = 1, | ||
290 | ASRC_PAIR_C = 2, | ||
291 | }; | ||
292 | |||
293 | #define ASRC_PAIR_MAX_NUM (ASRC_PAIR_C + 1) | ||
294 | |||
295 | enum asrc_inclk { | ||
296 | INCLK_NONE = 0x03, | ||
297 | INCLK_ESAI_RX = 0x00, | ||
298 | INCLK_SSI1_RX = 0x01, | ||
299 | INCLK_SSI2_RX = 0x02, | ||
300 | INCLK_SSI3_RX = 0x07, | ||
301 | INCLK_SPDIF_RX = 0x04, | ||
302 | INCLK_MLB_CLK = 0x05, | ||
303 | INCLK_PAD = 0x06, | ||
304 | INCLK_ESAI_TX = 0x08, | ||
305 | INCLK_SSI1_TX = 0x09, | ||
306 | INCLK_SSI2_TX = 0x0a, | ||
307 | INCLK_SSI3_TX = 0x0b, | ||
308 | INCLK_SPDIF_TX = 0x0c, | ||
309 | INCLK_ASRCK1_CLK = 0x0f, | ||
310 | }; | ||
311 | |||
312 | enum asrc_outclk { | ||
313 | OUTCLK_NONE = 0x03, | ||
314 | OUTCLK_ESAI_TX = 0x00, | ||
315 | OUTCLK_SSI1_TX = 0x01, | ||
316 | OUTCLK_SSI2_TX = 0x02, | ||
317 | OUTCLK_SSI3_TX = 0x07, | ||
318 | OUTCLK_SPDIF_TX = 0x04, | ||
319 | OUTCLK_MLB_CLK = 0x05, | ||
320 | OUTCLK_PAD = 0x06, | ||
321 | OUTCLK_ESAI_RX = 0x08, | ||
322 | OUTCLK_SSI1_RX = 0x09, | ||
323 | OUTCLK_SSI2_RX = 0x0a, | ||
324 | OUTCLK_SSI3_RX = 0x0b, | ||
325 | OUTCLK_SPDIF_RX = 0x0c, | ||
326 | OUTCLK_ASRCK1_CLK = 0x0f, | ||
327 | }; | ||
328 | |||
329 | #define ASRC_CLK_MAX_NUM 16 | ||
330 | |||
331 | enum asrc_word_width { | ||
332 | ASRC_WIDTH_24_BIT = 0, | ||
333 | ASRC_WIDTH_16_BIT = 1, | ||
334 | ASRC_WIDTH_8_BIT = 2, | ||
335 | }; | ||
336 | |||
337 | struct asrc_config { | ||
338 | enum asrc_pair_index pair; | ||
339 | unsigned int channel_num; | ||
340 | unsigned int buffer_num; | ||
341 | unsigned int dma_buffer_size; | ||
342 | unsigned int input_sample_rate; | ||
343 | unsigned int output_sample_rate; | ||
344 | enum asrc_word_width input_word_width; | ||
345 | enum asrc_word_width output_word_width; | ||
346 | enum asrc_inclk inclk; | ||
347 | enum asrc_outclk outclk; | ||
348 | }; | ||
349 | |||
350 | struct asrc_req { | ||
351 | unsigned int chn_num; | ||
352 | enum asrc_pair_index index; | ||
353 | }; | ||
354 | |||
355 | struct asrc_querybuf { | ||
356 | unsigned int buffer_index; | ||
357 | unsigned int input_length; | ||
358 | unsigned int output_length; | ||
359 | unsigned long input_offset; | ||
360 | unsigned long output_offset; | ||
361 | }; | ||
362 | |||
363 | struct asrc_convert_buffer { | ||
364 | void *input_buffer_vaddr; | ||
365 | void *output_buffer_vaddr; | ||
366 | unsigned int input_buffer_length; | ||
367 | unsigned int output_buffer_length; | ||
368 | }; | ||
369 | |||
370 | struct asrc_status_flags { | ||
371 | enum asrc_pair_index index; | ||
372 | unsigned int overload_error; | ||
373 | }; | ||
374 | |||
375 | enum asrc_error_status { | ||
376 | ASRC_TASK_Q_OVERLOAD = 0x01, | ||
377 | ASRC_OUTPUT_TASK_OVERLOAD = 0x02, | ||
378 | ASRC_INPUT_TASK_OVERLOAD = 0x04, | ||
379 | ASRC_OUTPUT_BUFFER_OVERFLOW = 0x08, | ||
380 | ASRC_INPUT_BUFFER_UNDERRUN = 0x10, | ||
381 | }; | ||
382 | |||
383 | struct dma_block { | ||
384 | dma_addr_t dma_paddr; | ||
385 | void *dma_vaddr; | ||
386 | unsigned int length; | ||
387 | }; | ||
388 | |||
389 | /** | ||
390 | * fsl_asrc_pair: ASRC Pair private data | ||
391 | * | ||
392 | * @asrc_priv: pointer to its parent module | ||
393 | * @config: configuration profile | ||
394 | * @error: error record | ||
395 | * @index: pair index (ASRC_PAIR_A, ASRC_PAIR_B, ASRC_PAIR_C) | ||
396 | * @channels: occupied channel number | ||
397 | * @desc: input and output dma descriptors | ||
398 | * @dma_chan: inputer and output DMA channels | ||
399 | * @dma_data: private dma data | ||
400 | * @pos: hardware pointer position | ||
401 | * @private: pair private area | ||
402 | */ | ||
403 | struct fsl_asrc_pair { | ||
404 | struct fsl_asrc *asrc_priv; | ||
405 | struct asrc_config *config; | ||
406 | unsigned int error; | ||
407 | |||
408 | enum asrc_pair_index index; | ||
409 | unsigned int channels; | ||
410 | |||
411 | struct dma_async_tx_descriptor *desc[2]; | ||
412 | struct dma_chan *dma_chan[2]; | ||
413 | struct imx_dma_data dma_data; | ||
414 | unsigned int pos; | ||
415 | |||
416 | void *private; | ||
417 | }; | ||
418 | |||
419 | /** | ||
420 | * fsl_asrc_pair: ASRC private data | ||
421 | * | ||
422 | * @dma_params_rx: DMA parameters for receive channel | ||
423 | * @dma_params_tx: DMA parameters for transmit channel | ||
424 | * @pdev: platform device pointer | ||
425 | * @regmap: regmap handler | ||
426 | * @paddr: physical address to the base address of registers | ||
427 | * @mem_clk: clock source to access register | ||
428 | * @ipg_clk: clock source to drive peripheral | ||
429 | * @asrck_clk: clock sources to driver ASRC internal logic | ||
430 | * @lock: spin lock for resource protection | ||
431 | * @pair: pair pointers | ||
432 | * @channel_bits: width of ASRCNCR register for each pair | ||
433 | * @channel_avail: non-occupied channel numbers | ||
434 | * @asrc_rate: default sample rate for ASoC Back-Ends | ||
435 | * @asrc_width: default sample width for ASoC Back-Ends | ||
436 | * @name: driver name | ||
437 | */ | ||
438 | struct fsl_asrc { | ||
439 | struct snd_dmaengine_dai_dma_data dma_params_rx; | ||
440 | struct snd_dmaengine_dai_dma_data dma_params_tx; | ||
441 | struct platform_device *pdev; | ||
442 | struct regmap *regmap; | ||
443 | unsigned long paddr; | ||
444 | struct clk *mem_clk; | ||
445 | struct clk *ipg_clk; | ||
446 | struct clk *asrck_clk[ASRC_CLK_MAX_NUM]; | ||
447 | spinlock_t lock; | ||
448 | |||
449 | struct fsl_asrc_pair *pair[ASRC_PAIR_MAX_NUM]; | ||
450 | unsigned int channel_bits; | ||
451 | unsigned int channel_avail; | ||
452 | |||
453 | int asrc_rate; | ||
454 | int asrc_width; | ||
455 | |||
456 | char name[32]; | ||
457 | }; | ||
458 | |||
459 | extern struct snd_soc_platform_driver fsl_asrc_platform; | ||
460 | struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir); | ||
461 | #endif /* _FSL_ASRC_H */ | ||
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c new file mode 100644 index 000000000000..ffc000bc1f15 --- /dev/null +++ b/sound/soc/fsl/fsl_asrc_dma.c | |||
@@ -0,0 +1,391 @@ | |||
1 | /* | ||
2 | * Freescale ASRC ALSA SoC Platform (DMA) driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Nicolin Chen <nicoleotsuka@gmail.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 | #include <linux/dma-mapping.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_data/dma-imx.h> | ||
16 | #include <sound/dmaengine_pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | |||
19 | #include "fsl_asrc.h" | ||
20 | |||
21 | #define FSL_ASRC_DMABUF_SIZE (256 * 1024) | ||
22 | |||
23 | static struct snd_pcm_hardware snd_imx_hardware = { | ||
24 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
25 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
26 | SNDRV_PCM_INFO_MMAP | | ||
27 | SNDRV_PCM_INFO_MMAP_VALID | | ||
28 | SNDRV_PCM_INFO_PAUSE | | ||
29 | SNDRV_PCM_INFO_RESUME, | ||
30 | .buffer_bytes_max = FSL_ASRC_DMABUF_SIZE, | ||
31 | .period_bytes_min = 128, | ||
32 | .period_bytes_max = 65535, /* Limited by SDMA engine */ | ||
33 | .periods_min = 2, | ||
34 | .periods_max = 255, | ||
35 | .fifo_size = 0, | ||
36 | }; | ||
37 | |||
38 | static bool filter(struct dma_chan *chan, void *param) | ||
39 | { | ||
40 | if (!imx_dma_is_general_purpose(chan)) | ||
41 | return false; | ||
42 | |||
43 | chan->private = param; | ||
44 | |||
45 | return true; | ||
46 | } | ||
47 | |||
48 | static void fsl_asrc_dma_complete(void *arg) | ||
49 | { | ||
50 | struct snd_pcm_substream *substream = arg; | ||
51 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
52 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
53 | |||
54 | pair->pos += snd_pcm_lib_period_bytes(substream); | ||
55 | if (pair->pos >= snd_pcm_lib_buffer_bytes(substream)) | ||
56 | pair->pos = 0; | ||
57 | |||
58 | snd_pcm_period_elapsed(substream); | ||
59 | } | ||
60 | |||
61 | static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream) | ||
62 | { | ||
63 | u8 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? OUT : IN; | ||
64 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
65 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
66 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
67 | struct device *dev = rtd->platform->dev; | ||
68 | unsigned long flags = DMA_CTRL_ACK; | ||
69 | |||
70 | /* Prepare and submit Front-End DMA channel */ | ||
71 | if (!substream->runtime->no_period_wakeup) | ||
72 | flags |= DMA_PREP_INTERRUPT; | ||
73 | |||
74 | pair->pos = 0; | ||
75 | pair->desc[!dir] = dmaengine_prep_dma_cyclic( | ||
76 | pair->dma_chan[!dir], runtime->dma_addr, | ||
77 | snd_pcm_lib_buffer_bytes(substream), | ||
78 | snd_pcm_lib_period_bytes(substream), | ||
79 | dir == OUT ? DMA_TO_DEVICE : DMA_FROM_DEVICE, flags); | ||
80 | if (!pair->desc[!dir]) { | ||
81 | dev_err(dev, "failed to prepare slave DMA for Front-End\n"); | ||
82 | return -ENOMEM; | ||
83 | } | ||
84 | |||
85 | pair->desc[!dir]->callback = fsl_asrc_dma_complete; | ||
86 | pair->desc[!dir]->callback_param = substream; | ||
87 | |||
88 | dmaengine_submit(pair->desc[!dir]); | ||
89 | |||
90 | /* Prepare and submit Back-End DMA channel */ | ||
91 | pair->desc[dir] = dmaengine_prep_dma_cyclic( | ||
92 | pair->dma_chan[dir], 0xffff, 64, 64, DMA_DEV_TO_DEV, 0); | ||
93 | if (!pair->desc[dir]) { | ||
94 | dev_err(dev, "failed to prepare slave DMA for Back-End\n"); | ||
95 | return -ENOMEM; | ||
96 | } | ||
97 | |||
98 | dmaengine_submit(pair->desc[dir]); | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int fsl_asrc_dma_trigger(struct snd_pcm_substream *substream, int cmd) | ||
104 | { | ||
105 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
106 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
107 | int ret; | ||
108 | |||
109 | switch (cmd) { | ||
110 | case SNDRV_PCM_TRIGGER_START: | ||
111 | case SNDRV_PCM_TRIGGER_RESUME: | ||
112 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
113 | ret = fsl_asrc_dma_prepare_and_submit(substream); | ||
114 | if (ret) | ||
115 | return ret; | ||
116 | dma_async_issue_pending(pair->dma_chan[IN]); | ||
117 | dma_async_issue_pending(pair->dma_chan[OUT]); | ||
118 | break; | ||
119 | case SNDRV_PCM_TRIGGER_STOP: | ||
120 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
121 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
122 | dmaengine_terminate_all(pair->dma_chan[OUT]); | ||
123 | dmaengine_terminate_all(pair->dma_chan[IN]); | ||
124 | break; | ||
125 | default: | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream, | ||
133 | struct snd_pcm_hw_params *params) | ||
134 | { | ||
135 | enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
136 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
137 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
138 | struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL; | ||
139 | struct snd_dmaengine_dai_dma_data *dma_params_be = NULL; | ||
140 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
141 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
142 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
143 | struct dma_slave_config config_fe, config_be; | ||
144 | enum asrc_pair_index index = pair->index; | ||
145 | struct device *dev = rtd->platform->dev; | ||
146 | int stream = substream->stream; | ||
147 | struct imx_dma_data *tmp_data; | ||
148 | struct snd_soc_dpcm *dpcm; | ||
149 | struct dma_chan *tmp_chan; | ||
150 | struct device *dev_be; | ||
151 | u8 dir = tx ? OUT : IN; | ||
152 | dma_cap_mask_t mask; | ||
153 | int ret; | ||
154 | |||
155 | /* Fetch the Back-End dma_data from DPCM */ | ||
156 | list_for_each_entry(dpcm, &rtd->dpcm[stream].be_clients, list_be) { | ||
157 | struct snd_soc_pcm_runtime *be = dpcm->be; | ||
158 | struct snd_pcm_substream *substream_be; | ||
159 | struct snd_soc_dai *dai = be->cpu_dai; | ||
160 | |||
161 | if (dpcm->fe != rtd) | ||
162 | continue; | ||
163 | |||
164 | substream_be = snd_soc_dpcm_get_substream(be, stream); | ||
165 | dma_params_be = snd_soc_dai_get_dma_data(dai, substream_be); | ||
166 | dev_be = dai->dev; | ||
167 | break; | ||
168 | } | ||
169 | |||
170 | if (!dma_params_be) { | ||
171 | dev_err(dev, "failed to get the substream of Back-End\n"); | ||
172 | return -EINVAL; | ||
173 | } | ||
174 | |||
175 | /* Override dma_data of the Front-End and config its dmaengine */ | ||
176 | dma_params_fe = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
177 | dma_params_fe->addr = asrc_priv->paddr + REG_ASRDx(!dir, index); | ||
178 | dma_params_fe->maxburst = dma_params_be->maxburst; | ||
179 | |||
180 | pair->dma_chan[!dir] = fsl_asrc_get_dma_channel(pair, !dir); | ||
181 | if (!pair->dma_chan[!dir]) { | ||
182 | dev_err(dev, "failed to request DMA channel\n"); | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | |||
186 | memset(&config_fe, 0, sizeof(config_fe)); | ||
187 | ret = snd_dmaengine_pcm_prepare_slave_config(substream, params, &config_fe); | ||
188 | if (ret) { | ||
189 | dev_err(dev, "failed to prepare DMA config for Front-End\n"); | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | ret = dmaengine_slave_config(pair->dma_chan[!dir], &config_fe); | ||
194 | if (ret) { | ||
195 | dev_err(dev, "failed to config DMA channel for Front-End\n"); | ||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | /* Request and config DMA channel for Back-End */ | ||
200 | dma_cap_zero(mask); | ||
201 | dma_cap_set(DMA_SLAVE, mask); | ||
202 | dma_cap_set(DMA_CYCLIC, mask); | ||
203 | |||
204 | /* Get DMA request of Back-End */ | ||
205 | tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx"); | ||
206 | tmp_data = tmp_chan->private; | ||
207 | pair->dma_data.dma_request = tmp_data->dma_request; | ||
208 | dma_release_channel(tmp_chan); | ||
209 | |||
210 | /* Get DMA request of Front-End */ | ||
211 | tmp_chan = fsl_asrc_get_dma_channel(pair, dir); | ||
212 | tmp_data = tmp_chan->private; | ||
213 | pair->dma_data.dma_request2 = tmp_data->dma_request; | ||
214 | pair->dma_data.peripheral_type = tmp_data->peripheral_type; | ||
215 | pair->dma_data.priority = tmp_data->priority; | ||
216 | dma_release_channel(tmp_chan); | ||
217 | |||
218 | pair->dma_chan[dir] = dma_request_channel(mask, filter, &pair->dma_data); | ||
219 | if (!pair->dma_chan[dir]) { | ||
220 | dev_err(dev, "failed to request DMA channel for Back-End\n"); | ||
221 | return -EINVAL; | ||
222 | } | ||
223 | |||
224 | if (asrc_priv->asrc_width == 16) | ||
225 | buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
226 | else | ||
227 | buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
228 | |||
229 | config_be.direction = DMA_DEV_TO_DEV; | ||
230 | config_be.src_addr_width = buswidth; | ||
231 | config_be.src_maxburst = dma_params_be->maxburst; | ||
232 | config_be.dst_addr_width = buswidth; | ||
233 | config_be.dst_maxburst = dma_params_be->maxburst; | ||
234 | |||
235 | if (tx) { | ||
236 | config_be.src_addr = asrc_priv->paddr + REG_ASRDO(index); | ||
237 | config_be.dst_addr = dma_params_be->addr; | ||
238 | } else { | ||
239 | config_be.dst_addr = asrc_priv->paddr + REG_ASRDI(index); | ||
240 | config_be.src_addr = dma_params_be->addr; | ||
241 | } | ||
242 | |||
243 | ret = dmaengine_slave_config(pair->dma_chan[dir], &config_be); | ||
244 | if (ret) { | ||
245 | dev_err(dev, "failed to config DMA channel for Back-End\n"); | ||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int fsl_asrc_dma_hw_free(struct snd_pcm_substream *substream) | ||
255 | { | ||
256 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
257 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
258 | |||
259 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
260 | |||
261 | if (pair->dma_chan[IN]) | ||
262 | dma_release_channel(pair->dma_chan[IN]); | ||
263 | |||
264 | if (pair->dma_chan[OUT]) | ||
265 | dma_release_channel(pair->dma_chan[OUT]); | ||
266 | |||
267 | pair->dma_chan[IN] = NULL; | ||
268 | pair->dma_chan[OUT] = NULL; | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int fsl_asrc_dma_startup(struct snd_pcm_substream *substream) | ||
274 | { | ||
275 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
276 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
277 | struct device *dev = rtd->platform->dev; | ||
278 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); | ||
279 | struct fsl_asrc_pair *pair; | ||
280 | |||
281 | pair = kzalloc(sizeof(struct fsl_asrc_pair), GFP_KERNEL); | ||
282 | if (!pair) { | ||
283 | dev_err(dev, "failed to allocate pair\n"); | ||
284 | return -ENOMEM; | ||
285 | } | ||
286 | |||
287 | pair->asrc_priv = asrc_priv; | ||
288 | |||
289 | runtime->private_data = pair; | ||
290 | |||
291 | snd_pcm_hw_constraint_integer(substream->runtime, | ||
292 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
293 | snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int fsl_asrc_dma_shutdown(struct snd_pcm_substream *substream) | ||
299 | { | ||
300 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
301 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
302 | struct fsl_asrc *asrc_priv; | ||
303 | |||
304 | if (!pair) | ||
305 | return 0; | ||
306 | |||
307 | asrc_priv = pair->asrc_priv; | ||
308 | |||
309 | if (asrc_priv->pair[pair->index] == pair) | ||
310 | asrc_priv->pair[pair->index] = NULL; | ||
311 | |||
312 | kfree(pair); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static snd_pcm_uframes_t fsl_asrc_dma_pcm_pointer(struct snd_pcm_substream *substream) | ||
318 | { | ||
319 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
320 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
321 | |||
322 | return bytes_to_frames(substream->runtime, pair->pos); | ||
323 | } | ||
324 | |||
325 | static struct snd_pcm_ops fsl_asrc_dma_pcm_ops = { | ||
326 | .ioctl = snd_pcm_lib_ioctl, | ||
327 | .hw_params = fsl_asrc_dma_hw_params, | ||
328 | .hw_free = fsl_asrc_dma_hw_free, | ||
329 | .trigger = fsl_asrc_dma_trigger, | ||
330 | .open = fsl_asrc_dma_startup, | ||
331 | .close = fsl_asrc_dma_shutdown, | ||
332 | .pointer = fsl_asrc_dma_pcm_pointer, | ||
333 | }; | ||
334 | |||
335 | static int fsl_asrc_dma_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
336 | { | ||
337 | struct snd_card *card = rtd->card->snd_card; | ||
338 | struct snd_pcm_substream *substream; | ||
339 | struct snd_pcm *pcm = rtd->pcm; | ||
340 | int ret, i; | ||
341 | |||
342 | ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); | ||
343 | if (ret) { | ||
344 | dev_err(card->dev, "failed to set DMA mask\n"); | ||
345 | return ret; | ||
346 | } | ||
347 | |||
348 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) { | ||
349 | substream = pcm->streams[i].substream; | ||
350 | if (!substream) | ||
351 | continue; | ||
352 | |||
353 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev, | ||
354 | FSL_ASRC_DMABUF_SIZE, &substream->dma_buffer); | ||
355 | if (ret) { | ||
356 | dev_err(card->dev, "failed to allocate DMA buffer\n"); | ||
357 | goto err; | ||
358 | } | ||
359 | } | ||
360 | |||
361 | return 0; | ||
362 | |||
363 | err: | ||
364 | if (--i == 0 && pcm->streams[i].substream) | ||
365 | snd_dma_free_pages(&pcm->streams[i].substream->dma_buffer); | ||
366 | |||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | static void fsl_asrc_dma_pcm_free(struct snd_pcm *pcm) | ||
371 | { | ||
372 | struct snd_pcm_substream *substream; | ||
373 | int i; | ||
374 | |||
375 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) { | ||
376 | substream = pcm->streams[i].substream; | ||
377 | if (!substream) | ||
378 | continue; | ||
379 | |||
380 | snd_dma_free_pages(&substream->dma_buffer); | ||
381 | substream->dma_buffer.area = NULL; | ||
382 | substream->dma_buffer.addr = 0; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | struct snd_soc_platform_driver fsl_asrc_platform = { | ||
387 | .ops = &fsl_asrc_dma_pcm_ops, | ||
388 | .pcm_new = fsl_asrc_dma_pcm_new, | ||
389 | .pcm_free = fsl_asrc_dma_pcm_free, | ||
390 | }; | ||
391 | EXPORT_SYMBOL_GPL(fsl_asrc_platform); | ||
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 6bb0ea59284f..a609aafc994d 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
@@ -923,8 +923,8 @@ static int fsl_soc_dma_probe(struct platform_device *pdev) | |||
923 | dma->dai.pcm_free = fsl_dma_free_dma_buffers; | 923 | dma->dai.pcm_free = fsl_dma_free_dma_buffers; |
924 | 924 | ||
925 | /* Store the SSI-specific information that we need */ | 925 | /* Store the SSI-specific information that we need */ |
926 | dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0); | 926 | dma->ssi_stx_phys = res.start + CCSR_SSI_STX0; |
927 | dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0); | 927 | dma->ssi_srx_phys = res.start + CCSR_SSI_SRX0; |
928 | 928 | ||
929 | iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL); | 929 | iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL); |
930 | if (iprop) | 930 | if (iprop) |
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index d719caf26dc2..72d154e7dd03 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c | |||
@@ -624,12 +624,14 @@ static int fsl_esai_dai_probe(struct snd_soc_dai *dai) | |||
624 | static struct snd_soc_dai_driver fsl_esai_dai = { | 624 | static struct snd_soc_dai_driver fsl_esai_dai = { |
625 | .probe = fsl_esai_dai_probe, | 625 | .probe = fsl_esai_dai_probe, |
626 | .playback = { | 626 | .playback = { |
627 | .stream_name = "CPU-Playback", | ||
627 | .channels_min = 1, | 628 | .channels_min = 1, |
628 | .channels_max = 12, | 629 | .channels_max = 12, |
629 | .rates = FSL_ESAI_RATES, | 630 | .rates = FSL_ESAI_RATES, |
630 | .formats = FSL_ESAI_FORMATS, | 631 | .formats = FSL_ESAI_FORMATS, |
631 | }, | 632 | }, |
632 | .capture = { | 633 | .capture = { |
634 | .stream_name = "CPU-Capture", | ||
633 | .channels_min = 1, | 635 | .channels_min = 1, |
634 | .channels_max = 8, | 636 | .channels_max = 8, |
635 | .rates = FSL_ESAI_RATES, | 637 | .rates = FSL_ESAI_RATES, |
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index c5a0e8af8226..faa049797897 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c | |||
@@ -106,7 +106,7 @@ irq_rx: | |||
106 | xcsr &= ~FSL_SAI_CSR_xF_MASK; | 106 | xcsr &= ~FSL_SAI_CSR_xF_MASK; |
107 | 107 | ||
108 | if (flags) | 108 | if (flags) |
109 | regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr); | 109 | regmap_write(sai->regmap, FSL_SAI_RCSR, flags | xcsr); |
110 | 110 | ||
111 | out: | 111 | out: |
112 | if (irq_none) | 112 | if (irq_none) |
@@ -327,7 +327,7 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
327 | { | 327 | { |
328 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | 328 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); |
329 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 329 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
330 | u32 tcsr, rcsr; | 330 | u32 xcsr, count = 100; |
331 | 331 | ||
332 | /* | 332 | /* |
333 | * The transmitter bit clock and frame sync are to be | 333 | * The transmitter bit clock and frame sync are to be |
@@ -338,9 +338,6 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
338 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, | 338 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, |
339 | FSL_SAI_CR2_SYNC); | 339 | FSL_SAI_CR2_SYNC); |
340 | 340 | ||
341 | regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr); | ||
342 | regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr); | ||
343 | |||
344 | /* | 341 | /* |
345 | * It is recommended that the transmitter is the last enabled | 342 | * It is recommended that the transmitter is the last enabled |
346 | * and the first disabled. | 343 | * and the first disabled. |
@@ -349,17 +346,16 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
349 | case SNDRV_PCM_TRIGGER_START: | 346 | case SNDRV_PCM_TRIGGER_START: |
350 | case SNDRV_PCM_TRIGGER_RESUME: | 347 | case SNDRV_PCM_TRIGGER_RESUME: |
351 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 348 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
352 | if (!(tcsr & FSL_SAI_CSR_FRDE || rcsr & FSL_SAI_CSR_FRDE)) { | 349 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), |
353 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, | 350 | FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE); |
354 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); | 351 | |
355 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, | 352 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, |
356 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); | 353 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); |
357 | } | 354 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, |
355 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); | ||
358 | 356 | ||
359 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), | 357 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), |
360 | FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS); | 358 | FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS); |
361 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), | ||
362 | FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE); | ||
363 | break; | 359 | break; |
364 | case SNDRV_PCM_TRIGGER_STOP: | 360 | case SNDRV_PCM_TRIGGER_STOP: |
365 | case SNDRV_PCM_TRIGGER_SUSPEND: | 361 | case SNDRV_PCM_TRIGGER_SUSPEND: |
@@ -370,11 +366,24 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
370 | FSL_SAI_CSR_xIE_MASK, 0); | 366 | FSL_SAI_CSR_xIE_MASK, 0); |
371 | 367 | ||
372 | /* Check if the opposite FRDE is also disabled */ | 368 | /* Check if the opposite FRDE is also disabled */ |
373 | if (!(tx ? rcsr & FSL_SAI_CSR_FRDE : tcsr & FSL_SAI_CSR_FRDE)) { | 369 | regmap_read(sai->regmap, FSL_SAI_xCSR(!tx), &xcsr); |
370 | if (!(xcsr & FSL_SAI_CSR_FRDE)) { | ||
371 | /* Disable both directions and reset their FIFOs */ | ||
374 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, | 372 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, |
375 | FSL_SAI_CSR_TERE, 0); | 373 | FSL_SAI_CSR_TERE, 0); |
376 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, | 374 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, |
377 | FSL_SAI_CSR_TERE, 0); | 375 | FSL_SAI_CSR_TERE, 0); |
376 | |||
377 | /* TERE will remain set till the end of current frame */ | ||
378 | do { | ||
379 | udelay(10); | ||
380 | regmap_read(sai->regmap, FSL_SAI_xCSR(tx), &xcsr); | ||
381 | } while (--count && xcsr & FSL_SAI_CSR_TERE); | ||
382 | |||
383 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, | ||
384 | FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); | ||
385 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, | ||
386 | FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); | ||
378 | } | 387 | } |
379 | break; | 388 | break; |
380 | default: | 389 | default: |
@@ -446,12 +455,14 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) | |||
446 | static struct snd_soc_dai_driver fsl_sai_dai = { | 455 | static struct snd_soc_dai_driver fsl_sai_dai = { |
447 | .probe = fsl_sai_dai_probe, | 456 | .probe = fsl_sai_dai_probe, |
448 | .playback = { | 457 | .playback = { |
458 | .stream_name = "CPU-Playback", | ||
449 | .channels_min = 1, | 459 | .channels_min = 1, |
450 | .channels_max = 2, | 460 | .channels_max = 2, |
451 | .rates = SNDRV_PCM_RATE_8000_96000, | 461 | .rates = SNDRV_PCM_RATE_8000_96000, |
452 | .formats = FSL_SAI_FORMATS, | 462 | .formats = FSL_SAI_FORMATS, |
453 | }, | 463 | }, |
454 | .capture = { | 464 | .capture = { |
465 | .stream_name = "CPU-Capture", | ||
455 | .channels_min = 1, | 466 | .channels_min = 1, |
456 | .channels_max = 2, | 467 | .channels_max = 2, |
457 | .rates = SNDRV_PCM_RATE_8000_96000, | 468 | .rates = SNDRV_PCM_RATE_8000_96000, |
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index b912d45a2a4c..70acfe4a9bd5 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -32,10 +32,13 @@ | |||
32 | #define FSL_SPDIF_TXFIFO_WML 0x8 | 32 | #define FSL_SPDIF_TXFIFO_WML 0x8 |
33 | #define FSL_SPDIF_RXFIFO_WML 0x8 | 33 | #define FSL_SPDIF_RXFIFO_WML 0x8 |
34 | 34 | ||
35 | #define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC) | 35 | #define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC) |
36 | #define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL | INT_URX_OV|\ | 36 | #define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL |\ |
37 | INT_QRX_FUL | INT_QRX_OV | INT_UQ_SYNC | INT_UQ_ERR |\ | 37 | INT_URX_OV | INT_QRX_FUL | INT_QRX_OV |\ |
38 | INT_RXFIFO_RESYNC | INT_LOSS_LOCK | INT_DPLL_LOCKED) | 38 | INT_UQ_SYNC | INT_UQ_ERR | INT_RXFIFO_RESYNC |\ |
39 | INT_LOSS_LOCK | INT_DPLL_LOCKED) | ||
40 | |||
41 | #define SIE_INTR_FOR(tx) (tx ? INTR_FOR_PLAYBACK : INTR_FOR_CAPTURE) | ||
39 | 42 | ||
40 | /* Index list for the values that has if (DPLL Locked) condition */ | 43 | /* Index list for the values that has if (DPLL Locked) condition */ |
41 | static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb }; | 44 | static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb }; |
@@ -96,7 +99,7 @@ struct fsl_spdif_priv { | |||
96 | struct platform_device *pdev; | 99 | struct platform_device *pdev; |
97 | struct regmap *regmap; | 100 | struct regmap *regmap; |
98 | bool dpll_locked; | 101 | bool dpll_locked; |
99 | u16 txrate[SPDIF_TXRATE_MAX]; | 102 | u32 txrate[SPDIF_TXRATE_MAX]; |
100 | u8 txclk_df[SPDIF_TXRATE_MAX]; | 103 | u8 txclk_df[SPDIF_TXRATE_MAX]; |
101 | u8 sysclk_df[SPDIF_TXRATE_MAX]; | 104 | u8 sysclk_df[SPDIF_TXRATE_MAX]; |
102 | u8 txclk_src[SPDIF_TXRATE_MAX]; | 105 | u8 txclk_src[SPDIF_TXRATE_MAX]; |
@@ -137,10 +140,9 @@ static void spdif_irq_sym_error(struct fsl_spdif_priv *spdif_priv) | |||
137 | 140 | ||
138 | dev_dbg(&pdev->dev, "isr: receiver found illegal symbol\n"); | 141 | dev_dbg(&pdev->dev, "isr: receiver found illegal symbol\n"); |
139 | 142 | ||
140 | if (!spdif_priv->dpll_locked) { | 143 | /* Clear illegal symbol if DPLL unlocked since no audio stream */ |
141 | /* DPLL unlocked seems no audio stream */ | 144 | if (!spdif_priv->dpll_locked) |
142 | regmap_update_bits(regmap, REG_SPDIF_SIE, INT_SYM_ERR, 0); | 145 | regmap_update_bits(regmap, REG_SPDIF_SIE, INT_SYM_ERR, 0); |
143 | } | ||
144 | } | 146 | } |
145 | 147 | ||
146 | /* U/Q Channel receive register full */ | 148 | /* U/Q Channel receive register full */ |
@@ -335,8 +337,8 @@ static void spdif_write_channel_status(struct fsl_spdif_priv *spdif_priv) | |||
335 | u32 ch_status; | 337 | u32 ch_status; |
336 | 338 | ||
337 | ch_status = (bitrev8(ctrl->ch_status[0]) << 16) | | 339 | ch_status = (bitrev8(ctrl->ch_status[0]) << 16) | |
338 | (bitrev8(ctrl->ch_status[1]) << 8) | | 340 | (bitrev8(ctrl->ch_status[1]) << 8) | |
339 | bitrev8(ctrl->ch_status[2]); | 341 | bitrev8(ctrl->ch_status[2]); |
340 | regmap_write(regmap, REG_SPDIF_STCSCH, ch_status); | 342 | regmap_write(regmap, REG_SPDIF_STCSCH, ch_status); |
341 | 343 | ||
342 | dev_dbg(&pdev->dev, "STCSCH: 0x%06x\n", ch_status); | 344 | dev_dbg(&pdev->dev, "STCSCH: 0x%06x\n", ch_status); |
@@ -390,6 +392,14 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream, | |||
390 | rate = SPDIF_TXRATE_48000; | 392 | rate = SPDIF_TXRATE_48000; |
391 | csfs = IEC958_AES3_CON_FS_48000; | 393 | csfs = IEC958_AES3_CON_FS_48000; |
392 | break; | 394 | break; |
395 | case 96000: | ||
396 | rate = SPDIF_TXRATE_96000; | ||
397 | csfs = IEC958_AES3_CON_FS_96000; | ||
398 | break; | ||
399 | case 192000: | ||
400 | rate = SPDIF_TXRATE_192000; | ||
401 | csfs = IEC958_AES3_CON_FS_192000; | ||
402 | break; | ||
393 | default: | 403 | default: |
394 | dev_err(&pdev->dev, "unsupported sample rate %d\n", sample_rate); | 404 | dev_err(&pdev->dev, "unsupported sample rate %d\n", sample_rate); |
395 | return -EINVAL; | 405 | return -EINVAL; |
@@ -433,13 +443,12 @@ clk_set_bypass: | |||
433 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs); | 443 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs); |
434 | 444 | ||
435 | /* select clock source and divisor */ | 445 | /* select clock source and divisor */ |
436 | stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) | STC_TXCLK_DF(txclk_df); | 446 | stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) | |
437 | mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK | STC_TXCLK_DF_MASK; | 447 | STC_TXCLK_DF(txclk_df) | STC_SYSCLK_DF(sysclk_df); |
448 | mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK | | ||
449 | STC_TXCLK_DF_MASK | STC_SYSCLK_DF_MASK; | ||
438 | regmap_update_bits(regmap, REG_SPDIF_STC, mask, stc); | 450 | regmap_update_bits(regmap, REG_SPDIF_STC, mask, stc); |
439 | 451 | ||
440 | regmap_update_bits(regmap, REG_SPDIF_STC, | ||
441 | STC_SYSCLK_DF_MASK, STC_SYSCLK_DF(sysclk_df)); | ||
442 | |||
443 | dev_dbg(&pdev->dev, "set sample rate to %dHz for %dHz playback\n", | 452 | dev_dbg(&pdev->dev, "set sample rate to %dHz for %dHz playback\n", |
444 | spdif_priv->txrate[rate], sample_rate); | 453 | spdif_priv->txrate[rate], sample_rate); |
445 | 454 | ||
@@ -553,7 +562,7 @@ static int fsl_spdif_hw_params(struct snd_pcm_substream *substream, | |||
553 | return ret; | 562 | return ret; |
554 | } | 563 | } |
555 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_CLOCK, | 564 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_CLOCK, |
556 | IEC958_AES3_CON_CLOCK_1000PPM); | 565 | IEC958_AES3_CON_CLOCK_1000PPM); |
557 | spdif_write_channel_status(spdif_priv); | 566 | spdif_write_channel_status(spdif_priv); |
558 | } else { | 567 | } else { |
559 | /* Setup rx clock source */ | 568 | /* Setup rx clock source */ |
@@ -569,9 +578,9 @@ static int fsl_spdif_trigger(struct snd_pcm_substream *substream, | |||
569 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 578 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
570 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 579 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
571 | struct regmap *regmap = spdif_priv->regmap; | 580 | struct regmap *regmap = spdif_priv->regmap; |
572 | int is_playack = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | 581 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
573 | u32 intr = is_playack ? INTR_FOR_PLAYBACK : INTR_FOR_CAPTURE; | 582 | u32 intr = SIE_INTR_FOR(tx); |
574 | u32 dmaen = is_playack ? SCR_DMA_TX_EN : SCR_DMA_RX_EN;; | 583 | u32 dmaen = SCR_DMA_xX_EN(tx); |
575 | 584 | ||
576 | switch (cmd) { | 585 | switch (cmd) { |
577 | case SNDRV_PCM_TRIGGER_START: | 586 | case SNDRV_PCM_TRIGGER_START: |
@@ -662,9 +671,8 @@ static int fsl_spdif_capture_get(struct snd_kcontrol *kcontrol, | |||
662 | u32 cstatus, val; | 671 | u32 cstatus, val; |
663 | 672 | ||
664 | regmap_read(regmap, REG_SPDIF_SIS, &val); | 673 | regmap_read(regmap, REG_SPDIF_SIS, &val); |
665 | if (!(val & INT_CNEW)) { | 674 | if (!(val & INT_CNEW)) |
666 | return -EAGAIN; | 675 | return -EAGAIN; |
667 | } | ||
668 | 676 | ||
669 | regmap_read(regmap, REG_SPDIF_SRCSH, &cstatus); | 677 | regmap_read(regmap, REG_SPDIF_SRCSH, &cstatus); |
670 | ucontrol->value.iec958.status[0] = (cstatus >> 16) & 0xFF; | 678 | ucontrol->value.iec958.status[0] = (cstatus >> 16) & 0xFF; |
@@ -693,15 +701,14 @@ static int fsl_spdif_subcode_get(struct snd_kcontrol *kcontrol, | |||
693 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | 701 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); |
694 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | 702 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; |
695 | unsigned long flags; | 703 | unsigned long flags; |
696 | int ret = 0; | 704 | int ret = -EAGAIN; |
697 | 705 | ||
698 | spin_lock_irqsave(&ctrl->ctl_lock, flags); | 706 | spin_lock_irqsave(&ctrl->ctl_lock, flags); |
699 | if (ctrl->ready_buf) { | 707 | if (ctrl->ready_buf) { |
700 | int idx = (ctrl->ready_buf - 1) * SPDIF_UBITS_SIZE; | 708 | int idx = (ctrl->ready_buf - 1) * SPDIF_UBITS_SIZE; |
701 | memcpy(&ucontrol->value.iec958.subcode[0], | 709 | memcpy(&ucontrol->value.iec958.subcode[0], |
702 | &ctrl->subcode[idx], SPDIF_UBITS_SIZE); | 710 | &ctrl->subcode[idx], SPDIF_UBITS_SIZE); |
703 | } else { | 711 | ret = 0; |
704 | ret = -EAGAIN; | ||
705 | } | 712 | } |
706 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); | 713 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); |
707 | 714 | ||
@@ -726,15 +733,14 @@ static int fsl_spdif_qget(struct snd_kcontrol *kcontrol, | |||
726 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | 733 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); |
727 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | 734 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; |
728 | unsigned long flags; | 735 | unsigned long flags; |
729 | int ret = 0; | 736 | int ret = -EAGAIN; |
730 | 737 | ||
731 | spin_lock_irqsave(&ctrl->ctl_lock, flags); | 738 | spin_lock_irqsave(&ctrl->ctl_lock, flags); |
732 | if (ctrl->ready_buf) { | 739 | if (ctrl->ready_buf) { |
733 | int idx = (ctrl->ready_buf - 1) * SPDIF_QSUB_SIZE; | 740 | int idx = (ctrl->ready_buf - 1) * SPDIF_QSUB_SIZE; |
734 | memcpy(&ucontrol->value.bytes.data[0], | 741 | memcpy(&ucontrol->value.bytes.data[0], |
735 | &ctrl->qsub[idx], SPDIF_QSUB_SIZE); | 742 | &ctrl->qsub[idx], SPDIF_QSUB_SIZE); |
736 | } else { | 743 | ret = 0; |
737 | ret = -EAGAIN; | ||
738 | } | 744 | } |
739 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); | 745 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); |
740 | 746 | ||
@@ -762,7 +768,7 @@ static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol, | |||
762 | struct regmap *regmap = spdif_priv->regmap; | 768 | struct regmap *regmap = spdif_priv->regmap; |
763 | u32 val; | 769 | u32 val; |
764 | 770 | ||
765 | val = regmap_read(regmap, REG_SPDIF_SIS, &val); | 771 | regmap_read(regmap, REG_SPDIF_SIS, &val); |
766 | ucontrol->value.integer.value[0] = (val & INT_VAL_NOGOOD) != 0; | 772 | ucontrol->value.integer.value[0] = (val & INT_VAL_NOGOOD) != 0; |
767 | regmap_write(regmap, REG_SPDIF_SIC, INT_VAL_NOGOOD); | 773 | regmap_write(regmap, REG_SPDIF_SIC, INT_VAL_NOGOOD); |
768 | 774 | ||
@@ -799,10 +805,10 @@ static int spdif_get_rxclk_rate(struct fsl_spdif_priv *spdif_priv, | |||
799 | regmap_read(regmap, REG_SPDIF_SRPC, &phaseconf); | 805 | regmap_read(regmap, REG_SPDIF_SRPC, &phaseconf); |
800 | 806 | ||
801 | clksrc = (phaseconf >> SRPC_CLKSRC_SEL_OFFSET) & 0xf; | 807 | clksrc = (phaseconf >> SRPC_CLKSRC_SEL_OFFSET) & 0xf; |
802 | if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED)) { | 808 | |
803 | /* Get bus clock from system */ | 809 | /* Get bus clock from system */ |
810 | if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED)) | ||
804 | busclk_freq = clk_get_rate(spdif_priv->sysclk); | 811 | busclk_freq = clk_get_rate(spdif_priv->sysclk); |
805 | } | ||
806 | 812 | ||
807 | /* FreqMeas_CLK = (BUS_CLK * FreqMeas) / 2 ^ 10 / GAINSEL / 128 */ | 813 | /* FreqMeas_CLK = (BUS_CLK * FreqMeas) / 2 ^ 10 / GAINSEL / 128 */ |
808 | tmpval64 = (u64) busclk_freq * freqmeas; | 814 | tmpval64 = (u64) busclk_freq * freqmeas; |
@@ -826,12 +832,12 @@ static int fsl_spdif_rxrate_get(struct snd_kcontrol *kcontrol, | |||
826 | { | 832 | { |
827 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | 833 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); |
828 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | 834 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); |
829 | int rate = spdif_get_rxclk_rate(spdif_priv, SPDIF_DEFAULT_GAINSEL); | 835 | int rate = 0; |
830 | 836 | ||
831 | if (spdif_priv->dpll_locked) | 837 | if (spdif_priv->dpll_locked) |
832 | ucontrol->value.integer.value[0] = rate; | 838 | rate = spdif_get_rxclk_rate(spdif_priv, SPDIF_DEFAULT_GAINSEL); |
833 | else | 839 | |
834 | ucontrol->value.integer.value[0] = 0; | 840 | ucontrol->value.integer.value[0] = rate; |
835 | 841 | ||
836 | return 0; | 842 | return 0; |
837 | } | 843 | } |
@@ -969,12 +975,14 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai) | |||
969 | static struct snd_soc_dai_driver fsl_spdif_dai = { | 975 | static struct snd_soc_dai_driver fsl_spdif_dai = { |
970 | .probe = &fsl_spdif_dai_probe, | 976 | .probe = &fsl_spdif_dai_probe, |
971 | .playback = { | 977 | .playback = { |
978 | .stream_name = "CPU-Playback", | ||
972 | .channels_min = 2, | 979 | .channels_min = 2, |
973 | .channels_max = 2, | 980 | .channels_max = 2, |
974 | .rates = FSL_SPDIF_RATES_PLAYBACK, | 981 | .rates = FSL_SPDIF_RATES_PLAYBACK, |
975 | .formats = FSL_SPDIF_FORMATS_PLAYBACK, | 982 | .formats = FSL_SPDIF_FORMATS_PLAYBACK, |
976 | }, | 983 | }, |
977 | .capture = { | 984 | .capture = { |
985 | .stream_name = "CPU-Capture", | ||
978 | .channels_min = 2, | 986 | .channels_min = 2, |
979 | .channels_max = 2, | 987 | .channels_max = 2, |
980 | .rates = FSL_SPDIF_RATES_CAPTURE, | 988 | .rates = FSL_SPDIF_RATES_CAPTURE, |
@@ -1046,7 +1054,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, | |||
1046 | struct clk *clk, u64 savesub, | 1054 | struct clk *clk, u64 savesub, |
1047 | enum spdif_txrate index, bool round) | 1055 | enum spdif_txrate index, bool round) |
1048 | { | 1056 | { |
1049 | const u32 rate[] = { 32000, 44100, 48000 }; | 1057 | const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 }; |
1050 | bool is_sysclk = clk == spdif_priv->sysclk; | 1058 | bool is_sysclk = clk == spdif_priv->sysclk; |
1051 | u64 rate_ideal, rate_actual, sub; | 1059 | u64 rate_ideal, rate_actual, sub; |
1052 | u32 sysclk_dfmin, sysclk_dfmax; | 1060 | u32 sysclk_dfmin, sysclk_dfmax; |
@@ -1076,7 +1084,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, | |||
1076 | goto out; | 1084 | goto out; |
1077 | } else if (arate / rate[index] == 1) { | 1085 | } else if (arate / rate[index] == 1) { |
1078 | /* A little bigger than expect */ | 1086 | /* A little bigger than expect */ |
1079 | sub = (arate - rate[index]) * 100000; | 1087 | sub = (u64)(arate - rate[index]) * 100000; |
1080 | do_div(sub, rate[index]); | 1088 | do_div(sub, rate[index]); |
1081 | if (sub >= savesub) | 1089 | if (sub >= savesub) |
1082 | continue; | 1090 | continue; |
@@ -1086,7 +1094,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, | |||
1086 | spdif_priv->txrate[index] = arate; | 1094 | spdif_priv->txrate[index] = arate; |
1087 | } else if (rate[index] / arate == 1) { | 1095 | } else if (rate[index] / arate == 1) { |
1088 | /* A little smaller than expect */ | 1096 | /* A little smaller than expect */ |
1089 | sub = (rate[index] - arate) * 100000; | 1097 | sub = (u64)(rate[index] - arate) * 100000; |
1090 | do_div(sub, rate[index]); | 1098 | do_div(sub, rate[index]); |
1091 | if (sub >= savesub) | 1099 | if (sub >= savesub) |
1092 | continue; | 1100 | continue; |
@@ -1105,7 +1113,7 @@ out: | |||
1105 | static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, | 1113 | static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, |
1106 | enum spdif_txrate index) | 1114 | enum spdif_txrate index) |
1107 | { | 1115 | { |
1108 | const u32 rate[] = { 32000, 44100, 48000 }; | 1116 | const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 }; |
1109 | struct platform_device *pdev = spdif_priv->pdev; | 1117 | struct platform_device *pdev = spdif_priv->pdev; |
1110 | struct device *dev = &pdev->dev; | 1118 | struct device *dev = &pdev->dev; |
1111 | u64 savesub = 100000, ret; | 1119 | u64 savesub = 100000, ret; |
@@ -1238,12 +1246,12 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
1238 | spin_lock_init(&ctrl->ctl_lock); | 1246 | spin_lock_init(&ctrl->ctl_lock); |
1239 | 1247 | ||
1240 | /* Init tx channel status default value */ | 1248 | /* Init tx channel status default value */ |
1241 | ctrl->ch_status[0] = | 1249 | ctrl->ch_status[0] = IEC958_AES0_CON_NOT_COPYRIGHT | |
1242 | IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_5015; | 1250 | IEC958_AES0_CON_EMPHASIS_5015; |
1243 | ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID; | 1251 | ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID; |
1244 | ctrl->ch_status[2] = 0x00; | 1252 | ctrl->ch_status[2] = 0x00; |
1245 | ctrl->ch_status[3] = | 1253 | ctrl->ch_status[3] = IEC958_AES3_CON_FS_44100 | |
1246 | IEC958_AES3_CON_FS_44100 | IEC958_AES3_CON_CLOCK_1000PPM; | 1254 | IEC958_AES3_CON_CLOCK_1000PPM; |
1247 | 1255 | ||
1248 | spdif_priv->dpll_locked = false; | 1256 | spdif_priv->dpll_locked = false; |
1249 | 1257 | ||
diff --git a/sound/soc/fsl/fsl_spdif.h b/sound/soc/fsl/fsl_spdif.h index 16fde4b927d3..00bd3514c610 100644 --- a/sound/soc/fsl/fsl_spdif.h +++ b/sound/soc/fsl/fsl_spdif.h | |||
@@ -93,6 +93,8 @@ | |||
93 | #define SCR_USRC_SEL_RECV (0x1 << SCR_USRC_SEL_OFFSET) | 93 | #define SCR_USRC_SEL_RECV (0x1 << SCR_USRC_SEL_OFFSET) |
94 | #define SCR_USRC_SEL_CHIP (0x3 << SCR_USRC_SEL_OFFSET) | 94 | #define SCR_USRC_SEL_CHIP (0x3 << SCR_USRC_SEL_OFFSET) |
95 | 95 | ||
96 | #define SCR_DMA_xX_EN(tx) (tx ? SCR_DMA_TX_EN : SCR_DMA_RX_EN) | ||
97 | |||
96 | /* SPDIF CDText control */ | 98 | /* SPDIF CDText control */ |
97 | #define SRCD_CD_USER_OFFSET 1 | 99 | #define SRCD_CD_USER_OFFSET 1 |
98 | #define SRCD_CD_USER (1 << SRCD_CD_USER_OFFSET) | 100 | #define SRCD_CD_USER (1 << SRCD_CD_USER_OFFSET) |
@@ -164,8 +166,10 @@ enum spdif_txrate { | |||
164 | SPDIF_TXRATE_32000 = 0, | 166 | SPDIF_TXRATE_32000 = 0, |
165 | SPDIF_TXRATE_44100, | 167 | SPDIF_TXRATE_44100, |
166 | SPDIF_TXRATE_48000, | 168 | SPDIF_TXRATE_48000, |
169 | SPDIF_TXRATE_96000, | ||
170 | SPDIF_TXRATE_192000, | ||
167 | }; | 171 | }; |
168 | #define SPDIF_TXRATE_MAX (SPDIF_TXRATE_48000 + 1) | 172 | #define SPDIF_TXRATE_MAX (SPDIF_TXRATE_192000 + 1) |
169 | 173 | ||
170 | 174 | ||
171 | #define SPDIF_CSTATUS_BYTE 6 | 175 | #define SPDIF_CSTATUS_BYTE 6 |
@@ -175,7 +179,9 @@ enum spdif_txrate { | |||
175 | 179 | ||
176 | #define FSL_SPDIF_RATES_PLAYBACK (SNDRV_PCM_RATE_32000 | \ | 180 | #define FSL_SPDIF_RATES_PLAYBACK (SNDRV_PCM_RATE_32000 | \ |
177 | SNDRV_PCM_RATE_44100 | \ | 181 | SNDRV_PCM_RATE_44100 | \ |
178 | SNDRV_PCM_RATE_48000) | 182 | SNDRV_PCM_RATE_48000 | \ |
183 | SNDRV_PCM_RATE_96000 | \ | ||
184 | SNDRV_PCM_RATE_192000) | ||
179 | 185 | ||
180 | #define FSL_SPDIF_RATES_CAPTURE (SNDRV_PCM_RATE_16000 | \ | 186 | #define FSL_SPDIF_RATES_CAPTURE (SNDRV_PCM_RATE_16000 | \ |
181 | SNDRV_PCM_RATE_32000 | \ | 187 | SNDRV_PCM_RATE_32000 | \ |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 9bfef55d77d1..87eb5776a39b 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -590,8 +590,8 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, | |||
590 | else | 590 | else |
591 | clkrate = clk_round_rate(ssi_private->baudclk, tmprate); | 591 | clkrate = clk_round_rate(ssi_private->baudclk, tmprate); |
592 | 592 | ||
593 | do_div(clkrate, factor); | 593 | clkrate /= factor; |
594 | afreq = (u32)clkrate / (i + 1); | 594 | afreq = clkrate / (i + 1); |
595 | 595 | ||
596 | if (freq == afreq) | 596 | if (freq == afreq) |
597 | sub = 0; | 597 | sub = 0; |
@@ -1032,12 +1032,14 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { | |||
1032 | static struct snd_soc_dai_driver fsl_ssi_dai_template = { | 1032 | static struct snd_soc_dai_driver fsl_ssi_dai_template = { |
1033 | .probe = fsl_ssi_dai_probe, | 1033 | .probe = fsl_ssi_dai_probe, |
1034 | .playback = { | 1034 | .playback = { |
1035 | .stream_name = "CPU-Playback", | ||
1035 | .channels_min = 1, | 1036 | .channels_min = 1, |
1036 | .channels_max = 2, | 1037 | .channels_max = 2, |
1037 | .rates = FSLSSI_I2S_RATES, | 1038 | .rates = FSLSSI_I2S_RATES, |
1038 | .formats = FSLSSI_I2S_FORMATS, | 1039 | .formats = FSLSSI_I2S_FORMATS, |
1039 | }, | 1040 | }, |
1040 | .capture = { | 1041 | .capture = { |
1042 | .stream_name = "CPU-Capture", | ||
1041 | .channels_min = 1, | 1043 | .channels_min = 1, |
1042 | .channels_max = 2, | 1044 | .channels_max = 2, |
1043 | .rates = FSLSSI_I2S_RATES, | 1045 | .rates = FSLSSI_I2S_RATES, |
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 267717aa96c1..46f9beb6b273 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c | |||
@@ -67,7 +67,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, | |||
67 | { | 67 | { |
68 | ssize_t ret; | 68 | ssize_t ret; |
69 | char *buf; | 69 | char *buf; |
70 | int port = (int)file->private_data; | 70 | uintptr_t port = (uintptr_t)file->private_data; |
71 | u32 pdcr, ptcr; | 71 | u32 pdcr, ptcr; |
72 | 72 | ||
73 | if (audmux_clk) { | 73 | if (audmux_clk) { |
@@ -147,7 +147,7 @@ static const struct file_operations audmux_debugfs_fops = { | |||
147 | 147 | ||
148 | static void audmux_debugfs_init(void) | 148 | static void audmux_debugfs_init(void) |
149 | { | 149 | { |
150 | int i; | 150 | uintptr_t i; |
151 | char buf[20]; | 151 | char buf[20]; |
152 | 152 | ||
153 | audmux_debugfs_root = debugfs_create_dir("audmux", NULL); | 153 | audmux_debugfs_root = debugfs_create_dir("audmux", NULL); |
@@ -157,10 +157,10 @@ static void audmux_debugfs_init(void) | |||
157 | } | 157 | } |
158 | 158 | ||
159 | for (i = 0; i < MX31_AUDMUX_PORT7_SSI_PINS_7 + 1; i++) { | 159 | for (i = 0; i < MX31_AUDMUX_PORT7_SSI_PINS_7 + 1; i++) { |
160 | snprintf(buf, sizeof(buf), "ssi%d", i); | 160 | snprintf(buf, sizeof(buf), "ssi%lu", i); |
161 | if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, | 161 | if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, |
162 | (void *)i, &audmux_debugfs_fops)) | 162 | (void *)i, &audmux_debugfs_fops)) |
163 | pr_warning("Failed to create AUDMUX port %d debugfs file\n", | 163 | pr_warning("Failed to create AUDMUX port %lu debugfs file\n", |
164 | i); | 164 | i); |
165 | } | 165 | } |
166 | } | 166 | } |
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index 0849b7b83f0a..0db94f492e97 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c | |||
@@ -59,7 +59,6 @@ int imx_pcm_dma_init(struct platform_device *pdev) | |||
59 | { | 59 | { |
60 | return devm_snd_dmaengine_pcm_register(&pdev->dev, | 60 | return devm_snd_dmaengine_pcm_register(&pdev->dev, |
61 | &imx_dmaengine_pcm_config, | 61 | &imx_dmaengine_pcm_config, |
62 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | ||
63 | SND_DMAENGINE_PCM_FLAG_COMPAT); | 62 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
64 | } | 63 | } |
65 | EXPORT_SYMBOL_GPL(imx_pcm_dma_init); | 64 | EXPORT_SYMBOL_GPL(imx_pcm_dma_init); |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 03a7fdcdf114..159e517fa09a 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -116,6 +116,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
116 | { | 116 | { |
117 | struct device_node *node; | 117 | struct device_node *node; |
118 | struct clk *clk; | 118 | struct clk *clk; |
119 | u32 val; | ||
119 | int ret; | 120 | int ret; |
120 | 121 | ||
121 | /* | 122 | /* |
@@ -151,10 +152,8 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
151 | } | 152 | } |
152 | 153 | ||
153 | dai->sysclk = clk_get_rate(clk); | 154 | dai->sysclk = clk_get_rate(clk); |
154 | } else if (of_property_read_bool(np, "system-clock-frequency")) { | 155 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { |
155 | of_property_read_u32(np, | 156 | dai->sysclk = val; |
156 | "system-clock-frequency", | ||
157 | &dai->sysclk); | ||
158 | } else { | 157 | } else { |
159 | clk = of_clk_get(node, 0); | 158 | clk = of_clk_get(node, 0); |
160 | if (!IS_ERR(clk)) | 159 | if (!IS_ERR(clk)) |
@@ -303,6 +302,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
303 | { | 302 | { |
304 | struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; | 303 | struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; |
305 | struct simple_dai_props *dai_props = priv->dai_props; | 304 | struct simple_dai_props *dai_props = priv->dai_props; |
305 | u32 val; | ||
306 | int ret; | 306 | int ret; |
307 | 307 | ||
308 | /* parsing the card name from DT */ | 308 | /* parsing the card name from DT */ |
@@ -325,8 +325,9 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
325 | } | 325 | } |
326 | 326 | ||
327 | /* Factor to mclk, used in hw_params() */ | 327 | /* Factor to mclk, used in hw_params() */ |
328 | of_property_read_u32(node, "simple-audio-card,mclk-fs", | 328 | ret = of_property_read_u32(node, "simple-audio-card,mclk-fs", &val); |
329 | &priv->mclk_fs); | 329 | if (ret == 0) |
330 | priv->mclk_fs = val; | ||
330 | 331 | ||
331 | dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? | 332 | dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? |
332 | priv->snd_card.name : ""); | 333 | priv->snd_card.name : ""); |
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index c30fedb3e149..f5b4a9c79cdf 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -58,3 +58,15 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH | |||
58 | help | 58 | help |
59 | This adds audio driver for Intel Baytrail platform based boards | 59 | This adds audio driver for Intel Baytrail platform based boards |
60 | with the MAX98090 audio codec. | 60 | with the MAX98090 audio codec. |
61 | |||
62 | config SND_SOC_INTEL_BROADWELL_MACH | ||
63 | tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" | ||
64 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC | ||
65 | select SND_SOC_INTEL_HASWELL | ||
66 | select SND_COMPRESS_OFFLOAD | ||
67 | select SND_SOC_RT286 | ||
68 | help | ||
69 | This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell | ||
70 | Ultrabook platforms. | ||
71 | Say Y if you have such a device | ||
72 | If unsure select "N". | ||
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 4bfca79a42ba..7acbfc43a0c6 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile | |||
@@ -24,7 +24,9 @@ obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o | |||
24 | snd-soc-sst-haswell-objs := haswell.o | 24 | snd-soc-sst-haswell-objs := haswell.o |
25 | snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o | 25 | snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o |
26 | snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o | 26 | snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o |
27 | snd-soc-sst-broadwell-objs := broadwell.o | ||
27 | 28 | ||
28 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o | 29 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o |
29 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o | 30 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o |
30 | obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o | 31 | obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o |
32 | obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o | ||
diff --git a/sound/soc/intel/broadwell.c b/sound/soc/intel/broadwell.c new file mode 100644 index 000000000000..0e550f14028f --- /dev/null +++ b/sound/soc/intel/broadwell.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * Intel Broadwell Wildcatpoint SST Audio | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <sound/core.h> | ||
20 | #include <sound/pcm.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | |||
24 | #include "sst-dsp.h" | ||
25 | #include "sst-haswell-ipc.h" | ||
26 | |||
27 | #include "../codecs/rt286.h" | ||
28 | |||
29 | static const struct snd_soc_dapm_widget broadwell_widgets[] = { | ||
30 | SND_SOC_DAPM_HP("Headphones", NULL), | ||
31 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
32 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
33 | SND_SOC_DAPM_MIC("DMIC1", NULL), | ||
34 | SND_SOC_DAPM_MIC("DMIC2", NULL), | ||
35 | SND_SOC_DAPM_LINE("Line Jack", NULL), | ||
36 | }; | ||
37 | |||
38 | static const struct snd_soc_dapm_route broadwell_rt286_map[] = { | ||
39 | |||
40 | /* speaker */ | ||
41 | {"Speaker", NULL, "SPOR"}, | ||
42 | {"Speaker", NULL, "SPOL"}, | ||
43 | |||
44 | /* HP jack connectors - unknown if we have jack deteck */ | ||
45 | {"Headphones", NULL, "HPO Pin"}, | ||
46 | |||
47 | /* other jacks */ | ||
48 | {"MIC1", NULL, "Mic Jack"}, | ||
49 | {"LINE1", NULL, "Line Jack"}, | ||
50 | |||
51 | /* digital mics */ | ||
52 | {"DMIC1 Pin", NULL, "DMIC1"}, | ||
53 | {"DMIC2 Pin", NULL, "DMIC2"}, | ||
54 | |||
55 | /* CODEC BE connections */ | ||
56 | {"SSP0 CODEC IN", NULL, "AIF1 Capture"}, | ||
57 | {"AIF1 Playback", NULL, "SSP0 CODEC OUT"}, | ||
58 | }; | ||
59 | |||
60 | static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, | ||
61 | struct snd_pcm_hw_params *params) | ||
62 | { | ||
63 | struct snd_interval *rate = hw_param_interval(params, | ||
64 | SNDRV_PCM_HW_PARAM_RATE); | ||
65 | struct snd_interval *channels = hw_param_interval(params, | ||
66 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
67 | |||
68 | /* The ADSP will covert the FE rate to 48k, stereo */ | ||
69 | rate->min = rate->max = 48000; | ||
70 | channels->min = channels->max = 2; | ||
71 | |||
72 | /* set SSP0 to 16 bit */ | ||
73 | snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - | ||
74 | SNDRV_PCM_HW_PARAM_FIRST_MASK], | ||
75 | SNDRV_PCM_FORMAT_S16_LE); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int broadwell_rt286_hw_params(struct snd_pcm_substream *substream, | ||
80 | struct snd_pcm_hw_params *params) | ||
81 | { | ||
82 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
83 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
84 | int ret; | ||
85 | |||
86 | ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000, | ||
87 | SND_SOC_CLOCK_IN); | ||
88 | |||
89 | if (ret < 0) { | ||
90 | dev_err(rtd->dev, "can't set codec sysclk configuration\n"); | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | static struct snd_soc_ops broadwell_rt286_ops = { | ||
98 | .hw_params = broadwell_rt286_hw_params, | ||
99 | }; | ||
100 | |||
101 | static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) | ||
102 | { | ||
103 | struct snd_soc_codec *codec = rtd->codec; | ||
104 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
105 | struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev); | ||
106 | struct sst_hsw *broadwell = pdata->dsp; | ||
107 | int ret; | ||
108 | |||
109 | /* Set ADSP SSP port settings */ | ||
110 | ret = sst_hsw_device_set_config(broadwell, SST_HSW_DEVICE_SSP_0, | ||
111 | SST_HSW_DEVICE_MCLK_FREQ_24_MHZ, | ||
112 | SST_HSW_DEVICE_CLOCK_MASTER, 9); | ||
113 | if (ret < 0) { | ||
114 | dev_err(rtd->dev, "error: failed to set device config\n"); | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | /* always connected - check HP for jack detect */ | ||
119 | snd_soc_dapm_enable_pin(dapm, "Headphones"); | ||
120 | snd_soc_dapm_enable_pin(dapm, "Speaker"); | ||
121 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); | ||
122 | snd_soc_dapm_enable_pin(dapm, "Line Jack"); | ||
123 | snd_soc_dapm_enable_pin(dapm, "DMIC1"); | ||
124 | snd_soc_dapm_enable_pin(dapm, "DMIC2"); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | /* broadwell digital audio interface glue - connects codec <--> CPU */ | ||
130 | static struct snd_soc_dai_link broadwell_rt286_dais[] = { | ||
131 | /* Front End DAI links */ | ||
132 | { | ||
133 | .name = "System PCM", | ||
134 | .stream_name = "System Playback", | ||
135 | .cpu_dai_name = "System Pin", | ||
136 | .platform_name = "haswell-pcm-audio", | ||
137 | .dynamic = 1, | ||
138 | .codec_name = "snd-soc-dummy", | ||
139 | .codec_dai_name = "snd-soc-dummy-dai", | ||
140 | .init = broadwell_rtd_init, | ||
141 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
142 | .dpcm_playback = 1, | ||
143 | }, | ||
144 | { | ||
145 | .name = "Offload0", | ||
146 | .stream_name = "Offload0 Playback", | ||
147 | .cpu_dai_name = "Offload0 Pin", | ||
148 | .platform_name = "haswell-pcm-audio", | ||
149 | .dynamic = 1, | ||
150 | .codec_name = "snd-soc-dummy", | ||
151 | .codec_dai_name = "snd-soc-dummy-dai", | ||
152 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
153 | .dpcm_playback = 1, | ||
154 | }, | ||
155 | { | ||
156 | .name = "Offload1", | ||
157 | .stream_name = "Offload1 Playback", | ||
158 | .cpu_dai_name = "Offload1 Pin", | ||
159 | .platform_name = "haswell-pcm-audio", | ||
160 | .dynamic = 1, | ||
161 | .codec_name = "snd-soc-dummy", | ||
162 | .codec_dai_name = "snd-soc-dummy-dai", | ||
163 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
164 | .dpcm_playback = 1, | ||
165 | }, | ||
166 | { | ||
167 | .name = "Loopback PCM", | ||
168 | .stream_name = "Loopback", | ||
169 | .cpu_dai_name = "Loopback Pin", | ||
170 | .platform_name = "haswell-pcm-audio", | ||
171 | .dynamic = 0, | ||
172 | .codec_name = "snd-soc-dummy", | ||
173 | .codec_dai_name = "snd-soc-dummy-dai", | ||
174 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
175 | .dpcm_capture = 1, | ||
176 | }, | ||
177 | { | ||
178 | .name = "Capture PCM", | ||
179 | .stream_name = "Capture", | ||
180 | .cpu_dai_name = "Capture Pin", | ||
181 | .platform_name = "haswell-pcm-audio", | ||
182 | .dynamic = 1, | ||
183 | .codec_name = "snd-soc-dummy", | ||
184 | .codec_dai_name = "snd-soc-dummy-dai", | ||
185 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
186 | .dpcm_capture = 1, | ||
187 | }, | ||
188 | |||
189 | /* Back End DAI links */ | ||
190 | { | ||
191 | /* SSP0 - Codec */ | ||
192 | .name = "Codec", | ||
193 | .be_id = 0, | ||
194 | .cpu_dai_name = "snd-soc-dummy-dai", | ||
195 | .platform_name = "snd-soc-dummy", | ||
196 | .no_pcm = 1, | ||
197 | .codec_name = "i2c-INT343A:00", | ||
198 | .codec_dai_name = "rt286-aif1", | ||
199 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
200 | SND_SOC_DAIFMT_CBS_CFS, | ||
201 | .ignore_suspend = 1, | ||
202 | .ignore_pmdown_time = 1, | ||
203 | .be_hw_params_fixup = broadwell_ssp0_fixup, | ||
204 | .ops = &broadwell_rt286_ops, | ||
205 | .dpcm_playback = 1, | ||
206 | .dpcm_capture = 1, | ||
207 | }, | ||
208 | }; | ||
209 | |||
210 | /* broadwell audio machine driver for WPT + RT286S */ | ||
211 | static struct snd_soc_card broadwell_rt286 = { | ||
212 | .name = "broadwell-rt286", | ||
213 | .owner = THIS_MODULE, | ||
214 | .dai_link = broadwell_rt286_dais, | ||
215 | .num_links = ARRAY_SIZE(broadwell_rt286_dais), | ||
216 | .dapm_widgets = broadwell_widgets, | ||
217 | .num_dapm_widgets = ARRAY_SIZE(broadwell_widgets), | ||
218 | .dapm_routes = broadwell_rt286_map, | ||
219 | .num_dapm_routes = ARRAY_SIZE(broadwell_rt286_map), | ||
220 | .fully_routed = true, | ||
221 | }; | ||
222 | |||
223 | static int broadwell_audio_probe(struct platform_device *pdev) | ||
224 | { | ||
225 | broadwell_rt286.dev = &pdev->dev; | ||
226 | |||
227 | return snd_soc_register_card(&broadwell_rt286); | ||
228 | } | ||
229 | |||
230 | static int broadwell_audio_remove(struct platform_device *pdev) | ||
231 | { | ||
232 | snd_soc_unregister_card(&broadwell_rt286); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static struct platform_driver broadwell_audio = { | ||
237 | .probe = broadwell_audio_probe, | ||
238 | .remove = broadwell_audio_remove, | ||
239 | .driver = { | ||
240 | .name = "broadwell-audio", | ||
241 | .owner = THIS_MODULE, | ||
242 | }, | ||
243 | }; | ||
244 | |||
245 | module_platform_driver(broadwell_audio) | ||
246 | |||
247 | /* Module information */ | ||
248 | MODULE_AUTHOR("Liam Girdwood, Xingchao Wang"); | ||
249 | MODULE_DESCRIPTION("Intel SST Audio for WPT/Broadwell"); | ||
250 | MODULE_LICENSE("GPL v2"); | ||
251 | MODULE_ALIAS("platform:broadwell-audio"); | ||
diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c index 5fc98c64a3f4..b8b8af571ef1 100644 --- a/sound/soc/intel/byt-max98090.c +++ b/sound/soc/intel/byt-max98090.c | |||
@@ -39,8 +39,7 @@ static const struct snd_soc_dapm_widget byt_max98090_widgets[] = { | |||
39 | 39 | ||
40 | static const struct snd_soc_dapm_route byt_max98090_audio_map[] = { | 40 | static const struct snd_soc_dapm_route byt_max98090_audio_map[] = { |
41 | {"IN34", NULL, "Headset Mic"}, | 41 | {"IN34", NULL, "Headset Mic"}, |
42 | {"IN34", NULL, "MICBIAS"}, | 42 | {"Headset Mic", NULL, "MICBIAS"}, |
43 | {"MICBIAS", NULL, "Headset Mic"}, | ||
44 | {"DMICL", NULL, "Int Mic"}, | 43 | {"DMICL", NULL, "Int Mic"}, |
45 | {"Headphone", NULL, "HPL"}, | 44 | {"Headphone", NULL, "HPL"}, |
46 | {"Headphone", NULL, "HPR"}, | 45 | {"Headphone", NULL, "HPR"}, |
@@ -64,14 +63,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { | |||
64 | .pin = "Headset Mic", | 63 | .pin = "Headset Mic", |
65 | .mask = SND_JACK_MICROPHONE, | 64 | .mask = SND_JACK_MICROPHONE, |
66 | }, | 65 | }, |
67 | { | ||
68 | .pin = "Ext Spk", | ||
69 | .mask = SND_JACK_LINEOUT, | ||
70 | }, | ||
71 | { | ||
72 | .pin = "Int Mic", | ||
73 | .mask = SND_JACK_LINEIN, | ||
74 | }, | ||
75 | }; | 66 | }; |
76 | 67 | ||
77 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { | 68 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { |
@@ -84,7 +75,8 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = { | |||
84 | { | 75 | { |
85 | .name = "mic-gpio", | 76 | .name = "mic-gpio", |
86 | .idx = 1, | 77 | .idx = 1, |
87 | .report = SND_JACK_MICROPHONE | SND_JACK_LINEIN, | 78 | .invert = 1, |
79 | .report = SND_JACK_MICROPHONE, | ||
88 | .debounce_time = 200, | 80 | .debounce_time = 200, |
89 | }, | 81 | }, |
90 | }; | 82 | }; |
@@ -108,7 +100,8 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) | |||
108 | } | 100 | } |
109 | 101 | ||
110 | /* Enable jack detection */ | 102 | /* Enable jack detection */ |
111 | ret = snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, jack); | 103 | ret = snd_soc_jack_new(codec, "Headset", |
104 | SND_JACK_LINEOUT | SND_JACK_HEADSET, jack); | ||
112 | if (ret) | 105 | if (ret) |
113 | return ret; | 106 | return ret; |
114 | 107 | ||
@@ -117,13 +110,9 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) | |||
117 | if (ret) | 110 | if (ret) |
118 | return ret; | 111 | return ret; |
119 | 112 | ||
120 | ret = snd_soc_jack_add_gpiods(card->dev->parent, jack, | 113 | return snd_soc_jack_add_gpiods(card->dev->parent, jack, |
121 | ARRAY_SIZE(hs_jack_gpios), | 114 | ARRAY_SIZE(hs_jack_gpios), |
122 | hs_jack_gpios); | 115 | hs_jack_gpios); |
123 | if (ret) | ||
124 | return ret; | ||
125 | |||
126 | return max98090_mic_detect(codec, jack); | ||
127 | } | 116 | } |
128 | 117 | ||
129 | static struct snd_soc_dai_link byt_max98090_dais[] = { | 118 | static struct snd_soc_dai_link byt_max98090_dais[] = { |
diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c index 53d160d39972..234a58de3c53 100644 --- a/sound/soc/intel/byt-rt5640.c +++ b/sound/soc/intel/byt-rt5640.c | |||
@@ -34,6 +34,7 @@ static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { | |||
34 | }; | 34 | }; |
35 | 35 | ||
36 | static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { | 36 | static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { |
37 | {"Headset Mic", NULL, "MICBIAS1"}, | ||
37 | {"IN2P", NULL, "Headset Mic"}, | 38 | {"IN2P", NULL, "Headset Mic"}, |
38 | {"IN2N", NULL, "Headset Mic"}, | 39 | {"IN2N", NULL, "Headset Mic"}, |
39 | {"DMIC1", NULL, "Internal Mic"}, | 40 | {"DMIC1", NULL, "Internal Mic"}, |
diff --git a/sound/soc/intel/sst-atom-controls.h b/sound/soc/intel/sst-atom-controls.h new file mode 100644 index 000000000000..14063ab8c7c5 --- /dev/null +++ b/sound/soc/intel/sst-atom-controls.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013-14 Intel Corp | ||
3 | * Author: Ramesh Babu <ramesh.babu.koul@intel.com> | ||
4 | * Omair M Abdullah <omair.m.abdullah@intel.com> | ||
5 | * Samreen Nilofer <samreen.nilofer@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #ifndef __SST_CONTROLS_V2_H__ | ||
22 | #define __SST_CONTROLS_V2_H__ | ||
23 | |||
24 | enum { | ||
25 | MERR_DPCM_AUDIO = 0, | ||
26 | MERR_DPCM_COMPR, | ||
27 | }; | ||
28 | |||
29 | |||
30 | #endif | ||
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c index d207b22ea330..67673a2c0f41 100644 --- a/sound/soc/intel/sst-baytrail-ipc.c +++ b/sound/soc/intel/sst-baytrail-ipc.c | |||
@@ -122,6 +122,26 @@ struct sst_byt_tstamp { | |||
122 | u32 channel_peak[8]; | 122 | u32 channel_peak[8]; |
123 | } __packed; | 123 | } __packed; |
124 | 124 | ||
125 | struct sst_byt_fw_version { | ||
126 | u8 build; | ||
127 | u8 minor; | ||
128 | u8 major; | ||
129 | u8 type; | ||
130 | } __packed; | ||
131 | |||
132 | struct sst_byt_fw_build_info { | ||
133 | u8 date[16]; | ||
134 | u8 time[16]; | ||
135 | } __packed; | ||
136 | |||
137 | struct sst_byt_fw_init { | ||
138 | struct sst_byt_fw_version fw_version; | ||
139 | struct sst_byt_fw_build_info build_info; | ||
140 | u16 result; | ||
141 | u8 module_id; | ||
142 | u8 debug_info; | ||
143 | } __packed; | ||
144 | |||
125 | /* driver internal IPC message structure */ | 145 | /* driver internal IPC message structure */ |
126 | struct ipc_message { | 146 | struct ipc_message { |
127 | struct list_head list; | 147 | struct list_head list; |
@@ -868,6 +888,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
868 | { | 888 | { |
869 | struct sst_byt *byt; | 889 | struct sst_byt *byt; |
870 | struct sst_fw *byt_sst_fw; | 890 | struct sst_fw *byt_sst_fw; |
891 | struct sst_byt_fw_init init; | ||
871 | int err; | 892 | int err; |
872 | 893 | ||
873 | dev_dbg(dev, "initialising Byt DSP IPC\n"); | 894 | dev_dbg(dev, "initialising Byt DSP IPC\n"); |
@@ -929,6 +950,15 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
929 | goto boot_err; | 950 | goto boot_err; |
930 | } | 951 | } |
931 | 952 | ||
953 | /* show firmware information */ | ||
954 | sst_dsp_inbox_read(byt->dsp, &init, sizeof(init)); | ||
955 | dev_info(byt->dev, "FW version: %02x.%02x.%02x.%02x\n", | ||
956 | init.fw_version.major, init.fw_version.minor, | ||
957 | init.fw_version.build, init.fw_version.type); | ||
958 | dev_info(byt->dev, "Build type: %x\n", init.fw_version.type); | ||
959 | dev_info(byt->dev, "Build date: %s %s\n", | ||
960 | init.build_info.date, init.build_info.time); | ||
961 | |||
932 | pdata->dsp = byt; | 962 | pdata->dsp = byt; |
933 | byt->fw = byt_sst_fw; | 963 | byt->fw = byt_sst_fw; |
934 | 964 | ||
diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c index 8eab97368ea7..599401c0c655 100644 --- a/sound/soc/intel/sst-baytrail-pcm.c +++ b/sound/soc/intel/sst-baytrail-pcm.c | |||
@@ -32,7 +32,7 @@ static const struct snd_pcm_hardware sst_byt_pcm_hardware = { | |||
32 | SNDRV_PCM_INFO_PAUSE | | 32 | SNDRV_PCM_INFO_PAUSE | |
33 | SNDRV_PCM_INFO_RESUME, | 33 | SNDRV_PCM_INFO_RESUME, |
34 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 34 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
35 | SNDRV_PCM_FORMAT_S24_LE, | 35 | SNDRV_PCM_FMTBIT_S24_LE, |
36 | .period_bytes_min = 384, | 36 | .period_bytes_min = 384, |
37 | .period_bytes_max = 48000, | 37 | .period_bytes_max = 48000, |
38 | .periods_min = 2, | 38 | .periods_min = 2, |
diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c index 0b715b20a2d7..cd23060a0d86 100644 --- a/sound/soc/intel/sst-dsp.c +++ b/sound/soc/intel/sst-dsp.c | |||
@@ -224,19 +224,23 @@ EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64); | |||
224 | 224 | ||
225 | void sst_dsp_dump(struct sst_dsp *sst) | 225 | void sst_dsp_dump(struct sst_dsp *sst) |
226 | { | 226 | { |
227 | sst->ops->dump(sst); | 227 | if (sst->ops->dump) |
228 | sst->ops->dump(sst); | ||
228 | } | 229 | } |
229 | EXPORT_SYMBOL_GPL(sst_dsp_dump); | 230 | EXPORT_SYMBOL_GPL(sst_dsp_dump); |
230 | 231 | ||
231 | void sst_dsp_reset(struct sst_dsp *sst) | 232 | void sst_dsp_reset(struct sst_dsp *sst) |
232 | { | 233 | { |
233 | sst->ops->reset(sst); | 234 | if (sst->ops->reset) |
235 | sst->ops->reset(sst); | ||
234 | } | 236 | } |
235 | EXPORT_SYMBOL_GPL(sst_dsp_reset); | 237 | EXPORT_SYMBOL_GPL(sst_dsp_reset); |
236 | 238 | ||
237 | int sst_dsp_boot(struct sst_dsp *sst) | 239 | int sst_dsp_boot(struct sst_dsp *sst) |
238 | { | 240 | { |
239 | sst->ops->boot(sst); | 241 | if (sst->ops->boot) |
242 | sst->ops->boot(sst); | ||
243 | |||
240 | return 0; | 244 | return 0; |
241 | } | 245 | } |
242 | EXPORT_SYMBOL_GPL(sst_dsp_boot); | 246 | EXPORT_SYMBOL_GPL(sst_dsp_boot); |
diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h index e44423be66c4..3165dfa97408 100644 --- a/sound/soc/intel/sst-dsp.h +++ b/sound/soc/intel/sst-dsp.h | |||
@@ -52,7 +52,11 @@ | |||
52 | #define SST_CLKCTL 0x78 | 52 | #define SST_CLKCTL 0x78 |
53 | #define SST_CSR2 0x80 | 53 | #define SST_CSR2 0x80 |
54 | #define SST_LTRC 0xE0 | 54 | #define SST_LTRC 0xE0 |
55 | #define SST_HDMC 0xE8 | 55 | #define SST_HMDC 0xE8 |
56 | |||
57 | #define SST_SHIM_BEGIN SST_CSR | ||
58 | #define SST_SHIM_END SST_HDMC | ||
59 | |||
56 | #define SST_DBGO 0xF0 | 60 | #define SST_DBGO 0xF0 |
57 | 61 | ||
58 | #define SST_SHIM_SIZE 0x100 | 62 | #define SST_SHIM_SIZE 0x100 |
@@ -73,6 +77,8 @@ | |||
73 | #define SST_CSR_S0IOCS (0x1 << 21) | 77 | #define SST_CSR_S0IOCS (0x1 << 21) |
74 | #define SST_CSR_S1IOCS (0x1 << 23) | 78 | #define SST_CSR_S1IOCS (0x1 << 23) |
75 | #define SST_CSR_LPCS (0x1 << 31) | 79 | #define SST_CSR_LPCS (0x1 << 31) |
80 | #define SST_CSR_24MHZ_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1 | SST_CSR_LPCS) | ||
81 | #define SST_CSR_24MHZ_NO_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1) | ||
76 | #define SST_BYT_CSR_RST (0x1 << 0) | 82 | #define SST_BYT_CSR_RST (0x1 << 0) |
77 | #define SST_BYT_CSR_VECTOR_SEL (0x1 << 1) | 83 | #define SST_BYT_CSR_VECTOR_SEL (0x1 << 1) |
78 | #define SST_BYT_CSR_STALL (0x1 << 2) | 84 | #define SST_BYT_CSR_STALL (0x1 << 2) |
@@ -92,6 +98,14 @@ | |||
92 | #define SST_IMRX_DONE (0x1 << 0) | 98 | #define SST_IMRX_DONE (0x1 << 0) |
93 | #define SST_BYT_IMRX_REQUEST (0x1 << 1) | 99 | #define SST_BYT_IMRX_REQUEST (0x1 << 1) |
94 | 100 | ||
101 | /* IMRD / IMD */ | ||
102 | #define SST_IMRD_DONE (0x1 << 0) | ||
103 | #define SST_IMRD_BUSY (0x1 << 1) | ||
104 | #define SST_IMRD_SSP0 (0x1 << 16) | ||
105 | #define SST_IMRD_DMAC0 (0x1 << 21) | ||
106 | #define SST_IMRD_DMAC1 (0x1 << 22) | ||
107 | #define SST_IMRD_DMAC (SST_IMRD_DMAC0 | SST_IMRD_DMAC1) | ||
108 | |||
95 | /* IPCX / IPCC */ | 109 | /* IPCX / IPCC */ |
96 | #define SST_IPCX_DONE (0x1 << 30) | 110 | #define SST_IPCX_DONE (0x1 << 30) |
97 | #define SST_IPCX_BUSY (0x1 << 31) | 111 | #define SST_IPCX_BUSY (0x1 << 31) |
@@ -118,9 +132,21 @@ | |||
118 | /* LTRC */ | 132 | /* LTRC */ |
119 | #define SST_LTRC_VAL(x) (x << 0) | 133 | #define SST_LTRC_VAL(x) (x << 0) |
120 | 134 | ||
121 | /* HDMC */ | 135 | /* HMDC */ |
122 | #define SST_HDMC_HDDA0(x) (x << 0) | 136 | #define SST_HMDC_HDDA0(x) (x << 0) |
123 | #define SST_HDMC_HDDA1(x) (x << 7) | 137 | #define SST_HMDC_HDDA1(x) (x << 7) |
138 | #define SST_HMDC_HDDA_E0_CH0 1 | ||
139 | #define SST_HMDC_HDDA_E0_CH1 2 | ||
140 | #define SST_HMDC_HDDA_E0_CH2 4 | ||
141 | #define SST_HMDC_HDDA_E0_CH3 8 | ||
142 | #define SST_HMDC_HDDA_E1_CH0 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH0) | ||
143 | #define SST_HMDC_HDDA_E1_CH1 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH1) | ||
144 | #define SST_HMDC_HDDA_E1_CH2 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH2) | ||
145 | #define SST_HMDC_HDDA_E1_CH3 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH3) | ||
146 | #define SST_HMDC_HDDA_E0_ALLCH (SST_HMDC_HDDA_E0_CH0 | SST_HMDC_HDDA_E0_CH1 | \ | ||
147 | SST_HMDC_HDDA_E0_CH2 | SST_HMDC_HDDA_E0_CH3) | ||
148 | #define SST_HMDC_HDDA_E1_ALLCH (SST_HMDC_HDDA_E1_CH0 | SST_HMDC_HDDA_E1_CH1 | \ | ||
149 | SST_HMDC_HDDA_E1_CH2 | SST_HMDC_HDDA_E1_CH3) | ||
124 | 150 | ||
125 | 151 | ||
126 | /* SST Vendor Defined Registers and bits */ | 152 | /* SST Vendor Defined Registers and bits */ |
@@ -130,11 +156,16 @@ | |||
130 | #define SST_VDRTCTL3 0xaC | 156 | #define SST_VDRTCTL3 0xaC |
131 | 157 | ||
132 | /* VDRTCTL0 */ | 158 | /* VDRTCTL0 */ |
159 | #define SST_VDRTCL0_APLLSE_MASK 1 | ||
133 | #define SST_VDRTCL0_DSRAMPGE_SHIFT 16 | 160 | #define SST_VDRTCL0_DSRAMPGE_SHIFT 16 |
134 | #define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT) | 161 | #define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT) |
135 | #define SST_VDRTCL0_ISRAMPGE_SHIFT 6 | 162 | #define SST_VDRTCL0_ISRAMPGE_SHIFT 6 |
136 | #define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT) | 163 | #define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT) |
137 | 164 | ||
165 | /* PMCS */ | ||
166 | #define SST_PMCS 0x84 | ||
167 | #define SST_PMCS_PS_MASK 0x3 | ||
168 | |||
138 | struct sst_dsp; | 169 | struct sst_dsp; |
139 | 170 | ||
140 | /* | 171 | /* |
diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c index 535f517629fd..4b6c163c10ff 100644 --- a/sound/soc/intel/sst-haswell-dsp.c +++ b/sound/soc/intel/sst-haswell-dsp.c | |||
@@ -28,9 +28,6 @@ | |||
28 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
29 | #include <linux/pm_runtime.h> | 29 | #include <linux/pm_runtime.h> |
30 | 30 | ||
31 | #include <linux/acpi.h> | ||
32 | #include <acpi/acpi_bus.h> | ||
33 | |||
34 | #include "sst-dsp.h" | 31 | #include "sst-dsp.h" |
35 | #include "sst-dsp-priv.h" | 32 | #include "sst-dsp-priv.h" |
36 | #include "sst-haswell-ipc.h" | 33 | #include "sst-haswell-ipc.h" |
@@ -272,9 +269,9 @@ static void hsw_boot(struct sst_dsp *sst) | |||
272 | SST_CSR2_SDFD_SSP1); | 269 | SST_CSR2_SDFD_SSP1); |
273 | 270 | ||
274 | /* enable DMA engine 0,1 all channels to access host memory */ | 271 | /* enable DMA engine 0,1 all channels to access host memory */ |
275 | sst_dsp_shim_update_bits_unlocked(sst, SST_HDMC, | 272 | sst_dsp_shim_update_bits_unlocked(sst, SST_HMDC, |
276 | SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff), | 273 | SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff), |
277 | SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff)); | 274 | SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff)); |
278 | 275 | ||
279 | /* disable all clock gating */ | 276 | /* disable all clock gating */ |
280 | writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2); | 277 | writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2); |
@@ -313,9 +310,7 @@ static const struct sst_adsp_memregion lp_region[] = { | |||
313 | 310 | ||
314 | /* wild cat point ADSP mem regions */ | 311 | /* wild cat point ADSP mem regions */ |
315 | static const struct sst_adsp_memregion wpt_region[] = { | 312 | static const struct sst_adsp_memregion wpt_region[] = { |
316 | {0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ | 313 | {0x00000, 0xA0000, 20, SST_MEM_DRAM}, /* D-SRAM0,D-SRAM1,D-SRAM2 - 20 * 32kB */ |
317 | {0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */ | ||
318 | {0x80000, 0xA0000, 4, SST_MEM_DRAM}, /* D-SRAM2 - 4 * 32kB */ | ||
319 | {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */ | 314 | {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */ |
320 | }; | 315 | }; |
321 | 316 | ||
@@ -339,26 +334,56 @@ static int hsw_acpi_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata) | |||
339 | return 0; | 334 | return 0; |
340 | } | 335 | } |
341 | 336 | ||
337 | struct sst_sram_shift { | ||
338 | u32 dev_id; /* SST Device IDs */ | ||
339 | u32 iram_shift; | ||
340 | u32 dram_shift; | ||
341 | }; | ||
342 | |||
343 | static const struct sst_sram_shift sram_shift[] = { | ||
344 | {SST_DEV_ID_LYNX_POINT, 6, 16}, /* lp */ | ||
345 | {SST_DEV_ID_WILDCAT_POINT, 2, 12}, /* wpt */ | ||
346 | }; | ||
342 | static u32 hsw_block_get_bit(struct sst_mem_block *block) | 347 | static u32 hsw_block_get_bit(struct sst_mem_block *block) |
343 | { | 348 | { |
344 | u32 bit = 0, shift = 0; | 349 | u32 bit = 0, shift = 0, index; |
350 | struct sst_dsp *sst = block->dsp; | ||
345 | 351 | ||
346 | switch (block->type) { | 352 | for (index = 0; index < ARRAY_SIZE(sram_shift); index++) { |
347 | case SST_MEM_DRAM: | 353 | if (sram_shift[index].dev_id == sst->id) |
348 | shift = 16; | 354 | break; |
349 | break; | ||
350 | case SST_MEM_IRAM: | ||
351 | shift = 6; | ||
352 | break; | ||
353 | default: | ||
354 | return 0; | ||
355 | } | 355 | } |
356 | 356 | ||
357 | if (index < ARRAY_SIZE(sram_shift)) { | ||
358 | switch (block->type) { | ||
359 | case SST_MEM_DRAM: | ||
360 | shift = sram_shift[index].dram_shift; | ||
361 | break; | ||
362 | case SST_MEM_IRAM: | ||
363 | shift = sram_shift[index].iram_shift; | ||
364 | break; | ||
365 | default: | ||
366 | shift = 0; | ||
367 | } | ||
368 | } else | ||
369 | shift = 0; | ||
370 | |||
357 | bit = 1 << (block->index + shift); | 371 | bit = 1 << (block->index + shift); |
358 | 372 | ||
359 | return bit; | 373 | return bit; |
360 | } | 374 | } |
361 | 375 | ||
376 | /*dummy read a SRAM block.*/ | ||
377 | static void sst_mem_block_dummy_read(struct sst_mem_block *block) | ||
378 | { | ||
379 | u32 size; | ||
380 | u8 tmp_buf[4]; | ||
381 | struct sst_dsp *sst = block->dsp; | ||
382 | |||
383 | size = block->size > 4 ? 4 : block->size; | ||
384 | memcpy_fromio(tmp_buf, sst->addr.lpe + block->offset, size); | ||
385 | } | ||
386 | |||
362 | /* enable 32kB memory block - locks held by caller */ | 387 | /* enable 32kB memory block - locks held by caller */ |
363 | static int hsw_block_enable(struct sst_mem_block *block) | 388 | static int hsw_block_enable(struct sst_mem_block *block) |
364 | { | 389 | { |
@@ -378,6 +403,8 @@ static int hsw_block_enable(struct sst_mem_block *block) | |||
378 | /* wait 18 DSP clock ticks */ | 403 | /* wait 18 DSP clock ticks */ |
379 | udelay(10); | 404 | udelay(10); |
380 | 405 | ||
406 | /*add a dummy read before the SRAM block is written, otherwise the writing may miss bytes sometimes.*/ | ||
407 | sst_mem_block_dummy_read(block); | ||
381 | return 0; | 408 | return 0; |
382 | } | 409 | } |
383 | 410 | ||
@@ -488,8 +515,9 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) | |||
488 | } | 515 | } |
489 | } | 516 | } |
490 | 517 | ||
491 | /* set default power gating mask */ | 518 | /* set default power gating control, enable power gating control for all blocks. that is, |
492 | writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL0); | 519 | can't be accessed, please enable each block before accessing. */ |
520 | writel(0xffffffff, sst->addr.pci_cfg + SST_VDRTCTL0); | ||
493 | 521 | ||
494 | return 0; | 522 | return 0; |
495 | } | 523 | } |
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 434236343ddf..b6291516dbbf 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c | |||
@@ -183,7 +183,7 @@ struct sst_hsw_ipc_fw_ready { | |||
183 | u32 inbox_size; | 183 | u32 inbox_size; |
184 | u32 outbox_size; | 184 | u32 outbox_size; |
185 | u32 fw_info_size; | 185 | u32 fw_info_size; |
186 | u8 fw_info[1]; | 186 | u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)]; |
187 | } __attribute__((packed)); | 187 | } __attribute__((packed)); |
188 | 188 | ||
189 | struct ipc_message { | 189 | struct ipc_message { |
@@ -457,9 +457,10 @@ static void ipc_tx_msgs(struct kthread_work *work) | |||
457 | return; | 457 | return; |
458 | } | 458 | } |
459 | 459 | ||
460 | /* if the DSP is busy we will TX messages after IRQ */ | 460 | /* if the DSP is busy, we will TX messages after IRQ. |
461 | * also postpone if we are in the middle of procesing completion irq*/ | ||
461 | ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX); | 462 | ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX); |
462 | if (ipcx & SST_IPCX_BUSY) { | 463 | if (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)) { |
463 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); | 464 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); |
464 | return; | 465 | return; |
465 | } | 466 | } |
@@ -502,6 +503,7 @@ static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg, | |||
502 | ipc_shim_dbg(hsw, "message timeout"); | 503 | ipc_shim_dbg(hsw, "message timeout"); |
503 | 504 | ||
504 | trace_ipc_error("error message timeout for", msg->header); | 505 | trace_ipc_error("error message timeout for", msg->header); |
506 | list_del(&msg->list); | ||
505 | ret = -ETIMEDOUT; | 507 | ret = -ETIMEDOUT; |
506 | } else { | 508 | } else { |
507 | 509 | ||
@@ -569,6 +571,9 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) | |||
569 | { | 571 | { |
570 | struct sst_hsw_ipc_fw_ready fw_ready; | 572 | struct sst_hsw_ipc_fw_ready fw_ready; |
571 | u32 offset; | 573 | u32 offset; |
574 | u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)]; | ||
575 | char *tmp[5], *pinfo; | ||
576 | int i = 0; | ||
572 | 577 | ||
573 | offset = (header & 0x1FFFFFFF) << 3; | 578 | offset = (header & 0x1FFFFFFF) << 3; |
574 | 579 | ||
@@ -589,6 +594,19 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) | |||
589 | fw_ready.inbox_offset, fw_ready.inbox_size); | 594 | fw_ready.inbox_offset, fw_ready.inbox_size); |
590 | dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n", | 595 | dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n", |
591 | fw_ready.outbox_offset, fw_ready.outbox_size); | 596 | fw_ready.outbox_offset, fw_ready.outbox_size); |
597 | if (fw_ready.fw_info_size < sizeof(fw_ready.fw_info)) { | ||
598 | fw_ready.fw_info[fw_ready.fw_info_size] = 0; | ||
599 | dev_dbg(hsw->dev, " Firmware info: %s \n", fw_ready.fw_info); | ||
600 | |||
601 | /* log the FW version info got from the mailbox here. */ | ||
602 | memcpy(fw_info, fw_ready.fw_info, fw_ready.fw_info_size); | ||
603 | pinfo = &fw_info[0]; | ||
604 | for (i = 0; i < sizeof(tmp) / sizeof(char *); i++) | ||
605 | tmp[i] = strsep(&pinfo, " "); | ||
606 | dev_info(hsw->dev, "FW loaded, mailbox readback FW info: type %s, - " | ||
607 | "version: %s.%s, build %s, source commit id: %s\n", | ||
608 | tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]); | ||
609 | } | ||
592 | } | 610 | } |
593 | 611 | ||
594 | static void hsw_notification_work(struct work_struct *work) | 612 | static void hsw_notification_work(struct work_struct *work) |
@@ -671,7 +689,9 @@ static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg) | |||
671 | switch (stream_msg) { | 689 | switch (stream_msg) { |
672 | case IPC_STR_STAGE_MESSAGE: | 690 | case IPC_STR_STAGE_MESSAGE: |
673 | case IPC_STR_NOTIFICATION: | 691 | case IPC_STR_NOTIFICATION: |
692 | break; | ||
674 | case IPC_STR_RESET: | 693 | case IPC_STR_RESET: |
694 | trace_ipc_notification("stream reset", stream->reply.stream_hw_id); | ||
675 | break; | 695 | break; |
676 | case IPC_STR_PAUSE: | 696 | case IPC_STR_PAUSE: |
677 | stream->running = false; | 697 | stream->running = false; |
@@ -762,7 +782,8 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header) | |||
762 | } | 782 | } |
763 | 783 | ||
764 | /* update any stream states */ | 784 | /* update any stream states */ |
765 | hsw_stream_update(hsw, msg); | 785 | if (msg_get_global_type(header) == IPC_GLB_STREAM_MESSAGE) |
786 | hsw_stream_update(hsw, msg); | ||
766 | 787 | ||
767 | /* wake up and return the error if we have waiters on this message ? */ | 788 | /* wake up and return the error if we have waiters on this message ? */ |
768 | list_del(&msg->list); | 789 | list_del(&msg->list); |
@@ -1628,7 +1649,7 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw, | |||
1628 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) | 1649 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) |
1629 | { | 1650 | { |
1630 | u32 header, state_; | 1651 | u32 header, state_; |
1631 | int ret; | 1652 | int ret, item; |
1632 | 1653 | ||
1633 | header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); | 1654 | header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); |
1634 | state_ = state; | 1655 | state_ = state; |
@@ -1642,6 +1663,13 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw, | |||
1642 | return ret; | 1663 | return ret; |
1643 | } | 1664 | } |
1644 | 1665 | ||
1666 | for (item = 0; item < dx->entries_no; item++) { | ||
1667 | dev_dbg(hsw->dev, | ||
1668 | "Item[%d] offset[%x] - size[%x] - source[%x]\n", | ||
1669 | item, dx->mem_info[item].offset, | ||
1670 | dx->mem_info[item].size, | ||
1671 | dx->mem_info[item].source); | ||
1672 | } | ||
1645 | dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n", | 1673 | dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n", |
1646 | dx->entries_no, state); | 1674 | dx->entries_no, state); |
1647 | 1675 | ||
@@ -1775,8 +1803,6 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
1775 | 1803 | ||
1776 | /* get the FW version */ | 1804 | /* get the FW version */ |
1777 | sst_hsw_fw_get_version(hsw, &version); | 1805 | sst_hsw_fw_get_version(hsw, &version); |
1778 | dev_info(hsw->dev, "FW loaded: type %d - version: %d.%d build %d\n", | ||
1779 | version.type, version.major, version.minor, version.build); | ||
1780 | 1806 | ||
1781 | /* get the globalmixer */ | 1807 | /* get the globalmixer */ |
1782 | ret = sst_hsw_mixer_get_info(hsw); | 1808 | ret = sst_hsw_mixer_get_info(hsw); |
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index 058efb17c568..61bf6da4bb02 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c | |||
@@ -80,7 +80,7 @@ static const struct snd_pcm_hardware hsw_pcm_hardware = { | |||
80 | SNDRV_PCM_INFO_PAUSE | | 80 | SNDRV_PCM_INFO_PAUSE | |
81 | SNDRV_PCM_INFO_RESUME | | 81 | SNDRV_PCM_INFO_RESUME | |
82 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | 82 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, |
83 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE | | 83 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | |
84 | SNDRV_PCM_FMTBIT_S32_LE, | 84 | SNDRV_PCM_FMTBIT_S32_LE, |
85 | .period_bytes_min = PAGE_SIZE, | 85 | .period_bytes_min = PAGE_SIZE, |
86 | .period_bytes_max = (HSW_PCM_PERIODS_MAX / HSW_PCM_PERIODS_MIN) * PAGE_SIZE, | 86 | .period_bytes_max = (HSW_PCM_PERIODS_MAX / HSW_PCM_PERIODS_MIN) * PAGE_SIZE, |
@@ -400,7 +400,15 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, | |||
400 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 16); | 400 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 16); |
401 | break; | 401 | break; |
402 | case SNDRV_PCM_FORMAT_S24_LE: | 402 | case SNDRV_PCM_FORMAT_S24_LE: |
403 | bits = SST_HSW_DEPTH_24BIT; | 403 | bits = SST_HSW_DEPTH_32BIT; |
404 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 24); | ||
405 | break; | ||
406 | case SNDRV_PCM_FORMAT_S8: | ||
407 | bits = SST_HSW_DEPTH_8BIT; | ||
408 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 8); | ||
409 | break; | ||
410 | case SNDRV_PCM_FORMAT_S32_LE: | ||
411 | bits = SST_HSW_DEPTH_32BIT; | ||
404 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 32); | 412 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 32); |
405 | break; | 413 | break; |
406 | default: | 414 | default: |
@@ -685,8 +693,9 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
685 | } | 693 | } |
686 | 694 | ||
687 | #define HSW_FORMATS \ | 695 | #define HSW_FORMATS \ |
688 | (SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\ | 696 | (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ |
689 | SNDRV_PCM_FMTBIT_S32_LE) | 697 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\ |
698 | SNDRV_PCM_FMTBIT_S8) | ||
690 | 699 | ||
691 | static struct snd_soc_dai_driver hsw_dais[] = { | 700 | static struct snd_soc_dai_driver hsw_dais[] = { |
692 | { | 701 | { |
@@ -696,7 +705,7 @@ static struct snd_soc_dai_driver hsw_dais[] = { | |||
696 | .channels_min = 2, | 705 | .channels_min = 2, |
697 | .channels_max = 2, | 706 | .channels_max = 2, |
698 | .rates = SNDRV_PCM_RATE_48000, | 707 | .rates = SNDRV_PCM_RATE_48000, |
699 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 708 | .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, |
700 | }, | 709 | }, |
701 | }, | 710 | }, |
702 | { | 711 | { |
@@ -727,8 +736,8 @@ static struct snd_soc_dai_driver hsw_dais[] = { | |||
727 | .stream_name = "Loopback Capture", | 736 | .stream_name = "Loopback Capture", |
728 | .channels_min = 2, | 737 | .channels_min = 2, |
729 | .channels_max = 2, | 738 | .channels_max = 2, |
730 | .rates = SNDRV_PCM_RATE_8000_192000, | 739 | .rates = SNDRV_PCM_RATE_48000, |
731 | .formats = HSW_FORMATS, | 740 | .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, |
732 | }, | 741 | }, |
733 | }, | 742 | }, |
734 | { | 743 | { |
@@ -737,8 +746,8 @@ static struct snd_soc_dai_driver hsw_dais[] = { | |||
737 | .stream_name = "Analog Capture", | 746 | .stream_name = "Analog Capture", |
738 | .channels_min = 2, | 747 | .channels_min = 2, |
739 | .channels_max = 2, | 748 | .channels_max = 2, |
740 | .rates = SNDRV_PCM_RATE_8000_192000, | 749 | .rates = SNDRV_PCM_RATE_48000, |
741 | .formats = HSW_FORMATS, | 750 | .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, |
742 | }, | 751 | }, |
743 | }, | 752 | }, |
744 | }; | 753 | }; |
diff --git a/sound/soc/intel/sst-mfld-dsp.h b/sound/soc/intel/sst-mfld-dsp.h index 8d482d76475a..4257263157cd 100644 --- a/sound/soc/intel/sst-mfld-dsp.h +++ b/sound/soc/intel/sst-mfld-dsp.h | |||
@@ -3,7 +3,7 @@ | |||
3 | /* | 3 | /* |
4 | * sst_mfld_dsp.h - Intel SST Driver for audio engine | 4 | * sst_mfld_dsp.h - Intel SST Driver for audio engine |
5 | * | 5 | * |
6 | * Copyright (C) 2008-12 Intel Corporation | 6 | * Copyright (C) 2008-14 Intel Corporation |
7 | * Authors: Vinod Koul <vinod.koul@linux.intel.com> | 7 | * Authors: Vinod Koul <vinod.koul@linux.intel.com> |
8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
9 | * | 9 | * |
@@ -19,6 +19,142 @@ | |||
19 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 19 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define SST_MAX_BIN_BYTES 1024 | ||
23 | |||
24 | #define MAX_DBG_RW_BYTES 80 | ||
25 | #define MAX_NUM_SCATTER_BUFFERS 8 | ||
26 | #define MAX_LOOP_BACK_DWORDS 8 | ||
27 | /* IPC base address and mailbox, timestamp offsets */ | ||
28 | #define SST_MAILBOX_SIZE 0x0400 | ||
29 | #define SST_MAILBOX_SEND 0x0000 | ||
30 | #define SST_TIME_STAMP 0x1800 | ||
31 | #define SST_TIME_STAMP_MRFLD 0x800 | ||
32 | #define SST_RESERVED_OFFSET 0x1A00 | ||
33 | #define SST_SCU_LPE_MAILBOX 0x1000 | ||
34 | #define SST_LPE_SCU_MAILBOX 0x1400 | ||
35 | #define SST_SCU_LPE_LOG_BUF (SST_SCU_LPE_MAILBOX+16) | ||
36 | #define PROCESS_MSG 0x80 | ||
37 | |||
38 | /* Message ID's for IPC messages */ | ||
39 | /* Bits B7: SST or IA/SC ; B6-B4: Msg Category; B3-B0: Msg Type */ | ||
40 | |||
41 | /* I2L Firmware/Codec Download msgs */ | ||
42 | #define IPC_IA_PREP_LIB_DNLD 0x01 | ||
43 | #define IPC_IA_LIB_DNLD_CMPLT 0x02 | ||
44 | #define IPC_IA_GET_FW_VERSION 0x04 | ||
45 | #define IPC_IA_GET_FW_BUILD_INF 0x05 | ||
46 | #define IPC_IA_GET_FW_INFO 0x06 | ||
47 | #define IPC_IA_GET_FW_CTXT 0x07 | ||
48 | #define IPC_IA_SET_FW_CTXT 0x08 | ||
49 | #define IPC_IA_PREPARE_SHUTDOWN 0x31 | ||
50 | /* I2L Codec Config/control msgs */ | ||
51 | #define IPC_PREP_D3 0x10 | ||
52 | #define IPC_IA_SET_CODEC_PARAMS 0x10 | ||
53 | #define IPC_IA_GET_CODEC_PARAMS 0x11 | ||
54 | #define IPC_IA_SET_PPP_PARAMS 0x12 | ||
55 | #define IPC_IA_GET_PPP_PARAMS 0x13 | ||
56 | #define IPC_SST_PERIOD_ELAPSED_MRFLD 0xA | ||
57 | #define IPC_IA_ALG_PARAMS 0x1A | ||
58 | #define IPC_IA_TUNING_PARAMS 0x1B | ||
59 | #define IPC_IA_SET_RUNTIME_PARAMS 0x1C | ||
60 | #define IPC_IA_SET_PARAMS 0x1 | ||
61 | #define IPC_IA_GET_PARAMS 0x2 | ||
62 | |||
63 | #define IPC_EFFECTS_CREATE 0xE | ||
64 | #define IPC_EFFECTS_DESTROY 0xF | ||
65 | |||
66 | /* I2L Stream config/control msgs */ | ||
67 | #define IPC_IA_ALLOC_STREAM_MRFLD 0x2 | ||
68 | #define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */ | ||
69 | #define IPC_IA_FREE_STREAM_MRFLD 0x03 | ||
70 | #define IPC_IA_FREE_STREAM 0x21 /* Free the stream ID */ | ||
71 | #define IPC_IA_SET_STREAM_PARAMS 0x22 | ||
72 | #define IPC_IA_SET_STREAM_PARAMS_MRFLD 0x12 | ||
73 | #define IPC_IA_GET_STREAM_PARAMS 0x23 | ||
74 | #define IPC_IA_PAUSE_STREAM 0x24 | ||
75 | #define IPC_IA_PAUSE_STREAM_MRFLD 0x4 | ||
76 | #define IPC_IA_RESUME_STREAM 0x25 | ||
77 | #define IPC_IA_RESUME_STREAM_MRFLD 0x5 | ||
78 | #define IPC_IA_DROP_STREAM 0x26 | ||
79 | #define IPC_IA_DROP_STREAM_MRFLD 0x07 | ||
80 | #define IPC_IA_DRAIN_STREAM 0x27 /* Short msg with str_id */ | ||
81 | #define IPC_IA_DRAIN_STREAM_MRFLD 0x8 | ||
82 | #define IPC_IA_CONTROL_ROUTING 0x29 | ||
83 | #define IPC_IA_VTSV_UPDATE_MODULES 0x20 | ||
84 | #define IPC_IA_VTSV_DETECTED 0x21 | ||
85 | |||
86 | #define IPC_IA_START_STREAM_MRFLD 0X06 | ||
87 | #define IPC_IA_START_STREAM 0x30 /* Short msg with str_id */ | ||
88 | |||
89 | #define IPC_IA_SET_GAIN_MRFLD 0x21 | ||
90 | /* Debug msgs */ | ||
91 | #define IPC_IA_DBG_MEM_READ 0x40 | ||
92 | #define IPC_IA_DBG_MEM_WRITE 0x41 | ||
93 | #define IPC_IA_DBG_LOOP_BACK 0x42 | ||
94 | #define IPC_IA_DBG_LOG_ENABLE 0x45 | ||
95 | #define IPC_IA_DBG_SET_PROBE_PARAMS 0x47 | ||
96 | |||
97 | /* L2I Firmware/Codec Download msgs */ | ||
98 | #define IPC_IA_FW_INIT_CMPLT 0x81 | ||
99 | #define IPC_IA_FW_INIT_CMPLT_MRFLD 0x01 | ||
100 | #define IPC_IA_FW_ASYNC_ERR_MRFLD 0x11 | ||
101 | |||
102 | /* L2I Codec Config/control msgs */ | ||
103 | #define IPC_SST_FRAGMENT_ELPASED 0x90 /* Request IA more data */ | ||
104 | |||
105 | #define IPC_SST_BUF_UNDER_RUN 0x92 /* PB Under run and stopped */ | ||
106 | #define IPC_SST_BUF_OVER_RUN 0x93 /* CAP Under run and stopped */ | ||
107 | #define IPC_SST_DRAIN_END 0x94 /* PB Drain complete and stopped */ | ||
108 | #define IPC_SST_CHNGE_SSP_PARAMS 0x95 /* PB SSP parameters changed */ | ||
109 | #define IPC_SST_STREAM_PROCESS_FATAL_ERR 0x96/* error in processing a stream */ | ||
110 | #define IPC_SST_PERIOD_ELAPSED 0x97 /* period elapsed */ | ||
111 | |||
112 | #define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occurred */ | ||
113 | /* L2S messages */ | ||
114 | #define IPC_SC_DDR_LINK_UP 0xC0 | ||
115 | #define IPC_SC_DDR_LINK_DOWN 0xC1 | ||
116 | #define IPC_SC_SET_LPECLK_REQ 0xC2 | ||
117 | #define IPC_SC_SSP_BIT_BANG 0xC3 | ||
118 | |||
119 | /* L2I Error reporting msgs */ | ||
120 | #define IPC_IA_MEM_ALLOC_FAIL 0xE0 | ||
121 | #define IPC_IA_PROC_ERR 0xE1 /* error in processing a | ||
122 | stream can be used by playback and | ||
123 | capture modules */ | ||
124 | |||
125 | /* L2I Debug msgs */ | ||
126 | #define IPC_IA_PRINT_STRING 0xF0 | ||
127 | |||
128 | /* Buffer under-run */ | ||
129 | #define IPC_IA_BUF_UNDER_RUN_MRFLD 0x0B | ||
130 | |||
131 | /* Mrfld specific defines: | ||
132 | * For asynchronous messages(INIT_CMPLT, PERIOD_ELAPSED, ASYNC_ERROR) | ||
133 | * received from FW, the format is: | ||
134 | * - IPC High: pvt_id is set to zero. Always short message. | ||
135 | * - msg_id is in lower 16-bits of IPC low payload. | ||
136 | * - pipe_id is in higher 16-bits of IPC low payload for period_elapsed. | ||
137 | * - error id is in higher 16-bits of IPC low payload for async errors. | ||
138 | */ | ||
139 | #define SST_ASYNC_DRV_ID 0 | ||
140 | |||
141 | /* Command Response or Acknowledge message to any IPC message will have | ||
142 | * same message ID and stream ID information which is sent. | ||
143 | * There is no specific Ack message ID. The data field is used as response | ||
144 | * meaning. | ||
145 | */ | ||
146 | enum ackData { | ||
147 | IPC_ACK_SUCCESS = 0, | ||
148 | IPC_ACK_FAILURE, | ||
149 | }; | ||
150 | |||
151 | enum ipc_ia_msg_id { | ||
152 | IPC_CMD = 1, /*!< Task Control message ID */ | ||
153 | IPC_SET_PARAMS = 2,/*!< Task Set param message ID */ | ||
154 | IPC_GET_PARAMS = 3, /*!< Task Get param message ID */ | ||
155 | IPC_INVALID = 0xFF, /*!<Task Get param message ID */ | ||
156 | }; | ||
157 | |||
22 | enum sst_codec_types { | 158 | enum sst_codec_types { |
23 | /* AUDIO/MUSIC CODEC Type Definitions */ | 159 | /* AUDIO/MUSIC CODEC Type Definitions */ |
24 | SST_CODEC_TYPE_UNKNOWN = 0, | 160 | SST_CODEC_TYPE_UNKNOWN = 0, |
@@ -35,14 +171,157 @@ enum stream_type { | |||
35 | SST_STREAM_TYPE_MUSIC = 1, | 171 | SST_STREAM_TYPE_MUSIC = 1, |
36 | }; | 172 | }; |
37 | 173 | ||
174 | enum sst_error_codes { | ||
175 | /* Error code,response to msgId: Description */ | ||
176 | /* Common error codes */ | ||
177 | SST_SUCCESS = 0, /* Success */ | ||
178 | SST_ERR_INVALID_STREAM_ID = 1, | ||
179 | SST_ERR_INVALID_MSG_ID = 2, | ||
180 | SST_ERR_INVALID_STREAM_OP = 3, | ||
181 | SST_ERR_INVALID_PARAMS = 4, | ||
182 | SST_ERR_INVALID_CODEC = 5, | ||
183 | SST_ERR_INVALID_MEDIA_TYPE = 6, | ||
184 | SST_ERR_STREAM_ERR = 7, | ||
185 | |||
186 | SST_ERR_STREAM_IN_USE = 15, | ||
187 | }; | ||
188 | |||
189 | struct ipc_dsp_hdr { | ||
190 | u16 mod_index_id:8; /*!< DSP Command ID specific to tasks */ | ||
191 | u16 pipe_id:8; /*!< instance of the module in the pipeline */ | ||
192 | u16 mod_id; /*!< Pipe_id */ | ||
193 | u16 cmd_id; /*!< Module ID = lpe_algo_types_t */ | ||
194 | u16 length; /*!< Length of the payload only */ | ||
195 | } __packed; | ||
196 | |||
197 | union ipc_header_high { | ||
198 | struct { | ||
199 | u32 msg_id:8; /* Message ID - Max 256 Message Types */ | ||
200 | u32 task_id:4; /* Task ID associated with this comand */ | ||
201 | u32 drv_id:4; /* Identifier for the driver to track*/ | ||
202 | u32 rsvd1:8; /* Reserved */ | ||
203 | u32 result:4; /* Reserved */ | ||
204 | u32 res_rqd:1; /* Response rqd */ | ||
205 | u32 large:1; /* Large Message if large = 1 */ | ||
206 | u32 done:1; /* bit 30 - Done bit */ | ||
207 | u32 busy:1; /* bit 31 - busy bit*/ | ||
208 | } part; | ||
209 | u32 full; | ||
210 | } __packed; | ||
211 | /* IPC header */ | ||
212 | union ipc_header_mrfld { | ||
213 | struct { | ||
214 | u32 header_low_payload; | ||
215 | union ipc_header_high header_high; | ||
216 | } p; | ||
217 | u64 full; | ||
218 | } __packed; | ||
219 | /* CAUTION NOTE: All IPC message body must be multiple of 32 bits.*/ | ||
220 | |||
221 | /* IPC Header */ | ||
222 | union ipc_header { | ||
223 | struct { | ||
224 | u32 msg_id:8; /* Message ID - Max 256 Message Types */ | ||
225 | u32 str_id:5; | ||
226 | u32 large:1; /* Large Message if large = 1 */ | ||
227 | u32 reserved:2; /* Reserved for future use */ | ||
228 | u32 data:14; /* Ack/Info for msg, size of msg in Mailbox */ | ||
229 | u32 done:1; /* bit 30 */ | ||
230 | u32 busy:1; /* bit 31 */ | ||
231 | } part; | ||
232 | u32 full; | ||
233 | } __packed; | ||
234 | |||
235 | /* Firmware build info */ | ||
236 | struct sst_fw_build_info { | ||
237 | unsigned char date[16]; /* Firmware build date */ | ||
238 | unsigned char time[16]; /* Firmware build time */ | ||
239 | } __packed; | ||
240 | |||
241 | /* Firmware Version info */ | ||
242 | struct snd_sst_fw_version { | ||
243 | u8 build; /* build number*/ | ||
244 | u8 minor; /* minor number*/ | ||
245 | u8 major; /* major number*/ | ||
246 | u8 type; /* build type */ | ||
247 | }; | ||
248 | |||
249 | struct ipc_header_fw_init { | ||
250 | struct snd_sst_fw_version fw_version;/* Firmware version details */ | ||
251 | struct sst_fw_build_info build_info; | ||
252 | u16 result; /* Fw init result */ | ||
253 | u8 module_id; /* Module ID in case of error */ | ||
254 | u8 debug_info; /* Debug info from Module ID in case of fail */ | ||
255 | } __packed; | ||
256 | |||
257 | struct snd_sst_tstamp { | ||
258 | u64 ring_buffer_counter; /* PB/CP: Bytes copied from/to DDR. */ | ||
259 | u64 hardware_counter; /* PB/CP: Bytes DMAed to/from SSP. */ | ||
260 | u64 frames_decoded; | ||
261 | u64 bytes_decoded; | ||
262 | u64 bytes_copied; | ||
263 | u32 sampling_frequency; | ||
264 | u32 channel_peak[8]; | ||
265 | } __packed; | ||
266 | |||
267 | /* Stream type params struture for Alloc stream */ | ||
268 | struct snd_sst_str_type { | ||
269 | u8 codec_type; /* Codec type */ | ||
270 | u8 str_type; /* 1 = voice 2 = music */ | ||
271 | u8 operation; /* Playback or Capture */ | ||
272 | u8 protected_str; /* 0=Non DRM, 1=DRM */ | ||
273 | u8 time_slots; | ||
274 | u8 reserved; /* Reserved */ | ||
275 | u16 result; /* Result used for acknowledgment */ | ||
276 | } __packed; | ||
277 | |||
278 | /* Library info structure */ | ||
279 | struct module_info { | ||
280 | u32 lib_version; | ||
281 | u32 lib_type;/*TBD- KLOCKWORK u8 lib_type;*/ | ||
282 | u32 media_type; | ||
283 | u8 lib_name[12]; | ||
284 | u32 lib_caps; | ||
285 | unsigned char b_date[16]; /* Lib build date */ | ||
286 | unsigned char b_time[16]; /* Lib build time */ | ||
287 | } __packed; | ||
288 | |||
289 | /* Library slot info */ | ||
290 | struct lib_slot_info { | ||
291 | u8 slot_num; /* 1 or 2 */ | ||
292 | u8 reserved1; | ||
293 | u16 reserved2; | ||
294 | u32 iram_size; /* slot size in IRAM */ | ||
295 | u32 dram_size; /* slot size in DRAM */ | ||
296 | u32 iram_offset; /* starting offset of slot in IRAM */ | ||
297 | u32 dram_offset; /* starting offset of slot in DRAM */ | ||
298 | } __packed; | ||
299 | |||
300 | struct snd_ppp_mixer_params { | ||
301 | __u32 type; /*Type of the parameter */ | ||
302 | __u32 size; | ||
303 | __u32 input_stream_bitmap; /*Input stream Bit Map*/ | ||
304 | } __packed; | ||
305 | |||
306 | struct snd_sst_lib_download { | ||
307 | struct module_info lib_info; /* library info type, capabilities etc */ | ||
308 | struct lib_slot_info slot_info; /* slot info to be downloaded */ | ||
309 | u32 mod_entry_pt; | ||
310 | }; | ||
311 | |||
312 | struct snd_sst_lib_download_info { | ||
313 | struct snd_sst_lib_download dload_lib; | ||
314 | u16 result; /* Result used for acknowledgment */ | ||
315 | u8 pvt_id; /* Private ID */ | ||
316 | u8 reserved; /* for alignment */ | ||
317 | }; | ||
38 | struct snd_pcm_params { | 318 | struct snd_pcm_params { |
39 | u8 num_chan; /* 1=Mono, 2=Stereo */ | 319 | u8 num_chan; /* 1=Mono, 2=Stereo */ |
40 | u8 pcm_wd_sz; /* 16/24 - bit*/ | 320 | u8 pcm_wd_sz; /* 16/24 - bit*/ |
41 | u32 reserved; /* Bitrate in bits per second */ | 321 | u8 use_offload_path; /* 0-PCM using period elpased & ALSA interfaces |
42 | u32 sfreq; /* Sampling rate in Hz */ | 322 | 1-PCM stream via compressed interface */ |
43 | u8 use_offload_path; | ||
44 | u8 reserved2; | 323 | u8 reserved2; |
45 | u16 reserved3; | 324 | u32 sfreq; /* Sampling rate in Hz */ |
46 | u8 channel_map[8]; | 325 | u8 channel_map[8]; |
47 | } __packed; | 326 | } __packed; |
48 | 327 | ||
@@ -76,6 +355,7 @@ struct snd_aac_params { | |||
76 | struct snd_wma_params { | 355 | struct snd_wma_params { |
77 | u8 num_chan; /* 1=Mono, 2=Stereo */ | 356 | u8 num_chan; /* 1=Mono, 2=Stereo */ |
78 | u8 pcm_wd_sz; /* 16/24 - bit*/ | 357 | u8 pcm_wd_sz; /* 16/24 - bit*/ |
358 | u16 reserved1; | ||
79 | u32 brate; /* Use the hard coded value. */ | 359 | u32 brate; /* Use the hard coded value. */ |
80 | u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ | 360 | u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ |
81 | u32 channel_mask; /* Channel Mask */ | 361 | u32 channel_mask; /* Channel Mask */ |
@@ -101,26 +381,153 @@ struct sst_address_info { | |||
101 | }; | 381 | }; |
102 | 382 | ||
103 | struct snd_sst_alloc_params_ext { | 383 | struct snd_sst_alloc_params_ext { |
104 | struct sst_address_info ring_buf_info[8]; | 384 | __u16 sg_count; |
105 | u8 sg_count; | 385 | __u16 reserved; |
106 | u8 reserved; | 386 | __u32 frag_size; /*Number of samples after which period elapsed |
107 | u16 reserved2; | ||
108 | u32 frag_size; /*Number of samples after which period elapsed | ||
109 | message is sent valid only if path = 0*/ | 387 | message is sent valid only if path = 0*/ |
110 | } __packed; | 388 | struct sst_address_info ring_buf_info[8]; |
389 | }; | ||
111 | 390 | ||
112 | struct snd_sst_stream_params { | 391 | struct snd_sst_stream_params { |
113 | union snd_sst_codec_params uc; | 392 | union snd_sst_codec_params uc; |
114 | } __packed; | 393 | } __packed; |
115 | 394 | ||
116 | struct snd_sst_params { | 395 | struct snd_sst_params { |
396 | u32 result; | ||
117 | u32 stream_id; | 397 | u32 stream_id; |
118 | u8 codec; | 398 | u8 codec; |
119 | u8 ops; | 399 | u8 ops; |
120 | u8 stream_type; | 400 | u8 stream_type; |
121 | u8 device_type; | 401 | u8 device_type; |
402 | u8 task; | ||
122 | struct snd_sst_stream_params sparams; | 403 | struct snd_sst_stream_params sparams; |
123 | struct snd_sst_alloc_params_ext aparams; | 404 | struct snd_sst_alloc_params_ext aparams; |
124 | }; | 405 | }; |
125 | 406 | ||
407 | struct snd_sst_alloc_mrfld { | ||
408 | u16 codec_type; | ||
409 | u8 operation; | ||
410 | u8 sg_count; | ||
411 | struct sst_address_info ring_buf_info[8]; | ||
412 | u32 frag_size; | ||
413 | u32 ts; | ||
414 | struct snd_sst_stream_params codec_params; | ||
415 | } __packed; | ||
416 | |||
417 | /* Alloc stream params structure */ | ||
418 | struct snd_sst_alloc_params { | ||
419 | struct snd_sst_str_type str_type; | ||
420 | struct snd_sst_stream_params stream_params; | ||
421 | struct snd_sst_alloc_params_ext alloc_params; | ||
422 | } __packed; | ||
423 | |||
424 | /* Alloc stream response message */ | ||
425 | struct snd_sst_alloc_response { | ||
426 | struct snd_sst_str_type str_type; /* Stream type for allocation */ | ||
427 | struct snd_sst_lib_download lib_dnld; /* Valid only for codec dnld */ | ||
428 | }; | ||
429 | |||
430 | /* Drop response */ | ||
431 | struct snd_sst_drop_response { | ||
432 | u32 result; | ||
433 | u32 bytes; | ||
434 | }; | ||
435 | |||
436 | struct snd_sst_async_msg { | ||
437 | u32 msg_id; /* Async msg id */ | ||
438 | u32 payload[0]; | ||
439 | }; | ||
440 | |||
441 | struct snd_sst_async_err_msg { | ||
442 | u32 fw_resp; /* Firmware Result */ | ||
443 | u32 lib_resp; /*Library result */ | ||
444 | } __packed; | ||
445 | |||
446 | struct snd_sst_vol { | ||
447 | u32 stream_id; | ||
448 | s32 volume; | ||
449 | u32 ramp_duration; | ||
450 | u32 ramp_type; /* Ramp type, default=0 */ | ||
451 | }; | ||
452 | |||
453 | /* Gain library parameters for mrfld | ||
454 | * based on DSP command spec v0.82 | ||
455 | */ | ||
456 | struct snd_sst_gain_v2 { | ||
457 | u16 gain_cell_num; /* num of gain cells to modify*/ | ||
458 | u8 cell_nbr_idx; /* instance index*/ | ||
459 | u8 cell_path_idx; /* pipe-id */ | ||
460 | u16 module_id; /*module id */ | ||
461 | u16 left_cell_gain; /* left gain value in dB*/ | ||
462 | u16 right_cell_gain; /* right gain value in dB*/ | ||
463 | u16 gain_time_const; /* gain time constant*/ | ||
464 | } __packed; | ||
465 | |||
466 | struct snd_sst_mute { | ||
467 | u32 stream_id; | ||
468 | u32 mute; | ||
469 | }; | ||
470 | |||
471 | struct snd_sst_runtime_params { | ||
472 | u8 type; | ||
473 | u8 str_id; | ||
474 | u8 size; | ||
475 | u8 rsvd; | ||
476 | void *addr; | ||
477 | } __packed; | ||
478 | |||
479 | enum stream_param_type { | ||
480 | SST_SET_TIME_SLOT = 0, | ||
481 | SST_SET_CHANNEL_INFO = 1, | ||
482 | OTHERS = 2, /*reserved for future params*/ | ||
483 | }; | ||
484 | |||
485 | /* CSV Voice call routing structure */ | ||
486 | struct snd_sst_control_routing { | ||
487 | u8 control; /* 0=start, 1=Stop */ | ||
488 | u8 reserved[3]; /* Reserved- for 32 bit alignment */ | ||
489 | }; | ||
490 | |||
491 | struct ipc_post { | ||
492 | struct list_head node; | ||
493 | union ipc_header header; /* driver specific */ | ||
494 | bool is_large; | ||
495 | bool is_process_reply; | ||
496 | union ipc_header_mrfld mrfld_header; | ||
497 | char *mailbox_data; | ||
498 | }; | ||
499 | |||
500 | struct snd_sst_ctxt_params { | ||
501 | u32 address; /* Physical Address in DDR where the context is stored */ | ||
502 | u32 size; /* size of the context */ | ||
503 | }; | ||
504 | |||
505 | struct snd_sst_lpe_log_params { | ||
506 | u8 dbg_type; | ||
507 | u8 module_id; | ||
508 | u8 log_level; | ||
509 | u8 reserved; | ||
510 | } __packed; | ||
511 | |||
512 | enum snd_sst_bytes_type { | ||
513 | SND_SST_BYTES_SET = 0x1, | ||
514 | SND_SST_BYTES_GET = 0x2, | ||
515 | }; | ||
516 | |||
517 | struct snd_sst_bytes_v2 { | ||
518 | u8 type; | ||
519 | u8 ipc_msg; | ||
520 | u8 block; | ||
521 | u8 task_id; | ||
522 | u8 pipe_id; | ||
523 | u8 rsvd; | ||
524 | u16 len; | ||
525 | char bytes[0]; | ||
526 | }; | ||
527 | |||
528 | #define MAX_VTSV_FILES 2 | ||
529 | struct snd_sst_vtsv_info { | ||
530 | struct sst_address_info vfiles[MAX_VTSV_FILES]; | ||
531 | } __packed; | ||
532 | |||
126 | #endif /* __SST_MFLD_DSP_H__ */ | 533 | #endif /* __SST_MFLD_DSP_H__ */ |
diff --git a/sound/soc/intel/sst-mfld-platform-compress.c b/sound/soc/intel/sst-mfld-platform-compress.c index 02abd19fce1d..29c059ca19e8 100644 --- a/sound/soc/intel/sst-mfld-platform-compress.c +++ b/sound/soc/intel/sst-mfld-platform-compress.c | |||
@@ -100,14 +100,19 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, | |||
100 | int retval; | 100 | int retval; |
101 | struct snd_sst_params str_params; | 101 | struct snd_sst_params str_params; |
102 | struct sst_compress_cb cb; | 102 | struct sst_compress_cb cb; |
103 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
104 | struct snd_soc_platform *platform = rtd->platform; | ||
105 | struct sst_data *ctx = snd_soc_platform_get_drvdata(platform); | ||
103 | 106 | ||
104 | stream = cstream->runtime->private_data; | 107 | stream = cstream->runtime->private_data; |
105 | /* construct fw structure for this*/ | 108 | /* construct fw structure for this*/ |
106 | memset(&str_params, 0, sizeof(str_params)); | 109 | memset(&str_params, 0, sizeof(str_params)); |
107 | 110 | ||
108 | str_params.ops = STREAM_OPS_PLAYBACK; | 111 | /* fill the device type and stream id to pass to SST driver */ |
109 | str_params.stream_type = SST_STREAM_TYPE_MUSIC; | 112 | retval = sst_fill_stream_params(cstream, ctx, &str_params, true); |
110 | str_params.device_type = SND_SST_DEVICE_COMPRESS; | 113 | pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval); |
114 | if (retval < 0) | ||
115 | return retval; | ||
111 | 116 | ||
112 | switch (params->codec.id) { | 117 | switch (params->codec.id) { |
113 | case SND_AUDIOCODEC_MP3: { | 118 | case SND_AUDIOCODEC_MP3: { |
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c index 7c790f51d259..706212a6a68c 100644 --- a/sound/soc/intel/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/sst-mfld-platform-pcm.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * sst_mfld_platform.c - Intel MID Platform driver | 2 | * sst_mfld_platform.c - Intel MID Platform driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010-2013 Intel Corp | 4 | * Copyright (C) 2010-2014 Intel Corp |
5 | * Author: Vinod Koul <vinod.koul@intel.com> | 5 | * Author: Vinod Koul <vinod.koul@intel.com> |
6 | * Author: Harsha Priya <priya.harsha@intel.com> | 6 | * Author: Harsha Priya <priya.harsha@intel.com> |
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
@@ -27,7 +27,9 @@ | |||
27 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
28 | #include <sound/soc.h> | 28 | #include <sound/soc.h> |
29 | #include <sound/compress_driver.h> | 29 | #include <sound/compress_driver.h> |
30 | #include <asm/platform_sst_audio.h> | ||
30 | #include "sst-mfld-platform.h" | 31 | #include "sst-mfld-platform.h" |
32 | #include "sst-atom-controls.h" | ||
31 | 33 | ||
32 | struct sst_device *sst; | 34 | struct sst_device *sst; |
33 | static DEFINE_MUTEX(sst_lock); | 35 | static DEFINE_MUTEX(sst_lock); |
@@ -92,6 +94,13 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = { | |||
92 | .fifo_size = SST_FIFO_SIZE, | 94 | .fifo_size = SST_FIFO_SIZE, |
93 | }; | 95 | }; |
94 | 96 | ||
97 | static struct sst_dev_stream_map dpcm_strm_map[] = { | ||
98 | {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */ | ||
99 | {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0}, | ||
100 | {MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0}, | ||
101 | {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0}, | ||
102 | }; | ||
103 | |||
95 | /* MFLD - MSIC */ | 104 | /* MFLD - MSIC */ |
96 | static struct snd_soc_dai_driver sst_platform_dai[] = { | 105 | static struct snd_soc_dai_driver sst_platform_dai[] = { |
97 | { | 106 | { |
@@ -143,58 +152,142 @@ static inline int sst_get_stream_status(struct sst_runtime_stream *stream) | |||
143 | return state; | 152 | return state; |
144 | } | 153 | } |
145 | 154 | ||
155 | static void sst_fill_alloc_params(struct snd_pcm_substream *substream, | ||
156 | struct snd_sst_alloc_params_ext *alloc_param) | ||
157 | { | ||
158 | unsigned int channels; | ||
159 | snd_pcm_uframes_t period_size; | ||
160 | ssize_t periodbytes; | ||
161 | ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream); | ||
162 | u32 buffer_addr = virt_to_phys(substream->dma_buffer.area); | ||
163 | |||
164 | channels = substream->runtime->channels; | ||
165 | period_size = substream->runtime->period_size; | ||
166 | periodbytes = samples_to_bytes(substream->runtime, period_size); | ||
167 | alloc_param->ring_buf_info[0].addr = buffer_addr; | ||
168 | alloc_param->ring_buf_info[0].size = buffer_bytes; | ||
169 | alloc_param->sg_count = 1; | ||
170 | alloc_param->reserved = 0; | ||
171 | alloc_param->frag_size = periodbytes * channels; | ||
172 | |||
173 | } | ||
146 | static void sst_fill_pcm_params(struct snd_pcm_substream *substream, | 174 | static void sst_fill_pcm_params(struct snd_pcm_substream *substream, |
147 | struct sst_pcm_params *param) | 175 | struct snd_sst_stream_params *param) |
148 | { | 176 | { |
177 | param->uc.pcm_params.num_chan = (u8) substream->runtime->channels; | ||
178 | param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits; | ||
179 | param->uc.pcm_params.sfreq = substream->runtime->rate; | ||
180 | |||
181 | /* PCM stream via ALSA interface */ | ||
182 | param->uc.pcm_params.use_offload_path = 0; | ||
183 | param->uc.pcm_params.reserved2 = 0; | ||
184 | memset(param->uc.pcm_params.channel_map, 0, sizeof(u8)); | ||
149 | 185 | ||
150 | param->num_chan = (u8) substream->runtime->channels; | ||
151 | param->pcm_wd_sz = substream->runtime->sample_bits; | ||
152 | param->reserved = 0; | ||
153 | param->sfreq = substream->runtime->rate; | ||
154 | param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream); | ||
155 | param->period_count = substream->runtime->period_size; | ||
156 | param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area); | ||
157 | pr_debug("period_cnt = %d\n", param->period_count); | ||
158 | pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz); | ||
159 | } | 186 | } |
160 | 187 | ||
161 | static int sst_platform_alloc_stream(struct snd_pcm_substream *substream) | 188 | static int sst_get_stream_mapping(int dev, int sdev, int dir, |
189 | struct sst_dev_stream_map *map, int size) | ||
190 | { | ||
191 | int i; | ||
192 | |||
193 | if (map == NULL) | ||
194 | return -EINVAL; | ||
195 | |||
196 | |||
197 | /* index 0 is not used in stream map */ | ||
198 | for (i = 1; i < size; i++) { | ||
199 | if ((map[i].dev_num == dev) && (map[i].direction == dir)) | ||
200 | return i; | ||
201 | } | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | int sst_fill_stream_params(void *substream, | ||
206 | const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress) | ||
207 | { | ||
208 | int map_size; | ||
209 | int index; | ||
210 | struct sst_dev_stream_map *map; | ||
211 | struct snd_pcm_substream *pstream = NULL; | ||
212 | struct snd_compr_stream *cstream = NULL; | ||
213 | |||
214 | map = ctx->pdata->pdev_strm_map; | ||
215 | map_size = ctx->pdata->strm_map_size; | ||
216 | |||
217 | if (is_compress == true) | ||
218 | cstream = (struct snd_compr_stream *)substream; | ||
219 | else | ||
220 | pstream = (struct snd_pcm_substream *)substream; | ||
221 | |||
222 | str_params->stream_type = SST_STREAM_TYPE_MUSIC; | ||
223 | |||
224 | /* For pcm streams */ | ||
225 | if (pstream) { | ||
226 | index = sst_get_stream_mapping(pstream->pcm->device, | ||
227 | pstream->number, pstream->stream, | ||
228 | map, map_size); | ||
229 | if (index <= 0) | ||
230 | return -EINVAL; | ||
231 | |||
232 | str_params->stream_id = index; | ||
233 | str_params->device_type = map[index].device_id; | ||
234 | str_params->task = map[index].task_id; | ||
235 | |||
236 | str_params->ops = (u8)pstream->stream; | ||
237 | } | ||
238 | |||
239 | if (cstream) { | ||
240 | index = sst_get_stream_mapping(cstream->device->device, | ||
241 | 0, cstream->direction, | ||
242 | map, map_size); | ||
243 | if (index <= 0) | ||
244 | return -EINVAL; | ||
245 | str_params->stream_id = index; | ||
246 | str_params->device_type = map[index].device_id; | ||
247 | str_params->task = map[index].task_id; | ||
248 | |||
249 | str_params->ops = (u8)cstream->direction; | ||
250 | } | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int sst_platform_alloc_stream(struct snd_pcm_substream *substream, | ||
255 | struct snd_soc_platform *platform) | ||
162 | { | 256 | { |
163 | struct sst_runtime_stream *stream = | 257 | struct sst_runtime_stream *stream = |
164 | substream->runtime->private_data; | 258 | substream->runtime->private_data; |
165 | struct sst_pcm_params param = {0}; | 259 | struct snd_sst_stream_params param = {{{0,},},}; |
166 | struct sst_stream_params str_params = {0}; | 260 | struct snd_sst_params str_params = {0}; |
167 | int ret_val; | 261 | struct snd_sst_alloc_params_ext alloc_params = {0}; |
262 | int ret_val = 0; | ||
263 | struct sst_data *ctx = snd_soc_platform_get_drvdata(platform); | ||
168 | 264 | ||
169 | /* set codec params and inform SST driver the same */ | 265 | /* set codec params and inform SST driver the same */ |
170 | sst_fill_pcm_params(substream, ¶m); | 266 | sst_fill_pcm_params(substream, ¶m); |
267 | sst_fill_alloc_params(substream, &alloc_params); | ||
171 | substream->runtime->dma_area = substream->dma_buffer.area; | 268 | substream->runtime->dma_area = substream->dma_buffer.area; |
172 | str_params.sparams = param; | 269 | str_params.sparams = param; |
173 | str_params.codec = param.codec; | 270 | str_params.aparams = alloc_params; |
174 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 271 | str_params.codec = SST_CODEC_TYPE_PCM; |
175 | str_params.ops = STREAM_OPS_PLAYBACK; | 272 | |
176 | str_params.device_type = substream->pcm->device + 1; | 273 | /* fill the device type and stream id to pass to SST driver */ |
177 | pr_debug("Playbck stream,Device %d\n", | 274 | ret_val = sst_fill_stream_params(substream, ctx, &str_params, false); |
178 | substream->pcm->device); | ||
179 | } else { | ||
180 | str_params.ops = STREAM_OPS_CAPTURE; | ||
181 | str_params.device_type = SND_SST_DEVICE_CAPTURE; | ||
182 | pr_debug("Capture stream,Device %d\n", | ||
183 | substream->pcm->device); | ||
184 | } | ||
185 | ret_val = stream->ops->open(&str_params); | ||
186 | pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val); | ||
187 | if (ret_val < 0) | 275 | if (ret_val < 0) |
188 | return ret_val; | 276 | return ret_val; |
189 | 277 | ||
190 | stream->stream_info.str_id = ret_val; | 278 | stream->stream_info.str_id = str_params.stream_id; |
191 | pr_debug("str id : %d\n", stream->stream_info.str_id); | 279 | |
280 | ret_val = stream->ops->open(&str_params); | ||
281 | if (ret_val <= 0) | ||
282 | return ret_val; | ||
283 | |||
284 | |||
192 | return ret_val; | 285 | return ret_val; |
193 | } | 286 | } |
194 | 287 | ||
195 | static void sst_period_elapsed(void *mad_substream) | 288 | static void sst_period_elapsed(void *arg) |
196 | { | 289 | { |
197 | struct snd_pcm_substream *substream = mad_substream; | 290 | struct snd_pcm_substream *substream = arg; |
198 | struct sst_runtime_stream *stream; | 291 | struct sst_runtime_stream *stream; |
199 | int status; | 292 | int status; |
200 | 293 | ||
@@ -218,7 +311,7 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) | |||
218 | pr_debug("setting buffer ptr param\n"); | 311 | pr_debug("setting buffer ptr param\n"); |
219 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | 312 | sst_set_stream_status(stream, SST_PLATFORM_INIT); |
220 | stream->stream_info.period_elapsed = sst_period_elapsed; | 313 | stream->stream_info.period_elapsed = sst_period_elapsed; |
221 | stream->stream_info.mad_substream = substream; | 314 | stream->stream_info.arg = substream; |
222 | stream->stream_info.buffer_ptr = 0; | 315 | stream->stream_info.buffer_ptr = 0; |
223 | stream->stream_info.sfreq = substream->runtime->rate; | 316 | stream->stream_info.sfreq = substream->runtime->rate; |
224 | ret_val = stream->ops->device_control( | 317 | ret_val = stream->ops->device_control( |
@@ -230,19 +323,12 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) | |||
230 | } | 323 | } |
231 | /* end -- helper functions */ | 324 | /* end -- helper functions */ |
232 | 325 | ||
233 | static int sst_platform_open(struct snd_pcm_substream *substream) | 326 | static int sst_media_open(struct snd_pcm_substream *substream, |
327 | struct snd_soc_dai *dai) | ||
234 | { | 328 | { |
329 | int ret_val = 0; | ||
235 | struct snd_pcm_runtime *runtime = substream->runtime; | 330 | struct snd_pcm_runtime *runtime = substream->runtime; |
236 | struct sst_runtime_stream *stream; | 331 | struct sst_runtime_stream *stream; |
237 | int ret_val; | ||
238 | |||
239 | pr_debug("sst_platform_open called\n"); | ||
240 | |||
241 | snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw); | ||
242 | ret_val = snd_pcm_hw_constraint_integer(runtime, | ||
243 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
244 | if (ret_val < 0) | ||
245 | return ret_val; | ||
246 | 332 | ||
247 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); | 333 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); |
248 | if (!stream) | 334 | if (!stream) |
@@ -251,50 +337,69 @@ static int sst_platform_open(struct snd_pcm_substream *substream) | |||
251 | 337 | ||
252 | /* get the sst ops */ | 338 | /* get the sst ops */ |
253 | mutex_lock(&sst_lock); | 339 | mutex_lock(&sst_lock); |
254 | if (!sst) { | 340 | if (!sst || |
341 | !try_module_get(sst->dev->driver->owner)) { | ||
255 | pr_err("no device available to run\n"); | 342 | pr_err("no device available to run\n"); |
256 | mutex_unlock(&sst_lock); | 343 | ret_val = -ENODEV; |
257 | kfree(stream); | 344 | goto out_ops; |
258 | return -ENODEV; | ||
259 | } | ||
260 | if (!try_module_get(sst->dev->driver->owner)) { | ||
261 | mutex_unlock(&sst_lock); | ||
262 | kfree(stream); | ||
263 | return -ENODEV; | ||
264 | } | 345 | } |
265 | stream->ops = sst->ops; | 346 | stream->ops = sst->ops; |
266 | mutex_unlock(&sst_lock); | 347 | mutex_unlock(&sst_lock); |
267 | 348 | ||
268 | stream->stream_info.str_id = 0; | 349 | stream->stream_info.str_id = 0; |
269 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | 350 | |
270 | stream->stream_info.mad_substream = substream; | 351 | stream->stream_info.arg = substream; |
271 | /* allocate memory for SST API set */ | 352 | /* allocate memory for SST API set */ |
272 | runtime->private_data = stream; | 353 | runtime->private_data = stream; |
273 | 354 | ||
274 | return 0; | 355 | /* Make sure, that the period size is always even */ |
356 | snd_pcm_hw_constraint_step(substream->runtime, 0, | ||
357 | SNDRV_PCM_HW_PARAM_PERIODS, 2); | ||
358 | |||
359 | return snd_pcm_hw_constraint_integer(runtime, | ||
360 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
361 | out_ops: | ||
362 | kfree(stream); | ||
363 | mutex_unlock(&sst_lock); | ||
364 | return ret_val; | ||
275 | } | 365 | } |
276 | 366 | ||
277 | static int sst_platform_close(struct snd_pcm_substream *substream) | 367 | static void sst_media_close(struct snd_pcm_substream *substream, |
368 | struct snd_soc_dai *dai) | ||
278 | { | 369 | { |
279 | struct sst_runtime_stream *stream; | 370 | struct sst_runtime_stream *stream; |
280 | int ret_val = 0, str_id; | 371 | int ret_val = 0, str_id; |
281 | 372 | ||
282 | pr_debug("sst_platform_close called\n"); | ||
283 | stream = substream->runtime->private_data; | 373 | stream = substream->runtime->private_data; |
284 | str_id = stream->stream_info.str_id; | 374 | str_id = stream->stream_info.str_id; |
285 | if (str_id) | 375 | if (str_id) |
286 | ret_val = stream->ops->close(str_id); | 376 | ret_val = stream->ops->close(str_id); |
287 | module_put(sst->dev->driver->owner); | 377 | module_put(sst->dev->driver->owner); |
288 | kfree(stream); | 378 | kfree(stream); |
289 | return ret_val; | ||
290 | } | 379 | } |
291 | 380 | ||
292 | static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) | 381 | static inline unsigned int get_current_pipe_id(struct snd_soc_platform *platform, |
382 | struct snd_pcm_substream *substream) | ||
383 | { | ||
384 | struct sst_data *sst = snd_soc_platform_get_drvdata(platform); | ||
385 | struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map; | ||
386 | struct sst_runtime_stream *stream = | ||
387 | substream->runtime->private_data; | ||
388 | u32 str_id = stream->stream_info.str_id; | ||
389 | unsigned int pipe_id; | ||
390 | pipe_id = map[str_id].device_id; | ||
391 | |||
392 | pr_debug("%s: got pipe_id = %#x for str_id = %d\n", | ||
393 | __func__, pipe_id, str_id); | ||
394 | return pipe_id; | ||
395 | } | ||
396 | |||
397 | static int sst_media_prepare(struct snd_pcm_substream *substream, | ||
398 | struct snd_soc_dai *dai) | ||
293 | { | 399 | { |
294 | struct sst_runtime_stream *stream; | 400 | struct sst_runtime_stream *stream; |
295 | int ret_val = 0, str_id; | 401 | int ret_val = 0, str_id; |
296 | 402 | ||
297 | pr_debug("sst_platform_pcm_prepare called\n"); | ||
298 | stream = substream->runtime->private_data; | 403 | stream = substream->runtime->private_data; |
299 | str_id = stream->stream_info.str_id; | 404 | str_id = stream->stream_info.str_id; |
300 | if (stream->stream_info.str_id) { | 405 | if (stream->stream_info.str_id) { |
@@ -303,8 +408,8 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) | |||
303 | return ret_val; | 408 | return ret_val; |
304 | } | 409 | } |
305 | 410 | ||
306 | ret_val = sst_platform_alloc_stream(substream); | 411 | ret_val = sst_platform_alloc_stream(substream, dai->platform); |
307 | if (ret_val < 0) | 412 | if (ret_val <= 0) |
308 | return ret_val; | 413 | return ret_val; |
309 | snprintf(substream->pcm->id, sizeof(substream->pcm->id), | 414 | snprintf(substream->pcm->id, sizeof(substream->pcm->id), |
310 | "%d", stream->stream_info.str_id); | 415 | "%d", stream->stream_info.str_id); |
@@ -316,6 +421,41 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) | |||
316 | return ret_val; | 421 | return ret_val; |
317 | } | 422 | } |
318 | 423 | ||
424 | static int sst_media_hw_params(struct snd_pcm_substream *substream, | ||
425 | struct snd_pcm_hw_params *params, | ||
426 | struct snd_soc_dai *dai) | ||
427 | { | ||
428 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
429 | memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static int sst_media_hw_free(struct snd_pcm_substream *substream, | ||
434 | struct snd_soc_dai *dai) | ||
435 | { | ||
436 | return snd_pcm_lib_free_pages(substream); | ||
437 | } | ||
438 | |||
439 | static struct snd_soc_dai_ops sst_media_dai_ops = { | ||
440 | .startup = sst_media_open, | ||
441 | .shutdown = sst_media_close, | ||
442 | .prepare = sst_media_prepare, | ||
443 | .hw_params = sst_media_hw_params, | ||
444 | .hw_free = sst_media_hw_free, | ||
445 | }; | ||
446 | |||
447 | static int sst_platform_open(struct snd_pcm_substream *substream) | ||
448 | { | ||
449 | struct snd_pcm_runtime *runtime; | ||
450 | |||
451 | if (substream->pcm->internal) | ||
452 | return 0; | ||
453 | |||
454 | runtime = substream->runtime; | ||
455 | runtime->hw = sst_platform_pcm_hw; | ||
456 | return 0; | ||
457 | } | ||
458 | |||
319 | static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, | 459 | static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, |
320 | int cmd) | 460 | int cmd) |
321 | { | 461 | { |
@@ -331,7 +471,7 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, | |||
331 | pr_debug("sst: Trigger Start\n"); | 471 | pr_debug("sst: Trigger Start\n"); |
332 | str_cmd = SST_SND_START; | 472 | str_cmd = SST_SND_START; |
333 | status = SST_PLATFORM_RUNNING; | 473 | status = SST_PLATFORM_RUNNING; |
334 | stream->stream_info.mad_substream = substream; | 474 | stream->stream_info.arg = substream; |
335 | break; | 475 | break; |
336 | case SNDRV_PCM_TRIGGER_STOP: | 476 | case SNDRV_PCM_TRIGGER_STOP: |
337 | pr_debug("sst: in stop\n"); | 477 | pr_debug("sst: in stop\n"); |
@@ -377,32 +517,15 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer | |||
377 | pr_err("sst: error code = %d\n", ret_val); | 517 | pr_err("sst: error code = %d\n", ret_val); |
378 | return ret_val; | 518 | return ret_val; |
379 | } | 519 | } |
380 | return stream->stream_info.buffer_ptr; | 520 | substream->runtime->delay = str_info->pcm_delay; |
381 | } | 521 | return str_info->buffer_ptr; |
382 | |||
383 | static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream, | ||
384 | struct snd_pcm_hw_params *params) | ||
385 | { | ||
386 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
387 | memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream) | ||
393 | { | ||
394 | return snd_pcm_lib_free_pages(substream); | ||
395 | } | 522 | } |
396 | 523 | ||
397 | static struct snd_pcm_ops sst_platform_ops = { | 524 | static struct snd_pcm_ops sst_platform_ops = { |
398 | .open = sst_platform_open, | 525 | .open = sst_platform_open, |
399 | .close = sst_platform_close, | ||
400 | .ioctl = snd_pcm_lib_ioctl, | 526 | .ioctl = snd_pcm_lib_ioctl, |
401 | .prepare = sst_platform_pcm_prepare, | ||
402 | .trigger = sst_platform_pcm_trigger, | 527 | .trigger = sst_platform_pcm_trigger, |
403 | .pointer = sst_platform_pcm_pointer, | 528 | .pointer = sst_platform_pcm_pointer, |
404 | .hw_params = sst_platform_pcm_hw_params, | ||
405 | .hw_free = sst_platform_pcm_hw_free, | ||
406 | }; | 529 | }; |
407 | 530 | ||
408 | static void sst_pcm_free(struct snd_pcm *pcm) | 531 | static void sst_pcm_free(struct snd_pcm *pcm) |
@@ -413,15 +536,15 @@ static void sst_pcm_free(struct snd_pcm *pcm) | |||
413 | 536 | ||
414 | static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) | 537 | static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) |
415 | { | 538 | { |
539 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
416 | struct snd_pcm *pcm = rtd->pcm; | 540 | struct snd_pcm *pcm = rtd->pcm; |
417 | int retval = 0; | 541 | int retval = 0; |
418 | 542 | ||
419 | pr_debug("sst_pcm_new called\n"); | 543 | if (dai->driver->playback.channels_min || |
420 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || | 544 | dai->driver->capture.channels_min) { |
421 | pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
422 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, | 545 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, |
423 | SNDRV_DMA_TYPE_CONTINUOUS, | 546 | SNDRV_DMA_TYPE_CONTINUOUS, |
424 | snd_dma_continuous_data(GFP_KERNEL), | 547 | snd_dma_continuous_data(GFP_DMA), |
425 | SST_MIN_BUFFER, SST_MAX_BUFFER); | 548 | SST_MIN_BUFFER, SST_MAX_BUFFER); |
426 | if (retval) { | 549 | if (retval) { |
427 | pr_err("dma buffer allocationf fail\n"); | 550 | pr_err("dma buffer allocationf fail\n"); |
@@ -445,10 +568,28 @@ static const struct snd_soc_component_driver sst_component = { | |||
445 | 568 | ||
446 | static int sst_platform_probe(struct platform_device *pdev) | 569 | static int sst_platform_probe(struct platform_device *pdev) |
447 | { | 570 | { |
571 | struct sst_data *drv; | ||
448 | int ret; | 572 | int ret; |
573 | struct sst_platform_data *pdata; | ||
574 | |||
575 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); | ||
576 | if (drv == NULL) { | ||
577 | pr_err("kzalloc failed\n"); | ||
578 | return -ENOMEM; | ||
579 | } | ||
580 | |||
581 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
582 | if (pdata == NULL) { | ||
583 | pr_err("kzalloc failed for pdata\n"); | ||
584 | return -ENOMEM; | ||
585 | } | ||
586 | |||
587 | pdata->pdev_strm_map = dpcm_strm_map; | ||
588 | pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map); | ||
589 | drv->pdata = pdata; | ||
590 | mutex_init(&drv->lock); | ||
591 | dev_set_drvdata(&pdev->dev, drv); | ||
449 | 592 | ||
450 | pr_debug("sst_platform_probe called\n"); | ||
451 | sst = NULL; | ||
452 | ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); | 593 | ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); |
453 | if (ret) { | 594 | if (ret) { |
454 | pr_err("registering soc platform failed\n"); | 595 | pr_err("registering soc platform failed\n"); |
diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h index 6c5e7dc49e3c..6c6a42c08e24 100644 --- a/sound/soc/intel/sst-mfld-platform.h +++ b/sound/soc/intel/sst-mfld-platform.h | |||
@@ -39,9 +39,10 @@ extern struct sst_device *sst; | |||
39 | 39 | ||
40 | struct pcm_stream_info { | 40 | struct pcm_stream_info { |
41 | int str_id; | 41 | int str_id; |
42 | void *mad_substream; | 42 | void *arg; |
43 | void (*period_elapsed) (void *mad_substream); | 43 | void (*period_elapsed) (void *arg); |
44 | unsigned long long buffer_ptr; | 44 | unsigned long long buffer_ptr; |
45 | unsigned long long pcm_delay; | ||
45 | int sfreq; | 46 | int sfreq; |
46 | }; | 47 | }; |
47 | 48 | ||
@@ -62,7 +63,9 @@ enum sst_controls { | |||
62 | SST_SND_BUFFER_POINTER = 0x05, | 63 | SST_SND_BUFFER_POINTER = 0x05, |
63 | SST_SND_STREAM_INIT = 0x06, | 64 | SST_SND_STREAM_INIT = 0x06, |
64 | SST_SND_START = 0x07, | 65 | SST_SND_START = 0x07, |
65 | SST_MAX_CONTROLS = 0x07, | 66 | SST_SET_BYTE_STREAM = 0x100A, |
67 | SST_GET_BYTE_STREAM = 0x100B, | ||
68 | SST_MAX_CONTROLS = SST_GET_BYTE_STREAM, | ||
66 | }; | 69 | }; |
67 | 70 | ||
68 | enum sst_stream_ops { | 71 | enum sst_stream_ops { |
@@ -124,8 +127,9 @@ struct compress_sst_ops { | |||
124 | }; | 127 | }; |
125 | 128 | ||
126 | struct sst_ops { | 129 | struct sst_ops { |
127 | int (*open) (struct sst_stream_params *str_param); | 130 | int (*open) (struct snd_sst_params *str_param); |
128 | int (*device_control) (int cmd, void *arg); | 131 | int (*device_control) (int cmd, void *arg); |
132 | int (*set_generic_params)(enum sst_controls cmd, void *arg); | ||
129 | int (*close) (unsigned int str_id); | 133 | int (*close) (unsigned int str_id); |
130 | }; | 134 | }; |
131 | 135 | ||
@@ -143,10 +147,27 @@ struct sst_device { | |||
143 | char *name; | 147 | char *name; |
144 | struct device *dev; | 148 | struct device *dev; |
145 | struct sst_ops *ops; | 149 | struct sst_ops *ops; |
150 | struct platform_device *pdev; | ||
146 | struct compress_sst_ops *compr_ops; | 151 | struct compress_sst_ops *compr_ops; |
147 | }; | 152 | }; |
148 | 153 | ||
154 | struct sst_data; | ||
149 | void sst_set_stream_status(struct sst_runtime_stream *stream, int state); | 155 | void sst_set_stream_status(struct sst_runtime_stream *stream, int state); |
156 | int sst_fill_stream_params(void *substream, const struct sst_data *ctx, | ||
157 | struct snd_sst_params *str_params, bool is_compress); | ||
158 | |||
159 | struct sst_algo_int_control_v2 { | ||
160 | struct soc_mixer_control mc; | ||
161 | u16 module_id; /* module identifieer */ | ||
162 | u16 pipe_id; /* location info: pipe_id + instance_id */ | ||
163 | u16 instance_id; | ||
164 | unsigned int value; /* Value received is stored here */ | ||
165 | }; | ||
166 | struct sst_data { | ||
167 | struct platform_device *pdev; | ||
168 | struct sst_platform_data *pdata; | ||
169 | struct mutex lock; | ||
170 | }; | ||
150 | int sst_register_dsp(struct sst_device *sst); | 171 | int sst_register_dsp(struct sst_device *sst); |
151 | int sst_unregister_dsp(struct sst_device *sst); | 172 | int sst_unregister_dsp(struct sst_device *sst); |
152 | #endif | 173 | #endif |
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index 06f4e8aa93ae..132bb83f8e99 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config SND_KIRKWOOD_SOC | 1 | config SND_KIRKWOOD_SOC |
2 | tristate "SoC Audio for the Marvell Kirkwood and Dove chips" | 2 | tristate "SoC Audio for the Marvell Kirkwood and Dove chips" |
3 | depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || MACH_KIRKWOOD || COMPILE_TEST | 3 | depends on ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST |
4 | help | 4 | help |
5 | Say Y or M if you want to add support for codecs attached to | 5 | Say Y or M if you want to add support for codecs attached to |
6 | the Kirkwood I2S interface. You will also need to select the | 6 | the Kirkwood I2S interface. You will also need to select the |
@@ -15,20 +15,3 @@ config SND_KIRKWOOD_SOC_ARMADA370_DB | |||
15 | Say Y if you want to add support for SoC audio on | 15 | Say Y if you want to add support for SoC audio on |
16 | the Armada 370 Development Board. | 16 | the Armada 370 Development Board. |
17 | 17 | ||
18 | config SND_KIRKWOOD_SOC_OPENRD | ||
19 | tristate "SoC Audio support for Kirkwood Openrd Client" | ||
20 | depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST) | ||
21 | depends on I2C | ||
22 | select SND_SOC_CS42L51 | ||
23 | help | ||
24 | Say Y if you want to add support for SoC audio on | ||
25 | Openrd Client. | ||
26 | |||
27 | config SND_KIRKWOOD_SOC_T5325 | ||
28 | tristate "SoC Audio support for HP t5325" | ||
29 | depends on SND_KIRKWOOD_SOC && (MACH_T5325 || COMPILE_TEST) && I2C | ||
30 | select SND_SOC_ALC5623 | ||
31 | help | ||
32 | Say Y if you want to add support for SoC audio on | ||
33 | the HP t5325 thin client. | ||
34 | |||
diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile index 7c1d8fe09e6b..c36b03d8006c 100644 --- a/sound/soc/kirkwood/Makefile +++ b/sound/soc/kirkwood/Makefile | |||
@@ -2,10 +2,6 @@ snd-soc-kirkwood-objs := kirkwood-dma.o kirkwood-i2s.o | |||
2 | 2 | ||
3 | obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o | 3 | obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o |
4 | 4 | ||
5 | snd-soc-openrd-objs := kirkwood-openrd.o | ||
6 | snd-soc-t5325-objs := kirkwood-t5325.o | ||
7 | snd-soc-armada-370-db-objs := armada-370-db.o | 5 | snd-soc-armada-370-db-objs := armada-370-db.o |
8 | 6 | ||
9 | obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o | 7 | obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o |
10 | obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o | ||
11 | obj-$(CONFIG_SND_KIRKWOOD_SOC_T5325) += snd-soc-t5325.o | ||
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index aac22fccdcdc..4cf2245950d7 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c | |||
@@ -28,11 +28,12 @@ static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs) | |||
28 | } | 28 | } |
29 | 29 | ||
30 | static struct snd_pcm_hardware kirkwood_dma_snd_hw = { | 30 | static struct snd_pcm_hardware kirkwood_dma_snd_hw = { |
31 | .info = (SNDRV_PCM_INFO_INTERLEAVED | | 31 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
32 | SNDRV_PCM_INFO_MMAP | | 32 | SNDRV_PCM_INFO_MMAP | |
33 | SNDRV_PCM_INFO_MMAP_VALID | | 33 | SNDRV_PCM_INFO_MMAP_VALID | |
34 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 34 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
35 | SNDRV_PCM_INFO_PAUSE), | 35 | SNDRV_PCM_INFO_PAUSE | |
36 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | ||
36 | .buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES, | 37 | .buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES, |
37 | .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, | 38 | .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, |
38 | .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES, | 39 | .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES, |
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 9f842222e798..0704cd6d2314 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c | |||
@@ -212,7 +212,8 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, | |||
212 | KIRKWOOD_PLAYCTL_SIZE_MASK); | 212 | KIRKWOOD_PLAYCTL_SIZE_MASK); |
213 | priv->ctl_play |= ctl_play; | 213 | priv->ctl_play |= ctl_play; |
214 | } else { | 214 | } else { |
215 | priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK; | 215 | priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK | |
216 | KIRKWOOD_RECCTL_SIZE_MASK); | ||
216 | priv->ctl_rec |= ctl_rec; | 217 | priv->ctl_rec |= ctl_rec; |
217 | } | 218 | } |
218 | 219 | ||
@@ -221,14 +222,24 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, | |||
221 | return 0; | 222 | return 0; |
222 | } | 223 | } |
223 | 224 | ||
225 | static unsigned kirkwood_i2s_play_mute(unsigned ctl) | ||
226 | { | ||
227 | if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN)) | ||
228 | ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE; | ||
229 | if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN)) | ||
230 | ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE; | ||
231 | return ctl; | ||
232 | } | ||
233 | |||
224 | static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | 234 | static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, |
225 | int cmd, struct snd_soc_dai *dai) | 235 | int cmd, struct snd_soc_dai *dai) |
226 | { | 236 | { |
237 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
227 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); | 238 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); |
228 | uint32_t ctl, value; | 239 | uint32_t ctl, value; |
229 | 240 | ||
230 | ctl = readl(priv->io + KIRKWOOD_PLAYCTL); | 241 | ctl = readl(priv->io + KIRKWOOD_PLAYCTL); |
231 | if (ctl & KIRKWOOD_PLAYCTL_PAUSE) { | 242 | if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) { |
232 | unsigned timeout = 5000; | 243 | unsigned timeout = 5000; |
233 | /* | 244 | /* |
234 | * The Armada510 spec says that if we enter pause mode, the | 245 | * The Armada510 spec says that if we enter pause mode, the |
@@ -256,14 +267,16 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | |||
256 | ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */ | 267 | ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */ |
257 | else | 268 | else |
258 | ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */ | 269 | ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */ |
259 | 270 | ctl = kirkwood_i2s_play_mute(ctl); | |
260 | value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; | 271 | value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; |
261 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | 272 | writel(value, priv->io + KIRKWOOD_PLAYCTL); |
262 | 273 | ||
263 | /* enable interrupts */ | 274 | /* enable interrupts */ |
264 | value = readl(priv->io + KIRKWOOD_INT_MASK); | 275 | if (!runtime->no_period_wakeup) { |
265 | value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; | 276 | value = readl(priv->io + KIRKWOOD_INT_MASK); |
266 | writel(value, priv->io + KIRKWOOD_INT_MASK); | 277 | value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; |
278 | writel(value, priv->io + KIRKWOOD_INT_MASK); | ||
279 | } | ||
267 | 280 | ||
268 | /* enable playback */ | 281 | /* enable playback */ |
269 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); | 282 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); |
@@ -295,6 +308,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | |||
295 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 308 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
296 | ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | | 309 | ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | |
297 | KIRKWOOD_PLAYCTL_SPDIF_MUTE); | 310 | KIRKWOOD_PLAYCTL_SPDIF_MUTE); |
311 | ctl = kirkwood_i2s_play_mute(ctl); | ||
298 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); | 312 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); |
299 | break; | 313 | break; |
300 | 314 | ||
@@ -322,8 +336,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, | |||
322 | else | 336 | else |
323 | ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */ | 337 | ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */ |
324 | 338 | ||
325 | value = ctl & ~(KIRKWOOD_RECCTL_I2S_EN | | 339 | value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK; |
326 | KIRKWOOD_RECCTL_SPDIF_EN); | ||
327 | writel(value, priv->io + KIRKWOOD_RECCTL); | 340 | writel(value, priv->io + KIRKWOOD_RECCTL); |
328 | 341 | ||
329 | /* enable interrupts */ | 342 | /* enable interrupts */ |
@@ -347,7 +360,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, | |||
347 | 360 | ||
348 | /* disable all records */ | 361 | /* disable all records */ |
349 | value = readl(priv->io + KIRKWOOD_RECCTL); | 362 | value = readl(priv->io + KIRKWOOD_RECCTL); |
350 | value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); | 363 | value &= ~KIRKWOOD_RECCTL_ENABLE_MASK; |
351 | writel(value, priv->io + KIRKWOOD_RECCTL); | 364 | writel(value, priv->io + KIRKWOOD_RECCTL); |
352 | break; | 365 | break; |
353 | 366 | ||
@@ -411,7 +424,7 @@ static int kirkwood_i2s_init(struct kirkwood_dma_data *priv) | |||
411 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | 424 | writel(value, priv->io + KIRKWOOD_PLAYCTL); |
412 | 425 | ||
413 | value = readl(priv->io + KIRKWOOD_RECCTL); | 426 | value = readl(priv->io + KIRKWOOD_RECCTL); |
414 | value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); | 427 | value &= ~KIRKWOOD_RECCTL_ENABLE_MASK; |
415 | writel(value, priv->io + KIRKWOOD_RECCTL); | 428 | writel(value, priv->io + KIRKWOOD_RECCTL); |
416 | 429 | ||
417 | return 0; | 430 | return 0; |
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c deleted file mode 100644 index 65f2a5b9ec3b..000000000000 --- a/sound/soc/kirkwood/kirkwood-openrd.c +++ /dev/null | |||
@@ -1,109 +0,0 @@ | |||
1 | /* | ||
2 | * kirkwood-openrd.c | ||
3 | * | ||
4 | * (c) 2010 Arnaud Patard <apatard@mandriva.com> | ||
5 | * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <linux/platform_data/asoc-kirkwood.h> | ||
20 | #include "../codecs/cs42l51.h" | ||
21 | |||
22 | static int openrd_client_hw_params(struct snd_pcm_substream *substream, | ||
23 | struct snd_pcm_hw_params *params) | ||
24 | { | ||
25 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
26 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
27 | unsigned int freq; | ||
28 | |||
29 | switch (params_rate(params)) { | ||
30 | default: | ||
31 | case 44100: | ||
32 | freq = 11289600; | ||
33 | break; | ||
34 | case 48000: | ||
35 | freq = 12288000; | ||
36 | break; | ||
37 | case 96000: | ||
38 | freq = 24576000; | ||
39 | break; | ||
40 | } | ||
41 | |||
42 | return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); | ||
43 | |||
44 | } | ||
45 | |||
46 | static struct snd_soc_ops openrd_client_ops = { | ||
47 | .hw_params = openrd_client_hw_params, | ||
48 | }; | ||
49 | |||
50 | |||
51 | static struct snd_soc_dai_link openrd_client_dai[] = { | ||
52 | { | ||
53 | .name = "CS42L51", | ||
54 | .stream_name = "CS42L51 HiFi", | ||
55 | .cpu_dai_name = "i2s", | ||
56 | .platform_name = "mvebu-audio", | ||
57 | .codec_dai_name = "cs42l51-hifi", | ||
58 | .codec_name = "cs42l51-codec.0-004a", | ||
59 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, | ||
60 | .ops = &openrd_client_ops, | ||
61 | }, | ||
62 | }; | ||
63 | |||
64 | |||
65 | static struct snd_soc_card openrd_client = { | ||
66 | .name = "OpenRD Client", | ||
67 | .owner = THIS_MODULE, | ||
68 | .dai_link = openrd_client_dai, | ||
69 | .num_links = ARRAY_SIZE(openrd_client_dai), | ||
70 | }; | ||
71 | |||
72 | static int openrd_probe(struct platform_device *pdev) | ||
73 | { | ||
74 | struct snd_soc_card *card = &openrd_client; | ||
75 | int ret; | ||
76 | |||
77 | card->dev = &pdev->dev; | ||
78 | |||
79 | ret = snd_soc_register_card(card); | ||
80 | if (ret) | ||
81 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
82 | ret); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static int openrd_remove(struct platform_device *pdev) | ||
87 | { | ||
88 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
89 | |||
90 | snd_soc_unregister_card(card); | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static struct platform_driver openrd_driver = { | ||
95 | .driver = { | ||
96 | .name = "openrd-client-audio", | ||
97 | .owner = THIS_MODULE, | ||
98 | }, | ||
99 | .probe = openrd_probe, | ||
100 | .remove = openrd_remove, | ||
101 | }; | ||
102 | |||
103 | module_platform_driver(openrd_driver); | ||
104 | |||
105 | /* Module information */ | ||
106 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); | ||
107 | MODULE_DESCRIPTION("ALSA SoC OpenRD Client"); | ||
108 | MODULE_LICENSE("GPL"); | ||
109 | MODULE_ALIAS("platform:openrd-client-audio"); | ||
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c deleted file mode 100644 index 844b8415a011..000000000000 --- a/sound/soc/kirkwood/kirkwood-t5325.c +++ /dev/null | |||
@@ -1,116 +0,0 @@ | |||
1 | /* | ||
2 | * kirkwood-t5325.c | ||
3 | * | ||
4 | * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> | ||
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 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <sound/soc.h> | ||
18 | #include <linux/platform_data/asoc-kirkwood.h> | ||
19 | #include "../codecs/alc5623.h" | ||
20 | |||
21 | static int t5325_hw_params(struct snd_pcm_substream *substream, | ||
22 | struct snd_pcm_hw_params *params) | ||
23 | { | ||
24 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
25 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
26 | unsigned int freq; | ||
27 | |||
28 | freq = params_rate(params) * 256; | ||
29 | |||
30 | return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); | ||
31 | |||
32 | } | ||
33 | |||
34 | static struct snd_soc_ops t5325_ops = { | ||
35 | .hw_params = t5325_hw_params, | ||
36 | }; | ||
37 | |||
38 | static const struct snd_soc_dapm_widget t5325_dapm_widgets[] = { | ||
39 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
40 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
41 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
42 | }; | ||
43 | |||
44 | static const struct snd_soc_dapm_route t5325_route[] = { | ||
45 | { "Headphone Jack", NULL, "HPL" }, | ||
46 | { "Headphone Jack", NULL, "HPR" }, | ||
47 | |||
48 | {"Speaker", NULL, "SPKOUT"}, | ||
49 | {"Speaker", NULL, "SPKOUTN"}, | ||
50 | |||
51 | { "MIC1", NULL, "Mic Jack" }, | ||
52 | { "MIC2", NULL, "Mic Jack" }, | ||
53 | }; | ||
54 | |||
55 | static struct snd_soc_dai_link t5325_dai[] = { | ||
56 | { | ||
57 | .name = "ALC5621", | ||
58 | .stream_name = "ALC5621 HiFi", | ||
59 | .cpu_dai_name = "i2s", | ||
60 | .platform_name = "mvebu-audio", | ||
61 | .codec_dai_name = "alc5621-hifi", | ||
62 | .codec_name = "alc562x-codec.0-001a", | ||
63 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, | ||
64 | .ops = &t5325_ops, | ||
65 | }, | ||
66 | }; | ||
67 | |||
68 | static struct snd_soc_card t5325 = { | ||
69 | .name = "t5325", | ||
70 | .owner = THIS_MODULE, | ||
71 | .dai_link = t5325_dai, | ||
72 | .num_links = ARRAY_SIZE(t5325_dai), | ||
73 | |||
74 | .dapm_widgets = t5325_dapm_widgets, | ||
75 | .num_dapm_widgets = ARRAY_SIZE(t5325_dapm_widgets), | ||
76 | .dapm_routes = t5325_route, | ||
77 | .num_dapm_routes = ARRAY_SIZE(t5325_route), | ||
78 | }; | ||
79 | |||
80 | static int t5325_probe(struct platform_device *pdev) | ||
81 | { | ||
82 | struct snd_soc_card *card = &t5325; | ||
83 | int ret; | ||
84 | |||
85 | card->dev = &pdev->dev; | ||
86 | |||
87 | ret = snd_soc_register_card(card); | ||
88 | if (ret) | ||
89 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
90 | ret); | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | static int t5325_remove(struct platform_device *pdev) | ||
95 | { | ||
96 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
97 | |||
98 | snd_soc_unregister_card(card); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static struct platform_driver t5325_driver = { | ||
103 | .driver = { | ||
104 | .name = "t5325-audio", | ||
105 | .owner = THIS_MODULE, | ||
106 | }, | ||
107 | .probe = t5325_probe, | ||
108 | .remove = t5325_remove, | ||
109 | }; | ||
110 | |||
111 | module_platform_driver(t5325_driver); | ||
112 | |||
113 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); | ||
114 | MODULE_DESCRIPTION("ALSA SoC t5325 audio client"); | ||
115 | MODULE_LICENSE("GPL"); | ||
116 | MODULE_ALIAS("platform:t5325-audio"); | ||
diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h index bf23afbba1d7..90e32a781424 100644 --- a/sound/soc/kirkwood/kirkwood.h +++ b/sound/soc/kirkwood/kirkwood.h | |||
@@ -38,6 +38,9 @@ | |||
38 | #define KIRKWOOD_RECCTL_SIZE_24 (1<<0) | 38 | #define KIRKWOOD_RECCTL_SIZE_24 (1<<0) |
39 | #define KIRKWOOD_RECCTL_SIZE_32 (0<<0) | 39 | #define KIRKWOOD_RECCTL_SIZE_32 (0<<0) |
40 | 40 | ||
41 | #define KIRKWOOD_RECCTL_ENABLE_MASK (KIRKWOOD_RECCTL_SPDIF_EN | \ | ||
42 | KIRKWOOD_RECCTL_I2S_EN) | ||
43 | |||
41 | #define KIRKWOOD_REC_BUF_ADDR 0x1004 | 44 | #define KIRKWOOD_REC_BUF_ADDR 0x1004 |
42 | #define KIRKWOOD_REC_BUF_SIZE 0x1008 | 45 | #define KIRKWOOD_REC_BUF_SIZE 0x1008 |
43 | #define KIRKWOOD_REC_BYTE_COUNT 0x100C | 46 | #define KIRKWOOD_REC_BYTE_COUNT 0x100C |
@@ -121,9 +124,9 @@ | |||
121 | 124 | ||
122 | /* Theses values come from the marvell alsa driver */ | 125 | /* Theses values come from the marvell alsa driver */ |
123 | /* need to find where they come from */ | 126 | /* need to find where they come from */ |
124 | #define KIRKWOOD_SND_MIN_PERIODS 8 | 127 | #define KIRKWOOD_SND_MIN_PERIODS 2 |
125 | #define KIRKWOOD_SND_MAX_PERIODS 16 | 128 | #define KIRKWOOD_SND_MAX_PERIODS 16 |
126 | #define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x800 | 129 | #define KIRKWOOD_SND_MIN_PERIOD_BYTES 256 |
127 | #define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x8000 | 130 | #define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x8000 |
128 | #define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \ | 131 | #define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \ |
129 | * KIRKWOOD_SND_MAX_PERIODS) | 132 | * KIRKWOOD_SND_MAX_PERIODS) |
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 0cc41f94de4e..8c9cc64a9dfb 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -301,7 +301,7 @@ static int cx81801_open(struct tty_struct *tty) | |||
301 | static void cx81801_close(struct tty_struct *tty) | 301 | static void cx81801_close(struct tty_struct *tty) |
302 | { | 302 | { |
303 | struct snd_soc_codec *codec = tty->disc_data; | 303 | struct snd_soc_codec *codec = tty->disc_data; |
304 | struct snd_soc_dapm_context *dapm = &codec->card->dapm; | 304 | struct snd_soc_dapm_context *dapm = &codec->component.card->dapm; |
305 | 305 | ||
306 | del_timer_sync(&cx81801_timer); | 306 | del_timer_sync(&cx81801_timer); |
307 | 307 | ||
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 6925d7141215..0f34e28a3d55 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c | |||
@@ -466,7 +466,7 @@ static int asoc_dmic_probe(struct platform_device *pdev) | |||
466 | 466 | ||
467 | mutex_init(&dmic->mutex); | 467 | mutex_init(&dmic->mutex); |
468 | 468 | ||
469 | dmic->fclk = clk_get(dmic->dev, "fck"); | 469 | dmic->fclk = devm_clk_get(dmic->dev, "fck"); |
470 | if (IS_ERR(dmic->fclk)) { | 470 | if (IS_ERR(dmic->fclk)) { |
471 | dev_err(dmic->dev, "cant get fck\n"); | 471 | dev_err(dmic->dev, "cant get fck\n"); |
472 | return -ENODEV; | 472 | return -ENODEV; |
@@ -475,8 +475,7 @@ static int asoc_dmic_probe(struct platform_device *pdev) | |||
475 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); | 475 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); |
476 | if (!res) { | 476 | if (!res) { |
477 | dev_err(dmic->dev, "invalid dma memory resource\n"); | 477 | dev_err(dmic->dev, "invalid dma memory resource\n"); |
478 | ret = -ENODEV; | 478 | return -ENODEV; |
479 | goto err_put_clk; | ||
480 | } | 479 | } |
481 | dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG; | 480 | dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG; |
482 | 481 | ||
@@ -484,34 +483,19 @@ static int asoc_dmic_probe(struct platform_device *pdev) | |||
484 | 483 | ||
485 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); | 484 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); |
486 | dmic->io_base = devm_ioremap_resource(&pdev->dev, res); | 485 | dmic->io_base = devm_ioremap_resource(&pdev->dev, res); |
487 | if (IS_ERR(dmic->io_base)) { | 486 | if (IS_ERR(dmic->io_base)) |
488 | ret = PTR_ERR(dmic->io_base); | 487 | return PTR_ERR(dmic->io_base); |
489 | goto err_put_clk; | ||
490 | } | ||
491 | 488 | ||
492 | 489 | ||
493 | ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component, | 490 | ret = devm_snd_soc_register_component(&pdev->dev, |
494 | &omap_dmic_dai, 1); | 491 | &omap_dmic_component, |
492 | &omap_dmic_dai, 1); | ||
495 | if (ret) | 493 | if (ret) |
496 | goto err_put_clk; | 494 | return ret; |
497 | 495 | ||
498 | ret = omap_pcm_platform_register(&pdev->dev); | 496 | ret = omap_pcm_platform_register(&pdev->dev); |
499 | if (ret) | 497 | if (ret) |
500 | goto err_put_clk; | 498 | return ret; |
501 | |||
502 | return 0; | ||
503 | |||
504 | err_put_clk: | ||
505 | clk_put(dmic->fclk); | ||
506 | return ret; | ||
507 | } | ||
508 | |||
509 | static int asoc_dmic_remove(struct platform_device *pdev) | ||
510 | { | ||
511 | struct omap_dmic *dmic = platform_get_drvdata(pdev); | ||
512 | |||
513 | snd_soc_unregister_component(&pdev->dev); | ||
514 | clk_put(dmic->fclk); | ||
515 | 499 | ||
516 | return 0; | 500 | return 0; |
517 | } | 501 | } |
@@ -529,7 +513,6 @@ static struct platform_driver asoc_dmic_driver = { | |||
529 | .of_match_table = omap_dmic_of_match, | 513 | .of_match_table = omap_dmic_of_match, |
530 | }, | 514 | }, |
531 | .probe = asoc_dmic_probe, | 515 | .probe = asoc_dmic_probe, |
532 | .remove = asoc_dmic_remove, | ||
533 | }; | 516 | }; |
534 | 517 | ||
535 | module_platform_driver(asoc_dmic_driver); | 518 | module_platform_driver(asoc_dmic_driver); |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index efe2cd699b77..bd3ef2a88be0 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -805,8 +805,9 @@ static int asoc_mcbsp_probe(struct platform_device *pdev) | |||
805 | if (ret) | 805 | if (ret) |
806 | return ret; | 806 | return ret; |
807 | 807 | ||
808 | ret = snd_soc_register_component(&pdev->dev, &omap_mcbsp_component, | 808 | ret = devm_snd_soc_register_component(&pdev->dev, |
809 | &omap_mcbsp_dai, 1); | 809 | &omap_mcbsp_component, |
810 | &omap_mcbsp_dai, 1); | ||
810 | if (ret) | 811 | if (ret) |
811 | return ret; | 812 | return ret; |
812 | 813 | ||
@@ -817,8 +818,6 @@ static int asoc_mcbsp_remove(struct platform_device *pdev) | |||
817 | { | 818 | { |
818 | struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); | 819 | struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); |
819 | 820 | ||
820 | snd_soc_unregister_component(&pdev->dev); | ||
821 | |||
822 | if (mcbsp->pdata->ops && mcbsp->pdata->ops->free) | 821 | if (mcbsp->pdata->ops && mcbsp->pdata->ops->free) |
823 | mcbsp->pdata->ops->free(mcbsp->id); | 822 | mcbsp->pdata->ops->free(mcbsp->id); |
824 | 823 | ||
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 8d809f8509c8..f4b05bc23e4b 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <sound/pcm_params.h> | 31 | #include <sound/pcm_params.h> |
32 | #include <sound/dmaengine_pcm.h> | 32 | #include <sound/dmaengine_pcm.h> |
33 | #include <sound/soc.h> | 33 | #include <sound/soc.h> |
34 | #include <sound/omap-pcm.h> | ||
34 | 35 | ||
35 | #ifdef CONFIG_ARCH_OMAP1 | 36 | #ifdef CONFIG_ARCH_OMAP1 |
36 | #define pcm_omap1510() cpu_is_omap1510() | 37 | #define pcm_omap1510() cpu_is_omap1510() |
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 6acb225ec6fd..2434b6d61675 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -11,6 +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 MMP_SRAM | ||
14 | select SND_SOC_GENERIC_DMAENGINE_PCM | 15 | select SND_SOC_GENERIC_DMAENGINE_PCM |
15 | select SND_ARM | 16 | select SND_ARM |
16 | help | 17 | help |
@@ -40,7 +41,7 @@ config SND_MMP_SOC_SSPA | |||
40 | 41 | ||
41 | config SND_PXA2XX_SOC_CORGI | 42 | config SND_PXA2XX_SOC_CORGI |
42 | tristate "SoC Audio support for Sharp Zaurus SL-C7x0" | 43 | tristate "SoC Audio support for Sharp Zaurus SL-C7x0" |
43 | depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx | 44 | depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx && I2C |
44 | select SND_PXA2XX_SOC_I2S | 45 | select SND_PXA2XX_SOC_I2S |
45 | select SND_SOC_WM8731 | 46 | select SND_SOC_WM8731 |
46 | help | 47 | help |
@@ -49,7 +50,7 @@ config SND_PXA2XX_SOC_CORGI | |||
49 | 50 | ||
50 | config SND_PXA2XX_SOC_SPITZ | 51 | config SND_PXA2XX_SOC_SPITZ |
51 | tristate "SoC Audio support for Sharp Zaurus SL-Cxx00" | 52 | tristate "SoC Audio support for Sharp Zaurus SL-Cxx00" |
52 | depends on SND_PXA2XX_SOC && PXA_SHARP_Cxx00 | 53 | depends on SND_PXA2XX_SOC && PXA_SHARP_Cxx00 && I2C |
53 | select SND_PXA2XX_SOC_I2S | 54 | select SND_PXA2XX_SOC_I2S |
54 | select SND_SOC_WM8750 | 55 | select SND_SOC_WM8750 |
55 | help | 56 | help |
@@ -58,7 +59,7 @@ config SND_PXA2XX_SOC_SPITZ | |||
58 | 59 | ||
59 | config SND_PXA2XX_SOC_Z2 | 60 | config SND_PXA2XX_SOC_Z2 |
60 | tristate "SoC Audio support for Zipit Z2" | 61 | tristate "SoC Audio support for Zipit Z2" |
61 | depends on SND_PXA2XX_SOC && MACH_ZIPIT2 | 62 | depends on SND_PXA2XX_SOC && MACH_ZIPIT2 && I2C |
62 | select SND_PXA2XX_SOC_I2S | 63 | select SND_PXA2XX_SOC_I2S |
63 | select SND_SOC_WM8750 | 64 | select SND_SOC_WM8750 |
64 | help | 65 | help |
@@ -66,7 +67,7 @@ config SND_PXA2XX_SOC_Z2 | |||
66 | 67 | ||
67 | config SND_PXA2XX_SOC_POODLE | 68 | config SND_PXA2XX_SOC_POODLE |
68 | tristate "SoC Audio support for Poodle" | 69 | tristate "SoC Audio support for Poodle" |
69 | depends on SND_PXA2XX_SOC && MACH_POODLE | 70 | depends on SND_PXA2XX_SOC && MACH_POODLE && I2C |
70 | select SND_PXA2XX_SOC_I2S | 71 | select SND_PXA2XX_SOC_I2S |
71 | select SND_SOC_WM8731 | 72 | select SND_SOC_WM8731 |
72 | help | 73 | help |
@@ -181,7 +182,7 @@ config SND_PXA2XX_SOC_HX4700 | |||
181 | 182 | ||
182 | config SND_PXA2XX_SOC_MAGICIAN | 183 | config SND_PXA2XX_SOC_MAGICIAN |
183 | tristate "SoC Audio support for HTC Magician" | 184 | tristate "SoC Audio support for HTC Magician" |
184 | depends on SND_PXA2XX_SOC && MACH_MAGICIAN | 185 | depends on SND_PXA2XX_SOC && MACH_MAGICIAN && I2C |
185 | select SND_PXA2XX_SOC_I2S | 186 | select SND_PXA2XX_SOC_I2S |
186 | select SND_PXA_SOC_SSP | 187 | select SND_PXA_SOC_SSP |
187 | select SND_SOC_UDA1380 | 188 | select SND_SOC_UDA1380 |
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 199a8b377553..0109f6c2334e 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c | |||
@@ -723,7 +723,8 @@ static int pxa_ssp_probe(struct snd_soc_dai *dai) | |||
723 | ssp_handle = of_parse_phandle(dev->of_node, "port", 0); | 723 | ssp_handle = of_parse_phandle(dev->of_node, "port", 0); |
724 | if (!ssp_handle) { | 724 | if (!ssp_handle) { |
725 | dev_err(dev, "unable to get 'port' phandle\n"); | 725 | dev_err(dev, "unable to get 'port' phandle\n"); |
726 | return -ENODEV; | 726 | ret = -ENODEV; |
727 | goto err_priv; | ||
727 | } | 728 | } |
728 | 729 | ||
729 | priv->ssp = pxa_ssp_request_of(ssp_handle, "SoC audio"); | 730 | priv->ssp = pxa_ssp_request_of(ssp_handle, "SoC audio"); |
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig new file mode 100644 index 000000000000..c196a466eef6 --- /dev/null +++ b/sound/soc/rockchip/Kconfig | |||
@@ -0,0 +1,12 @@ | |||
1 | config SND_SOC_ROCKCHIP | ||
2 | tristate "ASoC support for Rockchip" | ||
3 | depends on COMPILE_TEST || ARCH_ROCKCHIP | ||
4 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
5 | select SND_ROCKCHIP_I2S | ||
6 | help | ||
7 | Say Y or M if you want to add support for codecs attached to | ||
8 | the Rockchip SoCs' Audio interfaces. You will also need to | ||
9 | select the audio interfaces to support below. | ||
10 | |||
11 | config SND_ROCKCHIP_I2S | ||
12 | tristate | ||
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile new file mode 100644 index 000000000000..1006418e1394 --- /dev/null +++ b/sound/soc/rockchip/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # ROCKCHIP Platform Support | ||
2 | snd-soc-i2s-objs := rockchip_i2s.o | ||
3 | |||
4 | obj-$(CONFIG_SND_ROCKCHIP_I2S) += snd-soc-i2s.o | ||
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c new file mode 100644 index 000000000000..8d8e4b59049f --- /dev/null +++ b/sound/soc/rockchip/rockchip_i2s.c | |||
@@ -0,0 +1,529 @@ | |||
1 | /* sound/soc/rockchip/rockchip_i2s.c | ||
2 | * | ||
3 | * ALSA SoC Audio Layer - Rockchip I2S Controller driver | ||
4 | * | ||
5 | * Copyright (c) 2014 Rockchip Electronics Co. Ltd. | ||
6 | * Author: Jianqun <jay.xu@rock-chips.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/of_gpio.h> | ||
16 | #include <linux/clk.h> | ||
17 | #include <linux/pm_runtime.h> | ||
18 | #include <linux/regmap.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/dmaengine_pcm.h> | ||
21 | |||
22 | #include "rockchip_i2s.h" | ||
23 | |||
24 | #define DRV_NAME "rockchip-i2s" | ||
25 | |||
26 | struct rk_i2s_dev { | ||
27 | struct device *dev; | ||
28 | |||
29 | struct clk *hclk; | ||
30 | struct clk *mclk; | ||
31 | |||
32 | struct snd_dmaengine_dai_dma_data capture_dma_data; | ||
33 | struct snd_dmaengine_dai_dma_data playback_dma_data; | ||
34 | |||
35 | struct regmap *regmap; | ||
36 | |||
37 | /* | ||
38 | * Used to indicate the tx/rx status. | ||
39 | * I2S controller hopes to start the tx and rx together, | ||
40 | * also to stop them when they are both try to stop. | ||
41 | */ | ||
42 | bool tx_start; | ||
43 | bool rx_start; | ||
44 | }; | ||
45 | |||
46 | static int i2s_runtime_suspend(struct device *dev) | ||
47 | { | ||
48 | struct rk_i2s_dev *i2s = dev_get_drvdata(dev); | ||
49 | |||
50 | clk_disable_unprepare(i2s->mclk); | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int i2s_runtime_resume(struct device *dev) | ||
56 | { | ||
57 | struct rk_i2s_dev *i2s = dev_get_drvdata(dev); | ||
58 | int ret; | ||
59 | |||
60 | ret = clk_prepare_enable(i2s->mclk); | ||
61 | if (ret) { | ||
62 | dev_err(i2s->dev, "clock enable failed %d\n", ret); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai) | ||
70 | { | ||
71 | return snd_soc_dai_get_drvdata(dai); | ||
72 | } | ||
73 | |||
74 | static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) | ||
75 | { | ||
76 | unsigned int val = 0; | ||
77 | int retry = 10; | ||
78 | |||
79 | if (on) { | ||
80 | regmap_update_bits(i2s->regmap, I2S_DMACR, | ||
81 | I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); | ||
82 | |||
83 | regmap_update_bits(i2s->regmap, I2S_XFER, | ||
84 | I2S_XFER_TXS_START | I2S_XFER_RXS_START, | ||
85 | I2S_XFER_TXS_START | I2S_XFER_RXS_START); | ||
86 | |||
87 | i2s->tx_start = true; | ||
88 | } else { | ||
89 | i2s->tx_start = false; | ||
90 | |||
91 | regmap_update_bits(i2s->regmap, I2S_DMACR, | ||
92 | I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE); | ||
93 | |||
94 | if (!i2s->rx_start) { | ||
95 | regmap_update_bits(i2s->regmap, I2S_XFER, | ||
96 | I2S_XFER_TXS_START | | ||
97 | I2S_XFER_RXS_START, | ||
98 | I2S_XFER_TXS_STOP | | ||
99 | I2S_XFER_RXS_STOP); | ||
100 | |||
101 | regmap_update_bits(i2s->regmap, I2S_CLR, | ||
102 | I2S_CLR_TXC | I2S_CLR_RXC, | ||
103 | I2S_CLR_TXC | I2S_CLR_RXC); | ||
104 | |||
105 | regmap_read(i2s->regmap, I2S_CLR, &val); | ||
106 | |||
107 | /* Should wait for clear operation to finish */ | ||
108 | while (val) { | ||
109 | regmap_read(i2s->regmap, I2S_CLR, &val); | ||
110 | retry--; | ||
111 | if (!retry) | ||
112 | dev_warn(i2s->dev, "fail to clear\n"); | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) | ||
119 | { | ||
120 | unsigned int val = 0; | ||
121 | int retry = 10; | ||
122 | |||
123 | if (on) { | ||
124 | regmap_update_bits(i2s->regmap, I2S_DMACR, | ||
125 | I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE); | ||
126 | |||
127 | regmap_update_bits(i2s->regmap, I2S_XFER, | ||
128 | I2S_XFER_TXS_START | I2S_XFER_RXS_START, | ||
129 | I2S_XFER_TXS_START | I2S_XFER_RXS_START); | ||
130 | |||
131 | i2s->rx_start = true; | ||
132 | } else { | ||
133 | i2s->rx_start = false; | ||
134 | |||
135 | regmap_update_bits(i2s->regmap, I2S_DMACR, | ||
136 | I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE); | ||
137 | |||
138 | if (!i2s->tx_start) { | ||
139 | regmap_update_bits(i2s->regmap, I2S_XFER, | ||
140 | I2S_XFER_TXS_START | | ||
141 | I2S_XFER_RXS_START, | ||
142 | I2S_XFER_TXS_STOP | | ||
143 | I2S_XFER_RXS_STOP); | ||
144 | |||
145 | regmap_update_bits(i2s->regmap, I2S_CLR, | ||
146 | I2S_CLR_TXC | I2S_CLR_RXC, | ||
147 | I2S_CLR_TXC | I2S_CLR_RXC); | ||
148 | |||
149 | regmap_read(i2s->regmap, I2S_CLR, &val); | ||
150 | |||
151 | /* Should wait for clear operation to finish */ | ||
152 | while (val) { | ||
153 | regmap_read(i2s->regmap, I2S_CLR, &val); | ||
154 | retry--; | ||
155 | if (!retry) | ||
156 | dev_warn(i2s->dev, "fail to clear\n"); | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | ||
163 | unsigned int fmt) | ||
164 | { | ||
165 | struct rk_i2s_dev *i2s = to_info(cpu_dai); | ||
166 | unsigned int mask = 0, val = 0; | ||
167 | |||
168 | mask = I2S_CKR_MSS_SLAVE; | ||
169 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
170 | case SND_SOC_DAIFMT_CBS_CFS: | ||
171 | val = I2S_CKR_MSS_SLAVE; | ||
172 | break; | ||
173 | case SND_SOC_DAIFMT_CBM_CFM: | ||
174 | val = I2S_CKR_MSS_MASTER; | ||
175 | break; | ||
176 | default: | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | regmap_update_bits(i2s->regmap, I2S_CKR, mask, val); | ||
181 | |||
182 | mask = I2S_TXCR_IBM_MASK; | ||
183 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
184 | case SND_SOC_DAIFMT_RIGHT_J: | ||
185 | val = I2S_TXCR_IBM_RSJM; | ||
186 | break; | ||
187 | case SND_SOC_DAIFMT_LEFT_J: | ||
188 | val = I2S_TXCR_IBM_LSJM; | ||
189 | break; | ||
190 | case SND_SOC_DAIFMT_I2S: | ||
191 | val = I2S_TXCR_IBM_NORMAL; | ||
192 | break; | ||
193 | default: | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val); | ||
198 | |||
199 | mask = I2S_RXCR_IBM_MASK; | ||
200 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
201 | case SND_SOC_DAIFMT_RIGHT_J: | ||
202 | val = I2S_RXCR_IBM_RSJM; | ||
203 | break; | ||
204 | case SND_SOC_DAIFMT_LEFT_J: | ||
205 | val = I2S_RXCR_IBM_LSJM; | ||
206 | break; | ||
207 | case SND_SOC_DAIFMT_I2S: | ||
208 | val = I2S_RXCR_IBM_NORMAL; | ||
209 | break; | ||
210 | default: | ||
211 | return -EINVAL; | ||
212 | } | ||
213 | |||
214 | regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, | ||
220 | struct snd_pcm_hw_params *params, | ||
221 | struct snd_soc_dai *dai) | ||
222 | { | ||
223 | struct rk_i2s_dev *i2s = to_info(dai); | ||
224 | unsigned int val = 0; | ||
225 | |||
226 | switch (params_format(params)) { | ||
227 | case SNDRV_PCM_FORMAT_S8: | ||
228 | val |= I2S_TXCR_VDW(8); | ||
229 | break; | ||
230 | case SNDRV_PCM_FORMAT_S16_LE: | ||
231 | val |= I2S_TXCR_VDW(16); | ||
232 | break; | ||
233 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
234 | val |= I2S_TXCR_VDW(20); | ||
235 | break; | ||
236 | case SNDRV_PCM_FORMAT_S24_LE: | ||
237 | val |= I2S_TXCR_VDW(24); | ||
238 | break; | ||
239 | default: | ||
240 | return -EINVAL; | ||
241 | } | ||
242 | |||
243 | regmap_update_bits(i2s->regmap, I2S_TXCR, I2S_TXCR_VDW_MASK, val); | ||
244 | regmap_update_bits(i2s->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK, val); | ||
245 | |||
246 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
247 | dai->playback_dma_data = &i2s->playback_dma_data; | ||
248 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK, | ||
249 | I2S_DMACR_TDL(1) | I2S_DMACR_TDE_ENABLE); | ||
250 | } else { | ||
251 | dai->capture_dma_data = &i2s->capture_dma_data; | ||
252 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, | ||
253 | I2S_DMACR_RDL(1) | I2S_DMACR_RDE_ENABLE); | ||
254 | } | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, | ||
260 | int cmd, struct snd_soc_dai *dai) | ||
261 | { | ||
262 | struct rk_i2s_dev *i2s = to_info(dai); | ||
263 | int ret = 0; | ||
264 | |||
265 | switch (cmd) { | ||
266 | case SNDRV_PCM_TRIGGER_START: | ||
267 | case SNDRV_PCM_TRIGGER_RESUME: | ||
268 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
269 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
270 | rockchip_snd_rxctrl(i2s, 1); | ||
271 | else | ||
272 | rockchip_snd_txctrl(i2s, 1); | ||
273 | break; | ||
274 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
275 | case SNDRV_PCM_TRIGGER_STOP: | ||
276 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
277 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
278 | rockchip_snd_rxctrl(i2s, 0); | ||
279 | else | ||
280 | rockchip_snd_txctrl(i2s, 0); | ||
281 | break; | ||
282 | default: | ||
283 | ret = -EINVAL; | ||
284 | break; | ||
285 | } | ||
286 | |||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, | ||
291 | unsigned int freq, int dir) | ||
292 | { | ||
293 | struct rk_i2s_dev *i2s = to_info(cpu_dai); | ||
294 | int ret; | ||
295 | |||
296 | ret = clk_set_rate(i2s->mclk, freq); | ||
297 | if (ret) | ||
298 | dev_err(i2s->dev, "Fail to set mclk %d\n", ret); | ||
299 | |||
300 | return ret; | ||
301 | } | ||
302 | |||
303 | static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { | ||
304 | .hw_params = rockchip_i2s_hw_params, | ||
305 | .set_sysclk = rockchip_i2s_set_sysclk, | ||
306 | .set_fmt = rockchip_i2s_set_fmt, | ||
307 | .trigger = rockchip_i2s_trigger, | ||
308 | }; | ||
309 | |||
310 | static struct snd_soc_dai_driver rockchip_i2s_dai = { | ||
311 | .playback = { | ||
312 | .channels_min = 2, | ||
313 | .channels_max = 8, | ||
314 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
315 | .formats = (SNDRV_PCM_FMTBIT_S8 | | ||
316 | SNDRV_PCM_FMTBIT_S16_LE | | ||
317 | SNDRV_PCM_FMTBIT_S20_3LE | | ||
318 | SNDRV_PCM_FMTBIT_S24_LE), | ||
319 | }, | ||
320 | .capture = { | ||
321 | .channels_min = 2, | ||
322 | .channels_max = 2, | ||
323 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
324 | .formats = (SNDRV_PCM_FMTBIT_S8 | | ||
325 | SNDRV_PCM_FMTBIT_S16_LE | | ||
326 | SNDRV_PCM_FMTBIT_S20_3LE | | ||
327 | SNDRV_PCM_FMTBIT_S24_LE), | ||
328 | }, | ||
329 | .ops = &rockchip_i2s_dai_ops, | ||
330 | }; | ||
331 | |||
332 | static const struct snd_soc_component_driver rockchip_i2s_component = { | ||
333 | .name = DRV_NAME, | ||
334 | }; | ||
335 | |||
336 | static bool rockchip_i2s_wr_reg(struct device *dev, unsigned int reg) | ||
337 | { | ||
338 | switch (reg) { | ||
339 | case I2S_TXCR: | ||
340 | case I2S_RXCR: | ||
341 | case I2S_CKR: | ||
342 | case I2S_DMACR: | ||
343 | case I2S_INTCR: | ||
344 | case I2S_XFER: | ||
345 | case I2S_CLR: | ||
346 | case I2S_TXDR: | ||
347 | return true; | ||
348 | default: | ||
349 | return false; | ||
350 | } | ||
351 | } | ||
352 | |||
353 | static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg) | ||
354 | { | ||
355 | switch (reg) { | ||
356 | case I2S_TXCR: | ||
357 | case I2S_RXCR: | ||
358 | case I2S_CKR: | ||
359 | case I2S_DMACR: | ||
360 | case I2S_INTCR: | ||
361 | case I2S_XFER: | ||
362 | case I2S_CLR: | ||
363 | case I2S_RXDR: | ||
364 | return true; | ||
365 | default: | ||
366 | return false; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg) | ||
371 | { | ||
372 | switch (reg) { | ||
373 | case I2S_FIFOLR: | ||
374 | case I2S_INTSR: | ||
375 | return true; | ||
376 | default: | ||
377 | return false; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg) | ||
382 | { | ||
383 | switch (reg) { | ||
384 | case I2S_FIFOLR: | ||
385 | return true; | ||
386 | default: | ||
387 | return false; | ||
388 | } | ||
389 | } | ||
390 | |||
391 | static const struct regmap_config rockchip_i2s_regmap_config = { | ||
392 | .reg_bits = 32, | ||
393 | .reg_stride = 4, | ||
394 | .val_bits = 32, | ||
395 | .max_register = I2S_RXDR, | ||
396 | .writeable_reg = rockchip_i2s_wr_reg, | ||
397 | .readable_reg = rockchip_i2s_rd_reg, | ||
398 | .volatile_reg = rockchip_i2s_volatile_reg, | ||
399 | .precious_reg = rockchip_i2s_precious_reg, | ||
400 | .cache_type = REGCACHE_FLAT, | ||
401 | }; | ||
402 | |||
403 | static int rockchip_i2s_probe(struct platform_device *pdev) | ||
404 | { | ||
405 | struct rk_i2s_dev *i2s; | ||
406 | struct resource *res; | ||
407 | void __iomem *regs; | ||
408 | int ret; | ||
409 | |||
410 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); | ||
411 | if (!i2s) { | ||
412 | dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n"); | ||
413 | return -ENOMEM; | ||
414 | } | ||
415 | |||
416 | /* try to prepare related clocks */ | ||
417 | i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk"); | ||
418 | if (IS_ERR(i2s->hclk)) { | ||
419 | dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n"); | ||
420 | return PTR_ERR(i2s->hclk); | ||
421 | } | ||
422 | |||
423 | i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk"); | ||
424 | if (IS_ERR(i2s->mclk)) { | ||
425 | dev_err(&pdev->dev, "Can't retrieve i2s master clock\n"); | ||
426 | return PTR_ERR(i2s->mclk); | ||
427 | } | ||
428 | |||
429 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
430 | regs = devm_ioremap_resource(&pdev->dev, res); | ||
431 | if (IS_ERR(regs)) | ||
432 | return PTR_ERR(regs); | ||
433 | |||
434 | i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, | ||
435 | &rockchip_i2s_regmap_config); | ||
436 | if (IS_ERR(i2s->regmap)) { | ||
437 | dev_err(&pdev->dev, | ||
438 | "Failed to initialise managed register map\n"); | ||
439 | return PTR_ERR(i2s->regmap); | ||
440 | } | ||
441 | |||
442 | i2s->playback_dma_data.addr = res->start + I2S_TXDR; | ||
443 | i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
444 | i2s->playback_dma_data.maxburst = 16; | ||
445 | |||
446 | i2s->capture_dma_data.addr = res->start + I2S_RXDR; | ||
447 | i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
448 | i2s->capture_dma_data.maxburst = 16; | ||
449 | |||
450 | i2s->dev = &pdev->dev; | ||
451 | dev_set_drvdata(&pdev->dev, i2s); | ||
452 | |||
453 | pm_runtime_enable(&pdev->dev); | ||
454 | if (!pm_runtime_enabled(&pdev->dev)) { | ||
455 | ret = i2s_runtime_resume(&pdev->dev); | ||
456 | if (ret) | ||
457 | goto err_pm_disable; | ||
458 | } | ||
459 | |||
460 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
461 | &rockchip_i2s_component, | ||
462 | &rockchip_i2s_dai, 1); | ||
463 | if (ret) { | ||
464 | dev_err(&pdev->dev, "Could not register DAI\n"); | ||
465 | goto err_suspend; | ||
466 | } | ||
467 | |||
468 | ret = snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | ||
469 | if (ret) { | ||
470 | dev_err(&pdev->dev, "Could not register PCM\n"); | ||
471 | goto err_pcm_register; | ||
472 | } | ||
473 | |||
474 | return 0; | ||
475 | |||
476 | err_pcm_register: | ||
477 | snd_dmaengine_pcm_unregister(&pdev->dev); | ||
478 | err_suspend: | ||
479 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
480 | i2s_runtime_suspend(&pdev->dev); | ||
481 | err_pm_disable: | ||
482 | pm_runtime_disable(&pdev->dev); | ||
483 | |||
484 | return ret; | ||
485 | } | ||
486 | |||
487 | static int rockchip_i2s_remove(struct platform_device *pdev) | ||
488 | { | ||
489 | struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev); | ||
490 | |||
491 | pm_runtime_disable(&pdev->dev); | ||
492 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
493 | i2s_runtime_suspend(&pdev->dev); | ||
494 | |||
495 | clk_disable_unprepare(i2s->mclk); | ||
496 | clk_disable_unprepare(i2s->hclk); | ||
497 | snd_dmaengine_pcm_unregister(&pdev->dev); | ||
498 | snd_soc_unregister_component(&pdev->dev); | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static const struct of_device_id rockchip_i2s_match[] = { | ||
504 | { .compatible = "rockchip,rk3066-i2s", }, | ||
505 | {}, | ||
506 | }; | ||
507 | |||
508 | static const struct dev_pm_ops rockchip_i2s_pm_ops = { | ||
509 | SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume, | ||
510 | NULL) | ||
511 | }; | ||
512 | |||
513 | static struct platform_driver rockchip_i2s_driver = { | ||
514 | .probe = rockchip_i2s_probe, | ||
515 | .remove = rockchip_i2s_remove, | ||
516 | .driver = { | ||
517 | .name = DRV_NAME, | ||
518 | .owner = THIS_MODULE, | ||
519 | .of_match_table = of_match_ptr(rockchip_i2s_match), | ||
520 | .pm = &rockchip_i2s_pm_ops, | ||
521 | }, | ||
522 | }; | ||
523 | module_platform_driver(rockchip_i2s_driver); | ||
524 | |||
525 | MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface"); | ||
526 | MODULE_AUTHOR("jianqun <jay.xu@rock-chips.com>"); | ||
527 | MODULE_LICENSE("GPL v2"); | ||
528 | MODULE_ALIAS("platform:" DRV_NAME); | ||
529 | MODULE_DEVICE_TABLE(of, rockchip_i2s_match); | ||
diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h new file mode 100644 index 000000000000..89a5d8bc6ee7 --- /dev/null +++ b/sound/soc/rockchip/rockchip_i2s.h | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * sound/soc/rockchip/rockchip_i2s.h | ||
3 | * | ||
4 | * ALSA SoC Audio Layer - Rockchip I2S Controller driver | ||
5 | * | ||
6 | * Copyright (c) 2014 Rockchip Electronics Co. Ltd. | ||
7 | * Author: Jianqun xu <jay.xu@rock-chips.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #ifndef _ROCKCHIP_IIS_H | ||
15 | #define _ROCKCHIP_IIS_H | ||
16 | |||
17 | /* | ||
18 | * TXCR | ||
19 | * transmit operation control register | ||
20 | */ | ||
21 | #define I2S_TXCR_RCNT_SHIFT 17 | ||
22 | #define I2S_TXCR_RCNT_MASK (0x3f << I2S_TXCR_RCNT_SHIFT) | ||
23 | #define I2S_TXCR_CSR_SHIFT 15 | ||
24 | #define I2S_TXCR_CSR(x) (x << I2S_TXCR_CSR_SHIFT) | ||
25 | #define I2S_TXCR_CSR_MASK (3 << I2S_TXCR_CSR_SHIFT) | ||
26 | #define I2S_TXCR_HWT BIT(14) | ||
27 | #define I2S_TXCR_SJM_SHIFT 12 | ||
28 | #define I2S_TXCR_SJM_R (0 << I2S_TXCR_SJM_SHIFT) | ||
29 | #define I2S_TXCR_SJM_L (1 << I2S_TXCR_SJM_SHIFT) | ||
30 | #define I2S_TXCR_FBM_SHIFT 11 | ||
31 | #define I2S_TXCR_FBM_MSB (0 << I2S_TXCR_FBM_SHIFT) | ||
32 | #define I2S_TXCR_FBM_LSB (1 << I2S_TXCR_FBM_SHIFT) | ||
33 | #define I2S_TXCR_IBM_SHIFT 9 | ||
34 | #define I2S_TXCR_IBM_NORMAL (0 << I2S_TXCR_IBM_SHIFT) | ||
35 | #define I2S_TXCR_IBM_LSJM (1 << I2S_TXCR_IBM_SHIFT) | ||
36 | #define I2S_TXCR_IBM_RSJM (2 << I2S_TXCR_IBM_SHIFT) | ||
37 | #define I2S_TXCR_IBM_MASK (3 << I2S_TXCR_IBM_SHIFT) | ||
38 | #define I2S_TXCR_PBM_SHIFT 7 | ||
39 | #define I2S_TXCR_PBM_MODE(x) (x << I2S_TXCR_PBM_SHIFT) | ||
40 | #define I2S_TXCR_PBM_MASK (3 << I2S_TXCR_PBM_SHIFT) | ||
41 | #define I2S_TXCR_TFS_SHIFT 5 | ||
42 | #define I2S_TXCR_TFS_I2S (0 << I2S_TXCR_TFS_SHIFT) | ||
43 | #define I2S_TXCR_TFS_PCM (1 << I2S_TXCR_TFS_SHIFT) | ||
44 | #define I2S_TXCR_VDW_SHIFT 0 | ||
45 | #define I2S_TXCR_VDW(x) ((x - 1) << I2S_TXCR_VDW_SHIFT) | ||
46 | #define I2S_TXCR_VDW_MASK (0x1f << I2S_TXCR_VDW_SHIFT) | ||
47 | |||
48 | /* | ||
49 | * RXCR | ||
50 | * receive operation control register | ||
51 | */ | ||
52 | #define I2S_RXCR_HWT BIT(14) | ||
53 | #define I2S_RXCR_SJM_SHIFT 12 | ||
54 | #define I2S_RXCR_SJM_R (0 << I2S_RXCR_SJM_SHIFT) | ||
55 | #define I2S_RXCR_SJM_L (1 << I2S_RXCR_SJM_SHIFT) | ||
56 | #define I2S_RXCR_FBM_SHIFT 11 | ||
57 | #define I2S_RXCR_FBM_MSB (0 << I2S_RXCR_FBM_SHIFT) | ||
58 | #define I2S_RXCR_FBM_LSB (1 << I2S_RXCR_FBM_SHIFT) | ||
59 | #define I2S_RXCR_IBM_SHIFT 9 | ||
60 | #define I2S_RXCR_IBM_NORMAL (0 << I2S_RXCR_IBM_SHIFT) | ||
61 | #define I2S_RXCR_IBM_LSJM (1 << I2S_RXCR_IBM_SHIFT) | ||
62 | #define I2S_RXCR_IBM_RSJM (2 << I2S_RXCR_IBM_SHIFT) | ||
63 | #define I2S_RXCR_IBM_MASK (3 << I2S_RXCR_IBM_SHIFT) | ||
64 | #define I2S_RXCR_PBM_SHIFT 7 | ||
65 | #define I2S_RXCR_PBM_MODE(x) (x << I2S_RXCR_PBM_SHIFT) | ||
66 | #define I2S_RXCR_PBM_MASK (3 << I2S_RXCR_PBM_SHIFT) | ||
67 | #define I2S_RXCR_TFS_SHIFT 5 | ||
68 | #define I2S_RXCR_TFS_I2S (0 << I2S_RXCR_TFS_SHIFT) | ||
69 | #define I2S_RXCR_TFS_PCM (1 << I2S_RXCR_TFS_SHIFT) | ||
70 | #define I2S_RXCR_VDW_SHIFT 0 | ||
71 | #define I2S_RXCR_VDW(x) ((x - 1) << I2S_RXCR_VDW_SHIFT) | ||
72 | #define I2S_RXCR_VDW_MASK (0x1f << I2S_RXCR_VDW_SHIFT) | ||
73 | |||
74 | /* | ||
75 | * CKR | ||
76 | * clock generation register | ||
77 | */ | ||
78 | #define I2S_CKR_MSS_SHIFT 27 | ||
79 | #define I2S_CKR_MSS_MASTER (0 << I2S_CKR_MSS_SHIFT) | ||
80 | #define I2S_CKR_MSS_SLAVE (1 << I2S_CKR_MSS_SHIFT) | ||
81 | #define I2S_CKR_MSS_MASK (1 << I2S_CKR_MSS_SHIFT) | ||
82 | #define I2S_CKR_CKP_SHIFT 26 | ||
83 | #define I2S_CKR_CKP_NEG (0 << I2S_CKR_CKP_SHIFT) | ||
84 | #define I2S_CKR_CKP_POS (1 << I2S_CKR_CKP_SHIFT) | ||
85 | #define I2S_CKR_RLP_SHIFT 25 | ||
86 | #define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT) | ||
87 | #define I2S_CKR_RLP_OPPSITE (1 << I2S_CKR_RLP_SHIFT) | ||
88 | #define I2S_CKR_TLP_SHIFT 24 | ||
89 | #define I2S_CKR_TLP_NORMAL (0 << I2S_CKR_TLP_SHIFT) | ||
90 | #define I2S_CKR_TLP_OPPSITE (1 << I2S_CKR_TLP_SHIFT) | ||
91 | #define I2S_CKR_MDIV_SHIFT 16 | ||
92 | #define I2S_CKR_MDIV(x) ((x - 1) << I2S_CKR_MDIV_SHIFT) | ||
93 | #define I2S_CKR_MDIV_MASK (0xff << I2S_CKR_MDIV_SHIFT) | ||
94 | #define I2S_CKR_RSD_SHIFT 8 | ||
95 | #define I2S_CKR_RSD(x) ((x - 1) << I2S_CKR_RSD_SHIFT) | ||
96 | #define I2S_CKR_RSD_MASK (0xff << I2S_CKR_RSD_SHIFT) | ||
97 | #define I2S_CKR_TSD_SHIFT 0 | ||
98 | #define I2S_CKR_TSD(x) ((x - 1) << I2S_CKR_TSD_SHIFT) | ||
99 | #define I2S_CKR_TSD_MASK (0xff << I2S_CKR_TSD_SHIFT) | ||
100 | |||
101 | /* | ||
102 | * FIFOLR | ||
103 | * FIFO level register | ||
104 | */ | ||
105 | #define I2S_FIFOLR_RFL_SHIFT 24 | ||
106 | #define I2S_FIFOLR_RFL_MASK (0x3f << I2S_FIFOLR_RFL_SHIFT) | ||
107 | #define I2S_FIFOLR_TFL3_SHIFT 18 | ||
108 | #define I2S_FIFOLR_TFL3_MASK (0x3f << I2S_FIFOLR_TFL3_SHIFT) | ||
109 | #define I2S_FIFOLR_TFL2_SHIFT 12 | ||
110 | #define I2S_FIFOLR_TFL2_MASK (0x3f << I2S_FIFOLR_TFL2_SHIFT) | ||
111 | #define I2S_FIFOLR_TFL1_SHIFT 6 | ||
112 | #define I2S_FIFOLR_TFL1_MASK (0x3f << I2S_FIFOLR_TFL1_SHIFT) | ||
113 | #define I2S_FIFOLR_TFL0_SHIFT 0 | ||
114 | #define I2S_FIFOLR_TFL0_MASK (0x3f << I2S_FIFOLR_TFL0_SHIFT) | ||
115 | |||
116 | /* | ||
117 | * DMACR | ||
118 | * DMA control register | ||
119 | */ | ||
120 | #define I2S_DMACR_RDE_SHIFT 24 | ||
121 | #define I2S_DMACR_RDE_DISABLE (0 << I2S_DMACR_RDE_SHIFT) | ||
122 | #define I2S_DMACR_RDE_ENABLE (1 << I2S_DMACR_RDE_SHIFT) | ||
123 | #define I2S_DMACR_RDL_SHIFT 16 | ||
124 | #define I2S_DMACR_RDL(x) ((x - 1) << I2S_DMACR_RDL_SHIFT) | ||
125 | #define I2S_DMACR_RDL_MASK (0x1f << I2S_DMACR_RDL_SHIFT) | ||
126 | #define I2S_DMACR_TDE_SHIFT 8 | ||
127 | #define I2S_DMACR_TDE_DISABLE (0 << I2S_DMACR_TDE_SHIFT) | ||
128 | #define I2S_DMACR_TDE_ENABLE (1 << I2S_DMACR_TDE_SHIFT) | ||
129 | #define I2S_DMACR_TDL_SHIFT 0 | ||
130 | #define I2S_DMACR_TDL(x) ((x - 1) << I2S_DMACR_TDL_SHIFT) | ||
131 | #define I2S_DMACR_TDL_MASK (0x1f << I2S_DMACR_TDL_SHIFT) | ||
132 | |||
133 | /* | ||
134 | * INTCR | ||
135 | * interrupt control register | ||
136 | */ | ||
137 | #define I2S_INTCR_RFT_SHIFT 20 | ||
138 | #define I2S_INTCR_RFT(x) ((x - 1) << I2S_INTCR_RFT_SHIFT) | ||
139 | #define I2S_INTCR_RXOIC BIT(18) | ||
140 | #define I2S_INTCR_RXOIE_SHIFT 17 | ||
141 | #define I2S_INTCR_RXOIE_DISABLE (0 << I2S_INTCR_RXOIE_SHIFT) | ||
142 | #define I2S_INTCR_RXOIE_ENABLE (1 << I2S_INTCR_RXOIE_SHIFT) | ||
143 | #define I2S_INTCR_RXFIE_SHIFT 16 | ||
144 | #define I2S_INTCR_RXFIE_DISABLE (0 << I2S_INTCR_RXFIE_SHIFT) | ||
145 | #define I2S_INTCR_RXFIE_ENABLE (1 << I2S_INTCR_RXFIE_SHIFT) | ||
146 | #define I2S_INTCR_TFT_SHIFT 4 | ||
147 | #define I2S_INTCR_TFT(x) ((x - 1) << I2S_INTCR_TFT_SHIFT) | ||
148 | #define I2S_INTCR_TFT_MASK (0x1f << I2S_INTCR_TFT_SHIFT) | ||
149 | #define I2S_INTCR_TXUIC BIT(2) | ||
150 | #define I2S_INTCR_TXUIE_SHIFT 1 | ||
151 | #define I2S_INTCR_TXUIE_DISABLE (0 << I2S_INTCR_TXUIE_SHIFT) | ||
152 | #define I2S_INTCR_TXUIE_ENABLE (1 << I2S_INTCR_TXUIE_SHIFT) | ||
153 | |||
154 | /* | ||
155 | * INTSR | ||
156 | * interrupt status register | ||
157 | */ | ||
158 | #define I2S_INTSR_TXEIE_SHIFT 0 | ||
159 | #define I2S_INTSR_TXEIE_DISABLE (0 << I2S_INTSR_TXEIE_SHIFT) | ||
160 | #define I2S_INTSR_TXEIE_ENABLE (1 << I2S_INTSR_TXEIE_SHIFT) | ||
161 | #define I2S_INTSR_RXOI_SHIFT 17 | ||
162 | #define I2S_INTSR_RXOI_INA (0 << I2S_INTSR_RXOI_SHIFT) | ||
163 | #define I2S_INTSR_RXOI_ACT (1 << I2S_INTSR_RXOI_SHIFT) | ||
164 | #define I2S_INTSR_RXFI_SHIFT 16 | ||
165 | #define I2S_INTSR_RXFI_INA (0 << I2S_INTSR_RXFI_SHIFT) | ||
166 | #define I2S_INTSR_RXFI_ACT (1 << I2S_INTSR_RXFI_SHIFT) | ||
167 | #define I2S_INTSR_TXUI_SHIFT 1 | ||
168 | #define I2S_INTSR_TXUI_INA (0 << I2S_INTSR_TXUI_SHIFT) | ||
169 | #define I2S_INTSR_TXUI_ACT (1 << I2S_INTSR_TXUI_SHIFT) | ||
170 | #define I2S_INTSR_TXEI_SHIFT 0 | ||
171 | #define I2S_INTSR_TXEI_INA (0 << I2S_INTSR_TXEI_SHIFT) | ||
172 | #define I2S_INTSR_TXEI_ACT (1 << I2S_INTSR_TXEI_SHIFT) | ||
173 | |||
174 | /* | ||
175 | * XFER | ||
176 | * Transfer start register | ||
177 | */ | ||
178 | #define I2S_XFER_RXS_SHIFT 1 | ||
179 | #define I2S_XFER_RXS_STOP (0 << I2S_XFER_RXS_SHIFT) | ||
180 | #define I2S_XFER_RXS_START (1 << I2S_XFER_RXS_SHIFT) | ||
181 | #define I2S_XFER_TXS_SHIFT 0 | ||
182 | #define I2S_XFER_TXS_STOP (0 << I2S_XFER_TXS_SHIFT) | ||
183 | #define I2S_XFER_TXS_START (1 << I2S_XFER_TXS_SHIFT) | ||
184 | |||
185 | /* | ||
186 | * CLR | ||
187 | * clear SCLK domain logic register | ||
188 | */ | ||
189 | #define I2S_CLR_RXC BIT(1) | ||
190 | #define I2S_CLR_TXC BIT(0) | ||
191 | |||
192 | /* | ||
193 | * TXDR | ||
194 | * Transimt FIFO data register, write only. | ||
195 | */ | ||
196 | #define I2S_TXDR_MASK (0xff) | ||
197 | |||
198 | /* | ||
199 | * RXDR | ||
200 | * Receive FIFO data register, write only. | ||
201 | */ | ||
202 | #define I2S_RXDR_MASK (0xff) | ||
203 | |||
204 | /* Clock divider id */ | ||
205 | enum { | ||
206 | ROCKCHIP_DIV_MCLK = 0, | ||
207 | ROCKCHIP_DIV_BCLK, | ||
208 | }; | ||
209 | |||
210 | /* I2S REGS */ | ||
211 | #define I2S_TXCR (0x0000) | ||
212 | #define I2S_RXCR (0x0004) | ||
213 | #define I2S_CKR (0x0008) | ||
214 | #define I2S_FIFOLR (0x000c) | ||
215 | #define I2S_DMACR (0x0010) | ||
216 | #define I2S_INTCR (0x0014) | ||
217 | #define I2S_INTSR (0x0018) | ||
218 | #define I2S_XFER (0x001c) | ||
219 | #define I2S_CLR (0x0020) | ||
220 | #define I2S_TXDR (0x0024) | ||
221 | #define I2S_RXDR (0x0028) | ||
222 | |||
223 | #endif /* _ROCKCHIP_IIS_H */ | ||
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 753b8c93ab51..55a38697443d 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -1,25 +1,16 @@ | |||
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 S3C2410_DMA if ARCH_S3C24XX | 4 | depends on S3C64XX_PL080 || !ARCH_S3C64XX |
5 | select S3C64XX_PL080 if ARCH_S3C64XX | 5 | depends on S3C24XX_DMAC || !ARCH_S3C24XX |
6 | select SND_S3C_DMA if !ARCH_S3C24XX | 6 | select SND_SOC_GENERIC_DMAENGINE_PCM |
7 | select SND_S3C_DMA_LEGACY if ARCH_S3C24XX | ||
8 | select SND_SOC_GENERIC_DMAENGINE_PCM if !ARCH_S3C24XX | ||
9 | help | 7 | help |
10 | Say Y or M if you want to add support for codecs attached to | 8 | Say Y or M if you want to add support for codecs attached to |
11 | the Samsung SoCs' Audio interfaces. You will also need to | 9 | the Samsung SoCs' Audio interfaces. You will also need to |
12 | select the audio interfaces to support below. | 10 | select the audio interfaces to support below. |
13 | 11 | ||
14 | config SND_S3C_DMA | ||
15 | tristate | ||
16 | |||
17 | config SND_S3C_DMA_LEGACY | ||
18 | tristate | ||
19 | |||
20 | config SND_S3C24XX_I2S | 12 | config SND_S3C24XX_I2S |
21 | tristate | 13 | tristate |
22 | select S3C24XX_DMA | ||
23 | 14 | ||
24 | config SND_S3C_I2SV2_SOC | 15 | config SND_S3C_I2SV2_SOC |
25 | tristate | 16 | tristate |
@@ -27,7 +18,6 @@ config SND_S3C_I2SV2_SOC | |||
27 | config SND_S3C2412_SOC_I2S | 18 | config SND_S3C2412_SOC_I2S |
28 | tristate | 19 | tristate |
29 | select SND_S3C_I2SV2_SOC | 20 | select SND_S3C_I2SV2_SOC |
30 | select S3C2410_DMA | ||
31 | 21 | ||
32 | config SND_SAMSUNG_PCM | 22 | config SND_SAMSUNG_PCM |
33 | tristate | 23 | tristate |
@@ -55,7 +45,7 @@ config SND_SOC_SAMSUNG_NEO1973_WM8753 | |||
55 | 45 | ||
56 | config SND_SOC_SAMSUNG_JIVE_WM8750 | 46 | config SND_SOC_SAMSUNG_JIVE_WM8750 |
57 | tristate "SoC I2S Audio support for Jive" | 47 | tristate "SoC I2S Audio support for Jive" |
58 | depends on SND_SOC_SAMSUNG && MACH_JIVE | 48 | depends on SND_SOC_SAMSUNG && MACH_JIVE && I2C |
59 | select SND_SOC_WM8750 | 49 | select SND_SOC_WM8750 |
60 | select SND_S3C2412_SOC_I2S | 50 | select SND_S3C2412_SOC_I2S |
61 | help | 51 | help |
@@ -63,7 +53,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 | |||
63 | 53 | ||
64 | config SND_SOC_SAMSUNG_SMDK_WM8580 | 54 | config SND_SOC_SAMSUNG_SMDK_WM8580 |
65 | tristate "SoC I2S Audio support for WM8580 on SMDK" | 55 | tristate "SoC I2S Audio support for WM8580 on SMDK" |
66 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDK6440 || MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110) | 56 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) |
67 | depends on REGMAP_I2C | 57 | depends on REGMAP_I2C |
68 | select SND_SOC_WM8580 | 58 | select SND_SOC_WM8580 |
69 | select SND_SAMSUNG_I2S | 59 | select SND_SAMSUNG_I2S |
@@ -83,7 +73,6 @@ config SND_SOC_SAMSUNG_SMDK_WM8994 | |||
83 | config SND_SOC_SAMSUNG_SMDK2443_WM9710 | 73 | config SND_SOC_SAMSUNG_SMDK2443_WM9710 |
84 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" | 74 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" |
85 | depends on SND_SOC_SAMSUNG && MACH_SMDK2443 | 75 | depends on SND_SOC_SAMSUNG && MACH_SMDK2443 |
86 | select S3C2410_DMA | ||
87 | select AC97_BUS | 76 | select AC97_BUS |
88 | select SND_SOC_AC97_CODEC | 77 | select SND_SOC_AC97_CODEC |
89 | select SND_SAMSUNG_AC97 | 78 | select SND_SAMSUNG_AC97 |
@@ -94,7 +83,6 @@ config SND_SOC_SAMSUNG_SMDK2443_WM9710 | |||
94 | config SND_SOC_SAMSUNG_LN2440SBC_ALC650 | 83 | config SND_SOC_SAMSUNG_LN2440SBC_ALC650 |
95 | tristate "SoC AC97 Audio support for LN2440SBC - ALC650" | 84 | tristate "SoC AC97 Audio support for LN2440SBC - ALC650" |
96 | depends on SND_SOC_SAMSUNG && ARCH_S3C24XX | 85 | depends on SND_SOC_SAMSUNG && ARCH_S3C24XX |
97 | select S3C2410_DMA | ||
98 | select AC97_BUS | 86 | select AC97_BUS |
99 | select SND_SOC_AC97_CODEC | 87 | select SND_SOC_AC97_CODEC |
100 | select SND_SAMSUNG_AC97 | 88 | select SND_SAMSUNG_AC97 |
@@ -154,7 +142,7 @@ config SND_SOC_SAMSUNG_SMDK_WM9713 | |||
154 | 142 | ||
155 | config SND_SOC_SMARTQ | 143 | config SND_SOC_SMARTQ |
156 | tristate "SoC I2S Audio support for SmartQ board" | 144 | tristate "SoC I2S Audio support for SmartQ board" |
157 | depends on SND_SOC_SAMSUNG && MACH_SMARTQ | 145 | depends on SND_SOC_SAMSUNG && MACH_SMARTQ && I2C |
158 | select SND_SAMSUNG_I2S | 146 | select SND_SAMSUNG_I2S |
159 | select SND_SOC_WM8750 | 147 | select SND_SOC_WM8750 |
160 | 148 | ||
@@ -178,7 +166,7 @@ config SND_SOC_SAMSUNG_SMDK_SPDIF | |||
178 | 166 | ||
179 | config SND_SOC_SMDK_WM8580_PCM | 167 | config SND_SOC_SMDK_WM8580_PCM |
180 | tristate "SoC PCM Audio support for WM8580 on SMDK" | 168 | tristate "SoC PCM Audio support for WM8580 on SMDK" |
181 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110) | 169 | depends on SND_SOC_SAMSUNG && (MACH_SMDKV210 || MACH_SMDKC110) |
182 | depends on REGMAP_I2C | 170 | depends on REGMAP_I2C |
183 | select SND_SOC_WM8580 | 171 | select SND_SOC_WM8580 |
184 | select SND_SAMSUNG_PCM | 172 | select SND_SAMSUNG_PCM |
@@ -206,7 +194,7 @@ config SND_SOC_SPEYSIDE | |||
206 | 194 | ||
207 | config SND_SOC_TOBERMORY | 195 | config SND_SOC_TOBERMORY |
208 | tristate "Audio support for Wolfson Tobermory" | 196 | tristate "Audio support for Wolfson Tobermory" |
209 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && INPUT | 197 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && INPUT && I2C |
210 | select SND_SAMSUNG_I2S | 198 | select SND_SAMSUNG_I2S |
211 | select SND_SOC_WM8962 | 199 | select SND_SOC_WM8962 |
212 | 200 | ||
@@ -222,7 +210,7 @@ config SND_SOC_BELLS | |||
222 | 210 | ||
223 | config SND_SOC_LOWLAND | 211 | config SND_SOC_LOWLAND |
224 | tristate "Audio support for Wolfson Lowland" | 212 | tristate "Audio support for Wolfson Lowland" |
225 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | 213 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && I2C |
226 | select SND_SAMSUNG_I2S | 214 | select SND_SAMSUNG_I2S |
227 | select SND_SOC_WM5100 | 215 | select SND_SOC_WM5100 |
228 | select SND_SOC_WM9081 | 216 | select SND_SOC_WM9081 |
@@ -236,10 +224,18 @@ config SND_SOC_LITTLEMILL | |||
236 | 224 | ||
237 | config SND_SOC_SNOW | 225 | config SND_SOC_SNOW |
238 | tristate "Audio support for Google Snow boards" | 226 | tristate "Audio support for Google Snow boards" |
239 | depends on SND_SOC_SAMSUNG | 227 | depends on SND_SOC_SAMSUNG && I2C |
240 | select SND_SOC_MAX98090 | 228 | select SND_SOC_MAX98090 |
241 | select SND_SOC_MAX98095 | 229 | select SND_SOC_MAX98095 |
242 | select SND_SAMSUNG_I2S | 230 | select SND_SAMSUNG_I2S |
243 | help | 231 | help |
244 | Say Y if you want to add audio support for various Snow | 232 | Say Y if you want to add audio support for various Snow |
245 | boards based on Exynos5 series of SoCs. | 233 | boards based on Exynos5 series of SoCs. |
234 | |||
235 | config SND_SOC_ODROIDX2 | ||
236 | tristate "Audio support for Odroid-X2 and Odroid-U3" | ||
237 | depends on SND_SOC_SAMSUNG | ||
238 | select SND_SOC_MAX98090 | ||
239 | select SND_SAMSUNG_I2S | ||
240 | help | ||
241 | Say Y here to enable audio support for the Odroid-X2/U3. | ||
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 6d0212ba571c..91505ddaaf95 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -1,6 +1,5 @@ | |||
1 | # S3c24XX Platform Support | 1 | # S3c24XX Platform Support |
2 | snd-soc-s3c-dma-objs := dmaengine.o | 2 | snd-soc-s3c-dma-objs := dmaengine.o |
3 | snd-soc-s3c-dma-legacy-objs := dma.o | ||
4 | snd-soc-idma-objs := idma.o | 3 | snd-soc-idma-objs := idma.o |
5 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o | 4 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o |
6 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o | 5 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o |
@@ -10,8 +9,7 @@ snd-soc-samsung-spdif-objs := spdif.o | |||
10 | snd-soc-pcm-objs := pcm.o | 9 | snd-soc-pcm-objs := pcm.o |
11 | snd-soc-i2s-objs := i2s.o | 10 | snd-soc-i2s-objs := i2s.o |
12 | 11 | ||
13 | obj-$(CONFIG_SND_S3C_DMA) += snd-soc-s3c-dma.o | 12 | obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c-dma.o |
14 | obj-$(CONFIG_SND_S3C_DMA_LEGACY) += snd-soc-s3c-dma-legacy.o | ||
15 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o | 13 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o |
16 | obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o | 14 | obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o |
17 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o | 15 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o |
@@ -46,6 +44,7 @@ snd-soc-tobermory-objs := tobermory.o | |||
46 | snd-soc-lowland-objs := lowland.o | 44 | snd-soc-lowland-objs := lowland.o |
47 | snd-soc-littlemill-objs := littlemill.o | 45 | snd-soc-littlemill-objs := littlemill.o |
48 | snd-soc-bells-objs := bells.o | 46 | snd-soc-bells-objs := bells.o |
47 | snd-soc-odroidx2-max98090-objs := odroidx2_max98090.o | ||
49 | 48 | ||
50 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o | 49 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o |
51 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 50 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
@@ -71,3 +70,4 @@ obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o | |||
71 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o | 70 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o |
72 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o | 71 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o |
73 | obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o | 72 | obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o |
73 | obj-$(CONFIG_SND_SOC_ODROIDX2) += snd-soc-odroidx2-max98090.o | ||
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 68d9303047e8..e1615113fd84 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | 21 | ||
22 | #include <mach/dma.h> | ||
23 | #include "regs-ac97.h" | 22 | #include "regs-ac97.h" |
24 | #include <linux/platform_data/asoc-s3c.h> | 23 | #include <linux/platform_data/asoc-s3c.h> |
25 | 24 | ||
@@ -39,30 +38,15 @@ struct s3c_ac97_info { | |||
39 | }; | 38 | }; |
40 | static struct s3c_ac97_info s3c_ac97; | 39 | static struct s3c_ac97_info s3c_ac97; |
41 | 40 | ||
42 | static struct s3c_dma_client s3c_dma_client_out = { | ||
43 | .name = "AC97 PCMOut" | ||
44 | }; | ||
45 | |||
46 | static struct s3c_dma_client s3c_dma_client_in = { | ||
47 | .name = "AC97 PCMIn" | ||
48 | }; | ||
49 | |||
50 | static struct s3c_dma_client s3c_dma_client_micin = { | ||
51 | .name = "AC97 MicIn" | ||
52 | }; | ||
53 | |||
54 | static struct s3c_dma_params s3c_ac97_pcm_out = { | 41 | static struct s3c_dma_params s3c_ac97_pcm_out = { |
55 | .client = &s3c_dma_client_out, | ||
56 | .dma_size = 4, | 42 | .dma_size = 4, |
57 | }; | 43 | }; |
58 | 44 | ||
59 | static struct s3c_dma_params s3c_ac97_pcm_in = { | 45 | static struct s3c_dma_params s3c_ac97_pcm_in = { |
60 | .client = &s3c_dma_client_in, | ||
61 | .dma_size = 4, | 46 | .dma_size = 4, |
62 | }; | 47 | }; |
63 | 48 | ||
64 | static struct s3c_dma_params s3c_ac97_mic_in = { | 49 | static struct s3c_dma_params s3c_ac97_mic_in = { |
65 | .client = &s3c_dma_client_micin, | ||
66 | .dma_size = 4, | 50 | .dma_size = 4, |
67 | }; | 51 | }; |
68 | 52 | ||
@@ -225,9 +209,6 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
225 | struct snd_soc_dai *dai) | 209 | struct snd_soc_dai *dai) |
226 | { | 210 | { |
227 | u32 ac_glbctrl; | 211 | u32 ac_glbctrl; |
228 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
229 | struct s3c_dma_params *dma_data = | ||
230 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
231 | 212 | ||
232 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | 213 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); |
233 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 214 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
@@ -253,11 +234,6 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
253 | 234 | ||
254 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | 235 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); |
255 | 236 | ||
256 | if (!dma_data->ops) | ||
257 | dma_data->ops = samsung_dma_get_ops(); | ||
258 | |||
259 | dma_data->ops->started(dma_data->channel); | ||
260 | |||
261 | return 0; | 237 | return 0; |
262 | } | 238 | } |
263 | 239 | ||
@@ -265,9 +241,6 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, | |||
265 | int cmd, struct snd_soc_dai *dai) | 241 | int cmd, struct snd_soc_dai *dai) |
266 | { | 242 | { |
267 | u32 ac_glbctrl; | 243 | u32 ac_glbctrl; |
268 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
269 | struct s3c_dma_params *dma_data = | ||
270 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
271 | 244 | ||
272 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | 245 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); |
273 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; | 246 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; |
@@ -287,11 +260,6 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, | |||
287 | 260 | ||
288 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | 261 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); |
289 | 262 | ||
290 | if (!dma_data->ops) | ||
291 | dma_data->ops = samsung_dma_get_ops(); | ||
292 | |||
293 | dma_data->ops->started(dma_data->channel); | ||
294 | |||
295 | return 0; | 263 | return 0; |
296 | } | 264 | } |
297 | 265 | ||
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c deleted file mode 100644 index d9dc7bcc0336..000000000000 --- a/sound/soc/samsung/dma.c +++ /dev/null | |||
@@ -1,454 +0,0 @@ | |||
1 | /* | ||
2 | * dma.c -- ALSA Soc Audio Layer | ||
3 | * | ||
4 | * (c) 2006 Wolfson Microelectronics PLC. | ||
5 | * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
6 | * | ||
7 | * Copyright 2004-2005 Simtec Electronics | ||
8 | * http://armlinux.simtec.co.uk/ | ||
9 | * Ben Dooks <ben@simtec.co.uk> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include <sound/soc.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | |||
24 | #include <asm/dma.h> | ||
25 | #include <mach/hardware.h> | ||
26 | #include <mach/dma.h> | ||
27 | |||
28 | #include "dma.h" | ||
29 | |||
30 | #define ST_RUNNING (1<<0) | ||
31 | #define ST_OPENED (1<<1) | ||
32 | |||
33 | static const struct snd_pcm_hardware dma_hardware = { | ||
34 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
35 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
36 | SNDRV_PCM_INFO_MMAP | | ||
37 | SNDRV_PCM_INFO_MMAP_VALID, | ||
38 | .buffer_bytes_max = 128*1024, | ||
39 | .period_bytes_min = PAGE_SIZE, | ||
40 | .period_bytes_max = PAGE_SIZE*2, | ||
41 | .periods_min = 2, | ||
42 | .periods_max = 128, | ||
43 | .fifo_size = 32, | ||
44 | }; | ||
45 | |||
46 | struct runtime_data { | ||
47 | spinlock_t lock; | ||
48 | int state; | ||
49 | unsigned int dma_loaded; | ||
50 | unsigned int dma_period; | ||
51 | dma_addr_t dma_start; | ||
52 | dma_addr_t dma_pos; | ||
53 | dma_addr_t dma_end; | ||
54 | struct s3c_dma_params *params; | ||
55 | }; | ||
56 | |||
57 | static void audio_buffdone(void *data); | ||
58 | |||
59 | /* dma_enqueue | ||
60 | * | ||
61 | * place a dma buffer onto the queue for the dma system | ||
62 | * to handle. | ||
63 | */ | ||
64 | static void dma_enqueue(struct snd_pcm_substream *substream) | ||
65 | { | ||
66 | struct runtime_data *prtd = substream->runtime->private_data; | ||
67 | dma_addr_t pos = prtd->dma_pos; | ||
68 | unsigned int limit; | ||
69 | struct samsung_dma_prep dma_info; | ||
70 | |||
71 | pr_debug("Entered %s\n", __func__); | ||
72 | |||
73 | limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; | ||
74 | |||
75 | pr_debug("%s: loaded %d, limit %d\n", | ||
76 | __func__, prtd->dma_loaded, limit); | ||
77 | |||
78 | dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE); | ||
79 | dma_info.direction = | ||
80 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
81 | ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); | ||
82 | dma_info.fp = audio_buffdone; | ||
83 | dma_info.fp_param = substream; | ||
84 | dma_info.period = prtd->dma_period; | ||
85 | dma_info.len = prtd->dma_period*limit; | ||
86 | |||
87 | if (dma_info.cap == DMA_CYCLIC) { | ||
88 | dma_info.buf = pos; | ||
89 | prtd->params->ops->prepare(prtd->params->ch, &dma_info); | ||
90 | prtd->dma_loaded += limit; | ||
91 | return; | ||
92 | } | ||
93 | |||
94 | while (prtd->dma_loaded < limit) { | ||
95 | pr_debug("dma_loaded: %d\n", prtd->dma_loaded); | ||
96 | |||
97 | if ((pos + dma_info.period) > prtd->dma_end) { | ||
98 | dma_info.period = prtd->dma_end - pos; | ||
99 | pr_debug("%s: corrected dma len %ld\n", | ||
100 | __func__, dma_info.period); | ||
101 | } | ||
102 | |||
103 | dma_info.buf = pos; | ||
104 | prtd->params->ops->prepare(prtd->params->ch, &dma_info); | ||
105 | |||
106 | prtd->dma_loaded++; | ||
107 | pos += prtd->dma_period; | ||
108 | if (pos >= prtd->dma_end) | ||
109 | pos = prtd->dma_start; | ||
110 | } | ||
111 | |||
112 | prtd->dma_pos = pos; | ||
113 | } | ||
114 | |||
115 | static void audio_buffdone(void *data) | ||
116 | { | ||
117 | struct snd_pcm_substream *substream = data; | ||
118 | struct runtime_data *prtd = substream->runtime->private_data; | ||
119 | |||
120 | pr_debug("Entered %s\n", __func__); | ||
121 | |||
122 | if (prtd->state & ST_RUNNING) { | ||
123 | prtd->dma_pos += prtd->dma_period; | ||
124 | if (prtd->dma_pos >= prtd->dma_end) | ||
125 | prtd->dma_pos = prtd->dma_start; | ||
126 | |||
127 | if (substream) | ||
128 | snd_pcm_period_elapsed(substream); | ||
129 | |||
130 | spin_lock(&prtd->lock); | ||
131 | if (!samsung_dma_has_circular()) { | ||
132 | prtd->dma_loaded--; | ||
133 | dma_enqueue(substream); | ||
134 | } | ||
135 | spin_unlock(&prtd->lock); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static int dma_hw_params(struct snd_pcm_substream *substream, | ||
140 | struct snd_pcm_hw_params *params) | ||
141 | { | ||
142 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
143 | struct runtime_data *prtd = runtime->private_data; | ||
144 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
145 | unsigned long totbytes = params_buffer_bytes(params); | ||
146 | struct s3c_dma_params *dma = | ||
147 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
148 | struct samsung_dma_req req; | ||
149 | struct samsung_dma_config config; | ||
150 | |||
151 | pr_debug("Entered %s\n", __func__); | ||
152 | |||
153 | /* return if this is a bufferless transfer e.g. | ||
154 | * codec <--> BT codec or GSM modem -- lg FIXME */ | ||
155 | if (!dma) | ||
156 | return 0; | ||
157 | |||
158 | /* this may get called several times by oss emulation | ||
159 | * with different params -HW */ | ||
160 | if (prtd->params == NULL) { | ||
161 | /* prepare DMA */ | ||
162 | prtd->params = dma; | ||
163 | |||
164 | pr_debug("params %p, client %p, channel %d\n", prtd->params, | ||
165 | prtd->params->client, prtd->params->channel); | ||
166 | |||
167 | prtd->params->ops = samsung_dma_get_ops(); | ||
168 | |||
169 | req.cap = (samsung_dma_has_circular() ? | ||
170 | DMA_CYCLIC : DMA_SLAVE); | ||
171 | req.client = prtd->params->client; | ||
172 | config.direction = | ||
173 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
174 | ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); | ||
175 | config.width = prtd->params->dma_size; | ||
176 | config.fifo = prtd->params->dma_addr; | ||
177 | prtd->params->ch = prtd->params->ops->request( | ||
178 | prtd->params->channel, &req, rtd->cpu_dai->dev, | ||
179 | prtd->params->ch_name); | ||
180 | if (!prtd->params->ch) { | ||
181 | pr_err("Failed to allocate DMA channel\n"); | ||
182 | return -ENXIO; | ||
183 | } | ||
184 | prtd->params->ops->config(prtd->params->ch, &config); | ||
185 | } | ||
186 | |||
187 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
188 | |||
189 | runtime->dma_bytes = totbytes; | ||
190 | |||
191 | spin_lock_irq(&prtd->lock); | ||
192 | prtd->dma_loaded = 0; | ||
193 | prtd->dma_period = params_period_bytes(params); | ||
194 | prtd->dma_start = runtime->dma_addr; | ||
195 | prtd->dma_pos = prtd->dma_start; | ||
196 | prtd->dma_end = prtd->dma_start + totbytes; | ||
197 | spin_unlock_irq(&prtd->lock); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int dma_hw_free(struct snd_pcm_substream *substream) | ||
203 | { | ||
204 | struct runtime_data *prtd = substream->runtime->private_data; | ||
205 | |||
206 | pr_debug("Entered %s\n", __func__); | ||
207 | |||
208 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
209 | |||
210 | if (prtd->params) { | ||
211 | prtd->params->ops->flush(prtd->params->ch); | ||
212 | prtd->params->ops->release(prtd->params->ch, | ||
213 | prtd->params->client); | ||
214 | prtd->params = NULL; | ||
215 | } | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int dma_prepare(struct snd_pcm_substream *substream) | ||
221 | { | ||
222 | struct runtime_data *prtd = substream->runtime->private_data; | ||
223 | int ret = 0; | ||
224 | |||
225 | pr_debug("Entered %s\n", __func__); | ||
226 | |||
227 | /* return if this is a bufferless transfer e.g. | ||
228 | * codec <--> BT codec or GSM modem -- lg FIXME */ | ||
229 | if (!prtd->params) | ||
230 | return 0; | ||
231 | |||
232 | /* flush the DMA channel */ | ||
233 | prtd->params->ops->flush(prtd->params->ch); | ||
234 | |||
235 | prtd->dma_loaded = 0; | ||
236 | prtd->dma_pos = prtd->dma_start; | ||
237 | |||
238 | /* enqueue dma buffers */ | ||
239 | dma_enqueue(substream); | ||
240 | |||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | static int dma_trigger(struct snd_pcm_substream *substream, int cmd) | ||
245 | { | ||
246 | struct runtime_data *prtd = substream->runtime->private_data; | ||
247 | int ret = 0; | ||
248 | |||
249 | pr_debug("Entered %s\n", __func__); | ||
250 | |||
251 | spin_lock(&prtd->lock); | ||
252 | |||
253 | switch (cmd) { | ||
254 | case SNDRV_PCM_TRIGGER_START: | ||
255 | prtd->state |= ST_RUNNING; | ||
256 | prtd->params->ops->trigger(prtd->params->ch); | ||
257 | break; | ||
258 | |||
259 | case SNDRV_PCM_TRIGGER_STOP: | ||
260 | prtd->state &= ~ST_RUNNING; | ||
261 | prtd->params->ops->stop(prtd->params->ch); | ||
262 | break; | ||
263 | |||
264 | default: | ||
265 | ret = -EINVAL; | ||
266 | break; | ||
267 | } | ||
268 | |||
269 | spin_unlock(&prtd->lock); | ||
270 | |||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | static snd_pcm_uframes_t | ||
275 | dma_pointer(struct snd_pcm_substream *substream) | ||
276 | { | ||
277 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
278 | struct runtime_data *prtd = runtime->private_data; | ||
279 | unsigned long res; | ||
280 | |||
281 | pr_debug("Entered %s\n", __func__); | ||
282 | |||
283 | res = prtd->dma_pos - prtd->dma_start; | ||
284 | |||
285 | pr_debug("Pointer offset: %lu\n", res); | ||
286 | |||
287 | /* we seem to be getting the odd error from the pcm library due | ||
288 | * to out-of-bounds pointers. this is maybe due to the dma engine | ||
289 | * not having loaded the new values for the channel before being | ||
290 | * called... (todo - fix ) | ||
291 | */ | ||
292 | |||
293 | if (res >= snd_pcm_lib_buffer_bytes(substream)) { | ||
294 | if (res == snd_pcm_lib_buffer_bytes(substream)) | ||
295 | res = 0; | ||
296 | } | ||
297 | |||
298 | return bytes_to_frames(substream->runtime, res); | ||
299 | } | ||
300 | |||
301 | static int dma_open(struct snd_pcm_substream *substream) | ||
302 | { | ||
303 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
304 | struct runtime_data *prtd; | ||
305 | |||
306 | pr_debug("Entered %s\n", __func__); | ||
307 | |||
308 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
309 | snd_soc_set_runtime_hwparams(substream, &dma_hardware); | ||
310 | |||
311 | prtd = kzalloc(sizeof(struct runtime_data), GFP_KERNEL); | ||
312 | if (prtd == NULL) | ||
313 | return -ENOMEM; | ||
314 | |||
315 | spin_lock_init(&prtd->lock); | ||
316 | |||
317 | runtime->private_data = prtd; | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int dma_close(struct snd_pcm_substream *substream) | ||
322 | { | ||
323 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
324 | struct runtime_data *prtd = runtime->private_data; | ||
325 | |||
326 | pr_debug("Entered %s\n", __func__); | ||
327 | |||
328 | if (!prtd) | ||
329 | pr_debug("dma_close called with prtd == NULL\n"); | ||
330 | |||
331 | kfree(prtd); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int dma_mmap(struct snd_pcm_substream *substream, | ||
337 | struct vm_area_struct *vma) | ||
338 | { | ||
339 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
340 | |||
341 | pr_debug("Entered %s\n", __func__); | ||
342 | |||
343 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
344 | runtime->dma_area, | ||
345 | runtime->dma_addr, | ||
346 | runtime->dma_bytes); | ||
347 | } | ||
348 | |||
349 | static struct snd_pcm_ops dma_ops = { | ||
350 | .open = dma_open, | ||
351 | .close = dma_close, | ||
352 | .ioctl = snd_pcm_lib_ioctl, | ||
353 | .hw_params = dma_hw_params, | ||
354 | .hw_free = dma_hw_free, | ||
355 | .prepare = dma_prepare, | ||
356 | .trigger = dma_trigger, | ||
357 | .pointer = dma_pointer, | ||
358 | .mmap = dma_mmap, | ||
359 | }; | ||
360 | |||
361 | static int preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
362 | { | ||
363 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
364 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
365 | size_t size = dma_hardware.buffer_bytes_max; | ||
366 | |||
367 | pr_debug("Entered %s\n", __func__); | ||
368 | |||
369 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
370 | buf->dev.dev = pcm->card->dev; | ||
371 | buf->private_data = NULL; | ||
372 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
373 | &buf->addr, GFP_KERNEL); | ||
374 | if (!buf->area) | ||
375 | return -ENOMEM; | ||
376 | buf->bytes = size; | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static void dma_free_dma_buffers(struct snd_pcm *pcm) | ||
381 | { | ||
382 | struct snd_pcm_substream *substream; | ||
383 | struct snd_dma_buffer *buf; | ||
384 | int stream; | ||
385 | |||
386 | pr_debug("Entered %s\n", __func__); | ||
387 | |||
388 | for (stream = 0; stream < 2; stream++) { | ||
389 | substream = pcm->streams[stream].substream; | ||
390 | if (!substream) | ||
391 | continue; | ||
392 | |||
393 | buf = &substream->dma_buffer; | ||
394 | if (!buf->area) | ||
395 | continue; | ||
396 | |||
397 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
398 | buf->area, buf->addr); | ||
399 | buf->area = NULL; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | static int dma_new(struct snd_soc_pcm_runtime *rtd) | ||
404 | { | ||
405 | struct snd_card *card = rtd->card->snd_card; | ||
406 | struct snd_pcm *pcm = rtd->pcm; | ||
407 | int ret; | ||
408 | |||
409 | pr_debug("Entered %s\n", __func__); | ||
410 | |||
411 | ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); | ||
412 | if (ret) | ||
413 | return ret; | ||
414 | |||
415 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
416 | ret = preallocate_dma_buffer(pcm, | ||
417 | SNDRV_PCM_STREAM_PLAYBACK); | ||
418 | if (ret) | ||
419 | goto out; | ||
420 | } | ||
421 | |||
422 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
423 | ret = preallocate_dma_buffer(pcm, | ||
424 | SNDRV_PCM_STREAM_CAPTURE); | ||
425 | if (ret) | ||
426 | goto out; | ||
427 | } | ||
428 | out: | ||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | static struct snd_soc_platform_driver samsung_asoc_platform = { | ||
433 | .ops = &dma_ops, | ||
434 | .pcm_new = dma_new, | ||
435 | .pcm_free = dma_free_dma_buffers, | ||
436 | }; | ||
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 | |||
446 | int samsung_asoc_dma_platform_register(struct device *dev) | ||
447 | { | ||
448 | return devm_snd_soc_register_platform(dev, &samsung_asoc_platform); | ||
449 | } | ||
450 | EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); | ||
451 | |||
452 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | ||
453 | MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); | ||
454 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h index 070ab0f09609..0e85dcfec023 100644 --- a/sound/soc/samsung/dma.h +++ b/sound/soc/samsung/dma.h | |||
@@ -14,17 +14,10 @@ | |||
14 | 14 | ||
15 | #include <sound/dmaengine_pcm.h> | 15 | #include <sound/dmaengine_pcm.h> |
16 | 16 | ||
17 | struct s3c_dma_client { | ||
18 | char *name; | ||
19 | }; | ||
20 | |||
21 | struct s3c_dma_params { | 17 | struct s3c_dma_params { |
22 | struct s3c_dma_client *client; /* stream identifier */ | ||
23 | int channel; /* Channel ID */ | 18 | int channel; /* Channel ID */ |
24 | dma_addr_t dma_addr; | 19 | dma_addr_t dma_addr; |
25 | int dma_size; /* Size of the DMA transfer */ | 20 | int dma_size; /* Size of the DMA transfer */ |
26 | unsigned ch; | ||
27 | struct samsung_dma_ops *ops; | ||
28 | char *ch_name; | 21 | char *ch_name; |
29 | struct snd_dmaengine_dai_dma_data dma_data; | 22 | struct snd_dmaengine_dai_dma_data dma_data; |
30 | }; | 23 | }; |
diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c index a0e4e7948909..506f5bf6d082 100644 --- a/sound/soc/samsung/dmaengine.c +++ b/sound/soc/samsung/dmaengine.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/amba/pl08x.h> | 19 | #include <linux/amba/pl08x.h> |
20 | #include <linux/platform_data/dma-s3c24xx.h> | ||
20 | 21 | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
@@ -29,6 +30,8 @@ | |||
29 | 30 | ||
30 | #ifdef CONFIG_ARCH_S3C64XX | 31 | #ifdef CONFIG_ARCH_S3C64XX |
31 | #define filter_fn pl08x_filter_id | 32 | #define filter_fn pl08x_filter_id |
33 | #elif defined(CONFIG_ARCH_S3C24XX) | ||
34 | #define filter_fn s3c24xx_dma_filter | ||
32 | #else | 35 | #else |
33 | #define filter_fn NULL | 36 | #define filter_fn NULL |
34 | #endif | 37 | #endif |
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 2ac76fa3e742..03eec22f0f46 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
@@ -68,6 +68,8 @@ struct i2s_dai { | |||
68 | #define DAI_OPENED (1 << 0) /* Dai is opened */ | 68 | #define DAI_OPENED (1 << 0) /* Dai is opened */ |
69 | #define DAI_MANAGER (1 << 1) /* Dai is the manager */ | 69 | #define DAI_MANAGER (1 << 1) /* Dai is the manager */ |
70 | unsigned mode; | 70 | unsigned mode; |
71 | /* CDCLK pin direction: 0 - input, 1 - output */ | ||
72 | unsigned int cdclk_out:1; | ||
71 | /* Driver for this DAI */ | 73 | /* Driver for this DAI */ |
72 | struct snd_soc_dai_driver i2s_dai_drv; | 74 | struct snd_soc_dai_driver i2s_dai_drv; |
73 | /* DMA parameters */ | 75 | /* DMA parameters */ |
@@ -737,6 +739,9 @@ static int i2s_startup(struct snd_pcm_substream *substream, | |||
737 | 739 | ||
738 | spin_unlock_irqrestore(&lock, flags); | 740 | spin_unlock_irqrestore(&lock, flags); |
739 | 741 | ||
742 | if (!is_opened(other) && i2s->cdclk_out) | ||
743 | i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, | ||
744 | 0, SND_SOC_CLOCK_OUT); | ||
740 | return 0; | 745 | return 0; |
741 | } | 746 | } |
742 | 747 | ||
@@ -752,9 +757,13 @@ static void i2s_shutdown(struct snd_pcm_substream *substream, | |||
752 | i2s->mode &= ~DAI_OPENED; | 757 | i2s->mode &= ~DAI_OPENED; |
753 | i2s->mode &= ~DAI_MANAGER; | 758 | i2s->mode &= ~DAI_MANAGER; |
754 | 759 | ||
755 | if (is_opened(other)) | 760 | if (is_opened(other)) { |
756 | other->mode |= DAI_MANAGER; | 761 | other->mode |= DAI_MANAGER; |
757 | 762 | } else { | |
763 | u32 mod = readl(i2s->addr + I2SMOD); | ||
764 | i2s->cdclk_out = !(mod & MOD_CDCLKCON); | ||
765 | other->cdclk_out = i2s->cdclk_out; | ||
766 | } | ||
758 | /* Reset any constraint on RFS and BFS */ | 767 | /* Reset any constraint on RFS and BFS */ |
759 | i2s->rfs = 0; | 768 | i2s->rfs = 0; |
760 | i2s->bfs = 0; | 769 | i2s->bfs = 0; |
@@ -920,11 +929,9 @@ static int i2s_suspend(struct snd_soc_dai *dai) | |||
920 | { | 929 | { |
921 | struct i2s_dai *i2s = to_info(dai); | 930 | struct i2s_dai *i2s = to_info(dai); |
922 | 931 | ||
923 | if (dai->active) { | 932 | i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); |
924 | i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); | 933 | i2s->suspend_i2scon = readl(i2s->addr + I2SCON); |
925 | i2s->suspend_i2scon = readl(i2s->addr + I2SCON); | 934 | i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); |
926 | i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); | ||
927 | } | ||
928 | 935 | ||
929 | return 0; | 936 | return 0; |
930 | } | 937 | } |
@@ -933,11 +940,9 @@ static int i2s_resume(struct snd_soc_dai *dai) | |||
933 | { | 940 | { |
934 | struct i2s_dai *i2s = to_info(dai); | 941 | struct i2s_dai *i2s = to_info(dai); |
935 | 942 | ||
936 | if (dai->active) { | 943 | writel(i2s->suspend_i2scon, i2s->addr + I2SCON); |
937 | writel(i2s->suspend_i2scon, i2s->addr + I2SCON); | 944 | writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); |
938 | writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); | 945 | writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); |
939 | writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); | ||
940 | } | ||
941 | 946 | ||
942 | return 0; | 947 | return 0; |
943 | } | 948 | } |
@@ -1216,11 +1221,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1216 | 1221 | ||
1217 | pri_dai->dma_playback.dma_addr = regs_base + I2STXD; | 1222 | pri_dai->dma_playback.dma_addr = regs_base + I2STXD; |
1218 | pri_dai->dma_capture.dma_addr = regs_base + I2SRXD; | 1223 | pri_dai->dma_capture.dma_addr = regs_base + I2SRXD; |
1219 | pri_dai->dma_playback.client = | ||
1220 | (struct s3c_dma_client *)&pri_dai->dma_playback; | ||
1221 | pri_dai->dma_playback.ch_name = "tx"; | 1224 | pri_dai->dma_playback.ch_name = "tx"; |
1222 | pri_dai->dma_capture.client = | ||
1223 | (struct s3c_dma_client *)&pri_dai->dma_capture; | ||
1224 | pri_dai->dma_capture.ch_name = "rx"; | 1225 | pri_dai->dma_capture.ch_name = "rx"; |
1225 | pri_dai->dma_playback.dma_size = 4; | 1226 | pri_dai->dma_playback.dma_size = 4; |
1226 | pri_dai->dma_capture.dma_size = 4; | 1227 | pri_dai->dma_capture.dma_size = 4; |
@@ -1238,8 +1239,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1238 | goto err; | 1239 | goto err; |
1239 | } | 1240 | } |
1240 | sec_dai->dma_playback.dma_addr = regs_base + I2STXDS; | 1241 | sec_dai->dma_playback.dma_addr = regs_base + I2STXDS; |
1241 | sec_dai->dma_playback.client = | ||
1242 | (struct s3c_dma_client *)&sec_dai->dma_playback; | ||
1243 | sec_dai->dma_playback.ch_name = "tx-sec"; | 1242 | sec_dai->dma_playback.ch_name = "tx-sec"; |
1244 | 1243 | ||
1245 | if (!np) { | 1244 | if (!np) { |
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c index 8cc5770abb39..db6cefa18017 100644 --- a/sound/soc/samsung/idma.c +++ b/sound/soc/samsung/idma.c | |||
@@ -261,10 +261,9 @@ static int idma_mmap(struct snd_pcm_substream *substream, | |||
261 | static irqreturn_t iis_irq(int irqno, void *dev_id) | 261 | static irqreturn_t iis_irq(int irqno, void *dev_id) |
262 | { | 262 | { |
263 | struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id; | 263 | struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id; |
264 | u32 iiscon, iisahb, val, addr; | 264 | u32 iisahb, val, addr; |
265 | 265 | ||
266 | iisahb = readl(idma.regs + I2SAHB); | 266 | iisahb = readl(idma.regs + I2SAHB); |
267 | iiscon = readl(idma.regs + I2SCON); | ||
268 | 267 | ||
269 | val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0; | 268 | val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0; |
270 | 269 | ||
diff --git a/sound/soc/samsung/odroidx2_max98090.c b/sound/soc/samsung/odroidx2_max98090.c new file mode 100644 index 000000000000..278edf9e2a87 --- /dev/null +++ b/sound/soc/samsung/odroidx2_max98090.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Samsung Electronics Co., Ltd. | ||
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 | |||
10 | #include <linux/of.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <sound/soc.h> | ||
13 | #include <sound/pcm_params.h> | ||
14 | #include "i2s.h" | ||
15 | |||
16 | struct odroidx2_drv_data { | ||
17 | const struct snd_soc_dapm_widget *dapm_widgets; | ||
18 | unsigned int num_dapm_widgets; | ||
19 | }; | ||
20 | |||
21 | /* The I2S CDCLK output clock frequency for the MAX98090 codec */ | ||
22 | #define MAX98090_MCLK 19200000 | ||
23 | |||
24 | static int odroidx2_late_probe(struct snd_soc_card *card) | ||
25 | { | ||
26 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
27 | struct snd_soc_dai *cpu_dai = card->rtd[0].cpu_dai; | ||
28 | int ret; | ||
29 | |||
30 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, MAX98090_MCLK, | ||
31 | SND_SOC_CLOCK_IN); | ||
32 | if (ret < 0) | ||
33 | return ret; | ||
34 | |||
35 | /* Set the cpu DAI configuration in order to use CDCLK */ | ||
36 | return snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK, | ||
37 | 0, SND_SOC_CLOCK_OUT); | ||
38 | } | ||
39 | |||
40 | static const struct snd_soc_dapm_widget odroidx2_dapm_widgets[] = { | ||
41 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
42 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
43 | SND_SOC_DAPM_MIC("DMIC", NULL), | ||
44 | }; | ||
45 | |||
46 | static const struct snd_soc_dapm_widget odroidu3_dapm_widgets[] = { | ||
47 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
48 | SND_SOC_DAPM_SPK("Speakers", NULL), | ||
49 | }; | ||
50 | |||
51 | static struct snd_soc_dai_link odroidx2_dai[] = { | ||
52 | { | ||
53 | .name = "MAX98090", | ||
54 | .stream_name = "MAX98090 PCM", | ||
55 | .codec_dai_name = "HiFi", | ||
56 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
57 | SND_SOC_DAIFMT_CBM_CFM, | ||
58 | } | ||
59 | }; | ||
60 | |||
61 | static struct snd_soc_card odroidx2 = { | ||
62 | .owner = THIS_MODULE, | ||
63 | .dai_link = odroidx2_dai, | ||
64 | .num_links = ARRAY_SIZE(odroidx2_dai), | ||
65 | .fully_routed = true, | ||
66 | .late_probe = odroidx2_late_probe, | ||
67 | }; | ||
68 | |||
69 | struct odroidx2_drv_data odroidx2_drvdata = { | ||
70 | .dapm_widgets = odroidx2_dapm_widgets, | ||
71 | .num_dapm_widgets = ARRAY_SIZE(odroidx2_dapm_widgets), | ||
72 | }; | ||
73 | |||
74 | struct odroidx2_drv_data odroidu3_drvdata = { | ||
75 | .dapm_widgets = odroidu3_dapm_widgets, | ||
76 | .num_dapm_widgets = ARRAY_SIZE(odroidu3_dapm_widgets), | ||
77 | }; | ||
78 | |||
79 | static const struct of_device_id odroidx2_audio_of_match[] = { | ||
80 | { | ||
81 | .compatible = "samsung,odroidx2-audio", | ||
82 | .data = &odroidx2_drvdata, | ||
83 | }, { | ||
84 | .compatible = "samsung,odroidu3-audio", | ||
85 | .data = &odroidu3_drvdata, | ||
86 | }, | ||
87 | { }, | ||
88 | }; | ||
89 | MODULE_DEVICE_TABLE(of, odroidx2_audio_of_match); | ||
90 | |||
91 | static int odroidx2_audio_probe(struct platform_device *pdev) | ||
92 | { | ||
93 | struct device_node *snd_node = pdev->dev.of_node; | ||
94 | struct snd_soc_card *card = &odroidx2; | ||
95 | struct device_node *i2s_node, *codec_node; | ||
96 | struct odroidx2_drv_data *dd; | ||
97 | const struct of_device_id *of_id; | ||
98 | int ret; | ||
99 | |||
100 | of_id = of_match_node(odroidx2_audio_of_match, snd_node); | ||
101 | dd = (struct odroidx2_drv_data *)of_id->data; | ||
102 | |||
103 | card->num_dapm_widgets = dd->num_dapm_widgets; | ||
104 | card->dapm_widgets = dd->dapm_widgets; | ||
105 | |||
106 | card->dev = &pdev->dev; | ||
107 | |||
108 | ret = snd_soc_of_parse_card_name(card, "samsung,model"); | ||
109 | if (ret < 0) | ||
110 | return ret; | ||
111 | |||
112 | ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); | ||
113 | if (ret < 0) | ||
114 | return ret; | ||
115 | |||
116 | codec_node = of_parse_phandle(snd_node, "samsung,audio-codec", 0); | ||
117 | if (!codec_node) { | ||
118 | dev_err(&pdev->dev, | ||
119 | "Failed parsing samsung,i2s-codec property\n"); | ||
120 | return -EINVAL; | ||
121 | } | ||
122 | |||
123 | i2s_node = of_parse_phandle(snd_node, "samsung,i2s-controller", 0); | ||
124 | if (!i2s_node) { | ||
125 | dev_err(&pdev->dev, | ||
126 | "Failed parsing samsung,i2s-controller property\n"); | ||
127 | ret = -EINVAL; | ||
128 | goto err_put_codec_n; | ||
129 | } | ||
130 | |||
131 | odroidx2_dai[0].codec_of_node = codec_node; | ||
132 | odroidx2_dai[0].cpu_of_node = i2s_node; | ||
133 | odroidx2_dai[0].platform_of_node = i2s_node; | ||
134 | |||
135 | ret = snd_soc_register_card(card); | ||
136 | if (ret) { | ||
137 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
138 | ret); | ||
139 | goto err_put_i2s_n; | ||
140 | } | ||
141 | return 0; | ||
142 | |||
143 | err_put_i2s_n: | ||
144 | of_node_put(i2s_node); | ||
145 | err_put_codec_n: | ||
146 | of_node_put(codec_node); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static int odroidx2_audio_remove(struct platform_device *pdev) | ||
151 | { | ||
152 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
153 | |||
154 | snd_soc_unregister_card(card); | ||
155 | |||
156 | of_node_put((struct device_node *)odroidx2_dai[0].cpu_of_node); | ||
157 | of_node_put((struct device_node *)odroidx2_dai[0].codec_of_node); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static struct platform_driver odroidx2_audio_driver = { | ||
163 | .driver = { | ||
164 | .name = "odroidx2-audio", | ||
165 | .owner = THIS_MODULE, | ||
166 | .of_match_table = odroidx2_audio_of_match, | ||
167 | .pm = &snd_soc_pm_ops, | ||
168 | }, | ||
169 | .probe = odroidx2_audio_probe, | ||
170 | .remove = odroidx2_audio_remove, | ||
171 | }; | ||
172 | module_platform_driver(odroidx2_audio_driver); | ||
173 | |||
174 | MODULE_AUTHOR("Chen Zhen <zhen1.chen@samsung.com>"); | ||
175 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); | ||
176 | MODULE_DESCRIPTION("ALSA SoC Odroid X2/U3 Audio Support"); | ||
177 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 4c5f97fe45c8..bac034b15a27 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c | |||
@@ -131,32 +131,20 @@ struct s3c_pcm_info { | |||
131 | struct s3c_dma_params *dma_capture; | 131 | struct s3c_dma_params *dma_capture; |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static struct s3c_dma_client s3c_pcm_dma_client_out = { | ||
135 | .name = "PCM Stereo out" | ||
136 | }; | ||
137 | |||
138 | static struct s3c_dma_client s3c_pcm_dma_client_in = { | ||
139 | .name = "PCM Stereo in" | ||
140 | }; | ||
141 | |||
142 | static struct s3c_dma_params s3c_pcm_stereo_out[] = { | 134 | static struct s3c_dma_params s3c_pcm_stereo_out[] = { |
143 | [0] = { | 135 | [0] = { |
144 | .client = &s3c_pcm_dma_client_out, | ||
145 | .dma_size = 4, | 136 | .dma_size = 4, |
146 | }, | 137 | }, |
147 | [1] = { | 138 | [1] = { |
148 | .client = &s3c_pcm_dma_client_out, | ||
149 | .dma_size = 4, | 139 | .dma_size = 4, |
150 | }, | 140 | }, |
151 | }; | 141 | }; |
152 | 142 | ||
153 | static struct s3c_dma_params s3c_pcm_stereo_in[] = { | 143 | static struct s3c_dma_params s3c_pcm_stereo_in[] = { |
154 | [0] = { | 144 | [0] = { |
155 | .client = &s3c_pcm_dma_client_in, | ||
156 | .dma_size = 4, | 145 | .dma_size = 4, |
157 | }, | 146 | }, |
158 | [1] = { | 147 | [1] = { |
159 | .client = &s3c_pcm_dma_client_in, | ||
160 | .dma_size = 4, | 148 | .dma_size = 4, |
161 | }, | 149 | }, |
162 | }; | 150 | }; |
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 0ff4bbe23af3..df65c5b494b1 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c | |||
@@ -22,8 +22,6 @@ | |||
22 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
23 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
24 | 24 | ||
25 | #include <mach/dma.h> | ||
26 | |||
27 | #include "regs-i2s-v2.h" | 25 | #include "regs-i2s-v2.h" |
28 | #include "s3c-i2s-v2.h" | 26 | #include "s3c-i2s-v2.h" |
29 | #include "dma.h" | 27 | #include "dma.h" |
@@ -392,8 +390,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
392 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); | 390 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
393 | unsigned long irqs; | 391 | unsigned long irqs; |
394 | int ret = 0; | 392 | int ret = 0; |
395 | struct s3c_dma_params *dma_data = | ||
396 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
397 | 393 | ||
398 | pr_debug("Entered %s\n", __func__); | 394 | pr_debug("Entered %s\n", __func__); |
399 | 395 | ||
@@ -424,13 +420,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
424 | 420 | ||
425 | local_irq_restore(irqs); | 421 | local_irq_restore(irqs); |
426 | 422 | ||
427 | /* | ||
428 | * Load the next buffer to DMA to meet the reqirement | ||
429 | * of the auto reload mechanism of S3C24XX. | ||
430 | * This call won't bother S3C64XX. | ||
431 | */ | ||
432 | s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); | ||
433 | |||
434 | break; | 423 | break; |
435 | 424 | ||
436 | case SNDRV_PCM_TRIGGER_STOP: | 425 | case SNDRV_PCM_TRIGGER_STOP: |
@@ -644,12 +633,6 @@ int s3c_i2sv2_probe(struct snd_soc_dai *dai, | |||
644 | /* record our i2s structure for later use in the callbacks */ | 633 | /* record our i2s structure for later use in the callbacks */ |
645 | snd_soc_dai_set_drvdata(dai, i2s); | 634 | snd_soc_dai_set_drvdata(dai, i2s); |
646 | 635 | ||
647 | i2s->regs = ioremap(base, 0x100); | ||
648 | if (i2s->regs == NULL) { | ||
649 | dev_err(dev, "cannot ioremap registers\n"); | ||
650 | return -ENXIO; | ||
651 | } | ||
652 | |||
653 | i2s->iis_pclk = clk_get(dev, "iis"); | 636 | i2s->iis_pclk = clk_get(dev, "iis"); |
654 | if (IS_ERR(i2s->iis_pclk)) { | 637 | if (IS_ERR(i2s->iis_pclk)) { |
655 | dev_err(dev, "failed to get iis_clock\n"); | 638 | dev_err(dev, "failed to get iis_clock\n"); |
@@ -729,7 +712,7 @@ int s3c_i2sv2_register_component(struct device *dev, int id, | |||
729 | struct snd_soc_component_driver *cmp_drv, | 712 | struct snd_soc_component_driver *cmp_drv, |
730 | struct snd_soc_dai_driver *dai_drv) | 713 | struct snd_soc_dai_driver *dai_drv) |
731 | { | 714 | { |
732 | struct snd_soc_dai_ops *ops = dai_drv->ops; | 715 | struct snd_soc_dai_ops *ops = (struct snd_soc_dai_ops *)dai_drv->ops; |
733 | 716 | ||
734 | ops->trigger = s3c2412_i2s_trigger; | 717 | ops->trigger = s3c2412_i2s_trigger; |
735 | if (!ops->hw_params) | 718 | if (!ops->hw_params) |
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 08c059be9104..27b339c6580e 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c | |||
@@ -33,25 +33,15 @@ | |||
33 | #include "regs-i2s-v2.h" | 33 | #include "regs-i2s-v2.h" |
34 | #include "s3c2412-i2s.h" | 34 | #include "s3c2412-i2s.h" |
35 | 35 | ||
36 | static struct s3c_dma_client s3c2412_dma_client_out = { | ||
37 | .name = "I2S PCM Stereo out" | ||
38 | }; | ||
39 | |||
40 | static struct s3c_dma_client s3c2412_dma_client_in = { | ||
41 | .name = "I2S PCM Stereo in" | ||
42 | }; | ||
43 | |||
44 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = { | 36 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = { |
45 | .client = &s3c2412_dma_client_out, | ||
46 | .channel = DMACH_I2S_OUT, | 37 | .channel = DMACH_I2S_OUT, |
47 | .dma_addr = S3C2410_PA_IIS + S3C2412_IISTXD, | 38 | .ch_name = "tx", |
48 | .dma_size = 4, | 39 | .dma_size = 4, |
49 | }; | 40 | }; |
50 | 41 | ||
51 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { | 42 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { |
52 | .client = &s3c2412_dma_client_in, | ||
53 | .channel = DMACH_I2S_IN, | 43 | .channel = DMACH_I2S_IN, |
54 | .dma_addr = S3C2410_PA_IIS + S3C2412_IISRXD, | 44 | .ch_name = "rx", |
55 | .dma_size = 4, | 45 | .dma_size = 4, |
56 | }; | 46 | }; |
57 | 47 | ||
@@ -63,6 +53,9 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) | |||
63 | 53 | ||
64 | pr_debug("Entered %s\n", __func__); | 54 | pr_debug("Entered %s\n", __func__); |
65 | 55 | ||
56 | samsung_asoc_init_dma_data(dai, &s3c2412_i2s_pcm_stereo_out, | ||
57 | &s3c2412_i2s_pcm_stereo_in); | ||
58 | |||
66 | ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); | 59 | ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); |
67 | if (ret) | 60 | if (ret) |
68 | return ret; | 61 | return ret; |
@@ -70,17 +63,16 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) | |||
70 | s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; | 63 | s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; |
71 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; | 64 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; |
72 | 65 | ||
73 | s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk"); | 66 | s3c2412_i2s.iis_cclk = devm_clk_get(dai->dev, "i2sclk"); |
74 | if (IS_ERR(s3c2412_i2s.iis_cclk)) { | 67 | if (IS_ERR(s3c2412_i2s.iis_cclk)) { |
75 | pr_err("failed to get i2sclk clock\n"); | 68 | pr_err("failed to get i2sclk clock\n"); |
76 | iounmap(s3c2412_i2s.regs); | ||
77 | return PTR_ERR(s3c2412_i2s.iis_cclk); | 69 | return PTR_ERR(s3c2412_i2s.iis_cclk); |
78 | } | 70 | } |
79 | 71 | ||
80 | /* Set MPLL as the source for IIS CLK */ | 72 | /* Set MPLL as the source for IIS CLK */ |
81 | 73 | ||
82 | clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll")); | 74 | clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll")); |
83 | clk_enable(s3c2412_i2s.iis_cclk); | 75 | clk_prepare_enable(s3c2412_i2s.iis_cclk); |
84 | 76 | ||
85 | s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; | 77 | s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; |
86 | 78 | ||
@@ -93,9 +85,7 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) | |||
93 | 85 | ||
94 | static int s3c2412_i2s_remove(struct snd_soc_dai *dai) | 86 | static int s3c2412_i2s_remove(struct snd_soc_dai *dai) |
95 | { | 87 | { |
96 | clk_disable(s3c2412_i2s.iis_cclk); | 88 | clk_disable_unprepare(s3c2412_i2s.iis_cclk); |
97 | clk_put(s3c2412_i2s.iis_cclk); | ||
98 | iounmap(s3c2412_i2s.regs); | ||
99 | 89 | ||
100 | return 0; | 90 | return 0; |
101 | } | 91 | } |
@@ -105,18 +95,10 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | |||
105 | struct snd_soc_dai *cpu_dai) | 95 | struct snd_soc_dai *cpu_dai) |
106 | { | 96 | { |
107 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); | 97 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); |
108 | struct s3c_dma_params *dma_data; | ||
109 | u32 iismod; | 98 | u32 iismod; |
110 | 99 | ||
111 | pr_debug("Entered %s\n", __func__); | 100 | pr_debug("Entered %s\n", __func__); |
112 | 101 | ||
113 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
114 | dma_data = i2s->dma_playback; | ||
115 | else | ||
116 | dma_data = i2s->dma_capture; | ||
117 | |||
118 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); | ||
119 | |||
120 | iismod = readl(i2s->regs + S3C2412_IISMOD); | 102 | iismod = readl(i2s->regs + S3C2412_IISMOD); |
121 | pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); | 103 | pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); |
122 | 104 | ||
@@ -169,6 +151,15 @@ static const struct snd_soc_component_driver s3c2412_i2s_component = { | |||
169 | static int s3c2412_iis_dev_probe(struct platform_device *pdev) | 151 | static int s3c2412_iis_dev_probe(struct platform_device *pdev) |
170 | { | 152 | { |
171 | int ret = 0; | 153 | int ret = 0; |
154 | struct resource *res; | ||
155 | |||
156 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
157 | s3c2412_i2s.regs = devm_ioremap_resource(&pdev->dev, res); | ||
158 | if (IS_ERR(s3c2412_i2s.regs)) | ||
159 | return PTR_ERR(s3c2412_i2s.regs); | ||
160 | |||
161 | s3c2412_i2s_pcm_stereo_out.dma_addr = res->start + S3C2412_IISTXD; | ||
162 | s3c2412_i2s_pcm_stereo_in.dma_addr = res->start + S3C2412_IISRXD; | ||
172 | 163 | ||
173 | ret = s3c_i2sv2_register_component(&pdev->dev, -1, | 164 | ret = s3c_i2sv2_register_component(&pdev->dev, -1, |
174 | &s3c2412_i2s_component, | 165 | &s3c2412_i2s_component, |
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 9aba9fb7df0e..e87d9a2053b8 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c | |||
@@ -31,25 +31,15 @@ | |||
31 | #include "dma.h" | 31 | #include "dma.h" |
32 | #include "s3c24xx-i2s.h" | 32 | #include "s3c24xx-i2s.h" |
33 | 33 | ||
34 | static struct s3c_dma_client s3c24xx_dma_client_out = { | ||
35 | .name = "I2S PCM Stereo out" | ||
36 | }; | ||
37 | |||
38 | static struct s3c_dma_client s3c24xx_dma_client_in = { | ||
39 | .name = "I2S PCM Stereo in" | ||
40 | }; | ||
41 | |||
42 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = { | 34 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = { |
43 | .client = &s3c24xx_dma_client_out, | ||
44 | .channel = DMACH_I2S_OUT, | 35 | .channel = DMACH_I2S_OUT, |
45 | .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, | 36 | .ch_name = "tx", |
46 | .dma_size = 2, | 37 | .dma_size = 2, |
47 | }; | 38 | }; |
48 | 39 | ||
49 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = { | 40 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = { |
50 | .client = &s3c24xx_dma_client_in, | ||
51 | .channel = DMACH_I2S_IN, | 41 | .channel = DMACH_I2S_IN, |
52 | .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, | 42 | .ch_name = "rx", |
53 | .dma_size = 2, | 43 | .dma_size = 2, |
54 | }; | 44 | }; |
55 | 45 | ||
@@ -231,18 +221,12 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
231 | struct snd_pcm_hw_params *params, | 221 | struct snd_pcm_hw_params *params, |
232 | struct snd_soc_dai *dai) | 222 | struct snd_soc_dai *dai) |
233 | { | 223 | { |
234 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 224 | struct snd_dmaengine_dai_dma_data *dma_data; |
235 | struct s3c_dma_params *dma_data; | ||
236 | u32 iismod; | 225 | u32 iismod; |
237 | 226 | ||
238 | pr_debug("Entered %s\n", __func__); | 227 | pr_debug("Entered %s\n", __func__); |
239 | 228 | ||
240 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 229 | dma_data = snd_soc_dai_get_dma_data(dai, substream); |
241 | dma_data = &s3c24xx_i2s_pcm_stereo_out; | ||
242 | else | ||
243 | dma_data = &s3c24xx_i2s_pcm_stereo_in; | ||
244 | |||
245 | snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); | ||
246 | 230 | ||
247 | /* Working copies of register */ | 231 | /* Working copies of register */ |
248 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 232 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -251,11 +235,11 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
251 | switch (params_width(params)) { | 235 | switch (params_width(params)) { |
252 | case 8: | 236 | case 8: |
253 | iismod &= ~S3C2410_IISMOD_16BIT; | 237 | iismod &= ~S3C2410_IISMOD_16BIT; |
254 | dma_data->dma_size = 1; | 238 | dma_data->addr_width = 1; |
255 | break; | 239 | break; |
256 | case 16: | 240 | case 16: |
257 | iismod |= S3C2410_IISMOD_16BIT; | 241 | iismod |= S3C2410_IISMOD_16BIT; |
258 | dma_data->dma_size = 2; | 242 | dma_data->addr_width = 2; |
259 | break; | 243 | break; |
260 | default: | 244 | default: |
261 | return -EINVAL; | 245 | return -EINVAL; |
@@ -270,8 +254,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
270 | struct snd_soc_dai *dai) | 254 | struct snd_soc_dai *dai) |
271 | { | 255 | { |
272 | int ret = 0; | 256 | int ret = 0; |
273 | struct s3c_dma_params *dma_data = | ||
274 | snd_soc_dai_get_dma_data(dai, substream); | ||
275 | 257 | ||
276 | pr_debug("Entered %s\n", __func__); | 258 | pr_debug("Entered %s\n", __func__); |
277 | 259 | ||
@@ -290,7 +272,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
290 | else | 272 | else |
291 | s3c24xx_snd_txctrl(1); | 273 | s3c24xx_snd_txctrl(1); |
292 | 274 | ||
293 | s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); | ||
294 | break; | 275 | break; |
295 | case SNDRV_PCM_TRIGGER_STOP: | 276 | case SNDRV_PCM_TRIGGER_STOP: |
296 | case SNDRV_PCM_TRIGGER_SUSPEND: | 277 | case SNDRV_PCM_TRIGGER_SUSPEND: |
@@ -380,17 +361,15 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) | |||
380 | { | 361 | { |
381 | pr_debug("Entered %s\n", __func__); | 362 | pr_debug("Entered %s\n", __func__); |
382 | 363 | ||
383 | s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100); | 364 | samsung_asoc_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out, |
384 | if (s3c24xx_i2s.regs == NULL) | 365 | &s3c24xx_i2s_pcm_stereo_in); |
385 | return -ENXIO; | ||
386 | 366 | ||
387 | s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis"); | 367 | s3c24xx_i2s.iis_clk = devm_clk_get(dai->dev, "iis"); |
388 | if (IS_ERR(s3c24xx_i2s.iis_clk)) { | 368 | if (IS_ERR(s3c24xx_i2s.iis_clk)) { |
389 | pr_err("failed to get iis_clock\n"); | 369 | pr_err("failed to get iis_clock\n"); |
390 | iounmap(s3c24xx_i2s.regs); | ||
391 | return PTR_ERR(s3c24xx_i2s.iis_clk); | 370 | return PTR_ERR(s3c24xx_i2s.iis_clk); |
392 | } | 371 | } |
393 | clk_enable(s3c24xx_i2s.iis_clk); | 372 | clk_prepare_enable(s3c24xx_i2s.iis_clk); |
394 | 373 | ||
395 | /* Configure the I2S pins (GPE0...GPE4) in correct mode */ | 374 | /* Configure the I2S pins (GPE0...GPE4) in correct mode */ |
396 | s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), | 375 | s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), |
@@ -414,7 +393,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) | |||
414 | s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); | 393 | s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); |
415 | s3c24xx_i2s.iispsr = readl(s3c24xx_i2s.regs + S3C2410_IISPSR); | 394 | s3c24xx_i2s.iispsr = readl(s3c24xx_i2s.regs + S3C2410_IISPSR); |
416 | 395 | ||
417 | clk_disable(s3c24xx_i2s.iis_clk); | 396 | clk_disable_unprepare(s3c24xx_i2s.iis_clk); |
418 | 397 | ||
419 | return 0; | 398 | return 0; |
420 | } | 399 | } |
@@ -422,7 +401,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) | |||
422 | static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) | 401 | static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) |
423 | { | 402 | { |
424 | pr_debug("Entered %s\n", __func__); | 403 | pr_debug("Entered %s\n", __func__); |
425 | clk_enable(s3c24xx_i2s.iis_clk); | 404 | clk_prepare_enable(s3c24xx_i2s.iis_clk); |
426 | 405 | ||
427 | writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); | 406 | writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); |
428 | writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); | 407 | writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -474,6 +453,19 @@ static const struct snd_soc_component_driver s3c24xx_i2s_component = { | |||
474 | static int s3c24xx_iis_dev_probe(struct platform_device *pdev) | 453 | static int s3c24xx_iis_dev_probe(struct platform_device *pdev) |
475 | { | 454 | { |
476 | int ret = 0; | 455 | int ret = 0; |
456 | struct resource *res; | ||
457 | |||
458 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
459 | if (!res) { | ||
460 | dev_err(&pdev->dev, "Can't get IO resource.\n"); | ||
461 | return -ENOENT; | ||
462 | } | ||
463 | s3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res); | ||
464 | if (s3c24xx_i2s.regs == NULL) | ||
465 | return -ENXIO; | ||
466 | |||
467 | s3c24xx_i2s_pcm_stereo_out.dma_addr = res->start + S3C2410_IISFIFO; | ||
468 | s3c24xx_i2s_pcm_stereo_in.dma_addr = res->start + S3C2410_IISFIFO; | ||
477 | 469 | ||
478 | ret = devm_snd_soc_register_component(&pdev->dev, | 470 | ret = devm_snd_soc_register_component(&pdev->dev, |
479 | &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); | 471 | &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); |
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c index e119aaa91c28..63d079303561 100644 --- a/sound/soc/samsung/smdk_wm8580pcm.c +++ b/sound/soc/samsung/smdk_wm8580pcm.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * o '0' means 'OFF' | 25 | * o '0' means 'OFF' |
26 | * o 'X' means 'Don't care' | 26 | * o 'X' means 'Don't care' |
27 | * | 27 | * |
28 | * SMDK6410, SMDK6440, SMDK6450 Base B/D: CFG1-0000, CFG2-1111 | 28 | * SMDK6410 Base B/D: CFG1-0000, CFG2-1111 |
29 | * SMDKC110, SMDKV210: CFGB11-100100, CFGB12-0000 | 29 | * SMDKC110, SMDKV210: CFGB11-100100, CFGB12-0000 |
30 | */ | 30 | */ |
31 | 31 | ||
diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 014c177840ba..0acf5d0eed53 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c | |||
@@ -92,6 +92,9 @@ static int snow_probe(struct platform_device *pdev) | |||
92 | 92 | ||
93 | card->dev = &pdev->dev; | 93 | card->dev = &pdev->dev; |
94 | 94 | ||
95 | /* Update card-name if provided through DT, else use default name */ | ||
96 | snd_soc_of_parse_card_name(card, "samsung,model"); | ||
97 | |||
95 | ret = devm_snd_soc_register_card(&pdev->dev, card); | 98 | ret = devm_snd_soc_register_card(&pdev->dev, card); |
96 | if (ret) { | 99 | if (ret) { |
97 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | 100 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); |
@@ -103,6 +106,7 @@ static int snow_probe(struct platform_device *pdev) | |||
103 | 106 | ||
104 | static const struct of_device_id snow_of_match[] = { | 107 | static const struct of_device_id snow_of_match[] = { |
105 | { .compatible = "google,snow-audio-max98090", }, | 108 | { .compatible = "google,snow-audio-max98090", }, |
109 | { .compatible = "google,snow-audio-max98091", }, | ||
106 | { .compatible = "google,snow-audio-max98095", }, | 110 | { .compatible = "google,snow-audio-max98095", }, |
107 | {}, | 111 | {}, |
108 | }; | 112 | }; |
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index d9ffc48fce5e..d7d2e208f486 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c | |||
@@ -93,10 +93,6 @@ struct samsung_spdif_info { | |||
93 | struct s3c_dma_params *dma_playback; | 93 | struct s3c_dma_params *dma_playback; |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static struct s3c_dma_client spdif_dma_client_out = { | ||
97 | .name = "S/PDIF Stereo out", | ||
98 | }; | ||
99 | |||
100 | static struct s3c_dma_params spdif_stereo_out; | 96 | static struct s3c_dma_params spdif_stereo_out; |
101 | static struct samsung_spdif_info spdif_info; | 97 | static struct samsung_spdif_info spdif_info; |
102 | 98 | ||
@@ -435,7 +431,6 @@ static int spdif_probe(struct platform_device *pdev) | |||
435 | } | 431 | } |
436 | 432 | ||
437 | spdif_stereo_out.dma_size = 2; | 433 | spdif_stereo_out.dma_size = 2; |
438 | spdif_stereo_out.client = &spdif_dma_client_out; | ||
439 | spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF; | 434 | spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF; |
440 | spdif_stereo_out.channel = dma_res->start; | 435 | spdif_stereo_out.channel = dma_res->start; |
441 | 436 | ||
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index b43fdf0d08af..80245b6eebd6 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig | |||
@@ -37,7 +37,7 @@ config SND_SOC_SH4_SIU | |||
37 | config SND_SOC_RCAR | 37 | config SND_SOC_RCAR |
38 | tristate "R-Car series SRU/SCU/SSIU/SSI support" | 38 | tristate "R-Car series SRU/SCU/SSIU/SSI support" |
39 | select SND_SIMPLE_CARD | 39 | select SND_SIMPLE_CARD |
40 | select REGMAP | 40 | select REGMAP_MMIO |
41 | help | 41 | help |
42 | This option enables R-Car SUR/SCU/SSIU/SSI sound support | 42 | This option enables R-Car SUR/SCU/SSIU/SSI sound support |
43 | 43 | ||
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 710a079a7377..c76344350e44 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -232,11 +232,7 @@ 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 work_struct work; | ||
236 | dma_addr_t dma; | ||
237 | int dma_id; | 235 | int dma_id; |
238 | int loop_cnt; | ||
239 | int additional_pos; | ||
240 | }; | 236 | }; |
241 | 237 | ||
242 | struct fsi_clk { | 238 | struct fsi_clk { |
@@ -264,12 +260,12 @@ struct fsi_priv { | |||
264 | u32 fmt; | 260 | u32 fmt; |
265 | 261 | ||
266 | int chan_num:16; | 262 | int chan_num:16; |
267 | int clk_master:1; | 263 | unsigned int clk_master:1; |
268 | int clk_cpg:1; | 264 | unsigned int clk_cpg:1; |
269 | int spdif:1; | 265 | unsigned int spdif:1; |
270 | int enable_stream:1; | 266 | unsigned int enable_stream:1; |
271 | int bit_clk_inv:1; | 267 | unsigned int bit_clk_inv:1; |
272 | int lr_clk_inv:1; | 268 | unsigned int lr_clk_inv:1; |
273 | }; | 269 | }; |
274 | 270 | ||
275 | struct fsi_stream_handler { | 271 | struct fsi_stream_handler { |
@@ -1042,6 +1038,26 @@ static int fsi_clk_set_rate_cpg(struct device *dev, | |||
1042 | return ret; | 1038 | return ret; |
1043 | } | 1039 | } |
1044 | 1040 | ||
1041 | static void fsi_pointer_update(struct fsi_stream *io, int size) | ||
1042 | { | ||
1043 | io->buff_sample_pos += size; | ||
1044 | |||
1045 | if (io->buff_sample_pos >= | ||
1046 | io->period_samples * (io->period_pos + 1)) { | ||
1047 | struct snd_pcm_substream *substream = io->substream; | ||
1048 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1049 | |||
1050 | io->period_pos++; | ||
1051 | |||
1052 | if (io->period_pos >= runtime->periods) { | ||
1053 | io->buff_sample_pos = 0; | ||
1054 | io->period_pos = 0; | ||
1055 | } | ||
1056 | |||
1057 | snd_pcm_period_elapsed(substream); | ||
1058 | } | ||
1059 | } | ||
1060 | |||
1045 | /* | 1061 | /* |
1046 | * pio data transfer handler | 1062 | * pio data transfer handler |
1047 | */ | 1063 | */ |
@@ -1108,31 +1124,11 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io, | |||
1108 | void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples), | 1124 | void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples), |
1109 | int samples) | 1125 | int samples) |
1110 | { | 1126 | { |
1111 | struct snd_pcm_runtime *runtime; | ||
1112 | struct snd_pcm_substream *substream; | ||
1113 | u8 *buf; | 1127 | u8 *buf; |
1114 | int over_period; | ||
1115 | 1128 | ||
1116 | if (!fsi_stream_is_working(fsi, io)) | 1129 | if (!fsi_stream_is_working(fsi, io)) |
1117 | return -EINVAL; | 1130 | return -EINVAL; |
1118 | 1131 | ||
1119 | over_period = 0; | ||
1120 | substream = io->substream; | ||
1121 | runtime = substream->runtime; | ||
1122 | |||
1123 | /* FSI FIFO has limit. | ||
1124 | * So, this driver can not send periods data at a time | ||
1125 | */ | ||
1126 | if (io->buff_sample_pos >= | ||
1127 | io->period_samples * (io->period_pos + 1)) { | ||
1128 | |||
1129 | over_period = 1; | ||
1130 | io->period_pos = (io->period_pos + 1) % runtime->periods; | ||
1131 | |||
1132 | if (0 == io->period_pos) | ||
1133 | io->buff_sample_pos = 0; | ||
1134 | } | ||
1135 | |||
1136 | buf = fsi_pio_get_area(fsi, io); | 1132 | buf = fsi_pio_get_area(fsi, io); |
1137 | 1133 | ||
1138 | switch (io->sample_width) { | 1134 | switch (io->sample_width) { |
@@ -1146,11 +1142,7 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io, | |||
1146 | return -EINVAL; | 1142 | return -EINVAL; |
1147 | } | 1143 | } |
1148 | 1144 | ||
1149 | /* update buff_sample_pos */ | 1145 | fsi_pointer_update(io, samples); |
1150 | io->buff_sample_pos += samples; | ||
1151 | |||
1152 | if (over_period) | ||
1153 | snd_pcm_period_elapsed(substream); | ||
1154 | 1146 | ||
1155 | return 0; | 1147 | return 0; |
1156 | } | 1148 | } |
@@ -1279,11 +1271,6 @@ static irqreturn_t fsi_interrupt(int irq, void *data) | |||
1279 | */ | 1271 | */ |
1280 | static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) | 1272 | static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) |
1281 | { | 1273 | { |
1282 | struct snd_pcm_runtime *runtime = io->substream->runtime; | ||
1283 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); | ||
1284 | enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? | ||
1285 | DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
1286 | |||
1287 | /* | 1274 | /* |
1288 | * 24bit data : 24bit bus / package in back | 1275 | * 24bit data : 24bit bus / package in back |
1289 | * 16bit data : 16bit bus / stream mode | 1276 | * 16bit data : 16bit bus / stream mode |
@@ -1291,107 +1278,48 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1291 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | | 1278 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | |
1292 | BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); | 1279 | BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); |
1293 | 1280 | ||
1294 | io->loop_cnt = 2; /* push 1st, 2nd period first, then 3rd, 4th... */ | ||
1295 | io->additional_pos = 0; | ||
1296 | io->dma = dma_map_single(dai->dev, runtime->dma_area, | ||
1297 | snd_pcm_lib_buffer_bytes(io->substream), dir); | ||
1298 | return 0; | 1281 | return 0; |
1299 | } | 1282 | } |
1300 | 1283 | ||
1301 | static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io) | ||
1302 | { | ||
1303 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); | ||
1304 | enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? | ||
1305 | DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
1306 | |||
1307 | dma_unmap_single(dai->dev, io->dma, | ||
1308 | snd_pcm_lib_buffer_bytes(io->substream), dir); | ||
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | static dma_addr_t fsi_dma_get_area(struct fsi_stream *io, int additional) | ||
1313 | { | ||
1314 | struct snd_pcm_runtime *runtime = io->substream->runtime; | ||
1315 | int period = io->period_pos + additional; | ||
1316 | |||
1317 | if (period >= runtime->periods) | ||
1318 | period = 0; | ||
1319 | |||
1320 | return io->dma + samples_to_bytes(runtime, period * io->period_samples); | ||
1321 | } | ||
1322 | |||
1323 | static void fsi_dma_complete(void *data) | 1284 | static void fsi_dma_complete(void *data) |
1324 | { | 1285 | { |
1325 | struct fsi_stream *io = (struct fsi_stream *)data; | 1286 | struct fsi_stream *io = (struct fsi_stream *)data; |
1326 | struct fsi_priv *fsi = fsi_stream_to_priv(io); | 1287 | struct fsi_priv *fsi = fsi_stream_to_priv(io); |
1327 | struct snd_pcm_runtime *runtime = io->substream->runtime; | ||
1328 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); | ||
1329 | enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? | ||
1330 | DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
1331 | 1288 | ||
1332 | dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io, 0), | 1289 | fsi_pointer_update(io, io->period_samples); |
1333 | samples_to_bytes(runtime, io->period_samples), dir); | ||
1334 | |||
1335 | io->buff_sample_pos += io->period_samples; | ||
1336 | io->period_pos++; | ||
1337 | |||
1338 | if (io->period_pos >= runtime->periods) { | ||
1339 | io->period_pos = 0; | ||
1340 | io->buff_sample_pos = 0; | ||
1341 | } | ||
1342 | 1290 | ||
1343 | fsi_count_fifo_err(fsi); | 1291 | fsi_count_fifo_err(fsi); |
1344 | fsi_stream_transfer(io); | ||
1345 | |||
1346 | snd_pcm_period_elapsed(io->substream); | ||
1347 | } | 1292 | } |
1348 | 1293 | ||
1349 | static void fsi_dma_do_work(struct work_struct *work) | 1294 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) |
1350 | { | 1295 | { |
1351 | struct fsi_stream *io = container_of(work, struct fsi_stream, work); | 1296 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); |
1352 | struct fsi_priv *fsi = fsi_stream_to_priv(io); | 1297 | struct snd_pcm_substream *substream = io->substream; |
1353 | struct snd_soc_dai *dai; | ||
1354 | struct dma_async_tx_descriptor *desc; | 1298 | struct dma_async_tx_descriptor *desc; |
1355 | struct snd_pcm_runtime *runtime; | ||
1356 | enum dma_data_direction dir; | ||
1357 | int is_play = fsi_stream_is_play(fsi, io); | 1299 | int is_play = fsi_stream_is_play(fsi, io); |
1358 | int len, i; | 1300 | enum dma_data_direction dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; |
1359 | dma_addr_t buf; | 1301 | int ret = -EIO; |
1360 | 1302 | ||
1361 | if (!fsi_stream_is_working(fsi, io)) | 1303 | desc = dmaengine_prep_dma_cyclic(io->chan, |
1362 | return; | 1304 | substream->runtime->dma_addr, |
1363 | 1305 | snd_pcm_lib_buffer_bytes(substream), | |
1364 | dai = fsi_get_dai(io->substream); | 1306 | snd_pcm_lib_period_bytes(substream), |
1365 | runtime = io->substream->runtime; | 1307 | dir, |
1366 | dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 1308 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
1367 | len = samples_to_bytes(runtime, io->period_samples); | 1309 | if (!desc) { |
1368 | 1310 | dev_err(dai->dev, "dmaengine_prep_dma_cyclic() fail\n"); | |
1369 | for (i = 0; i < io->loop_cnt; i++) { | 1311 | goto fsi_dma_transfer_err; |
1370 | buf = fsi_dma_get_area(io, io->additional_pos); | 1312 | } |
1371 | |||
1372 | dma_sync_single_for_device(dai->dev, buf, len, dir); | ||
1373 | |||
1374 | desc = dmaengine_prep_slave_single(io->chan, buf, len, dir, | ||
1375 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
1376 | if (!desc) { | ||
1377 | dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n"); | ||
1378 | return; | ||
1379 | } | ||
1380 | |||
1381 | desc->callback = fsi_dma_complete; | ||
1382 | desc->callback_param = io; | ||
1383 | |||
1384 | if (dmaengine_submit(desc) < 0) { | ||
1385 | dev_err(dai->dev, "tx_submit() fail\n"); | ||
1386 | return; | ||
1387 | } | ||
1388 | 1313 | ||
1389 | dma_async_issue_pending(io->chan); | 1314 | desc->callback = fsi_dma_complete; |
1315 | desc->callback_param = io; | ||
1390 | 1316 | ||
1391 | io->additional_pos = 1; | 1317 | if (dmaengine_submit(desc) < 0) { |
1318 | dev_err(dai->dev, "tx_submit() fail\n"); | ||
1319 | goto fsi_dma_transfer_err; | ||
1392 | } | 1320 | } |
1393 | 1321 | ||
1394 | io->loop_cnt = 1; | 1322 | dma_async_issue_pending(io->chan); |
1395 | 1323 | ||
1396 | /* | 1324 | /* |
1397 | * FIXME | 1325 | * FIXME |
@@ -1408,13 +1336,11 @@ static void fsi_dma_do_work(struct work_struct *work) | |||
1408 | fsi_reg_write(fsi, DIFF_ST, 0); | 1336 | fsi_reg_write(fsi, DIFF_ST, 0); |
1409 | } | 1337 | } |
1410 | } | 1338 | } |
1411 | } | ||
1412 | 1339 | ||
1413 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) | 1340 | ret = 0; |
1414 | { | ||
1415 | schedule_work(&io->work); | ||
1416 | 1341 | ||
1417 | return 0; | 1342 | fsi_dma_transfer_err: |
1343 | return ret; | ||
1418 | } | 1344 | } |
1419 | 1345 | ||
1420 | static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | 1346 | static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, |
@@ -1475,15 +1401,11 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev | |||
1475 | return fsi_stream_probe(fsi, dev); | 1401 | return fsi_stream_probe(fsi, dev); |
1476 | } | 1402 | } |
1477 | 1403 | ||
1478 | INIT_WORK(&io->work, fsi_dma_do_work); | ||
1479 | |||
1480 | return 0; | 1404 | return 0; |
1481 | } | 1405 | } |
1482 | 1406 | ||
1483 | static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) | 1407 | static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) |
1484 | { | 1408 | { |
1485 | cancel_work_sync(&io->work); | ||
1486 | |||
1487 | fsi_stream_stop(fsi, io); | 1409 | fsi_stream_stop(fsi, io); |
1488 | 1410 | ||
1489 | if (io->chan) | 1411 | if (io->chan) |
@@ -1495,7 +1417,6 @@ static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1495 | 1417 | ||
1496 | static struct fsi_stream_handler fsi_dma_push_handler = { | 1418 | static struct fsi_stream_handler fsi_dma_push_handler = { |
1497 | .init = fsi_dma_init, | 1419 | .init = fsi_dma_init, |
1498 | .quit = fsi_dma_quit, | ||
1499 | .probe = fsi_dma_probe, | 1420 | .probe = fsi_dma_probe, |
1500 | .transfer = fsi_dma_transfer, | 1421 | .transfer = fsi_dma_transfer, |
1501 | .remove = fsi_dma_remove, | 1422 | .remove = fsi_dma_remove, |
@@ -1657,9 +1578,9 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
1657 | if (!ret) | 1578 | if (!ret) |
1658 | ret = fsi_hw_startup(fsi, io, dai->dev); | 1579 | ret = fsi_hw_startup(fsi, io, dai->dev); |
1659 | if (!ret) | 1580 | if (!ret) |
1660 | ret = fsi_stream_transfer(io); | 1581 | ret = fsi_stream_start(fsi, io); |
1661 | if (!ret) | 1582 | if (!ret) |
1662 | fsi_stream_start(fsi, io); | 1583 | ret = fsi_stream_transfer(io); |
1663 | break; | 1584 | break; |
1664 | case SNDRV_PCM_TRIGGER_STOP: | 1585 | case SNDRV_PCM_TRIGGER_STOP: |
1665 | if (!ret) | 1586 | if (!ret) |
@@ -1850,16 +1771,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm) | |||
1850 | 1771 | ||
1851 | static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd) | 1772 | static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd) |
1852 | { | 1773 | { |
1853 | struct snd_pcm *pcm = rtd->pcm; | ||
1854 | |||
1855 | /* | ||
1856 | * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel | ||
1857 | * in MMAP mode (i.e. aplay -M) | ||
1858 | */ | ||
1859 | return snd_pcm_lib_preallocate_pages_for_all( | 1774 | return snd_pcm_lib_preallocate_pages_for_all( |
1860 | pcm, | 1775 | rtd->pcm, |
1861 | SNDRV_DMA_TYPE_CONTINUOUS, | 1776 | SNDRV_DMA_TYPE_DEV, |
1862 | snd_dma_continuous_data(GFP_KERNEL), | 1777 | rtd->card->snd_card->dev, |
1863 | PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); | 1778 | PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); |
1864 | } | 1779 | } |
1865 | 1780 | ||
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 91880156e1ae..19f78963e8b9 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -138,6 +138,17 @@ char *rsnd_mod_name(struct rsnd_mod *mod) | |||
138 | return mod->ops->name; | 138 | return mod->ops->name; |
139 | } | 139 | } |
140 | 140 | ||
141 | char *rsnd_mod_dma_name(struct rsnd_mod *mod) | ||
142 | { | ||
143 | if (!mod || !mod->ops) | ||
144 | return "unknown"; | ||
145 | |||
146 | if (!mod->ops->dma_name) | ||
147 | return mod->ops->name; | ||
148 | |||
149 | return mod->ops->dma_name(mod); | ||
150 | } | ||
151 | |||
141 | void rsnd_mod_init(struct rsnd_priv *priv, | 152 | void rsnd_mod_init(struct rsnd_priv *priv, |
142 | struct rsnd_mod *mod, | 153 | struct rsnd_mod *mod, |
143 | struct rsnd_mod_ops *ops, | 154 | struct rsnd_mod_ops *ops, |
@@ -153,26 +164,8 @@ void rsnd_mod_init(struct rsnd_priv *priv, | |||
153 | /* | 164 | /* |
154 | * rsnd_dma functions | 165 | * rsnd_dma functions |
155 | */ | 166 | */ |
156 | static void __rsnd_dma_start(struct rsnd_dma *dma); | ||
157 | static void rsnd_dma_continue(struct rsnd_dma *dma) | ||
158 | { | ||
159 | /* push next A or B plane */ | ||
160 | dma->submit_loop = 1; | ||
161 | schedule_work(&dma->work); | ||
162 | } | ||
163 | |||
164 | void rsnd_dma_start(struct rsnd_dma *dma) | ||
165 | { | ||
166 | /* push both A and B plane*/ | ||
167 | dma->offset = 0; | ||
168 | dma->submit_loop = 2; | ||
169 | __rsnd_dma_start(dma); | ||
170 | } | ||
171 | |||
172 | void rsnd_dma_stop(struct rsnd_dma *dma) | 167 | void rsnd_dma_stop(struct rsnd_dma *dma) |
173 | { | 168 | { |
174 | dma->submit_loop = 0; | ||
175 | cancel_work_sync(&dma->work); | ||
176 | dmaengine_terminate_all(dma->chan); | 169 | dmaengine_terminate_all(dma->chan); |
177 | } | 170 | } |
178 | 171 | ||
@@ -180,11 +173,7 @@ static void rsnd_dma_complete(void *data) | |||
180 | { | 173 | { |
181 | struct rsnd_dma *dma = (struct rsnd_dma *)data; | 174 | struct rsnd_dma *dma = (struct rsnd_dma *)data; |
182 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 175 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
183 | struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); | ||
184 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 176 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
185 | unsigned long flags; | ||
186 | |||
187 | rsnd_lock(priv, flags); | ||
188 | 177 | ||
189 | /* | 178 | /* |
190 | * Renesas sound Gen1 needs 1 DMAC, | 179 | * Renesas sound Gen1 needs 1 DMAC, |
@@ -197,57 +186,41 @@ static void rsnd_dma_complete(void *data) | |||
197 | * rsnd_dai_pointer_update() will be called twice, | 186 | * rsnd_dai_pointer_update() will be called twice, |
198 | * ant it will breaks io->byte_pos | 187 | * ant it will breaks io->byte_pos |
199 | */ | 188 | */ |
200 | if (dma->submit_loop) | ||
201 | rsnd_dma_continue(dma); | ||
202 | |||
203 | rsnd_unlock(priv, flags); | ||
204 | 189 | ||
205 | rsnd_dai_pointer_update(io, io->byte_per_period); | 190 | rsnd_dai_pointer_update(io, io->byte_per_period); |
206 | } | 191 | } |
207 | 192 | ||
208 | static void __rsnd_dma_start(struct rsnd_dma *dma) | 193 | void rsnd_dma_start(struct rsnd_dma *dma) |
209 | { | 194 | { |
210 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 195 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
211 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 196 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
212 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 197 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
213 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 198 | struct snd_pcm_substream *substream = io->substream; |
214 | struct device *dev = rsnd_priv_to_dev(priv); | 199 | struct device *dev = rsnd_priv_to_dev(priv); |
215 | struct dma_async_tx_descriptor *desc; | 200 | struct dma_async_tx_descriptor *desc; |
216 | dma_addr_t buf; | ||
217 | size_t len = io->byte_per_period; | ||
218 | int i; | ||
219 | 201 | ||
220 | for (i = 0; i < dma->submit_loop; i++) { | 202 | desc = dmaengine_prep_dma_cyclic(dma->chan, |
221 | 203 | (dma->addr) ? dma->addr : | |
222 | buf = runtime->dma_addr + | 204 | substream->runtime->dma_addr, |
223 | rsnd_dai_pointer_offset(io, dma->offset + len); | 205 | snd_pcm_lib_buffer_bytes(substream), |
224 | dma->offset = len; | 206 | snd_pcm_lib_period_bytes(substream), |
225 | 207 | dma->dir, | |
226 | desc = dmaengine_prep_slave_single( | 208 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
227 | dma->chan, buf, len, dma->dir, | ||
228 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
229 | if (!desc) { | ||
230 | dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); | ||
231 | return; | ||
232 | } | ||
233 | 209 | ||
234 | desc->callback = rsnd_dma_complete; | 210 | if (!desc) { |
235 | desc->callback_param = dma; | 211 | dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); |
212 | return; | ||
213 | } | ||
236 | 214 | ||
237 | if (dmaengine_submit(desc) < 0) { | 215 | desc->callback = rsnd_dma_complete; |
238 | dev_err(dev, "dmaengine_submit() fail\n"); | 216 | desc->callback_param = dma; |
239 | return; | ||
240 | } | ||
241 | 217 | ||
242 | dma_async_issue_pending(dma->chan); | 218 | if (dmaengine_submit(desc) < 0) { |
219 | dev_err(dev, "dmaengine_submit() fail\n"); | ||
220 | return; | ||
243 | } | 221 | } |
244 | } | ||
245 | |||
246 | static void rsnd_dma_do_work(struct work_struct *work) | ||
247 | { | ||
248 | struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); | ||
249 | 222 | ||
250 | __rsnd_dma_start(dma); | 223 | dma_async_issue_pending(dma->chan); |
251 | } | 224 | } |
252 | 225 | ||
253 | int rsnd_dma_available(struct rsnd_dma *dma) | 226 | int rsnd_dma_available(struct rsnd_dma *dma) |
@@ -261,14 +234,27 @@ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod) | |||
261 | { | 234 | { |
262 | if (mod) | 235 | if (mod) |
263 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", | 236 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", |
264 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | 237 | rsnd_mod_dma_name(mod), rsnd_mod_id(mod)); |
265 | else | 238 | else |
266 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); | 239 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); |
267 | 240 | ||
268 | } | 241 | } |
269 | 242 | ||
270 | static void rsnd_dma_of_name(struct rsnd_dma *dma, | 243 | static void rsnd_dma_of_name(struct rsnd_mod *mod_from, |
271 | int is_play, char *dma_name) | 244 | struct rsnd_mod *mod_to, |
245 | char *dma_name) | ||
246 | { | ||
247 | int index = 0; | ||
248 | |||
249 | index = _rsnd_dma_of_name(dma_name + index, mod_from); | ||
250 | *(dma_name + index++) = '_'; | ||
251 | index = _rsnd_dma_of_name(dma_name + index, mod_to); | ||
252 | } | ||
253 | |||
254 | static void rsnd_dma_of_path(struct rsnd_dma *dma, | ||
255 | int is_play, | ||
256 | struct rsnd_mod **mod_from, | ||
257 | struct rsnd_mod **mod_to) | ||
272 | { | 258 | { |
273 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); | 259 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); |
274 | struct rsnd_dai_stream *io = rsnd_mod_to_io(this); | 260 | struct rsnd_dai_stream *io = rsnd_mod_to_io(this); |
@@ -276,7 +262,6 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, | |||
276 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | 262 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); |
277 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); | 263 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); |
278 | struct rsnd_mod *mod[MOD_MAX]; | 264 | struct rsnd_mod *mod[MOD_MAX]; |
279 | struct rsnd_mod *src_mod, *dst_mod; | ||
280 | int i, index; | 265 | int i, index; |
281 | 266 | ||
282 | 267 | ||
@@ -297,31 +282,34 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, | |||
297 | for (i = 1; i < MOD_MAX; i++) { | 282 | for (i = 1; i < MOD_MAX; i++) { |
298 | if (!src) { | 283 | if (!src) { |
299 | mod[i] = ssi; | 284 | mod[i] = ssi; |
300 | break; | ||
301 | } else if (!dvc) { | 285 | } else if (!dvc) { |
302 | mod[i] = src; | 286 | mod[i] = src; |
303 | src = NULL; | 287 | src = NULL; |
304 | } else { | 288 | } else { |
305 | mod[i] = dvc; | 289 | if ((!is_play) && (this == src)) |
290 | this = dvc; | ||
291 | |||
292 | mod[i] = (is_play) ? src : dvc; | ||
293 | i++; | ||
294 | mod[i] = (is_play) ? dvc : src; | ||
295 | src = NULL; | ||
306 | dvc = NULL; | 296 | dvc = NULL; |
307 | } | 297 | } |
308 | 298 | ||
309 | if (mod[i] == this) | 299 | if (mod[i] == this) |
310 | index = i; | 300 | index = i; |
301 | |||
302 | if (mod[i] == ssi) | ||
303 | break; | ||
311 | } | 304 | } |
312 | 305 | ||
313 | if (is_play) { | 306 | if (is_play) { |
314 | src_mod = mod[index - 1]; | 307 | *mod_from = mod[index - 1]; |
315 | dst_mod = mod[index]; | 308 | *mod_to = mod[index]; |
316 | } else { | 309 | } else { |
317 | src_mod = mod[index]; | 310 | *mod_from = mod[index]; |
318 | dst_mod = mod[index + 1]; | 311 | *mod_to = mod[index - 1]; |
319 | } | 312 | } |
320 | |||
321 | index = 0; | ||
322 | index = _rsnd_dma_of_name(dma_name + index, src_mod); | ||
323 | *(dma_name + index++) = '_'; | ||
324 | index = _rsnd_dma_of_name(dma_name + index, dst_mod); | ||
325 | } | 313 | } |
326 | 314 | ||
327 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | 315 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, |
@@ -329,6 +317,8 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
329 | { | 317 | { |
330 | struct device *dev = rsnd_priv_to_dev(priv); | 318 | struct device *dev = rsnd_priv_to_dev(priv); |
331 | struct dma_slave_config cfg; | 319 | struct dma_slave_config cfg; |
320 | struct rsnd_mod *mod_from; | ||
321 | struct rsnd_mod *mod_to; | ||
332 | char dma_name[DMA_NAME_SIZE]; | 322 | char dma_name[DMA_NAME_SIZE]; |
333 | dma_cap_mask_t mask; | 323 | dma_cap_mask_t mask; |
334 | int ret; | 324 | int ret; |
@@ -341,13 +331,18 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
341 | dma_cap_zero(mask); | 331 | dma_cap_zero(mask); |
342 | dma_cap_set(DMA_SLAVE, mask); | 332 | dma_cap_set(DMA_SLAVE, mask); |
343 | 333 | ||
344 | if (dev->of_node) | 334 | rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to); |
345 | rsnd_dma_of_name(dma, is_play, dma_name); | 335 | rsnd_dma_of_name(mod_from, mod_to, dma_name); |
346 | else | ||
347 | snprintf(dma_name, DMA_NAME_SIZE, | ||
348 | is_play ? "tx" : "rx"); | ||
349 | 336 | ||
350 | dev_dbg(dev, "dma name : %s\n", dma_name); | 337 | cfg.slave_id = id; |
338 | cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; | ||
339 | cfg.src_addr = rsnd_gen_dma_addr(priv, mod_from, is_play, 1); | ||
340 | cfg.dst_addr = rsnd_gen_dma_addr(priv, mod_to, is_play, 0); | ||
341 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
342 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
343 | |||
344 | dev_dbg(dev, "dma : %s %pad -> %pad\n", | ||
345 | dma_name, &cfg.src_addr, &cfg.dst_addr); | ||
351 | 346 | ||
352 | dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, | 347 | dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, |
353 | (void *)id, dev, | 348 | (void *)id, dev, |
@@ -357,14 +352,12 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
357 | return -EIO; | 352 | return -EIO; |
358 | } | 353 | } |
359 | 354 | ||
360 | rsnd_gen_dma_addr(priv, dma, &cfg, is_play, id); | ||
361 | |||
362 | ret = dmaengine_slave_config(dma->chan, &cfg); | 355 | ret = dmaengine_slave_config(dma->chan, &cfg); |
363 | if (ret < 0) | 356 | if (ret < 0) |
364 | goto rsnd_dma_init_err; | 357 | goto rsnd_dma_init_err; |
365 | 358 | ||
366 | dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 359 | dma->addr = is_play ? cfg.src_addr : cfg.dst_addr; |
367 | INIT_WORK(&dma->work, rsnd_dma_do_work); | 360 | dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; |
368 | 361 | ||
369 | return 0; | 362 | return 0; |
370 | 363 | ||
@@ -631,40 +624,41 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
631 | return -EINVAL; | 624 | return -EINVAL; |
632 | } | 625 | } |
633 | 626 | ||
634 | /* set clock inversion */ | ||
635 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
636 | case SND_SOC_DAIFMT_NB_IF: | ||
637 | rdai->bit_clk_inv = 0; | ||
638 | rdai->frm_clk_inv = 1; | ||
639 | break; | ||
640 | case SND_SOC_DAIFMT_IB_NF: | ||
641 | rdai->bit_clk_inv = 1; | ||
642 | rdai->frm_clk_inv = 0; | ||
643 | break; | ||
644 | case SND_SOC_DAIFMT_IB_IF: | ||
645 | rdai->bit_clk_inv = 1; | ||
646 | rdai->frm_clk_inv = 1; | ||
647 | break; | ||
648 | case SND_SOC_DAIFMT_NB_NF: | ||
649 | default: | ||
650 | rdai->bit_clk_inv = 0; | ||
651 | rdai->frm_clk_inv = 0; | ||
652 | break; | ||
653 | } | ||
654 | |||
655 | /* set format */ | 627 | /* set format */ |
656 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 628 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
657 | case SND_SOC_DAIFMT_I2S: | 629 | case SND_SOC_DAIFMT_I2S: |
658 | rdai->sys_delay = 0; | 630 | rdai->sys_delay = 0; |
659 | rdai->data_alignment = 0; | 631 | rdai->data_alignment = 0; |
632 | rdai->frm_clk_inv = 0; | ||
660 | break; | 633 | break; |
661 | case SND_SOC_DAIFMT_LEFT_J: | 634 | case SND_SOC_DAIFMT_LEFT_J: |
662 | rdai->sys_delay = 1; | 635 | rdai->sys_delay = 1; |
663 | rdai->data_alignment = 0; | 636 | rdai->data_alignment = 0; |
637 | rdai->frm_clk_inv = 1; | ||
664 | break; | 638 | break; |
665 | case SND_SOC_DAIFMT_RIGHT_J: | 639 | case SND_SOC_DAIFMT_RIGHT_J: |
666 | rdai->sys_delay = 1; | 640 | rdai->sys_delay = 1; |
667 | rdai->data_alignment = 1; | 641 | rdai->data_alignment = 1; |
642 | rdai->frm_clk_inv = 1; | ||
643 | break; | ||
644 | } | ||
645 | |||
646 | /* set clock inversion */ | ||
647 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
648 | case SND_SOC_DAIFMT_NB_IF: | ||
649 | rdai->bit_clk_inv = rdai->bit_clk_inv; | ||
650 | rdai->frm_clk_inv = !rdai->frm_clk_inv; | ||
651 | break; | ||
652 | case SND_SOC_DAIFMT_IB_NF: | ||
653 | rdai->bit_clk_inv = !rdai->bit_clk_inv; | ||
654 | rdai->frm_clk_inv = rdai->frm_clk_inv; | ||
655 | break; | ||
656 | case SND_SOC_DAIFMT_IB_IF: | ||
657 | rdai->bit_clk_inv = !rdai->bit_clk_inv; | ||
658 | rdai->frm_clk_inv = !rdai->frm_clk_inv; | ||
659 | break; | ||
660 | case SND_SOC_DAIFMT_NB_NF: | ||
661 | default: | ||
668 | break; | 662 | break; |
669 | } | 663 | } |
670 | 664 | ||
@@ -734,12 +728,13 @@ static void rsnd_of_parse_dai(struct platform_device *pdev, | |||
734 | struct device_node *dai_node, *dai_np; | 728 | struct device_node *dai_node, *dai_np; |
735 | struct device_node *ssi_node, *ssi_np; | 729 | struct device_node *ssi_node, *ssi_np; |
736 | struct device_node *src_node, *src_np; | 730 | struct device_node *src_node, *src_np; |
731 | struct device_node *dvc_node, *dvc_np; | ||
737 | struct device_node *playback, *capture; | 732 | struct device_node *playback, *capture; |
738 | struct rsnd_dai_platform_info *dai_info; | 733 | struct rsnd_dai_platform_info *dai_info; |
739 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | 734 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); |
740 | struct device *dev = &pdev->dev; | 735 | struct device *dev = &pdev->dev; |
741 | int nr, i; | 736 | int nr, i; |
742 | int dai_i, ssi_i, src_i; | 737 | int dai_i, ssi_i, src_i, dvc_i; |
743 | 738 | ||
744 | if (!of_data) | 739 | if (!of_data) |
745 | return; | 740 | return; |
@@ -765,6 +760,7 @@ static void rsnd_of_parse_dai(struct platform_device *pdev, | |||
765 | 760 | ||
766 | ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); | 761 | ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); |
767 | src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); | 762 | src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); |
763 | dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); | ||
768 | 764 | ||
769 | #define mod_parse(name) \ | 765 | #define mod_parse(name) \ |
770 | if (name##_node) { \ | 766 | if (name##_node) { \ |
@@ -800,6 +796,7 @@ if (name##_node) { \ | |||
800 | 796 | ||
801 | mod_parse(ssi); | 797 | mod_parse(ssi); |
802 | mod_parse(src); | 798 | mod_parse(src); |
799 | mod_parse(dvc); | ||
803 | 800 | ||
804 | if (playback) | 801 | if (playback) |
805 | of_node_put(playback); | 802 | of_node_put(playback); |
@@ -948,19 +945,17 @@ static struct snd_pcm_ops rsnd_pcm_ops = { | |||
948 | 945 | ||
949 | static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) | 946 | static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) |
950 | { | 947 | { |
951 | struct rsnd_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 948 | struct snd_soc_dai *dai = rtd->cpu_dai; |
952 | struct rsnd_dai *rdai; | 949 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
953 | int i, ret; | 950 | int ret; |
954 | 951 | ||
955 | for_each_rsnd_dai(rdai, priv, i) { | 952 | ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd); |
956 | ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd); | 953 | if (ret) |
957 | if (ret) | 954 | return ret; |
958 | return ret; | ||
959 | 955 | ||
960 | ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd); | 956 | ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd); |
961 | if (ret) | 957 | if (ret) |
962 | return ret; | 958 | return ret; |
963 | } | ||
964 | 959 | ||
965 | return snd_pcm_lib_preallocate_pages_for_all( | 960 | return snd_pcm_lib_preallocate_pages_for_all( |
966 | rtd->pcm, | 961 | rtd->pcm, |
@@ -1047,11 +1042,11 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1047 | for_each_rsnd_dai(rdai, priv, i) { | 1042 | for_each_rsnd_dai(rdai, priv, i) { |
1048 | ret = rsnd_dai_call(probe, &rdai->playback, rdai); | 1043 | ret = rsnd_dai_call(probe, &rdai->playback, rdai); |
1049 | if (ret) | 1044 | if (ret) |
1050 | return ret; | 1045 | goto exit_snd_probe; |
1051 | 1046 | ||
1052 | ret = rsnd_dai_call(probe, &rdai->capture, rdai); | 1047 | ret = rsnd_dai_call(probe, &rdai->capture, rdai); |
1053 | if (ret) | 1048 | if (ret) |
1054 | return ret; | 1049 | goto exit_snd_probe; |
1055 | } | 1050 | } |
1056 | 1051 | ||
1057 | /* | 1052 | /* |
@@ -1079,6 +1074,11 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1079 | 1074 | ||
1080 | exit_snd_soc: | 1075 | exit_snd_soc: |
1081 | snd_soc_unregister_platform(dev); | 1076 | snd_soc_unregister_platform(dev); |
1077 | exit_snd_probe: | ||
1078 | for_each_rsnd_dai(rdai, priv, i) { | ||
1079 | rsnd_dai_call(remove, &rdai->playback, rdai); | ||
1080 | rsnd_dai_call(remove, &rdai->capture, rdai); | ||
1081 | } | ||
1082 | 1082 | ||
1083 | return ret; | 1083 | return ret; |
1084 | } | 1084 | } |
@@ -1087,21 +1087,16 @@ static int rsnd_remove(struct platform_device *pdev) | |||
1087 | { | 1087 | { |
1088 | struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); | 1088 | struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); |
1089 | struct rsnd_dai *rdai; | 1089 | struct rsnd_dai *rdai; |
1090 | int ret, i; | 1090 | int ret = 0, i; |
1091 | 1091 | ||
1092 | pm_runtime_disable(&pdev->dev); | 1092 | pm_runtime_disable(&pdev->dev); |
1093 | 1093 | ||
1094 | for_each_rsnd_dai(rdai, priv, i) { | 1094 | for_each_rsnd_dai(rdai, priv, i) { |
1095 | ret = rsnd_dai_call(remove, &rdai->playback, rdai); | 1095 | ret |= rsnd_dai_call(remove, &rdai->playback, rdai); |
1096 | if (ret) | 1096 | ret |= rsnd_dai_call(remove, &rdai->capture, rdai); |
1097 | return ret; | ||
1098 | |||
1099 | ret = rsnd_dai_call(remove, &rdai->capture, rdai); | ||
1100 | if (ret) | ||
1101 | return ret; | ||
1102 | } | 1097 | } |
1103 | 1098 | ||
1104 | return 0; | 1099 | return ret; |
1105 | } | 1100 | } |
1106 | 1101 | ||
1107 | static struct platform_driver rsnd_driver = { | 1102 | static struct platform_driver rsnd_driver = { |
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index ed0007006899..3f443930c2b1 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c | |||
@@ -20,7 +20,8 @@ struct rsnd_dvc { | |||
20 | struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ | 20 | struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ |
21 | struct rsnd_mod mod; | 21 | struct rsnd_mod mod; |
22 | struct clk *clk; | 22 | struct clk *clk; |
23 | long volume[RSND_DVC_VOLUME_NUM]; | 23 | u8 volume[RSND_DVC_VOLUME_NUM]; |
24 | u8 mute[RSND_DVC_VOLUME_NUM]; | ||
24 | }; | 25 | }; |
25 | 26 | ||
26 | #define rsnd_mod_to_dvc(_mod) \ | 27 | #define rsnd_mod_to_dvc(_mod) \ |
@@ -37,13 +38,18 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod) | |||
37 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 38 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); |
38 | u32 max = (0x00800000 - 1); | 39 | u32 max = (0x00800000 - 1); |
39 | u32 vol[RSND_DVC_VOLUME_NUM]; | 40 | u32 vol[RSND_DVC_VOLUME_NUM]; |
41 | u32 mute = 0; | ||
40 | int i; | 42 | int i; |
41 | 43 | ||
42 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | 44 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { |
43 | vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i]; | 45 | vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i]; |
46 | mute |= (!!dvc->mute[i]) << i; | ||
47 | } | ||
44 | 48 | ||
45 | rsnd_mod_write(mod, DVC_VOL0R, vol[0]); | 49 | rsnd_mod_write(mod, DVC_VOL0R, vol[0]); |
46 | rsnd_mod_write(mod, DVC_VOL1R, vol[1]); | 50 | rsnd_mod_write(mod, DVC_VOL1R, vol[1]); |
51 | |||
52 | rsnd_mod_write(mod, DVC_ZCMCR, mute); | ||
47 | } | 53 | } |
48 | 54 | ||
49 | static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, | 55 | static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, |
@@ -96,8 +102,8 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | |||
96 | 102 | ||
97 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); | 103 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); |
98 | 104 | ||
99 | /* enable Volume */ | 105 | /* enable Volume / Mute */ |
100 | rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x100); | 106 | rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x101); |
101 | 107 | ||
102 | /* ch0/ch1 Volume */ | 108 | /* ch0/ch1 Volume */ |
103 | rsnd_dvc_volume_update(dvc_mod); | 109 | rsnd_dvc_volume_update(dvc_mod); |
@@ -140,10 +146,20 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod, | |||
140 | static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, | 146 | static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, |
141 | struct snd_ctl_elem_info *uinfo) | 147 | struct snd_ctl_elem_info *uinfo) |
142 | { | 148 | { |
143 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 149 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); |
150 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
151 | u8 *val = (u8 *)kctrl->private_value; | ||
152 | |||
144 | uinfo->count = RSND_DVC_VOLUME_NUM; | 153 | uinfo->count = RSND_DVC_VOLUME_NUM; |
145 | uinfo->value.integer.min = 0; | 154 | uinfo->value.integer.min = 0; |
146 | uinfo->value.integer.max = RSND_DVC_VOLUME_MAX; | 155 | |
156 | if (val == dvc->volume) { | ||
157 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
158 | uinfo->value.integer.max = RSND_DVC_VOLUME_MAX; | ||
159 | } else { | ||
160 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
161 | uinfo->value.integer.max = 1; | ||
162 | } | ||
147 | 163 | ||
148 | return 0; | 164 | return 0; |
149 | } | 165 | } |
@@ -151,12 +167,11 @@ static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, | |||
151 | static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl, | 167 | static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl, |
152 | struct snd_ctl_elem_value *ucontrol) | 168 | struct snd_ctl_elem_value *ucontrol) |
153 | { | 169 | { |
154 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); | 170 | u8 *val = (u8 *)kctrl->private_value; |
155 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
156 | int i; | 171 | int i; |
157 | 172 | ||
158 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | 173 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) |
159 | ucontrol->value.integer.value[i] = dvc->volume[i]; | 174 | ucontrol->value.integer.value[i] = val[i]; |
160 | 175 | ||
161 | return 0; | 176 | return 0; |
162 | } | 177 | } |
@@ -165,51 +180,38 @@ static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl, | |||
165 | struct snd_ctl_elem_value *ucontrol) | 180 | struct snd_ctl_elem_value *ucontrol) |
166 | { | 181 | { |
167 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); | 182 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); |
168 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 183 | u8 *val = (u8 *)kctrl->private_value; |
169 | int i, change = 0; | 184 | int i, change = 0; |
170 | 185 | ||
171 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { | 186 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { |
172 | if (ucontrol->value.integer.value[i] < 0 || | 187 | change |= (ucontrol->value.integer.value[i] != val[i]); |
173 | ucontrol->value.integer.value[i] > RSND_DVC_VOLUME_MAX) | 188 | val[i] = ucontrol->value.integer.value[i]; |
174 | return -EINVAL; | ||
175 | |||
176 | change |= (ucontrol->value.integer.value[i] != dvc->volume[i]); | ||
177 | } | 189 | } |
178 | 190 | ||
179 | if (change) { | 191 | if (change) |
180 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | ||
181 | dvc->volume[i] = ucontrol->value.integer.value[i]; | ||
182 | |||
183 | rsnd_dvc_volume_update(mod); | 192 | rsnd_dvc_volume_update(mod); |
184 | } | ||
185 | 193 | ||
186 | return change; | 194 | return change; |
187 | } | 195 | } |
188 | 196 | ||
189 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | 197 | static int __rsnd_dvc_pcm_new(struct rsnd_mod *mod, |
190 | struct rsnd_dai *rdai, | 198 | struct rsnd_dai *rdai, |
191 | struct snd_soc_pcm_runtime *rtd) | 199 | struct snd_soc_pcm_runtime *rtd, |
200 | const unsigned char *name, | ||
201 | u8 *private) | ||
192 | { | 202 | { |
193 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
194 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
195 | struct device *dev = rsnd_priv_to_dev(priv); | ||
196 | struct snd_card *card = rtd->card->snd_card; | 203 | struct snd_card *card = rtd->card->snd_card; |
197 | struct snd_kcontrol *kctrl; | 204 | struct snd_kcontrol *kctrl; |
198 | static struct snd_kcontrol_new knew = { | 205 | struct snd_kcontrol_new knew = { |
199 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 206 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
200 | .name = "Playback Volume", | 207 | .name = name, |
201 | .info = rsnd_dvc_volume_info, | 208 | .info = rsnd_dvc_volume_info, |
202 | .get = rsnd_dvc_volume_get, | 209 | .get = rsnd_dvc_volume_get, |
203 | .put = rsnd_dvc_volume_put, | 210 | .put = rsnd_dvc_volume_put, |
211 | .private_value = (unsigned long)private, | ||
204 | }; | 212 | }; |
205 | int ret; | 213 | int ret; |
206 | 214 | ||
207 | if (!rsnd_dai_is_play(rdai, io)) { | ||
208 | dev_err(dev, "DVC%d is connected to Capture DAI\n", | ||
209 | rsnd_mod_id(mod)); | ||
210 | return -EINVAL; | ||
211 | } | ||
212 | |||
213 | kctrl = snd_ctl_new1(&knew, mod); | 215 | kctrl = snd_ctl_new1(&knew, mod); |
214 | if (!kctrl) | 216 | if (!kctrl) |
215 | return -ENOMEM; | 217 | return -ENOMEM; |
@@ -221,6 +223,33 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
221 | return 0; | 223 | return 0; |
222 | } | 224 | } |
223 | 225 | ||
226 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | ||
227 | struct rsnd_dai *rdai, | ||
228 | struct snd_soc_pcm_runtime *rtd) | ||
229 | { | ||
230 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
231 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
232 | int ret; | ||
233 | |||
234 | /* Volume */ | ||
235 | ret = __rsnd_dvc_pcm_new(mod, rdai, rtd, | ||
236 | rsnd_dai_is_play(rdai, io) ? | ||
237 | "DVC Out Playback Volume" : "DVC In Capture Volume", | ||
238 | dvc->volume); | ||
239 | if (ret < 0) | ||
240 | return ret; | ||
241 | |||
242 | /* Mute */ | ||
243 | ret = __rsnd_dvc_pcm_new(mod, rdai, rtd, | ||
244 | rsnd_dai_is_play(rdai, io) ? | ||
245 | "DVC Out Mute Switch" : "DVC In Mute Switch", | ||
246 | dvc->mute); | ||
247 | if (ret < 0) | ||
248 | return ret; | ||
249 | |||
250 | return 0; | ||
251 | } | ||
252 | |||
224 | static struct rsnd_mod_ops rsnd_dvc_ops = { | 253 | static struct rsnd_mod_ops rsnd_dvc_ops = { |
225 | .name = DVC_NAME, | 254 | .name = DVC_NAME, |
226 | .probe = rsnd_dvc_probe_gen2, | 255 | .probe = rsnd_dvc_probe_gen2, |
@@ -239,6 +268,42 @@ struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id) | |||
239 | return &((struct rsnd_dvc *)(priv->dvc) + id)->mod; | 268 | return &((struct rsnd_dvc *)(priv->dvc) + id)->mod; |
240 | } | 269 | } |
241 | 270 | ||
271 | static void rsnd_of_parse_dvc(struct platform_device *pdev, | ||
272 | const struct rsnd_of_data *of_data, | ||
273 | struct rsnd_priv *priv) | ||
274 | { | ||
275 | struct device_node *node; | ||
276 | struct rsnd_dvc_platform_info *dvc_info; | ||
277 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
278 | struct device *dev = &pdev->dev; | ||
279 | int nr; | ||
280 | |||
281 | if (!of_data) | ||
282 | return; | ||
283 | |||
284 | node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); | ||
285 | if (!node) | ||
286 | return; | ||
287 | |||
288 | nr = of_get_child_count(node); | ||
289 | if (!nr) | ||
290 | goto rsnd_of_parse_dvc_end; | ||
291 | |||
292 | dvc_info = devm_kzalloc(dev, | ||
293 | sizeof(struct rsnd_dvc_platform_info) * nr, | ||
294 | GFP_KERNEL); | ||
295 | if (!dvc_info) { | ||
296 | dev_err(dev, "dvc info allocation error\n"); | ||
297 | goto rsnd_of_parse_dvc_end; | ||
298 | } | ||
299 | |||
300 | info->dvc_info = dvc_info; | ||
301 | info->dvc_info_nr = nr; | ||
302 | |||
303 | rsnd_of_parse_dvc_end: | ||
304 | of_node_put(node); | ||
305 | } | ||
306 | |||
242 | int rsnd_dvc_probe(struct platform_device *pdev, | 307 | int rsnd_dvc_probe(struct platform_device *pdev, |
243 | const struct rsnd_of_data *of_data, | 308 | const struct rsnd_of_data *of_data, |
244 | struct rsnd_priv *priv) | 309 | struct rsnd_priv *priv) |
@@ -250,6 +315,8 @@ int rsnd_dvc_probe(struct platform_device *pdev, | |||
250 | char name[RSND_DVC_NAME_SIZE]; | 315 | char name[RSND_DVC_NAME_SIZE]; |
251 | int i, nr; | 316 | int i, nr; |
252 | 317 | ||
318 | rsnd_of_parse_dvc(pdev, of_data, priv); | ||
319 | |||
253 | nr = info->dvc_info_nr; | 320 | nr = info->dvc_info_nr; |
254 | if (!nr) | 321 | if (!nr) |
255 | return 0; | 322 | return 0; |
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 1dd2b7d38c2c..3fdf3be7b99a 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -15,63 +15,35 @@ struct rsnd_gen { | |||
15 | 15 | ||
16 | struct rsnd_gen_ops *ops; | 16 | struct rsnd_gen_ops *ops; |
17 | 17 | ||
18 | struct regmap *regmap; | 18 | struct regmap *regmap[RSND_BASE_MAX]; |
19 | struct regmap_field *regs[RSND_REG_MAX]; | 19 | struct regmap_field *regs[RSND_REG_MAX]; |
20 | }; | 20 | }; |
21 | 21 | ||
22 | #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) | 22 | #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) |
23 | 23 | ||
24 | #define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \ | 24 | struct rsnd_regmap_field_conf { |
25 | [id] = { \ | 25 | int idx; |
26 | .reg = (unsigned int)gen->base[reg_id] + offset, \ | 26 | unsigned int reg_offset; |
27 | .lsb = 0, \ | 27 | unsigned int id_offset; |
28 | .msb = 31, \ | 28 | }; |
29 | .id_size = _id_size, \ | ||
30 | .id_offset = _id_offset, \ | ||
31 | } | ||
32 | |||
33 | /* | ||
34 | * basic function | ||
35 | */ | ||
36 | static int rsnd_regmap_write32(void *context, const void *_data, size_t count) | ||
37 | { | ||
38 | struct rsnd_priv *priv = context; | ||
39 | struct device *dev = rsnd_priv_to_dev(priv); | ||
40 | u32 *data = (u32 *)_data; | ||
41 | u32 val = data[1]; | ||
42 | void __iomem *reg = (void *)data[0]; | ||
43 | |||
44 | iowrite32(val, reg); | ||
45 | |||
46 | dev_dbg(dev, "w %p : %08x\n", reg, val); | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static int rsnd_regmap_read32(void *context, | ||
52 | const void *_data, size_t reg_size, | ||
53 | void *_val, size_t val_size) | ||
54 | { | ||
55 | struct rsnd_priv *priv = context; | ||
56 | struct device *dev = rsnd_priv_to_dev(priv); | ||
57 | u32 *data = (u32 *)_data; | ||
58 | u32 *val = (u32 *)_val; | ||
59 | void __iomem *reg = (void *)data[0]; | ||
60 | |||
61 | *val = ioread32(reg); | ||
62 | |||
63 | dev_dbg(dev, "r %p : %08x\n", reg, *val); | ||
64 | 29 | ||
65 | return 0; | 30 | #define RSND_REG_SET(id, offset, _id_offset) \ |
31 | { \ | ||
32 | .idx = id, \ | ||
33 | .reg_offset = offset, \ | ||
34 | .id_offset = _id_offset, \ | ||
66 | } | 35 | } |
36 | /* single address mapping */ | ||
37 | #define RSND_GEN_S_REG(id, offset) \ | ||
38 | RSND_REG_SET(RSND_REG_##id, offset, 0) | ||
67 | 39 | ||
68 | static struct regmap_bus rsnd_regmap_bus = { | 40 | /* multi address mapping */ |
69 | .write = rsnd_regmap_write32, | 41 | #define RSND_GEN_M_REG(id, offset, _id_offset) \ |
70 | .read = rsnd_regmap_read32, | 42 | RSND_REG_SET(RSND_REG_##id, offset, _id_offset) |
71 | .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
72 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
73 | }; | ||
74 | 43 | ||
44 | /* | ||
45 | * basic function | ||
46 | */ | ||
75 | static int rsnd_is_accessible_reg(struct rsnd_priv *priv, | 47 | static int rsnd_is_accessible_reg(struct rsnd_priv *priv, |
76 | struct rsnd_gen *gen, enum rsnd_reg reg) | 48 | struct rsnd_gen *gen, enum rsnd_reg reg) |
77 | { | 49 | { |
@@ -88,6 +60,7 @@ static int rsnd_is_accessible_reg(struct rsnd_priv *priv, | |||
88 | u32 rsnd_read(struct rsnd_priv *priv, | 60 | u32 rsnd_read(struct rsnd_priv *priv, |
89 | struct rsnd_mod *mod, enum rsnd_reg reg) | 61 | struct rsnd_mod *mod, enum rsnd_reg reg) |
90 | { | 62 | { |
63 | struct device *dev = rsnd_priv_to_dev(priv); | ||
91 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 64 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
92 | u32 val; | 65 | u32 val; |
93 | 66 | ||
@@ -96,6 +69,8 @@ u32 rsnd_read(struct rsnd_priv *priv, | |||
96 | 69 | ||
97 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); | 70 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); |
98 | 71 | ||
72 | dev_dbg(dev, "r %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, val); | ||
73 | |||
99 | return val; | 74 | return val; |
100 | } | 75 | } |
101 | 76 | ||
@@ -103,17 +78,21 @@ void rsnd_write(struct rsnd_priv *priv, | |||
103 | struct rsnd_mod *mod, | 78 | struct rsnd_mod *mod, |
104 | enum rsnd_reg reg, u32 data) | 79 | enum rsnd_reg reg, u32 data) |
105 | { | 80 | { |
81 | struct device *dev = rsnd_priv_to_dev(priv); | ||
106 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 82 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
107 | 83 | ||
108 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | 84 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
109 | return; | 85 | return; |
110 | 86 | ||
111 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); | 87 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); |
88 | |||
89 | dev_dbg(dev, "w %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, data); | ||
112 | } | 90 | } |
113 | 91 | ||
114 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | 92 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, |
115 | enum rsnd_reg reg, u32 mask, u32 data) | 93 | enum rsnd_reg reg, u32 mask, u32 data) |
116 | { | 94 | { |
95 | struct device *dev = rsnd_priv_to_dev(priv); | ||
117 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 96 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
118 | 97 | ||
119 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | 98 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
@@ -121,35 +100,63 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | |||
121 | 100 | ||
122 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), | 101 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), |
123 | mask, data); | 102 | mask, data); |
103 | |||
104 | dev_dbg(dev, "b %s - 0x%04d : %08x/%08x\n", | ||
105 | rsnd_mod_name(mod), reg, data, mask); | ||
124 | } | 106 | } |
125 | 107 | ||
126 | static int rsnd_gen_regmap_init(struct rsnd_priv *priv, | 108 | #define rsnd_gen_regmap_init(priv, id_size, reg_id, conf) \ |
127 | struct rsnd_gen *gen, | 109 | _rsnd_gen_regmap_init(priv, id_size, reg_id, conf, ARRAY_SIZE(conf)) |
128 | struct reg_field *regf) | 110 | static int _rsnd_gen_regmap_init(struct rsnd_priv *priv, |
111 | int id_size, | ||
112 | int reg_id, | ||
113 | struct rsnd_regmap_field_conf *conf, | ||
114 | int conf_size) | ||
129 | { | 115 | { |
130 | int i; | 116 | struct platform_device *pdev = rsnd_priv_to_pdev(priv); |
117 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
131 | struct device *dev = rsnd_priv_to_dev(priv); | 118 | struct device *dev = rsnd_priv_to_dev(priv); |
119 | struct resource *res; | ||
132 | struct regmap_config regc; | 120 | struct regmap_config regc; |
121 | struct regmap_field *regs; | ||
122 | struct regmap *regmap; | ||
123 | struct reg_field regf; | ||
124 | void __iomem *base; | ||
125 | int i; | ||
133 | 126 | ||
134 | memset(®c, 0, sizeof(regc)); | 127 | memset(®c, 0, sizeof(regc)); |
135 | regc.reg_bits = 32; | 128 | regc.reg_bits = 32; |
136 | regc.val_bits = 32; | 129 | regc.val_bits = 32; |
130 | regc.reg_stride = 4; | ||
137 | 131 | ||
138 | gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, ®c); | 132 | res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id); |
139 | if (IS_ERR(gen->regmap)) { | 133 | if (!res) |
140 | dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap)); | 134 | return -ENODEV; |
141 | return PTR_ERR(gen->regmap); | ||
142 | } | ||
143 | 135 | ||
144 | for (i = 0; i < RSND_REG_MAX; i++) { | 136 | base = devm_ioremap_resource(dev, res); |
145 | gen->regs[i] = NULL; | 137 | if (IS_ERR(base)) |
146 | if (!regf[i].reg) | 138 | return PTR_ERR(base); |
147 | continue; | ||
148 | 139 | ||
149 | gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]); | 140 | regmap = devm_regmap_init_mmio(dev, base, ®c); |
150 | if (IS_ERR(gen->regs[i])) | 141 | if (IS_ERR(regmap)) |
151 | return PTR_ERR(gen->regs[i]); | 142 | return PTR_ERR(regmap); |
152 | 143 | ||
144 | gen->base[reg_id] = base; | ||
145 | gen->regmap[reg_id] = regmap; | ||
146 | |||
147 | for (i = 0; i < conf_size; i++) { | ||
148 | |||
149 | regf.reg = conf[i].reg_offset; | ||
150 | regf.id_offset = conf[i].id_offset; | ||
151 | regf.lsb = 0; | ||
152 | regf.msb = 31; | ||
153 | regf.id_size = id_size; | ||
154 | |||
155 | regs = devm_regmap_field_alloc(dev, regmap, regf); | ||
156 | if (IS_ERR(regs)) | ||
157 | return PTR_ERR(regs); | ||
158 | |||
159 | gen->regs[conf[i].idx] = regs; | ||
153 | } | 160 | } |
154 | 161 | ||
155 | return 0; | 162 | return 0; |
@@ -165,15 +172,19 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, | |||
165 | * | 172 | * |
166 | * ex) R-Car H2 case | 173 | * ex) R-Car H2 case |
167 | * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out | 174 | * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out |
168 | * SSI : 0xec541000 / 0xec241008 / 0xec24100c / 0xec400000 / 0xec400000 | 175 | * SSI : 0xec541000 / 0xec241008 / 0xec24100c |
176 | * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000 | ||
169 | * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 | 177 | * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 |
170 | * CMD : 0xec500000 / 0xec008000 0xec308000 | 178 | * CMD : 0xec500000 / / 0xec008000 0xec308000 |
171 | */ | 179 | */ |
172 | #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) | 180 | #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) |
173 | #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) | 181 | #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) |
174 | 182 | ||
175 | #define RDMA_SSI_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | 183 | #define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) |
176 | #define RDMA_SSI_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | 184 | #define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) |
185 | |||
186 | #define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | ||
187 | #define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | ||
177 | 188 | ||
178 | #define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) | 189 | #define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) |
179 | #define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) | 190 | #define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) |
@@ -184,14 +195,13 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, | |||
184 | #define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) | 195 | #define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) |
185 | #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) | 196 | #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) |
186 | 197 | ||
187 | void rsnd_gen_dma_addr(struct rsnd_priv *priv, | 198 | static dma_addr_t |
188 | struct rsnd_dma *dma, | 199 | rsnd_gen2_dma_addr(struct rsnd_priv *priv, |
189 | struct dma_slave_config *cfg, | 200 | struct rsnd_mod *mod, |
190 | int is_play, int slave_id) | 201 | int is_play, int is_from) |
191 | { | 202 | { |
192 | struct platform_device *pdev = rsnd_priv_to_pdev(priv); | 203 | struct platform_device *pdev = rsnd_priv_to_pdev(priv); |
193 | struct device *dev = rsnd_priv_to_dev(priv); | 204 | struct device *dev = rsnd_priv_to_dev(priv); |
194 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | ||
195 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 205 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
196 | dma_addr_t ssi_reg = platform_get_resource(pdev, | 206 | dma_addr_t ssi_reg = platform_get_resource(pdev, |
197 | IORESOURCE_MEM, RSND_GEN2_SSI)->start; | 207 | IORESOURCE_MEM, RSND_GEN2_SSI)->start; |
@@ -202,170 +212,152 @@ void rsnd_gen_dma_addr(struct rsnd_priv *priv, | |||
202 | int use_dvc = !!rsnd_io_to_mod_dvc(io); | 212 | int use_dvc = !!rsnd_io_to_mod_dvc(io); |
203 | int id = rsnd_mod_id(mod); | 213 | int id = rsnd_mod_id(mod); |
204 | struct dma_addr { | 214 | struct dma_addr { |
205 | dma_addr_t src_addr; | 215 | dma_addr_t out_addr; |
206 | dma_addr_t dst_addr; | 216 | dma_addr_t in_addr; |
207 | } dma_addrs[2][2][3] = { | 217 | } dma_addrs[3][2][3] = { |
208 | { /* SRC */ | 218 | /* SRC */ |
209 | /* Capture */ | 219 | {{{ 0, 0 }, |
210 | {{ 0, 0 }, | 220 | /* Capture */ |
211 | { RDMA_SRC_O_N(src, id), 0 }, | 221 | { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) }, |
212 | { RDMA_CMD_O_N(src, id), 0 }}, | 222 | { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } }, |
213 | /* Playback */ | 223 | /* Playback */ |
214 | {{ 0, 0, }, | 224 | {{ 0, 0, }, |
215 | { 0, RDMA_SRC_I_N(src, id) }, | 225 | { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) }, |
216 | { 0, RDMA_SRC_I_N(src, id) }} | 226 | { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } } |
217 | }, { /* SSI */ | 227 | }, |
218 | /* Capture */ | 228 | /* SSI */ |
219 | {{ RDMA_SSI_O_N(ssi, id), 0 }, | 229 | /* Capture */ |
220 | { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }, | 230 | {{{ RDMA_SSI_O_N(ssi, id), 0 }, |
221 | { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }}, | 231 | { RDMA_SSIU_O_P(ssi, id), 0 }, |
222 | /* Playback */ | 232 | { RDMA_SSIU_O_P(ssi, id), 0 } }, |
223 | {{ 0, RDMA_SSI_I_N(ssi, id) }, | 233 | /* Playback */ |
224 | { RDMA_SRC_O_P(src, id), RDMA_SSI_I_P(ssi, id) }, | 234 | {{ 0, RDMA_SSI_I_N(ssi, id) }, |
225 | { RDMA_CMD_O_P(src, id), RDMA_SSI_I_P(ssi, id) }} | 235 | { 0, RDMA_SSIU_I_P(ssi, id) }, |
226 | } | 236 | { 0, RDMA_SSIU_I_P(ssi, id) } } |
237 | }, | ||
238 | /* SSIU */ | ||
239 | /* Capture */ | ||
240 | {{{ RDMA_SSIU_O_N(ssi, id), 0 }, | ||
241 | { RDMA_SSIU_O_P(ssi, id), 0 }, | ||
242 | { RDMA_SSIU_O_P(ssi, id), 0 } }, | ||
243 | /* Playback */ | ||
244 | {{ 0, RDMA_SSIU_I_N(ssi, id) }, | ||
245 | { 0, RDMA_SSIU_I_P(ssi, id) }, | ||
246 | { 0, RDMA_SSIU_I_P(ssi, id) } } }, | ||
227 | }; | 247 | }; |
228 | 248 | ||
229 | cfg->slave_id = slave_id; | 249 | /* it shouldn't happen */ |
230 | cfg->src_addr = 0; | 250 | if (use_dvc & !use_src) |
231 | cfg->dst_addr = 0; | 251 | dev_err(dev, "DVC is selected without SRC\n"); |
232 | cfg->direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; | 252 | |
253 | /* use SSIU or SSI ? */ | ||
254 | if (is_ssi && (0 == strcmp(rsnd_mod_dma_name(mod), "ssiu"))) | ||
255 | is_ssi++; | ||
256 | |||
257 | return (is_from) ? | ||
258 | dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr : | ||
259 | dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; | ||
260 | } | ||
233 | 261 | ||
262 | dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv, | ||
263 | struct rsnd_mod *mod, | ||
264 | int is_play, int is_from) | ||
265 | { | ||
234 | /* | 266 | /* |
235 | * gen1 uses default DMA addr | 267 | * gen1 uses default DMA addr |
236 | */ | 268 | */ |
237 | if (rsnd_is_gen1(priv)) | 269 | if (rsnd_is_gen1(priv)) |
238 | return; | 270 | return 0; |
239 | |||
240 | /* it shouldn't happen */ | ||
241 | if (use_dvc & !use_src) { | ||
242 | dev_err(dev, "DVC is selected without SRC\n"); | ||
243 | return; | ||
244 | } | ||
245 | 271 | ||
246 | cfg->src_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].src_addr; | 272 | if (!mod) |
247 | cfg->dst_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].dst_addr; | 273 | return 0; |
248 | 274 | ||
249 | dev_dbg(dev, "dma%d addr - src : %x / dst : %x\n", | 275 | return rsnd_gen2_dma_addr(priv, mod, is_play, is_from); |
250 | id, cfg->src_addr, cfg->dst_addr); | ||
251 | } | 276 | } |
252 | 277 | ||
253 | /* | 278 | /* |
254 | * Gen2 | 279 | * Gen2 |
255 | */ | 280 | */ |
256 | |||
257 | /* single address mapping */ | ||
258 | #define RSND_GEN2_S_REG(gen, reg, id, offset) \ | ||
259 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10) | ||
260 | |||
261 | /* multi address mapping */ | ||
262 | #define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset) \ | ||
263 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10) | ||
264 | |||
265 | static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | ||
266 | { | ||
267 | struct reg_field regf[RSND_REG_MAX] = { | ||
268 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), | ||
269 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), | ||
270 | /* FIXME: it needs SSI_MODE2/3 in the future */ | ||
271 | RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), | ||
272 | RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), | ||
273 | RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), | ||
274 | RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), | ||
275 | |||
276 | RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), | ||
277 | RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), | ||
278 | RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), | ||
279 | RSND_GEN2_M_REG(gen, SCU, CMD_ROUTE_SLCT, 0x18c, 0x20), | ||
280 | RSND_GEN2_M_REG(gen, SCU, CMD_CTRL, 0x190, 0x20), | ||
281 | RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), | ||
282 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), | ||
283 | RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), | ||
284 | RSND_GEN2_M_REG(gen, SCU, SRC_IFSCR, 0x21c, 0x40), | ||
285 | RSND_GEN2_M_REG(gen, SCU, SRC_IFSVR, 0x220, 0x40), | ||
286 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), | ||
287 | RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), | ||
288 | RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), | ||
289 | RSND_GEN2_M_REG(gen, SCU, DVC_SWRSR, 0xe00, 0x100), | ||
290 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUIR, 0xe04, 0x100), | ||
291 | RSND_GEN2_M_REG(gen, SCU, DVC_ADINR, 0xe08, 0x100), | ||
292 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUCR, 0xe10, 0x100), | ||
293 | RSND_GEN2_M_REG(gen, SCU, DVC_ZCMCR, 0xe14, 0x100), | ||
294 | RSND_GEN2_M_REG(gen, SCU, DVC_VOL0R, 0xe28, 0x100), | ||
295 | RSND_GEN2_M_REG(gen, SCU, DVC_VOL1R, 0xe2c, 0x100), | ||
296 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUER, 0xe48, 0x100), | ||
297 | |||
298 | RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), | ||
299 | RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), | ||
300 | RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), | ||
301 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), | ||
302 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), | ||
303 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), | ||
304 | RSND_GEN2_S_REG(gen, ADG, DIV_EN, 0x30), | ||
305 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), | ||
306 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), | ||
307 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), | ||
308 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL3, 0x40), | ||
309 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL4, 0x44), | ||
310 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL0, 0x48), | ||
311 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL1, 0x4c), | ||
312 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), | ||
313 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), | ||
314 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), | ||
315 | RSND_GEN2_S_REG(gen, ADG, CMDOUT_TIMSEL, 0x5c), | ||
316 | |||
317 | RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), | ||
318 | RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), | ||
319 | RSND_GEN2_M_REG(gen, SSI, SSITDR, 0x08, 0x40), | ||
320 | RSND_GEN2_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), | ||
321 | RSND_GEN2_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), | ||
322 | }; | ||
323 | |||
324 | return rsnd_gen_regmap_init(priv, gen, regf); | ||
325 | } | ||
326 | |||
327 | static int rsnd_gen2_probe(struct platform_device *pdev, | 281 | static int rsnd_gen2_probe(struct platform_device *pdev, |
328 | struct rsnd_priv *priv) | 282 | struct rsnd_priv *priv) |
329 | { | 283 | { |
330 | struct device *dev = rsnd_priv_to_dev(priv); | 284 | struct device *dev = rsnd_priv_to_dev(priv); |
331 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 285 | struct rsnd_regmap_field_conf conf_ssiu[] = { |
332 | struct resource *scu_res; | 286 | RSND_GEN_S_REG(SSI_MODE0, 0x800), |
333 | struct resource *adg_res; | 287 | RSND_GEN_S_REG(SSI_MODE1, 0x804), |
334 | struct resource *ssiu_res; | 288 | /* FIXME: it needs SSI_MODE2/3 in the future */ |
335 | struct resource *ssi_res; | 289 | RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), |
336 | int ret; | 290 | RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80), |
337 | 291 | RSND_GEN_M_REG(BUSIF_DALIGN, 0x8, 0x80), | |
338 | /* | 292 | RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), |
339 | * map address | 293 | RSND_GEN_M_REG(INT_ENABLE, 0x18, 0x80), |
340 | */ | 294 | }; |
341 | scu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SCU); | 295 | struct rsnd_regmap_field_conf conf_scu[] = { |
342 | adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_ADG); | 296 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20), |
343 | ssiu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSIU); | 297 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), |
344 | ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSI); | 298 | RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), |
345 | 299 | RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20), | |
346 | gen->base[RSND_GEN2_SCU] = devm_ioremap_resource(dev, scu_res); | 300 | RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20), |
347 | gen->base[RSND_GEN2_ADG] = devm_ioremap_resource(dev, adg_res); | 301 | RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), |
348 | gen->base[RSND_GEN2_SSIU] = devm_ioremap_resource(dev, ssiu_res); | 302 | RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), |
349 | gen->base[RSND_GEN2_SSI] = devm_ioremap_resource(dev, ssi_res); | 303 | RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), |
350 | if (IS_ERR(gen->base[RSND_GEN2_SCU]) || | 304 | RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40), |
351 | IS_ERR(gen->base[RSND_GEN2_ADG]) || | 305 | RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), |
352 | IS_ERR(gen->base[RSND_GEN2_SSIU]) || | 306 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), |
353 | IS_ERR(gen->base[RSND_GEN2_SSI])) | 307 | RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40), |
354 | return -ENODEV; | 308 | RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), |
355 | 309 | RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100), | |
356 | ret = rsnd_gen2_regmap_init(priv, gen); | 310 | RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100), |
357 | if (ret < 0) | 311 | RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), |
358 | return ret; | 312 | RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100), |
359 | 313 | RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100), | |
360 | dev_dbg(dev, "Gen2 device probed\n"); | 314 | RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100), |
361 | dev_dbg(dev, "SCU : %pap => %p\n", &scu_res->start, | 315 | RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100), |
362 | gen->base[RSND_GEN2_SCU]); | 316 | RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100), |
363 | dev_dbg(dev, "ADG : %pap => %p\n", &adg_res->start, | 317 | }; |
364 | gen->base[RSND_GEN2_ADG]); | 318 | struct rsnd_regmap_field_conf conf_adg[] = { |
365 | dev_dbg(dev, "SSIU : %pap => %p\n", &ssiu_res->start, | 319 | RSND_GEN_S_REG(BRRA, 0x00), |
366 | gen->base[RSND_GEN2_SSIU]); | 320 | RSND_GEN_S_REG(BRRB, 0x04), |
367 | dev_dbg(dev, "SSI : %pap => %p\n", &ssi_res->start, | 321 | RSND_GEN_S_REG(SSICKR, 0x08), |
368 | gen->base[RSND_GEN2_SSI]); | 322 | RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), |
323 | RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), | ||
324 | RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14), | ||
325 | RSND_GEN_S_REG(DIV_EN, 0x30), | ||
326 | RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34), | ||
327 | RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38), | ||
328 | RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c), | ||
329 | RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40), | ||
330 | RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44), | ||
331 | RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48), | ||
332 | RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c), | ||
333 | RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50), | ||
334 | RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54), | ||
335 | RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58), | ||
336 | RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c), | ||
337 | }; | ||
338 | struct rsnd_regmap_field_conf conf_ssi[] = { | ||
339 | RSND_GEN_M_REG(SSICR, 0x00, 0x40), | ||
340 | RSND_GEN_M_REG(SSISR, 0x04, 0x40), | ||
341 | RSND_GEN_M_REG(SSITDR, 0x08, 0x40), | ||
342 | RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40), | ||
343 | RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), | ||
344 | }; | ||
345 | int ret_ssiu; | ||
346 | int ret_scu; | ||
347 | int ret_adg; | ||
348 | int ret_ssi; | ||
349 | |||
350 | ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, conf_ssiu); | ||
351 | ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, conf_scu); | ||
352 | ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG, conf_adg); | ||
353 | ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, conf_ssi); | ||
354 | if (ret_ssiu < 0 || | ||
355 | ret_scu < 0 || | ||
356 | ret_adg < 0 || | ||
357 | ret_ssi < 0) | ||
358 | return ret_ssiu | ret_scu | ret_adg | ret_ssi; | ||
359 | |||
360 | dev_dbg(dev, "Gen2 is probed\n"); | ||
369 | 361 | ||
370 | return 0; | 362 | return 0; |
371 | } | 363 | } |
@@ -374,92 +366,60 @@ static int rsnd_gen2_probe(struct platform_device *pdev, | |||
374 | * Gen1 | 366 | * Gen1 |
375 | */ | 367 | */ |
376 | 368 | ||
377 | /* single address mapping */ | ||
378 | #define RSND_GEN1_S_REG(gen, reg, id, offset) \ | ||
379 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9) | ||
380 | |||
381 | /* multi address mapping */ | ||
382 | #define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \ | ||
383 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9) | ||
384 | |||
385 | static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | ||
386 | { | ||
387 | struct reg_field regf[RSND_REG_MAX] = { | ||
388 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_SEL, 0x00), | ||
389 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08), | ||
390 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL1, 0x0c), | ||
391 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL2, 0x10), | ||
392 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_CTRL, 0xc0), | ||
393 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), | ||
394 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), | ||
395 | RSND_GEN1_M_REG(gen, SRU, SRC_BUSIF_MODE, 0x20, 0x4), | ||
396 | RSND_GEN1_M_REG(gen, SRU, SRC_ROUTE_MODE0,0x50, 0x8), | ||
397 | RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), | ||
398 | RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), | ||
399 | RSND_GEN1_M_REG(gen, SRU, SRC_ADINR, 0x214, 0x40), | ||
400 | RSND_GEN1_M_REG(gen, SRU, SRC_IFSCR, 0x21c, 0x40), | ||
401 | RSND_GEN1_M_REG(gen, SRU, SRC_IFSVR, 0x220, 0x40), | ||
402 | RSND_GEN1_M_REG(gen, SRU, SRC_SRCCR, 0x224, 0x40), | ||
403 | RSND_GEN1_M_REG(gen, SRU, SRC_MNFSR, 0x228, 0x40), | ||
404 | |||
405 | RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00), | ||
406 | RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04), | ||
407 | RSND_GEN1_S_REG(gen, ADG, SSICKR, 0x08), | ||
408 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), | ||
409 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), | ||
410 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL3, 0x18), | ||
411 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL4, 0x1c), | ||
412 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL5, 0x20), | ||
413 | |||
414 | RSND_GEN1_M_REG(gen, SSI, SSICR, 0x00, 0x40), | ||
415 | RSND_GEN1_M_REG(gen, SSI, SSISR, 0x04, 0x40), | ||
416 | RSND_GEN1_M_REG(gen, SSI, SSITDR, 0x08, 0x40), | ||
417 | RSND_GEN1_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), | ||
418 | RSND_GEN1_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), | ||
419 | }; | ||
420 | |||
421 | return rsnd_gen_regmap_init(priv, gen, regf); | ||
422 | } | ||
423 | |||
424 | static int rsnd_gen1_probe(struct platform_device *pdev, | 369 | static int rsnd_gen1_probe(struct platform_device *pdev, |
425 | struct rsnd_priv *priv) | 370 | struct rsnd_priv *priv) |
426 | { | 371 | { |
427 | struct device *dev = rsnd_priv_to_dev(priv); | 372 | struct device *dev = rsnd_priv_to_dev(priv); |
428 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 373 | struct rsnd_regmap_field_conf conf_sru[] = { |
429 | struct resource *sru_res; | 374 | RSND_GEN_S_REG(SRC_ROUTE_SEL, 0x00), |
430 | struct resource *adg_res; | 375 | RSND_GEN_S_REG(SRC_TMG_SEL0, 0x08), |
431 | struct resource *ssi_res; | 376 | RSND_GEN_S_REG(SRC_TMG_SEL1, 0x0c), |
432 | int ret; | 377 | RSND_GEN_S_REG(SRC_TMG_SEL2, 0x10), |
433 | 378 | RSND_GEN_S_REG(SRC_ROUTE_CTRL, 0xc0), | |
434 | /* | 379 | RSND_GEN_S_REG(SSI_MODE0, 0xD0), |
435 | * map address | 380 | RSND_GEN_S_REG(SSI_MODE1, 0xD4), |
436 | */ | 381 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x20, 0x4), |
437 | sru_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU); | 382 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0x50, 0x8), |
438 | adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG); | 383 | RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), |
439 | ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SSI); | 384 | RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), |
440 | 385 | RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), | |
441 | gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res); | 386 | RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40), |
442 | gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res); | 387 | RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), |
443 | gen->base[RSND_GEN1_SSI] = devm_ioremap_resource(dev, ssi_res); | 388 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), |
444 | if (IS_ERR(gen->base[RSND_GEN1_SRU]) || | 389 | RSND_GEN_M_REG(SRC_MNFSR, 0x228, 0x40), |
445 | IS_ERR(gen->base[RSND_GEN1_ADG]) || | 390 | }; |
446 | IS_ERR(gen->base[RSND_GEN1_SSI])) | 391 | struct rsnd_regmap_field_conf conf_adg[] = { |
447 | return -ENODEV; | 392 | RSND_GEN_S_REG(BRRA, 0x00), |
393 | RSND_GEN_S_REG(BRRB, 0x04), | ||
394 | RSND_GEN_S_REG(SSICKR, 0x08), | ||
395 | RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), | ||
396 | RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), | ||
397 | RSND_GEN_S_REG(AUDIO_CLK_SEL3, 0x18), | ||
398 | RSND_GEN_S_REG(AUDIO_CLK_SEL4, 0x1c), | ||
399 | RSND_GEN_S_REG(AUDIO_CLK_SEL5, 0x20), | ||
400 | }; | ||
401 | struct rsnd_regmap_field_conf conf_ssi[] = { | ||
402 | RSND_GEN_M_REG(SSICR, 0x00, 0x40), | ||
403 | RSND_GEN_M_REG(SSISR, 0x04, 0x40), | ||
404 | RSND_GEN_M_REG(SSITDR, 0x08, 0x40), | ||
405 | RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40), | ||
406 | RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), | ||
407 | }; | ||
408 | int ret_sru; | ||
409 | int ret_adg; | ||
410 | int ret_ssi; | ||
448 | 411 | ||
449 | ret = rsnd_gen1_regmap_init(priv, gen); | 412 | ret_sru = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SRU, conf_sru); |
450 | if (ret < 0) | 413 | ret_adg = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, conf_adg); |
451 | return ret; | 414 | ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, conf_ssi); |
415 | if (ret_sru < 0 || | ||
416 | ret_adg < 0 || | ||
417 | ret_ssi < 0) | ||
418 | return ret_sru | ret_adg | ret_ssi; | ||
452 | 419 | ||
453 | dev_dbg(dev, "Gen1 device probed\n"); | 420 | dev_dbg(dev, "Gen1 is probed\n"); |
454 | dev_dbg(dev, "SRU : %pap => %p\n", &sru_res->start, | ||
455 | gen->base[RSND_GEN1_SRU]); | ||
456 | dev_dbg(dev, "ADG : %pap => %p\n", &adg_res->start, | ||
457 | gen->base[RSND_GEN1_ADG]); | ||
458 | dev_dbg(dev, "SSI : %pap => %p\n", &ssi_res->start, | ||
459 | gen->base[RSND_GEN1_SSI]); | ||
460 | 421 | ||
461 | return 0; | 422 | return 0; |
462 | |||
463 | } | 423 | } |
464 | 424 | ||
465 | /* | 425 | /* |
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 39d98af5ee05..d119adf97c9c 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -90,6 +90,7 @@ enum rsnd_reg { | |||
90 | RSND_REG_SHARE19, | 90 | RSND_REG_SHARE19, |
91 | RSND_REG_SHARE20, | 91 | RSND_REG_SHARE20, |
92 | RSND_REG_SHARE21, | 92 | RSND_REG_SHARE21, |
93 | RSND_REG_SHARE22, | ||
93 | 94 | ||
94 | RSND_REG_MAX, | 95 | RSND_REG_MAX, |
95 | }; | 96 | }; |
@@ -127,6 +128,7 @@ enum rsnd_reg { | |||
127 | #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 | 128 | #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 |
128 | #define RSND_REG_CMD_CTRL RSND_REG_SHARE20 | 129 | #define RSND_REG_CMD_CTRL RSND_REG_SHARE20 |
129 | #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 | 130 | #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 |
131 | #define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22 | ||
130 | 132 | ||
131 | struct rsnd_of_data; | 133 | struct rsnd_of_data; |
132 | struct rsnd_priv; | 134 | struct rsnd_priv; |
@@ -156,12 +158,9 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod); | |||
156 | */ | 158 | */ |
157 | struct rsnd_dma { | 159 | struct rsnd_dma { |
158 | struct sh_dmae_slave slave; | 160 | struct sh_dmae_slave slave; |
159 | struct work_struct work; | ||
160 | struct dma_chan *chan; | 161 | struct dma_chan *chan; |
161 | enum dma_data_direction dir; | 162 | enum dma_transfer_direction dir; |
162 | 163 | dma_addr_t addr; | |
163 | int submit_loop; | ||
164 | int offset; /* it cares A/B plane */ | ||
165 | }; | 164 | }; |
166 | 165 | ||
167 | void rsnd_dma_start(struct rsnd_dma *dma); | 166 | void rsnd_dma_start(struct rsnd_dma *dma); |
@@ -185,6 +184,7 @@ enum rsnd_mod_type { | |||
185 | 184 | ||
186 | struct rsnd_mod_ops { | 185 | struct rsnd_mod_ops { |
187 | char *name; | 186 | char *name; |
187 | char* (*dma_name)(struct rsnd_mod *mod); | ||
188 | int (*probe)(struct rsnd_mod *mod, | 188 | int (*probe)(struct rsnd_mod *mod, |
189 | struct rsnd_dai *rdai); | 189 | struct rsnd_dai *rdai); |
190 | int (*remove)(struct rsnd_mod *mod, | 190 | int (*remove)(struct rsnd_mod *mod, |
@@ -224,6 +224,7 @@ void rsnd_mod_init(struct rsnd_priv *priv, | |||
224 | enum rsnd_mod_type type, | 224 | enum rsnd_mod_type type, |
225 | int id); | 225 | int id); |
226 | char *rsnd_mod_name(struct rsnd_mod *mod); | 226 | char *rsnd_mod_name(struct rsnd_mod *mod); |
227 | char *rsnd_mod_dma_name(struct rsnd_mod *mod); | ||
227 | 228 | ||
228 | /* | 229 | /* |
229 | * R-Car sound DAI | 230 | * R-Car sound DAI |
@@ -281,10 +282,9 @@ int rsnd_gen_probe(struct platform_device *pdev, | |||
281 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, | 282 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, |
282 | struct rsnd_mod *mod, | 283 | struct rsnd_mod *mod, |
283 | enum rsnd_reg reg); | 284 | enum rsnd_reg reg); |
284 | void rsnd_gen_dma_addr(struct rsnd_priv *priv, | 285 | dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv, |
285 | struct rsnd_dma *dma, | 286 | struct rsnd_mod *mod, |
286 | struct dma_slave_config *cfg, | 287 | int is_play, int is_from); |
287 | int is_play, int slave_id); | ||
288 | 288 | ||
289 | #define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1) | 289 | #define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1) |
290 | #define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2) | 290 | #define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2) |
@@ -391,8 +391,12 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); | |||
391 | unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, | 391 | unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, |
392 | struct rsnd_dai_stream *io, | 392 | struct rsnd_dai_stream *io, |
393 | struct snd_pcm_runtime *runtime); | 393 | struct snd_pcm_runtime *runtime); |
394 | int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, | 394 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
395 | struct rsnd_dai *rdai); | 395 | struct rsnd_dai *rdai, |
396 | int use_busif); | ||
397 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | ||
398 | struct rsnd_dai *rdai, | ||
399 | int use_busif); | ||
396 | int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, | 400 | int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, |
397 | struct rsnd_dai *rdai); | 401 | struct rsnd_dai *rdai); |
398 | 402 | ||
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 200eda019bc7..9183e0145503 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c | |||
@@ -106,18 +106,19 @@ struct rsnd_src { | |||
106 | /* | 106 | /* |
107 | * Gen1/Gen2 common functions | 107 | * Gen1/Gen2 common functions |
108 | */ | 108 | */ |
109 | int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, | 109 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
110 | struct rsnd_dai *rdai) | 110 | struct rsnd_dai *rdai, |
111 | int use_busif) | ||
111 | { | 112 | { |
112 | struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); | 113 | struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); |
113 | struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); | 114 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
114 | int ssi_id = rsnd_mod_id(ssi_mod); | 115 | int ssi_id = rsnd_mod_id(ssi_mod); |
115 | 116 | ||
116 | /* | 117 | /* |
117 | * SSI_MODE0 | 118 | * SSI_MODE0 |
118 | */ | 119 | */ |
119 | rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), | 120 | rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), |
120 | src_mod ? 0 : (1 << ssi_id)); | 121 | !use_busif << ssi_id); |
121 | 122 | ||
122 | /* | 123 | /* |
123 | * SSI_MODE1 | 124 | * SSI_MODE1 |
@@ -143,6 +144,46 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, | |||
143 | 0x2 << shift : 0x1 << shift); | 144 | 0x2 << shift : 0x1 << shift); |
144 | } | 145 | } |
145 | 146 | ||
147 | /* | ||
148 | * DMA settings for SSIU | ||
149 | */ | ||
150 | if (use_busif) { | ||
151 | u32 val = 0x76543210; | ||
152 | u32 mask = ~0; | ||
153 | |||
154 | rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, | ||
155 | rsnd_get_adinr(ssi_mod)); | ||
156 | rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); | ||
157 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); | ||
158 | |||
159 | mask <<= runtime->channels * 4; | ||
160 | val = val & mask; | ||
161 | |||
162 | switch (runtime->sample_bits) { | ||
163 | case 16: | ||
164 | val |= 0x67452301 & ~mask; | ||
165 | break; | ||
166 | case 32: | ||
167 | val |= 0x76543210 & ~mask; | ||
168 | break; | ||
169 | } | ||
170 | rsnd_mod_write(ssi_mod, BUSIF_DALIGN, val); | ||
171 | |||
172 | } | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | ||
178 | struct rsnd_dai *rdai, | ||
179 | int use_busif) | ||
180 | { | ||
181 | /* | ||
182 | * DMA settings for SSIU | ||
183 | */ | ||
184 | if (use_busif) | ||
185 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0); | ||
186 | |||
146 | return 0; | 187 | return 0; |
147 | } | 188 | } |
148 | 189 | ||
@@ -461,18 +502,45 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = { | |||
461 | static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, | 502 | static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, |
462 | struct rsnd_dai *rdai) | 503 | struct rsnd_dai *rdai) |
463 | { | 504 | { |
505 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
506 | struct device *dev = rsnd_priv_to_dev(priv); | ||
507 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
508 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
509 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
510 | uint ratio; | ||
464 | int ret; | 511 | int ret; |
465 | 512 | ||
513 | /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ | ||
514 | if (!rsnd_src_convert_rate(src)) | ||
515 | ratio = 0; | ||
516 | else if (rsnd_src_convert_rate(src) > runtime->rate) | ||
517 | ratio = 100 * rsnd_src_convert_rate(src) / runtime->rate; | ||
518 | else | ||
519 | ratio = 100 * runtime->rate / rsnd_src_convert_rate(src); | ||
520 | |||
521 | if (ratio > 600) { | ||
522 | dev_err(dev, "FSO/FSI ratio error\n"); | ||
523 | return -EINVAL; | ||
524 | } | ||
525 | |||
466 | ret = rsnd_src_set_convert_rate(mod, rdai); | 526 | ret = rsnd_src_set_convert_rate(mod, rdai); |
467 | if (ret < 0) | 527 | if (ret < 0) |
468 | return ret; | 528 | return ret; |
469 | 529 | ||
470 | rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_get_adinr(mod)); | ||
471 | rsnd_mod_write(mod, SSI_BUSIF_MODE, 1); | ||
472 | |||
473 | rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); | 530 | rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); |
474 | 531 | ||
475 | rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); | 532 | switch (rsnd_mod_id(mod)) { |
533 | case 5: | ||
534 | case 6: | ||
535 | case 7: | ||
536 | case 8: | ||
537 | rsnd_mod_write(mod, SRC_BSDSR, 0x02400000); | ||
538 | break; | ||
539 | default: | ||
540 | rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); | ||
541 | break; | ||
542 | } | ||
543 | |||
476 | rsnd_mod_write(mod, SRC_BSISR, 0x00100060); | 544 | rsnd_mod_write(mod, SRC_BSISR, 0x00100060); |
477 | 545 | ||
478 | return 0; | 546 | return 0; |
@@ -554,7 +622,6 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod, | |||
554 | 622 | ||
555 | rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); | 623 | rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); |
556 | 624 | ||
557 | rsnd_mod_write(mod, SSI_CTRL, 0x1); | ||
558 | rsnd_mod_write(mod, SRC_CTRL, val); | 625 | rsnd_mod_write(mod, SRC_CTRL, val); |
559 | 626 | ||
560 | return rsnd_src_start(mod, rdai); | 627 | return rsnd_src_start(mod, rdai); |
@@ -565,7 +632,6 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod, | |||
565 | { | 632 | { |
566 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 633 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
567 | 634 | ||
568 | rsnd_mod_write(mod, SSI_CTRL, 0); | ||
569 | rsnd_mod_write(mod, SRC_CTRL, 0); | 635 | rsnd_mod_write(mod, SRC_CTRL, 0); |
570 | 636 | ||
571 | rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); | 637 | rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); |
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 2df723df5d19..34e84009162b 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -90,6 +90,20 @@ struct rsnd_ssi { | |||
90 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) | 90 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) |
91 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) | 91 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) |
92 | 92 | ||
93 | static int rsnd_ssi_use_busif(struct rsnd_mod *mod) | ||
94 | { | ||
95 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
96 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
97 | int use_busif = 0; | ||
98 | |||
99 | if (!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_NO_BUSIF)) | ||
100 | use_busif = 1; | ||
101 | if (rsnd_io_to_mod_src(io)) | ||
102 | use_busif = 1; | ||
103 | |||
104 | return use_busif; | ||
105 | } | ||
106 | |||
93 | static void rsnd_ssi_status_check(struct rsnd_mod *mod, | 107 | static void rsnd_ssi_status_check(struct rsnd_mod *mod, |
94 | u32 bit) | 108 | u32 bit) |
95 | { | 109 | { |
@@ -289,8 +303,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, | |||
289 | ssi->cr_own = cr; | 303 | ssi->cr_own = cr; |
290 | ssi->err = -1; /* ignore 1st error */ | 304 | ssi->err = -1; /* ignore 1st error */ |
291 | 305 | ||
292 | rsnd_src_ssi_mode_init(mod, rdai); | ||
293 | |||
294 | return 0; | 306 | return 0; |
295 | } | 307 | } |
296 | 308 | ||
@@ -389,6 +401,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, | |||
389 | /* enable PIO IRQ */ | 401 | /* enable PIO IRQ */ |
390 | ssi->cr_etc = UIEN | OIEN | DIEN; | 402 | ssi->cr_etc = UIEN | OIEN | DIEN; |
391 | 403 | ||
404 | rsnd_src_ssiu_start(mod, rdai, 0); | ||
405 | |||
392 | rsnd_src_enable_ssi_irq(mod, rdai); | 406 | rsnd_src_enable_ssi_irq(mod, rdai); |
393 | 407 | ||
394 | rsnd_ssi_hw_start(ssi, rdai, io); | 408 | rsnd_ssi_hw_start(ssi, rdai, io); |
@@ -405,6 +419,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, | |||
405 | 419 | ||
406 | rsnd_ssi_hw_stop(ssi, rdai); | 420 | rsnd_ssi_hw_stop(ssi, rdai); |
407 | 421 | ||
422 | rsnd_src_ssiu_stop(mod, rdai, 0); | ||
423 | |||
408 | return 0; | 424 | return 0; |
409 | } | 425 | } |
410 | 426 | ||
@@ -457,6 +473,8 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, | |||
457 | /* enable DMA transfer */ | 473 | /* enable DMA transfer */ |
458 | ssi->cr_etc = DMEN; | 474 | ssi->cr_etc = DMEN; |
459 | 475 | ||
476 | rsnd_src_ssiu_start(mod, rdai, rsnd_ssi_use_busif(mod)); | ||
477 | |||
460 | rsnd_dma_start(dma); | 478 | rsnd_dma_start(dma); |
461 | 479 | ||
462 | rsnd_ssi_hw_start(ssi, ssi->rdai, io); | 480 | rsnd_ssi_hw_start(ssi, ssi->rdai, io); |
@@ -482,11 +500,19 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, | |||
482 | 500 | ||
483 | rsnd_dma_stop(dma); | 501 | rsnd_dma_stop(dma); |
484 | 502 | ||
503 | rsnd_src_ssiu_stop(mod, rdai, 1); | ||
504 | |||
485 | return 0; | 505 | return 0; |
486 | } | 506 | } |
487 | 507 | ||
508 | static char *rsnd_ssi_dma_name(struct rsnd_mod *mod) | ||
509 | { | ||
510 | return rsnd_ssi_use_busif(mod) ? "ssiu" : SSI_NAME; | ||
511 | } | ||
512 | |||
488 | static struct rsnd_mod_ops rsnd_ssi_dma_ops = { | 513 | static struct rsnd_mod_ops rsnd_ssi_dma_ops = { |
489 | .name = SSI_NAME, | 514 | .name = SSI_NAME, |
515 | .dma_name = rsnd_ssi_dma_name, | ||
490 | .probe = rsnd_ssi_dma_probe, | 516 | .probe = rsnd_ssi_dma_probe, |
491 | .remove = rsnd_ssi_dma_remove, | 517 | .remove = rsnd_ssi_dma_remove, |
492 | .init = rsnd_ssi_init, | 518 | .init = rsnd_ssi_init, |
@@ -595,6 +621,9 @@ static void rsnd_of_parse_ssi(struct platform_device *pdev, | |||
595 | */ | 621 | */ |
596 | ssi_info->dma_id = of_get_property(np, "pio-transfer", NULL) ? | 622 | ssi_info->dma_id = of_get_property(np, "pio-transfer", NULL) ? |
597 | 0 : 1; | 623 | 0 : 1; |
624 | |||
625 | if (of_get_property(np, "no-busif", NULL)) | ||
626 | ssi_info->flags |= RSND_SSI_NO_BUSIF; | ||
598 | } | 627 | } |
599 | 628 | ||
600 | rsnd_of_parse_ssi_end: | 629 | rsnd_of_parse_ssi_end: |
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 00e70b6c7da2..a9f82b5aba9d 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -78,7 +78,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec) | |||
78 | mutex_init(&codec->cache_rw_mutex); | 78 | mutex_init(&codec->cache_rw_mutex); |
79 | 79 | ||
80 | dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n", | 80 | dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n", |
81 | codec->name); | 81 | codec->component.name); |
82 | 82 | ||
83 | if (codec_drv->reg_cache_default) | 83 | if (codec_drv->reg_cache_default) |
84 | codec->reg_cache = kmemdup(codec_drv->reg_cache_default, | 84 | codec->reg_cache = kmemdup(codec_drv->reg_cache_default, |
@@ -98,8 +98,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec) | |||
98 | int snd_soc_cache_exit(struct snd_soc_codec *codec) | 98 | int snd_soc_cache_exit(struct snd_soc_codec *codec) |
99 | { | 99 | { |
100 | dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n", | 100 | dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n", |
101 | codec->name); | 101 | codec->component.name); |
102 | |||
103 | kfree(codec->reg_cache); | 102 | kfree(codec->reg_cache); |
104 | codec->reg_cache = NULL; | 103 | codec->reg_cache = NULL; |
105 | return 0; | 104 | return 0; |
@@ -192,7 +191,7 @@ int snd_soc_cache_sync(struct snd_soc_codec *codec) | |||
192 | return 0; | 191 | return 0; |
193 | 192 | ||
194 | dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n", | 193 | dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n", |
195 | codec->name); | 194 | codec->component.name); |
196 | trace_snd_soc_cache_sync(codec, name, "start"); | 195 | trace_snd_soc_cache_sync(codec, name, "start"); |
197 | ret = snd_soc_flat_cache_sync(codec); | 196 | ret = snd_soc_flat_cache_sync(codec); |
198 | if (!ret) | 197 | if (!ret) |
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 10f7f1da2aca..27c06acce205 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c | |||
@@ -37,7 +37,8 @@ static int soc_compr_open(struct snd_compr_stream *cstream) | |||
37 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { | 37 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { |
38 | ret = platform->driver->compr_ops->open(cstream); | 38 | ret = platform->driver->compr_ops->open(cstream); |
39 | if (ret < 0) { | 39 | if (ret < 0) { |
40 | pr_err("compress asoc: can't open platform %s\n", platform->name); | 40 | pr_err("compress asoc: can't open platform %s\n", |
41 | platform->component.name); | ||
41 | goto out; | 42 | goto out; |
42 | } | 43 | } |
43 | } | 44 | } |
@@ -84,7 +85,8 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) | |||
84 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { | 85 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { |
85 | ret = platform->driver->compr_ops->open(cstream); | 86 | ret = platform->driver->compr_ops->open(cstream); |
86 | if (ret < 0) { | 87 | if (ret < 0) { |
87 | pr_err("compress asoc: can't open platform %s\n", platform->name); | 88 | pr_err("compress asoc: can't open platform %s\n", |
89 | platform->component.name); | ||
88 | goto out; | 90 | goto out; |
89 | } | 91 | } |
90 | } | 92 | } |
@@ -627,6 +629,11 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) | |||
627 | char new_name[64]; | 629 | char new_name[64]; |
628 | int ret = 0, direction = 0; | 630 | int ret = 0, direction = 0; |
629 | 631 | ||
632 | if (rtd->num_codecs > 1) { | ||
633 | dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n"); | ||
634 | return -EINVAL; | ||
635 | } | ||
636 | |||
630 | /* check client and interface hw capabilities */ | 637 | /* check client and interface hw capabilities */ |
631 | snprintf(new_name, sizeof(new_name), "%s %s-%d", | 638 | snprintf(new_name, sizeof(new_name), "%s %s-%d", |
632 | rtd->dai_link->stream_name, codec_dai->name, num); | 639 | rtd->dai_link->stream_name, codec_dai->name, num); |
@@ -680,7 +687,7 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) | |||
680 | ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); | 687 | ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); |
681 | if (ret < 0) { | 688 | if (ret < 0) { |
682 | pr_err("compress asoc: can't create compress for codec %s\n", | 689 | pr_err("compress asoc: can't create compress for codec %s\n", |
683 | codec->name); | 690 | codec->component.name); |
684 | goto compr_err; | 691 | goto compr_err; |
685 | } | 692 | } |
686 | 693 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b87d7d882e6d..2d6c8b86b7d3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -270,12 +270,33 @@ static const struct file_operations codec_reg_fops = { | |||
270 | .llseek = default_llseek, | 270 | .llseek = default_llseek, |
271 | }; | 271 | }; |
272 | 272 | ||
273 | static struct dentry *soc_debugfs_create_dir(struct dentry *parent, | ||
274 | const char *fmt, ...) | ||
275 | { | ||
276 | struct dentry *de; | ||
277 | va_list ap; | ||
278 | char *s; | ||
279 | |||
280 | va_start(ap, fmt); | ||
281 | s = kvasprintf(GFP_KERNEL, fmt, ap); | ||
282 | va_end(ap); | ||
283 | |||
284 | if (!s) | ||
285 | return NULL; | ||
286 | |||
287 | de = debugfs_create_dir(s, parent); | ||
288 | kfree(s); | ||
289 | |||
290 | return de; | ||
291 | } | ||
292 | |||
273 | static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | 293 | static void soc_init_codec_debugfs(struct snd_soc_codec *codec) |
274 | { | 294 | { |
275 | struct dentry *debugfs_card_root = codec->card->debugfs_card_root; | 295 | struct dentry *debugfs_card_root = codec->component.card->debugfs_card_root; |
276 | 296 | ||
277 | codec->debugfs_codec_root = debugfs_create_dir(codec->name, | 297 | codec->debugfs_codec_root = soc_debugfs_create_dir(debugfs_card_root, |
278 | debugfs_card_root); | 298 | "codec:%s", |
299 | codec->component.name); | ||
279 | if (!codec->debugfs_codec_root) { | 300 | if (!codec->debugfs_codec_root) { |
280 | dev_warn(codec->dev, | 301 | dev_warn(codec->dev, |
281 | "ASoC: Failed to create codec debugfs directory\n"); | 302 | "ASoC: Failed to create codec debugfs directory\n"); |
@@ -304,17 +325,18 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | |||
304 | 325 | ||
305 | static void soc_init_platform_debugfs(struct snd_soc_platform *platform) | 326 | static void soc_init_platform_debugfs(struct snd_soc_platform *platform) |
306 | { | 327 | { |
307 | struct dentry *debugfs_card_root = platform->card->debugfs_card_root; | 328 | struct dentry *debugfs_card_root = platform->component.card->debugfs_card_root; |
308 | 329 | ||
309 | platform->debugfs_platform_root = debugfs_create_dir(platform->name, | 330 | platform->debugfs_platform_root = soc_debugfs_create_dir(debugfs_card_root, |
310 | debugfs_card_root); | 331 | "platform:%s", |
332 | platform->component.name); | ||
311 | if (!platform->debugfs_platform_root) { | 333 | if (!platform->debugfs_platform_root) { |
312 | dev_warn(platform->dev, | 334 | dev_warn(platform->dev, |
313 | "ASoC: Failed to create platform debugfs directory\n"); | 335 | "ASoC: Failed to create platform debugfs directory\n"); |
314 | return; | 336 | return; |
315 | } | 337 | } |
316 | 338 | ||
317 | snd_soc_dapm_debugfs_init(&platform->dapm, | 339 | snd_soc_dapm_debugfs_init(&platform->component.dapm, |
318 | platform->debugfs_platform_root); | 340 | platform->debugfs_platform_root); |
319 | } | 341 | } |
320 | 342 | ||
@@ -335,7 +357,7 @@ static ssize_t codec_list_read_file(struct file *file, char __user *user_buf, | |||
335 | 357 | ||
336 | list_for_each_entry(codec, &codec_list, list) { | 358 | list_for_each_entry(codec, &codec_list, list) { |
337 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", | 359 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", |
338 | codec->name); | 360 | codec->component.name); |
339 | if (len >= 0) | 361 | if (len >= 0) |
340 | ret += len; | 362 | ret += len; |
341 | if (ret > PAGE_SIZE) { | 363 | if (ret > PAGE_SIZE) { |
@@ -406,7 +428,7 @@ static ssize_t platform_list_read_file(struct file *file, | |||
406 | 428 | ||
407 | list_for_each_entry(platform, &platform_list, list) { | 429 | list_for_each_entry(platform, &platform_list, list) { |
408 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", | 430 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", |
409 | platform->name); | 431 | platform->component.name); |
410 | if (len >= 0) | 432 | if (len >= 0) |
411 | ret += len; | 433 | ret += len; |
412 | if (ret > PAGE_SIZE) { | 434 | if (ret > PAGE_SIZE) { |
@@ -524,11 +546,12 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) | |||
524 | int err; | 546 | int err; |
525 | 547 | ||
526 | codec->ac97->dev.bus = &ac97_bus_type; | 548 | codec->ac97->dev.bus = &ac97_bus_type; |
527 | codec->ac97->dev.parent = codec->card->dev; | 549 | codec->ac97->dev.parent = codec->component.card->dev; |
528 | codec->ac97->dev.release = soc_ac97_device_release; | 550 | codec->ac97->dev.release = soc_ac97_device_release; |
529 | 551 | ||
530 | dev_set_name(&codec->ac97->dev, "%d-%d:%s", | 552 | dev_set_name(&codec->ac97->dev, "%d-%d:%s", |
531 | codec->card->snd_card->number, 0, codec->name); | 553 | codec->component.card->snd_card->number, 0, |
554 | codec->component.name); | ||
532 | err = device_register(&codec->ac97->dev); | 555 | err = device_register(&codec->ac97->dev); |
533 | if (err < 0) { | 556 | if (err < 0) { |
534 | dev_err(codec->dev, "ASoC: Can't register ac97 bus\n"); | 557 | dev_err(codec->dev, "ASoC: Can't register ac97 bus\n"); |
@@ -554,7 +577,7 @@ int snd_soc_suspend(struct device *dev) | |||
554 | { | 577 | { |
555 | struct snd_soc_card *card = dev_get_drvdata(dev); | 578 | struct snd_soc_card *card = dev_get_drvdata(dev); |
556 | struct snd_soc_codec *codec; | 579 | struct snd_soc_codec *codec; |
557 | int i; | 580 | int i, j; |
558 | 581 | ||
559 | /* If the initialization of this soc device failed, there is no codec | 582 | /* If the initialization of this soc device failed, there is no codec |
560 | * associated with it. Just bail out in this case. | 583 | * associated with it. Just bail out in this case. |
@@ -574,14 +597,17 @@ int snd_soc_suspend(struct device *dev) | |||
574 | 597 | ||
575 | /* mute any active DACs */ | 598 | /* mute any active DACs */ |
576 | for (i = 0; i < card->num_rtd; i++) { | 599 | for (i = 0; i < card->num_rtd; i++) { |
577 | struct snd_soc_dai *dai = card->rtd[i].codec_dai; | ||
578 | struct snd_soc_dai_driver *drv = dai->driver; | ||
579 | 600 | ||
580 | if (card->rtd[i].dai_link->ignore_suspend) | 601 | if (card->rtd[i].dai_link->ignore_suspend) |
581 | continue; | 602 | continue; |
582 | 603 | ||
583 | if (drv->ops->digital_mute && dai->playback_active) | 604 | for (j = 0; j < card->rtd[i].num_codecs; j++) { |
584 | drv->ops->digital_mute(dai, 1); | 605 | struct snd_soc_dai *dai = card->rtd[i].codec_dais[j]; |
606 | struct snd_soc_dai_driver *drv = dai->driver; | ||
607 | |||
608 | if (drv->ops->digital_mute && dai->playback_active) | ||
609 | drv->ops->digital_mute(dai, 1); | ||
610 | } | ||
585 | } | 611 | } |
586 | 612 | ||
587 | /* suspend all pcms */ | 613 | /* suspend all pcms */ |
@@ -612,8 +638,12 @@ int snd_soc_suspend(struct device *dev) | |||
612 | 638 | ||
613 | /* close any waiting streams and save state */ | 639 | /* close any waiting streams and save state */ |
614 | for (i = 0; i < card->num_rtd; i++) { | 640 | for (i = 0; i < card->num_rtd; i++) { |
641 | struct snd_soc_dai **codec_dais = card->rtd[i].codec_dais; | ||
615 | flush_delayed_work(&card->rtd[i].delayed_work); | 642 | flush_delayed_work(&card->rtd[i].delayed_work); |
616 | card->rtd[i].codec->dapm.suspend_bias_level = card->rtd[i].codec->dapm.bias_level; | 643 | for (j = 0; j < card->rtd[i].num_codecs; j++) { |
644 | codec_dais[j]->codec->dapm.suspend_bias_level = | ||
645 | codec_dais[j]->codec->dapm.bias_level; | ||
646 | } | ||
617 | } | 647 | } |
618 | 648 | ||
619 | for (i = 0; i < card->num_rtd; i++) { | 649 | for (i = 0; i < card->num_rtd; i++) { |
@@ -697,7 +727,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
697 | struct snd_soc_card *card = | 727 | struct snd_soc_card *card = |
698 | container_of(work, struct snd_soc_card, deferred_resume_work); | 728 | container_of(work, struct snd_soc_card, deferred_resume_work); |
699 | struct snd_soc_codec *codec; | 729 | struct snd_soc_codec *codec; |
700 | int i; | 730 | int i, j; |
701 | 731 | ||
702 | /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, | 732 | /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, |
703 | * so userspace apps are blocked from touching us | 733 | * so userspace apps are blocked from touching us |
@@ -758,14 +788,17 @@ static void soc_resume_deferred(struct work_struct *work) | |||
758 | 788 | ||
759 | /* unmute any active DACs */ | 789 | /* unmute any active DACs */ |
760 | for (i = 0; i < card->num_rtd; i++) { | 790 | for (i = 0; i < card->num_rtd; i++) { |
761 | struct snd_soc_dai *dai = card->rtd[i].codec_dai; | ||
762 | struct snd_soc_dai_driver *drv = dai->driver; | ||
763 | 791 | ||
764 | if (card->rtd[i].dai_link->ignore_suspend) | 792 | if (card->rtd[i].dai_link->ignore_suspend) |
765 | continue; | 793 | continue; |
766 | 794 | ||
767 | if (drv->ops->digital_mute && dai->playback_active) | 795 | for (j = 0; j < card->rtd[i].num_codecs; j++) { |
768 | drv->ops->digital_mute(dai, 0); | 796 | struct snd_soc_dai *dai = card->rtd[i].codec_dais[j]; |
797 | struct snd_soc_dai_driver *drv = dai->driver; | ||
798 | |||
799 | if (drv->ops->digital_mute && dai->playback_active) | ||
800 | drv->ops->digital_mute(dai, 0); | ||
801 | } | ||
769 | } | 802 | } |
770 | 803 | ||
771 | for (i = 0; i < card->num_rtd; i++) { | 804 | for (i = 0; i < card->num_rtd; i++) { |
@@ -810,12 +843,19 @@ int snd_soc_resume(struct device *dev) | |||
810 | 843 | ||
811 | /* activate pins from sleep state */ | 844 | /* activate pins from sleep state */ |
812 | for (i = 0; i < card->num_rtd; i++) { | 845 | for (i = 0; i < card->num_rtd; i++) { |
813 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 846 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; |
814 | struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; | 847 | struct snd_soc_dai **codec_dais = rtd->codec_dais; |
848 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
849 | int j; | ||
850 | |||
815 | if (cpu_dai->active) | 851 | if (cpu_dai->active) |
816 | pinctrl_pm_select_default_state(cpu_dai->dev); | 852 | pinctrl_pm_select_default_state(cpu_dai->dev); |
817 | if (codec_dai->active) | 853 | |
818 | pinctrl_pm_select_default_state(codec_dai->dev); | 854 | for (j = 0; j < rtd->num_codecs; j++) { |
855 | struct snd_soc_dai *codec_dai = codec_dais[j]; | ||
856 | if (codec_dai->active) | ||
857 | pinctrl_pm_select_default_state(codec_dai->dev); | ||
858 | } | ||
819 | } | 859 | } |
820 | 860 | ||
821 | /* AC97 devices might have other drivers hanging off them so | 861 | /* AC97 devices might have other drivers hanging off them so |
@@ -847,8 +887,9 @@ EXPORT_SYMBOL_GPL(snd_soc_resume); | |||
847 | static const struct snd_soc_dai_ops null_dai_ops = { | 887 | static const struct snd_soc_dai_ops null_dai_ops = { |
848 | }; | 888 | }; |
849 | 889 | ||
850 | static struct snd_soc_codec *soc_find_codec(const struct device_node *codec_of_node, | 890 | static struct snd_soc_codec *soc_find_codec( |
851 | const char *codec_name) | 891 | const struct device_node *codec_of_node, |
892 | const char *codec_name) | ||
852 | { | 893 | { |
853 | struct snd_soc_codec *codec; | 894 | struct snd_soc_codec *codec; |
854 | 895 | ||
@@ -857,7 +898,7 @@ static struct snd_soc_codec *soc_find_codec(const struct device_node *codec_of_n | |||
857 | if (codec->dev->of_node != codec_of_node) | 898 | if (codec->dev->of_node != codec_of_node) |
858 | continue; | 899 | continue; |
859 | } else { | 900 | } else { |
860 | if (strcmp(codec->name, codec_name)) | 901 | if (strcmp(codec->component.name, codec_name)) |
861 | continue; | 902 | continue; |
862 | } | 903 | } |
863 | 904 | ||
@@ -886,9 +927,12 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
886 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 927 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
887 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 928 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
888 | struct snd_soc_component *component; | 929 | struct snd_soc_component *component; |
930 | struct snd_soc_dai_link_component *codecs = dai_link->codecs; | ||
931 | struct snd_soc_dai **codec_dais = rtd->codec_dais; | ||
889 | struct snd_soc_platform *platform; | 932 | struct snd_soc_platform *platform; |
890 | struct snd_soc_dai *cpu_dai; | 933 | struct snd_soc_dai *cpu_dai; |
891 | const char *platform_name; | 934 | const char *platform_name; |
935 | int i; | ||
892 | 936 | ||
893 | dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); | 937 | dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); |
894 | 938 | ||
@@ -915,24 +959,30 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
915 | return -EPROBE_DEFER; | 959 | return -EPROBE_DEFER; |
916 | } | 960 | } |
917 | 961 | ||
918 | /* Find CODEC from registered list */ | 962 | rtd->num_codecs = dai_link->num_codecs; |
919 | rtd->codec = soc_find_codec(dai_link->codec_of_node, | ||
920 | dai_link->codec_name); | ||
921 | if (!rtd->codec) { | ||
922 | dev_err(card->dev, "ASoC: CODEC %s not registered\n", | ||
923 | dai_link->codec_name); | ||
924 | return -EPROBE_DEFER; | ||
925 | } | ||
926 | 963 | ||
927 | /* Find CODEC DAI from registered list */ | 964 | /* Find CODEC from registered CODECs */ |
928 | rtd->codec_dai = soc_find_codec_dai(rtd->codec, | 965 | for (i = 0; i < rtd->num_codecs; i++) { |
929 | dai_link->codec_dai_name); | 966 | struct snd_soc_codec *codec; |
930 | if (!rtd->codec_dai) { | 967 | codec = soc_find_codec(codecs[i].of_node, codecs[i].name); |
931 | dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", | 968 | if (!codec) { |
932 | dai_link->codec_dai_name); | 969 | dev_err(card->dev, "ASoC: CODEC %s not registered\n", |
933 | return -EPROBE_DEFER; | 970 | codecs[i].name); |
971 | return -EPROBE_DEFER; | ||
972 | } | ||
973 | |||
974 | codec_dais[i] = soc_find_codec_dai(codec, codecs[i].dai_name); | ||
975 | if (!codec_dais[i]) { | ||
976 | dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", | ||
977 | codecs[i].dai_name); | ||
978 | return -EPROBE_DEFER; | ||
979 | } | ||
934 | } | 980 | } |
935 | 981 | ||
982 | /* Single codec links expect codec and codec_dai in runtime data */ | ||
983 | rtd->codec_dai = codec_dais[0]; | ||
984 | rtd->codec = rtd->codec_dai->codec; | ||
985 | |||
936 | /* if there's no platform we match on the empty platform */ | 986 | /* if there's no platform we match on the empty platform */ |
937 | platform_name = dai_link->platform_name; | 987 | platform_name = dai_link->platform_name; |
938 | if (!platform_name && !dai_link->platform_of_node) | 988 | if (!platform_name && !dai_link->platform_of_node) |
@@ -945,7 +995,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
945 | dai_link->platform_of_node) | 995 | dai_link->platform_of_node) |
946 | continue; | 996 | continue; |
947 | } else { | 997 | } else { |
948 | if (strcmp(platform->name, platform_name)) | 998 | if (strcmp(platform->component.name, platform_name)) |
949 | continue; | 999 | continue; |
950 | } | 1000 | } |
951 | 1001 | ||
@@ -974,11 +1024,10 @@ static int soc_remove_platform(struct snd_soc_platform *platform) | |||
974 | } | 1024 | } |
975 | 1025 | ||
976 | /* Make sure all DAPM widgets are freed */ | 1026 | /* Make sure all DAPM widgets are freed */ |
977 | snd_soc_dapm_free(&platform->dapm); | 1027 | snd_soc_dapm_free(&platform->component.dapm); |
978 | 1028 | ||
979 | soc_cleanup_platform_debugfs(platform); | 1029 | soc_cleanup_platform_debugfs(platform); |
980 | platform->probed = 0; | 1030 | platform->probed = 0; |
981 | list_del(&platform->card_list); | ||
982 | module_put(platform->dev->driver->owner); | 1031 | module_put(platform->dev->driver->owner); |
983 | 1032 | ||
984 | return 0; | 1033 | return 0; |
@@ -1023,8 +1072,8 @@ static void soc_remove_codec_dai(struct snd_soc_dai *codec_dai, int order) | |||
1023 | static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) | 1072 | static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) |
1024 | { | 1073 | { |
1025 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1074 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1026 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; | 1075 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1027 | int err; | 1076 | int i, err; |
1028 | 1077 | ||
1029 | /* unregister the rtd device */ | 1078 | /* unregister the rtd device */ |
1030 | if (rtd->dev_registered) { | 1079 | if (rtd->dev_registered) { |
@@ -1035,7 +1084,8 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) | |||
1035 | } | 1084 | } |
1036 | 1085 | ||
1037 | /* remove the CODEC DAI */ | 1086 | /* remove the CODEC DAI */ |
1038 | soc_remove_codec_dai(codec_dai, order); | 1087 | for (i = 0; i < rtd->num_codecs; i++) |
1088 | soc_remove_codec_dai(rtd->codec_dais[i], order); | ||
1039 | 1089 | ||
1040 | /* remove the cpu_dai */ | 1090 | /* remove the cpu_dai */ |
1041 | if (cpu_dai && cpu_dai->probed && | 1091 | if (cpu_dai && cpu_dai->probed && |
@@ -1048,11 +1098,8 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) | |||
1048 | cpu_dai->name, err); | 1098 | cpu_dai->name, err); |
1049 | } | 1099 | } |
1050 | cpu_dai->probed = 0; | 1100 | cpu_dai->probed = 0; |
1051 | 1101 | if (!cpu_dai->codec) | |
1052 | if (!cpu_dai->codec) { | ||
1053 | snd_soc_dapm_free(&cpu_dai->dapm); | ||
1054 | module_put(cpu_dai->dev->driver->owner); | 1102 | module_put(cpu_dai->dev->driver->owner); |
1055 | } | ||
1056 | } | 1103 | } |
1057 | } | 1104 | } |
1058 | 1105 | ||
@@ -1061,9 +1108,9 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num, | |||
1061 | { | 1108 | { |
1062 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1109 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1063 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1110 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1064 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1065 | struct snd_soc_platform *platform = rtd->platform; | 1111 | struct snd_soc_platform *platform = rtd->platform; |
1066 | struct snd_soc_codec *codec; | 1112 | struct snd_soc_codec *codec; |
1113 | int i; | ||
1067 | 1114 | ||
1068 | /* remove the platform */ | 1115 | /* remove the platform */ |
1069 | if (platform && platform->probed && | 1116 | if (platform && platform->probed && |
@@ -1072,8 +1119,8 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num, | |||
1072 | } | 1119 | } |
1073 | 1120 | ||
1074 | /* remove the CODEC-side CODEC */ | 1121 | /* remove the CODEC-side CODEC */ |
1075 | if (codec_dai) { | 1122 | for (i = 0; i < rtd->num_codecs; i++) { |
1076 | codec = codec_dai->codec; | 1123 | codec = rtd->codec_dais[i]->codec; |
1077 | if (codec && codec->probed && | 1124 | if (codec && codec->probed && |
1078 | codec->driver->remove_order == order) | 1125 | codec->driver->remove_order == order) |
1079 | soc_remove_codec(codec); | 1126 | soc_remove_codec(codec); |
@@ -1108,7 +1155,7 @@ static void soc_remove_dai_links(struct snd_soc_card *card) | |||
1108 | } | 1155 | } |
1109 | 1156 | ||
1110 | static void soc_set_name_prefix(struct snd_soc_card *card, | 1157 | static void soc_set_name_prefix(struct snd_soc_card *card, |
1111 | struct snd_soc_codec *codec) | 1158 | struct snd_soc_component *component) |
1112 | { | 1159 | { |
1113 | int i; | 1160 | int i; |
1114 | 1161 | ||
@@ -1117,11 +1164,11 @@ static void soc_set_name_prefix(struct snd_soc_card *card, | |||
1117 | 1164 | ||
1118 | for (i = 0; i < card->num_configs; i++) { | 1165 | for (i = 0; i < card->num_configs; i++) { |
1119 | struct snd_soc_codec_conf *map = &card->codec_conf[i]; | 1166 | struct snd_soc_codec_conf *map = &card->codec_conf[i]; |
1120 | if (map->of_node && codec->dev->of_node != map->of_node) | 1167 | if (map->of_node && component->dev->of_node != map->of_node) |
1121 | continue; | 1168 | continue; |
1122 | if (map->dev_name && strcmp(codec->name, map->dev_name)) | 1169 | if (map->dev_name && strcmp(component->name, map->dev_name)) |
1123 | continue; | 1170 | continue; |
1124 | codec->name_prefix = map->name_prefix; | 1171 | component->name_prefix = map->name_prefix; |
1125 | break; | 1172 | break; |
1126 | } | 1173 | } |
1127 | } | 1174 | } |
@@ -1133,9 +1180,9 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1133 | const struct snd_soc_codec_driver *driver = codec->driver; | 1180 | const struct snd_soc_codec_driver *driver = codec->driver; |
1134 | struct snd_soc_dai *dai; | 1181 | struct snd_soc_dai *dai; |
1135 | 1182 | ||
1136 | codec->card = card; | 1183 | codec->component.card = card; |
1137 | codec->dapm.card = card; | 1184 | codec->dapm.card = card; |
1138 | soc_set_name_prefix(card, codec); | 1185 | soc_set_name_prefix(card, &codec->component); |
1139 | 1186 | ||
1140 | if (!try_module_get(codec->dev->driver->owner)) | 1187 | if (!try_module_get(codec->dev->driver->owner)) |
1141 | return -ENODEV; | 1188 | return -ENODEV; |
@@ -1177,7 +1224,7 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1177 | WARN(codec->dapm.idle_bias_off && | 1224 | WARN(codec->dapm.idle_bias_off && |
1178 | codec->dapm.bias_level != SND_SOC_BIAS_OFF, | 1225 | codec->dapm.bias_level != SND_SOC_BIAS_OFF, |
1179 | "codec %s can not start from non-off bias with idle_bias_off==1\n", | 1226 | "codec %s can not start from non-off bias with idle_bias_off==1\n", |
1180 | codec->name); | 1227 | codec->component.name); |
1181 | } | 1228 | } |
1182 | 1229 | ||
1183 | if (driver->controls) | 1230 | if (driver->controls) |
@@ -1209,8 +1256,8 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1209 | struct snd_soc_component *component; | 1256 | struct snd_soc_component *component; |
1210 | struct snd_soc_dai *dai; | 1257 | struct snd_soc_dai *dai; |
1211 | 1258 | ||
1212 | platform->card = card; | 1259 | platform->component.card = card; |
1213 | platform->dapm.card = card; | 1260 | platform->component.dapm.card = card; |
1214 | 1261 | ||
1215 | if (!try_module_get(platform->dev->driver->owner)) | 1262 | if (!try_module_get(platform->dev->driver->owner)) |
1216 | return -ENODEV; | 1263 | return -ENODEV; |
@@ -1218,7 +1265,7 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1218 | soc_init_platform_debugfs(platform); | 1265 | soc_init_platform_debugfs(platform); |
1219 | 1266 | ||
1220 | if (driver->dapm_widgets) | 1267 | if (driver->dapm_widgets) |
1221 | snd_soc_dapm_new_controls(&platform->dapm, | 1268 | snd_soc_dapm_new_controls(&platform->component.dapm, |
1222 | driver->dapm_widgets, driver->num_dapm_widgets); | 1269 | driver->dapm_widgets, driver->num_dapm_widgets); |
1223 | 1270 | ||
1224 | /* Create DAPM widgets for each DAI stream */ | 1271 | /* Create DAPM widgets for each DAI stream */ |
@@ -1226,10 +1273,11 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1226 | if (component->dev != platform->dev) | 1273 | if (component->dev != platform->dev) |
1227 | continue; | 1274 | continue; |
1228 | list_for_each_entry(dai, &component->dai_list, list) | 1275 | list_for_each_entry(dai, &component->dai_list, list) |
1229 | snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); | 1276 | snd_soc_dapm_new_dai_widgets(&platform->component.dapm, |
1277 | dai); | ||
1230 | } | 1278 | } |
1231 | 1279 | ||
1232 | platform->dapm.idle_bias_off = 1; | 1280 | platform->component.dapm.idle_bias_off = 1; |
1233 | 1281 | ||
1234 | if (driver->probe) { | 1282 | if (driver->probe) { |
1235 | ret = driver->probe(platform); | 1283 | ret = driver->probe(platform); |
@@ -1244,13 +1292,12 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1244 | snd_soc_add_platform_controls(platform, driver->controls, | 1292 | snd_soc_add_platform_controls(platform, driver->controls, |
1245 | driver->num_controls); | 1293 | driver->num_controls); |
1246 | if (driver->dapm_routes) | 1294 | if (driver->dapm_routes) |
1247 | snd_soc_dapm_add_routes(&platform->dapm, driver->dapm_routes, | 1295 | snd_soc_dapm_add_routes(&platform->component.dapm, |
1248 | driver->num_dapm_routes); | 1296 | driver->dapm_routes, driver->num_dapm_routes); |
1249 | 1297 | ||
1250 | /* mark platform as probed and add to card platform list */ | 1298 | /* mark platform as probed and add to card platform list */ |
1251 | platform->probed = 1; | 1299 | platform->probed = 1; |
1252 | list_add(&platform->card_list, &card->platform_dev_list); | 1300 | list_add(&platform->component.dapm.list, &card->dapm_list); |
1253 | list_add(&platform->dapm.list, &card->dapm_list); | ||
1254 | 1301 | ||
1255 | return 0; | 1302 | return 0; |
1256 | 1303 | ||
@@ -1266,83 +1313,17 @@ static void rtd_release(struct device *dev) | |||
1266 | kfree(dev); | 1313 | kfree(dev); |
1267 | } | 1314 | } |
1268 | 1315 | ||
1269 | static int soc_aux_dev_init(struct snd_soc_card *card, | 1316 | static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, |
1270 | struct snd_soc_codec *codec, | 1317 | const char *name) |
1271 | int num) | ||
1272 | { | ||
1273 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | ||
1274 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | ||
1275 | int ret; | ||
1276 | |||
1277 | rtd->card = card; | ||
1278 | |||
1279 | /* do machine specific initialization */ | ||
1280 | if (aux_dev->init) { | ||
1281 | ret = aux_dev->init(&codec->dapm); | ||
1282 | if (ret < 0) | ||
1283 | return ret; | ||
1284 | } | ||
1285 | |||
1286 | rtd->codec = codec; | ||
1287 | |||
1288 | return 0; | ||
1289 | } | ||
1290 | |||
1291 | static int soc_dai_link_init(struct snd_soc_card *card, | ||
1292 | struct snd_soc_codec *codec, | ||
1293 | int num) | ||
1294 | { | ||
1295 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | ||
1296 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
1297 | int ret; | ||
1298 | |||
1299 | rtd->card = card; | ||
1300 | |||
1301 | /* do machine specific initialization */ | ||
1302 | if (dai_link->init) { | ||
1303 | ret = dai_link->init(rtd); | ||
1304 | if (ret < 0) | ||
1305 | return ret; | ||
1306 | } | ||
1307 | |||
1308 | rtd->codec = codec; | ||
1309 | |||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | static int soc_post_component_init(struct snd_soc_card *card, | ||
1314 | struct snd_soc_codec *codec, | ||
1315 | int num, int dailess) | ||
1316 | { | 1318 | { |
1317 | struct snd_soc_dai_link *dai_link = NULL; | ||
1318 | struct snd_soc_aux_dev *aux_dev = NULL; | ||
1319 | struct snd_soc_pcm_runtime *rtd; | ||
1320 | const char *name; | ||
1321 | int ret = 0; | 1319 | int ret = 0; |
1322 | 1320 | ||
1323 | if (!dailess) { | ||
1324 | dai_link = &card->dai_link[num]; | ||
1325 | rtd = &card->rtd[num]; | ||
1326 | name = dai_link->name; | ||
1327 | ret = soc_dai_link_init(card, codec, num); | ||
1328 | } else { | ||
1329 | aux_dev = &card->aux_dev[num]; | ||
1330 | rtd = &card->rtd_aux[num]; | ||
1331 | name = aux_dev->name; | ||
1332 | ret = soc_aux_dev_init(card, codec, num); | ||
1333 | } | ||
1334 | |||
1335 | if (ret < 0) { | ||
1336 | dev_err(card->dev, "ASoC: failed to init %s: %d\n", name, ret); | ||
1337 | return ret; | ||
1338 | } | ||
1339 | |||
1340 | /* register the rtd device */ | 1321 | /* register the rtd device */ |
1341 | rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL); | 1322 | rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL); |
1342 | if (!rtd->dev) | 1323 | if (!rtd->dev) |
1343 | return -ENOMEM; | 1324 | return -ENOMEM; |
1344 | device_initialize(rtd->dev); | 1325 | device_initialize(rtd->dev); |
1345 | rtd->dev->parent = card->dev; | 1326 | rtd->dev->parent = rtd->card->dev; |
1346 | rtd->dev->release = rtd_release; | 1327 | rtd->dev->release = rtd_release; |
1347 | rtd->dev->init_name = name; | 1328 | rtd->dev->init_name = name; |
1348 | dev_set_drvdata(rtd->dev, rtd); | 1329 | dev_set_drvdata(rtd->dev, rtd); |
@@ -1355,7 +1336,7 @@ static int soc_post_component_init(struct snd_soc_card *card, | |||
1355 | if (ret < 0) { | 1336 | if (ret < 0) { |
1356 | /* calling put_device() here to free the rtd->dev */ | 1337 | /* calling put_device() here to free the rtd->dev */ |
1357 | put_device(rtd->dev); | 1338 | put_device(rtd->dev); |
1358 | dev_err(card->dev, | 1339 | dev_err(rtd->card->dev, |
1359 | "ASoC: failed to register runtime device: %d\n", ret); | 1340 | "ASoC: failed to register runtime device: %d\n", ret); |
1360 | return ret; | 1341 | return ret; |
1361 | } | 1342 | } |
@@ -1364,26 +1345,15 @@ static int soc_post_component_init(struct snd_soc_card *card, | |||
1364 | /* add DAPM sysfs entries for this codec */ | 1345 | /* add DAPM sysfs entries for this codec */ |
1365 | ret = snd_soc_dapm_sys_add(rtd->dev); | 1346 | ret = snd_soc_dapm_sys_add(rtd->dev); |
1366 | if (ret < 0) | 1347 | if (ret < 0) |
1367 | dev_err(codec->dev, | 1348 | dev_err(rtd->dev, |
1368 | "ASoC: failed to add codec dapm sysfs entries: %d\n", ret); | 1349 | "ASoC: failed to add codec dapm sysfs entries: %d\n", ret); |
1369 | 1350 | ||
1370 | /* add codec sysfs entries */ | 1351 | /* add codec sysfs entries */ |
1371 | ret = device_create_file(rtd->dev, &dev_attr_codec_reg); | 1352 | ret = device_create_file(rtd->dev, &dev_attr_codec_reg); |
1372 | if (ret < 0) | 1353 | if (ret < 0) |
1373 | dev_err(codec->dev, | 1354 | dev_err(rtd->dev, |
1374 | "ASoC: failed to add codec sysfs files: %d\n", ret); | 1355 | "ASoC: failed to add codec sysfs files: %d\n", ret); |
1375 | 1356 | ||
1376 | #ifdef CONFIG_DEBUG_FS | ||
1377 | /* add DPCM sysfs entries */ | ||
1378 | if (!dailess && !dai_link->dynamic) | ||
1379 | goto out; | ||
1380 | |||
1381 | ret = soc_dpcm_debugfs_add(rtd); | ||
1382 | if (ret < 0) | ||
1383 | dev_err(rtd->dev, "ASoC: failed to add dpcm sysfs entries: %d\n", ret); | ||
1384 | |||
1385 | out: | ||
1386 | #endif | ||
1387 | return 0; | 1357 | return 0; |
1388 | } | 1358 | } |
1389 | 1359 | ||
@@ -1392,9 +1362,8 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num, | |||
1392 | { | 1362 | { |
1393 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1363 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1394 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1364 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1395 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1396 | struct snd_soc_platform *platform = rtd->platform; | 1365 | struct snd_soc_platform *platform = rtd->platform; |
1397 | int ret; | 1366 | int i, ret; |
1398 | 1367 | ||
1399 | /* probe the CPU-side component, if it is a CODEC */ | 1368 | /* probe the CPU-side component, if it is a CODEC */ |
1400 | if (cpu_dai->codec && | 1369 | if (cpu_dai->codec && |
@@ -1405,12 +1374,14 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num, | |||
1405 | return ret; | 1374 | return ret; |
1406 | } | 1375 | } |
1407 | 1376 | ||
1408 | /* probe the CODEC-side component */ | 1377 | /* probe the CODEC-side components */ |
1409 | if (!codec_dai->codec->probed && | 1378 | for (i = 0; i < rtd->num_codecs; i++) { |
1410 | codec_dai->codec->driver->probe_order == order) { | 1379 | if (!rtd->codec_dais[i]->codec->probed && |
1411 | ret = soc_probe_codec(card, codec_dai->codec); | 1380 | rtd->codec_dais[i]->codec->driver->probe_order == order) { |
1412 | if (ret < 0) | 1381 | ret = soc_probe_codec(card, rtd->codec_dais[i]->codec); |
1413 | return ret; | 1382 | if (ret < 0) |
1383 | return ret; | ||
1384 | } | ||
1414 | } | 1385 | } |
1415 | 1386 | ||
1416 | /* probe the platform */ | 1387 | /* probe the platform */ |
@@ -1450,12 +1421,16 @@ static int soc_probe_codec_dai(struct snd_soc_card *card, | |||
1450 | 1421 | ||
1451 | static int soc_link_dai_widgets(struct snd_soc_card *card, | 1422 | static int soc_link_dai_widgets(struct snd_soc_card *card, |
1452 | struct snd_soc_dai_link *dai_link, | 1423 | struct snd_soc_dai_link *dai_link, |
1453 | struct snd_soc_dai *cpu_dai, | 1424 | struct snd_soc_pcm_runtime *rtd) |
1454 | struct snd_soc_dai *codec_dai) | ||
1455 | { | 1425 | { |
1426 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
1427 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1456 | struct snd_soc_dapm_widget *play_w, *capture_w; | 1428 | struct snd_soc_dapm_widget *play_w, *capture_w; |
1457 | int ret; | 1429 | int ret; |
1458 | 1430 | ||
1431 | if (rtd->num_codecs > 1) | ||
1432 | dev_warn(card->dev, "ASoC: Multiple codecs not supported yet\n"); | ||
1433 | |||
1459 | /* link the DAI widgets */ | 1434 | /* link the DAI widgets */ |
1460 | play_w = codec_dai->playback_widget; | 1435 | play_w = codec_dai->playback_widget; |
1461 | capture_w = cpu_dai->capture_widget; | 1436 | capture_w = cpu_dai->capture_widget; |
@@ -1488,19 +1463,18 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1488 | { | 1463 | { |
1489 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1464 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
1490 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1465 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1491 | struct snd_soc_codec *codec = rtd->codec; | ||
1492 | struct snd_soc_platform *platform = rtd->platform; | 1466 | struct snd_soc_platform *platform = rtd->platform; |
1493 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1494 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1467 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1495 | int ret; | 1468 | int i, ret; |
1496 | 1469 | ||
1497 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", | 1470 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", |
1498 | card->name, num, order); | 1471 | card->name, num, order); |
1499 | 1472 | ||
1500 | /* config components */ | 1473 | /* config components */ |
1501 | cpu_dai->platform = platform; | 1474 | cpu_dai->platform = platform; |
1502 | codec_dai->card = card; | ||
1503 | cpu_dai->card = card; | 1475 | cpu_dai->card = card; |
1476 | for (i = 0; i < rtd->num_codecs; i++) | ||
1477 | rtd->codec_dais[i]->card = card; | ||
1504 | 1478 | ||
1505 | /* set default power off timeout */ | 1479 | /* set default power off timeout */ |
1506 | rtd->pmdown_time = pmdown_time; | 1480 | rtd->pmdown_time = pmdown_time; |
@@ -1509,11 +1483,8 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1509 | if (!cpu_dai->probed && | 1483 | if (!cpu_dai->probed && |
1510 | cpu_dai->driver->probe_order == order) { | 1484 | cpu_dai->driver->probe_order == order) { |
1511 | if (!cpu_dai->codec) { | 1485 | if (!cpu_dai->codec) { |
1512 | cpu_dai->dapm.card = card; | ||
1513 | if (!try_module_get(cpu_dai->dev->driver->owner)) | 1486 | if (!try_module_get(cpu_dai->dev->driver->owner)) |
1514 | return -ENODEV; | 1487 | return -ENODEV; |
1515 | |||
1516 | list_add(&cpu_dai->dapm.list, &card->dapm_list); | ||
1517 | } | 1488 | } |
1518 | 1489 | ||
1519 | if (cpu_dai->driver->probe) { | 1490 | if (cpu_dai->driver->probe) { |
@@ -1530,18 +1501,43 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1530 | } | 1501 | } |
1531 | 1502 | ||
1532 | /* probe the CODEC DAI */ | 1503 | /* probe the CODEC DAI */ |
1533 | ret = soc_probe_codec_dai(card, codec_dai, order); | 1504 | for (i = 0; i < rtd->num_codecs; i++) { |
1534 | if (ret) | 1505 | ret = soc_probe_codec_dai(card, rtd->codec_dais[i], order); |
1535 | return ret; | 1506 | if (ret) |
1507 | return ret; | ||
1508 | } | ||
1536 | 1509 | ||
1537 | /* complete DAI probe during last probe */ | 1510 | /* complete DAI probe during last probe */ |
1538 | if (order != SND_SOC_COMP_ORDER_LAST) | 1511 | if (order != SND_SOC_COMP_ORDER_LAST) |
1539 | return 0; | 1512 | return 0; |
1540 | 1513 | ||
1541 | ret = soc_post_component_init(card, codec, num, 0); | 1514 | /* do machine specific initialization */ |
1515 | if (dai_link->init) { | ||
1516 | ret = dai_link->init(rtd); | ||
1517 | if (ret < 0) { | ||
1518 | dev_err(card->dev, "ASoC: failed to init %s: %d\n", | ||
1519 | dai_link->name, ret); | ||
1520 | return ret; | ||
1521 | } | ||
1522 | } | ||
1523 | |||
1524 | ret = soc_post_component_init(rtd, dai_link->name); | ||
1542 | if (ret) | 1525 | if (ret) |
1543 | return ret; | 1526 | return ret; |
1544 | 1527 | ||
1528 | #ifdef CONFIG_DEBUG_FS | ||
1529 | /* add DPCM sysfs entries */ | ||
1530 | if (dai_link->dynamic) { | ||
1531 | ret = soc_dpcm_debugfs_add(rtd); | ||
1532 | if (ret < 0) { | ||
1533 | dev_err(rtd->dev, | ||
1534 | "ASoC: failed to add dpcm sysfs entries: %d\n", | ||
1535 | ret); | ||
1536 | return ret; | ||
1537 | } | ||
1538 | } | ||
1539 | #endif | ||
1540 | |||
1545 | ret = device_create_file(rtd->dev, &dev_attr_pmdown_time); | 1541 | ret = device_create_file(rtd->dev, &dev_attr_pmdown_time); |
1546 | if (ret < 0) | 1542 | if (ret < 0) |
1547 | dev_warn(rtd->dev, "ASoC: failed to add pmdown_time sysfs: %d\n", | 1543 | dev_warn(rtd->dev, "ASoC: failed to add pmdown_time sysfs: %d\n", |
@@ -1570,16 +1566,18 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1570 | codec2codec_close_delayed_work); | 1566 | codec2codec_close_delayed_work); |
1571 | 1567 | ||
1572 | /* link the DAI widgets */ | 1568 | /* link the DAI widgets */ |
1573 | ret = soc_link_dai_widgets(card, dai_link, | 1569 | ret = soc_link_dai_widgets(card, dai_link, rtd); |
1574 | cpu_dai, codec_dai); | ||
1575 | if (ret) | 1570 | if (ret) |
1576 | return ret; | 1571 | return ret; |
1577 | } | 1572 | } |
1578 | } | 1573 | } |
1579 | 1574 | ||
1580 | /* add platform data for AC97 devices */ | 1575 | /* add platform data for AC97 devices */ |
1581 | if (rtd->codec_dai->driver->ac97_control) | 1576 | for (i = 0; i < rtd->num_codecs; i++) { |
1582 | snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata); | 1577 | if (rtd->codec_dais[i]->driver->ac97_control) |
1578 | snd_ac97_dev_add_pdata(rtd->codec_dais[i]->codec->ac97, | ||
1579 | rtd->cpu_dai->ac97_pdata); | ||
1580 | } | ||
1583 | 1581 | ||
1584 | return 0; | 1582 | return 0; |
1585 | } | 1583 | } |
@@ -1617,11 +1615,6 @@ static int soc_register_ac97_codec(struct snd_soc_codec *codec, | |||
1617 | return 0; | 1615 | return 0; |
1618 | } | 1616 | } |
1619 | 1617 | ||
1620 | static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | ||
1621 | { | ||
1622 | return soc_register_ac97_codec(rtd->codec, rtd->codec_dai); | ||
1623 | } | ||
1624 | |||
1625 | static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) | 1618 | static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) |
1626 | { | 1619 | { |
1627 | if (codec->ac97_registered) { | 1620 | if (codec->ac97_registered) { |
@@ -1630,74 +1623,77 @@ static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) | |||
1630 | } | 1623 | } |
1631 | } | 1624 | } |
1632 | 1625 | ||
1633 | static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | 1626 | static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) |
1634 | { | 1627 | { |
1635 | soc_unregister_ac97_codec(rtd->codec); | 1628 | int i, ret; |
1636 | } | ||
1637 | #endif | ||
1638 | 1629 | ||
1639 | static struct snd_soc_codec *soc_find_matching_codec(struct snd_soc_card *card, | 1630 | for (i = 0; i < rtd->num_codecs; i++) { |
1640 | int num) | 1631 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; |
1641 | { | ||
1642 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | ||
1643 | struct snd_soc_codec *codec; | ||
1644 | 1632 | ||
1645 | /* find CODEC from registered CODECs */ | 1633 | ret = soc_register_ac97_codec(codec_dai->codec, codec_dai); |
1646 | list_for_each_entry(codec, &codec_list, list) { | 1634 | if (ret) { |
1647 | if (aux_dev->codec_of_node && | 1635 | while (--i >= 0) |
1648 | (codec->dev->of_node != aux_dev->codec_of_node)) | 1636 | soc_unregister_ac97_codec(codec_dai->codec); |
1649 | continue; | 1637 | return ret; |
1650 | if (aux_dev->codec_name && strcmp(codec->name, aux_dev->codec_name)) | 1638 | } |
1651 | continue; | ||
1652 | return codec; | ||
1653 | } | 1639 | } |
1654 | 1640 | ||
1655 | return NULL; | 1641 | return 0; |
1656 | } | 1642 | } |
1657 | 1643 | ||
1658 | static int soc_check_aux_dev(struct snd_soc_card *card, int num) | 1644 | static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) |
1659 | { | 1645 | { |
1660 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | 1646 | int i; |
1661 | const char *codecname = aux_dev->codec_name; | ||
1662 | struct snd_soc_codec *codec = soc_find_matching_codec(card, num); | ||
1663 | |||
1664 | if (codec) | ||
1665 | return 0; | ||
1666 | if (aux_dev->codec_of_node) | ||
1667 | codecname = of_node_full_name(aux_dev->codec_of_node); | ||
1668 | 1647 | ||
1669 | dev_err(card->dev, "ASoC: %s not registered\n", codecname); | 1648 | for (i = 0; i < rtd->num_codecs; i++) |
1670 | return -EPROBE_DEFER; | 1649 | soc_unregister_ac97_codec(rtd->codec_dais[i]->codec); |
1671 | } | 1650 | } |
1651 | #endif | ||
1672 | 1652 | ||
1673 | static int soc_probe_aux_dev(struct snd_soc_card *card, int num) | 1653 | static int soc_bind_aux_dev(struct snd_soc_card *card, int num) |
1674 | { | 1654 | { |
1655 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | ||
1675 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | 1656 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; |
1676 | const char *codecname = aux_dev->codec_name; | 1657 | const char *codecname = aux_dev->codec_name; |
1677 | int ret = -ENODEV; | ||
1678 | struct snd_soc_codec *codec = soc_find_matching_codec(card, num); | ||
1679 | 1658 | ||
1680 | if (!codec) { | 1659 | rtd->codec = soc_find_codec(aux_dev->codec_of_node, codecname); |
1660 | if (!rtd->codec) { | ||
1681 | if (aux_dev->codec_of_node) | 1661 | if (aux_dev->codec_of_node) |
1682 | codecname = of_node_full_name(aux_dev->codec_of_node); | 1662 | codecname = of_node_full_name(aux_dev->codec_of_node); |
1683 | 1663 | ||
1684 | /* codec not found */ | 1664 | dev_err(card->dev, "ASoC: %s not registered\n", codecname); |
1685 | dev_err(card->dev, "ASoC: codec %s not found", codecname); | ||
1686 | return -EPROBE_DEFER; | 1665 | return -EPROBE_DEFER; |
1687 | } | 1666 | } |
1688 | 1667 | ||
1689 | if (codec->probed) { | 1668 | return 0; |
1690 | dev_err(codec->dev, "ASoC: codec already probed"); | 1669 | } |
1670 | |||
1671 | static int soc_probe_aux_dev(struct snd_soc_card *card, int num) | ||
1672 | { | ||
1673 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | ||
1674 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | ||
1675 | int ret; | ||
1676 | |||
1677 | if (rtd->codec->probed) { | ||
1678 | dev_err(rtd->codec->dev, "ASoC: codec already probed\n"); | ||
1691 | return -EBUSY; | 1679 | return -EBUSY; |
1692 | } | 1680 | } |
1693 | 1681 | ||
1694 | ret = soc_probe_codec(card, codec); | 1682 | ret = soc_probe_codec(card, rtd->codec); |
1695 | if (ret < 0) | 1683 | if (ret < 0) |
1696 | return ret; | 1684 | return ret; |
1697 | 1685 | ||
1698 | ret = soc_post_component_init(card, codec, num, 1); | 1686 | /* do machine specific initialization */ |
1687 | if (aux_dev->init) { | ||
1688 | ret = aux_dev->init(&rtd->codec->dapm); | ||
1689 | if (ret < 0) { | ||
1690 | dev_err(card->dev, "ASoC: failed to init %s: %d\n", | ||
1691 | aux_dev->name, ret); | ||
1692 | return ret; | ||
1693 | } | ||
1694 | } | ||
1699 | 1695 | ||
1700 | return ret; | 1696 | return soc_post_component_init(rtd, aux_dev->name); |
1701 | } | 1697 | } |
1702 | 1698 | ||
1703 | static void soc_remove_aux_dev(struct snd_soc_card *card, int num) | 1699 | static void soc_remove_aux_dev(struct snd_soc_card *card, int num) |
@@ -1749,9 +1745,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1749 | goto base_error; | 1745 | goto base_error; |
1750 | } | 1746 | } |
1751 | 1747 | ||
1752 | /* check aux_devs too */ | 1748 | /* bind aux_devs too */ |
1753 | for (i = 0; i < card->num_aux_devs; i++) { | 1749 | for (i = 0; i < card->num_aux_devs; i++) { |
1754 | ret = soc_check_aux_dev(card, i); | 1750 | ret = soc_bind_aux_dev(card, i); |
1755 | if (ret != 0) | 1751 | if (ret != 0) |
1756 | goto base_error; | 1752 | goto base_error; |
1757 | } | 1753 | } |
@@ -1849,16 +1845,23 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1849 | card->num_dapm_routes); | 1845 | card->num_dapm_routes); |
1850 | 1846 | ||
1851 | for (i = 0; i < card->num_links; i++) { | 1847 | for (i = 0; i < card->num_links; i++) { |
1848 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | ||
1852 | dai_link = &card->dai_link[i]; | 1849 | dai_link = &card->dai_link[i]; |
1853 | dai_fmt = dai_link->dai_fmt; | 1850 | dai_fmt = dai_link->dai_fmt; |
1854 | 1851 | ||
1855 | if (dai_fmt) { | 1852 | if (dai_fmt) { |
1856 | ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai, | 1853 | struct snd_soc_dai **codec_dais = rtd->codec_dais; |
1857 | dai_fmt); | 1854 | int j; |
1858 | if (ret != 0 && ret != -ENOTSUPP) | 1855 | |
1859 | dev_warn(card->rtd[i].codec_dai->dev, | 1856 | for (j = 0; j < rtd->num_codecs; j++) { |
1860 | "ASoC: Failed to set DAI format: %d\n", | 1857 | struct snd_soc_dai *codec_dai = codec_dais[j]; |
1861 | ret); | 1858 | |
1859 | ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt); | ||
1860 | if (ret != 0 && ret != -ENOTSUPP) | ||
1861 | dev_warn(codec_dai->dev, | ||
1862 | "ASoC: Failed to set DAI format: %d\n", | ||
1863 | ret); | ||
1864 | } | ||
1862 | } | 1865 | } |
1863 | 1866 | ||
1864 | /* If this is a regular CPU link there will be a platform */ | 1867 | /* If this is a regular CPU link there will be a platform */ |
@@ -1927,8 +1930,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1927 | } | 1930 | } |
1928 | 1931 | ||
1929 | if (card->fully_routed) | 1932 | if (card->fully_routed) |
1930 | list_for_each_entry(codec, &card->codec_dev_list, card_list) | 1933 | snd_soc_dapm_auto_nc_pins(card); |
1931 | snd_soc_dapm_auto_nc_codec_pins(codec); | ||
1932 | 1934 | ||
1933 | snd_soc_dapm_new_widgets(card); | 1935 | snd_soc_dapm_new_widgets(card); |
1934 | 1936 | ||
@@ -2058,10 +2060,15 @@ int snd_soc_poweroff(struct device *dev) | |||
2058 | 2060 | ||
2059 | /* deactivate pins to sleep state */ | 2061 | /* deactivate pins to sleep state */ |
2060 | for (i = 0; i < card->num_rtd; i++) { | 2062 | for (i = 0; i < card->num_rtd; i++) { |
2061 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 2063 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; |
2062 | struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; | 2064 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
2063 | pinctrl_pm_select_sleep_state(codec_dai->dev); | 2065 | int j; |
2066 | |||
2064 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 2067 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
2068 | for (j = 0; j < rtd->num_codecs; j++) { | ||
2069 | struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; | ||
2070 | pinctrl_pm_select_sleep_state(codec_dai->dev); | ||
2071 | } | ||
2065 | } | 2072 | } |
2066 | 2073 | ||
2067 | return 0; | 2074 | return 0; |
@@ -2387,6 +2394,25 @@ struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, | |||
2387 | EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); | 2394 | EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); |
2388 | 2395 | ||
2389 | /** | 2396 | /** |
2397 | * snd_soc_add_component_controls - Add an array of controls to a component. | ||
2398 | * | ||
2399 | * @component: Component to add controls to | ||
2400 | * @controls: Array of controls to add | ||
2401 | * @num_controls: Number of elements in the array | ||
2402 | * | ||
2403 | * Return: 0 for success, else error. | ||
2404 | */ | ||
2405 | int snd_soc_add_component_controls(struct snd_soc_component *component, | ||
2406 | const struct snd_kcontrol_new *controls, unsigned int num_controls) | ||
2407 | { | ||
2408 | struct snd_card *card = component->card->snd_card; | ||
2409 | |||
2410 | return snd_soc_add_controls(card, component->dev, controls, | ||
2411 | num_controls, component->name_prefix, component); | ||
2412 | } | ||
2413 | EXPORT_SYMBOL_GPL(snd_soc_add_component_controls); | ||
2414 | |||
2415 | /** | ||
2390 | * snd_soc_add_codec_controls - add an array of controls to a codec. | 2416 | * snd_soc_add_codec_controls - add an array of controls to a codec. |
2391 | * Convenience function to add a list of controls. Many codecs were | 2417 | * Convenience function to add a list of controls. Many codecs were |
2392 | * duplicating this code. | 2418 | * duplicating this code. |
@@ -2398,12 +2424,10 @@ EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); | |||
2398 | * Return 0 for success, else error. | 2424 | * Return 0 for success, else error. |
2399 | */ | 2425 | */ |
2400 | int snd_soc_add_codec_controls(struct snd_soc_codec *codec, | 2426 | int snd_soc_add_codec_controls(struct snd_soc_codec *codec, |
2401 | const struct snd_kcontrol_new *controls, int num_controls) | 2427 | const struct snd_kcontrol_new *controls, unsigned int num_controls) |
2402 | { | 2428 | { |
2403 | struct snd_card *card = codec->card->snd_card; | 2429 | return snd_soc_add_component_controls(&codec->component, controls, |
2404 | 2430 | num_controls); | |
2405 | return snd_soc_add_controls(card, codec->dev, controls, num_controls, | ||
2406 | codec->name_prefix, &codec->component); | ||
2407 | } | 2431 | } |
2408 | EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls); | 2432 | EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls); |
2409 | 2433 | ||
@@ -2418,12 +2442,10 @@ EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls); | |||
2418 | * Return 0 for success, else error. | 2442 | * Return 0 for success, else error. |
2419 | */ | 2443 | */ |
2420 | int snd_soc_add_platform_controls(struct snd_soc_platform *platform, | 2444 | int snd_soc_add_platform_controls(struct snd_soc_platform *platform, |
2421 | const struct snd_kcontrol_new *controls, int num_controls) | 2445 | const struct snd_kcontrol_new *controls, unsigned int num_controls) |
2422 | { | 2446 | { |
2423 | struct snd_card *card = platform->card->snd_card; | 2447 | return snd_soc_add_component_controls(&platform->component, controls, |
2424 | 2448 | num_controls); | |
2425 | return snd_soc_add_controls(card, platform->dev, controls, num_controls, | ||
2426 | NULL, &platform->component); | ||
2427 | } | 2449 | } |
2428 | EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls); | 2450 | EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls); |
2429 | 2451 | ||
@@ -3095,7 +3117,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); | |||
3095 | int snd_soc_limit_volume(struct snd_soc_codec *codec, | 3117 | int snd_soc_limit_volume(struct snd_soc_codec *codec, |
3096 | const char *name, int max) | 3118 | const char *name, int max) |
3097 | { | 3119 | { |
3098 | struct snd_card *card = codec->card->snd_card; | 3120 | struct snd_card *card = codec->component.card->snd_card; |
3099 | struct snd_kcontrol *kctl; | 3121 | struct snd_kcontrol *kctl; |
3100 | struct soc_mixer_control *mc; | 3122 | struct soc_mixer_control *mc; |
3101 | int found = 0; | 3123 | int found = 0; |
@@ -3641,6 +3663,9 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | |||
3641 | else | 3663 | else |
3642 | snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); | 3664 | snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); |
3643 | 3665 | ||
3666 | dai->tx_mask = tx_mask; | ||
3667 | dai->rx_mask = rx_mask; | ||
3668 | |||
3644 | if (dai->driver && dai->driver->ops->set_tdm_slot) | 3669 | if (dai->driver && dai->driver->ops->set_tdm_slot) |
3645 | return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, | 3670 | return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, |
3646 | slots, slot_width); | 3671 | slots, slot_width); |
@@ -3713,6 +3738,33 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, | |||
3713 | } | 3738 | } |
3714 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | 3739 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); |
3715 | 3740 | ||
3741 | static int snd_soc_init_multicodec(struct snd_soc_card *card, | ||
3742 | struct snd_soc_dai_link *dai_link) | ||
3743 | { | ||
3744 | /* Legacy codec/codec_dai link is a single entry in multicodec */ | ||
3745 | if (dai_link->codec_name || dai_link->codec_of_node || | ||
3746 | dai_link->codec_dai_name) { | ||
3747 | dai_link->num_codecs = 1; | ||
3748 | |||
3749 | dai_link->codecs = devm_kzalloc(card->dev, | ||
3750 | sizeof(struct snd_soc_dai_link_component), | ||
3751 | GFP_KERNEL); | ||
3752 | if (!dai_link->codecs) | ||
3753 | return -ENOMEM; | ||
3754 | |||
3755 | dai_link->codecs[0].name = dai_link->codec_name; | ||
3756 | dai_link->codecs[0].of_node = dai_link->codec_of_node; | ||
3757 | dai_link->codecs[0].dai_name = dai_link->codec_dai_name; | ||
3758 | } | ||
3759 | |||
3760 | if (!dai_link->codecs) { | ||
3761 | dev_err(card->dev, "ASoC: DAI link has no CODECs\n"); | ||
3762 | return -EINVAL; | ||
3763 | } | ||
3764 | |||
3765 | return 0; | ||
3766 | } | ||
3767 | |||
3716 | /** | 3768 | /** |
3717 | * snd_soc_register_card - Register a card with the ASoC core | 3769 | * snd_soc_register_card - Register a card with the ASoC core |
3718 | * | 3770 | * |
@@ -3721,7 +3773,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | |||
3721 | */ | 3773 | */ |
3722 | int snd_soc_register_card(struct snd_soc_card *card) | 3774 | int snd_soc_register_card(struct snd_soc_card *card) |
3723 | { | 3775 | { |
3724 | int i, ret; | 3776 | int i, j, ret; |
3725 | 3777 | ||
3726 | if (!card->name || !card->dev) | 3778 | if (!card->name || !card->dev) |
3727 | return -EINVAL; | 3779 | return -EINVAL; |
@@ -3729,22 +3781,29 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3729 | for (i = 0; i < card->num_links; i++) { | 3781 | for (i = 0; i < card->num_links; i++) { |
3730 | struct snd_soc_dai_link *link = &card->dai_link[i]; | 3782 | struct snd_soc_dai_link *link = &card->dai_link[i]; |
3731 | 3783 | ||
3732 | /* | 3784 | ret = snd_soc_init_multicodec(card, link); |
3733 | * Codec must be specified by 1 of name or OF node, | 3785 | if (ret) { |
3734 | * not both or neither. | 3786 | dev_err(card->dev, "ASoC: failed to init multicodec\n"); |
3735 | */ | 3787 | return ret; |
3736 | if (!!link->codec_name == !!link->codec_of_node) { | ||
3737 | dev_err(card->dev, | ||
3738 | "ASoC: Neither/both codec name/of_node are set for %s\n", | ||
3739 | link->name); | ||
3740 | return -EINVAL; | ||
3741 | } | 3788 | } |
3742 | /* Codec DAI name must be specified */ | 3789 | |
3743 | if (!link->codec_dai_name) { | 3790 | for (j = 0; j < link->num_codecs; j++) { |
3744 | dev_err(card->dev, | 3791 | /* |
3745 | "ASoC: codec_dai_name not set for %s\n", | 3792 | * Codec must be specified by 1 of name or OF node, |
3746 | link->name); | 3793 | * not both or neither. |
3747 | return -EINVAL; | 3794 | */ |
3795 | if (!!link->codecs[j].name == | ||
3796 | !!link->codecs[j].of_node) { | ||
3797 | dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n", | ||
3798 | link->name); | ||
3799 | return -EINVAL; | ||
3800 | } | ||
3801 | /* Codec DAI name must be specified */ | ||
3802 | if (!link->codecs[j].dai_name) { | ||
3803 | dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n", | ||
3804 | link->name); | ||
3805 | return -EINVAL; | ||
3806 | } | ||
3748 | } | 3807 | } |
3749 | 3808 | ||
3750 | /* | 3809 | /* |
@@ -3797,8 +3856,19 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3797 | card->num_rtd = 0; | 3856 | card->num_rtd = 0; |
3798 | card->rtd_aux = &card->rtd[card->num_links]; | 3857 | card->rtd_aux = &card->rtd[card->num_links]; |
3799 | 3858 | ||
3800 | for (i = 0; i < card->num_links; i++) | 3859 | for (i = 0; i < card->num_links; i++) { |
3860 | card->rtd[i].card = card; | ||
3801 | card->rtd[i].dai_link = &card->dai_link[i]; | 3861 | card->rtd[i].dai_link = &card->dai_link[i]; |
3862 | card->rtd[i].codec_dais = devm_kzalloc(card->dev, | ||
3863 | sizeof(struct snd_soc_dai *) * | ||
3864 | (card->rtd[i].dai_link->num_codecs), | ||
3865 | GFP_KERNEL); | ||
3866 | if (card->rtd[i].codec_dais == NULL) | ||
3867 | return -ENOMEM; | ||
3868 | } | ||
3869 | |||
3870 | for (i = 0; i < card->num_aux_devs; i++) | ||
3871 | card->rtd_aux[i].card = card; | ||
3802 | 3872 | ||
3803 | INIT_LIST_HEAD(&card->dapm_dirty); | 3873 | INIT_LIST_HEAD(&card->dapm_dirty); |
3804 | card->instantiated = 0; | 3874 | card->instantiated = 0; |
@@ -3811,10 +3881,16 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3811 | 3881 | ||
3812 | /* deactivate pins to sleep state */ | 3882 | /* deactivate pins to sleep state */ |
3813 | for (i = 0; i < card->num_rtd; i++) { | 3883 | for (i = 0; i < card->num_rtd; i++) { |
3814 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 3884 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; |
3815 | struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; | 3885 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
3816 | if (!codec_dai->active) | 3886 | int j; |
3817 | pinctrl_pm_select_sleep_state(codec_dai->dev); | 3887 | |
3888 | for (j = 0; j < rtd->num_codecs; j++) { | ||
3889 | struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; | ||
3890 | if (!codec_dai->active) | ||
3891 | pinctrl_pm_select_sleep_state(codec_dai->dev); | ||
3892 | } | ||
3893 | |||
3818 | if (!cpu_dai->active) | 3894 | if (!cpu_dai->active) |
3819 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 3895 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
3820 | } | 3896 | } |
@@ -3921,16 +3997,14 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component) | |||
3921 | * snd_soc_register_dais - Register a DAI with the ASoC core | 3997 | * snd_soc_register_dais - Register a DAI with the ASoC core |
3922 | * | 3998 | * |
3923 | * @component: The component the DAIs are registered for | 3999 | * @component: The component the DAIs are registered for |
3924 | * @codec: The CODEC that the DAIs are registered for, NULL if the component is | ||
3925 | * not a CODEC. | ||
3926 | * @dai_drv: DAI driver to use for the DAIs | 4000 | * @dai_drv: DAI driver to use for the DAIs |
3927 | * @count: Number of DAIs | 4001 | * @count: Number of DAIs |
3928 | * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the | 4002 | * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the |
3929 | * parent's name. | 4003 | * parent's name. |
3930 | */ | 4004 | */ |
3931 | static int snd_soc_register_dais(struct snd_soc_component *component, | 4005 | static int snd_soc_register_dais(struct snd_soc_component *component, |
3932 | struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, | 4006 | struct snd_soc_dai_driver *dai_drv, size_t count, |
3933 | size_t count, bool legacy_dai_naming) | 4007 | bool legacy_dai_naming) |
3934 | { | 4008 | { |
3935 | struct device *dev = component->dev; | 4009 | struct device *dev = component->dev; |
3936 | struct snd_soc_dai *dai; | 4010 | struct snd_soc_dai *dai; |
@@ -3939,6 +4013,9 @@ static int snd_soc_register_dais(struct snd_soc_component *component, | |||
3939 | 4013 | ||
3940 | dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); | 4014 | dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); |
3941 | 4015 | ||
4016 | component->dai_drv = dai_drv; | ||
4017 | component->num_dai = count; | ||
4018 | |||
3942 | for (i = 0; i < count; i++) { | 4019 | for (i = 0; i < count; i++) { |
3943 | 4020 | ||
3944 | dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); | 4021 | dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); |
@@ -3971,16 +4048,11 @@ static int snd_soc_register_dais(struct snd_soc_component *component, | |||
3971 | } | 4048 | } |
3972 | 4049 | ||
3973 | dai->component = component; | 4050 | dai->component = component; |
3974 | dai->codec = codec; | ||
3975 | dai->dev = dev; | 4051 | dai->dev = dev; |
3976 | dai->driver = &dai_drv[i]; | 4052 | dai->driver = &dai_drv[i]; |
3977 | dai->dapm.dev = dev; | ||
3978 | if (!dai->driver->ops) | 4053 | if (!dai->driver->ops) |
3979 | dai->driver->ops = &null_dai_ops; | 4054 | dai->driver->ops = &null_dai_ops; |
3980 | 4055 | ||
3981 | if (!dai->codec) | ||
3982 | dai->dapm.idle_bias_off = 1; | ||
3983 | |||
3984 | list_add(&dai->list, &component->dai_list); | 4056 | list_add(&dai->list, &component->dai_list); |
3985 | 4057 | ||
3986 | dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); | 4058 | dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); |
@@ -3994,60 +4066,82 @@ err: | |||
3994 | return ret; | 4066 | return ret; |
3995 | } | 4067 | } |
3996 | 4068 | ||
3997 | /** | 4069 | static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm, |
3998 | * snd_soc_register_component - Register a component with the ASoC core | 4070 | enum snd_soc_dapm_type type, int subseq) |
3999 | * | ||
4000 | */ | ||
4001 | static int | ||
4002 | __snd_soc_register_component(struct device *dev, | ||
4003 | struct snd_soc_component *cmpnt, | ||
4004 | const struct snd_soc_component_driver *cmpnt_drv, | ||
4005 | struct snd_soc_codec *codec, | ||
4006 | struct snd_soc_dai_driver *dai_drv, | ||
4007 | int num_dai, bool allow_single_dai) | ||
4008 | { | 4071 | { |
4009 | int ret; | 4072 | struct snd_soc_component *component = dapm->component; |
4010 | 4073 | ||
4011 | dev_dbg(dev, "component register %s\n", dev_name(dev)); | 4074 | component->driver->seq_notifier(component, type, subseq); |
4075 | } | ||
4012 | 4076 | ||
4013 | if (!cmpnt) { | 4077 | static int snd_soc_component_stream_event(struct snd_soc_dapm_context *dapm, |
4014 | dev_err(dev, "ASoC: Failed to connecting component\n"); | 4078 | int event) |
4015 | return -ENOMEM; | 4079 | { |
4016 | } | 4080 | struct snd_soc_component *component = dapm->component; |
4017 | 4081 | ||
4018 | mutex_init(&cmpnt->io_mutex); | 4082 | return component->driver->stream_event(component, event); |
4083 | } | ||
4084 | |||
4085 | static int snd_soc_component_initialize(struct snd_soc_component *component, | ||
4086 | const struct snd_soc_component_driver *driver, struct device *dev) | ||
4087 | { | ||
4088 | struct snd_soc_dapm_context *dapm; | ||
4019 | 4089 | ||
4020 | cmpnt->name = fmt_single_name(dev, &cmpnt->id); | 4090 | component->name = fmt_single_name(dev, &component->id); |
4021 | if (!cmpnt->name) { | 4091 | if (!component->name) { |
4022 | dev_err(dev, "ASoC: Failed to simplifying name\n"); | 4092 | dev_err(dev, "ASoC: Failed to allocate name\n"); |
4023 | return -ENOMEM; | 4093 | return -ENOMEM; |
4024 | } | 4094 | } |
4025 | 4095 | ||
4026 | cmpnt->dev = dev; | 4096 | component->dev = dev; |
4027 | cmpnt->driver = cmpnt_drv; | 4097 | component->driver = driver; |
4028 | cmpnt->dai_drv = dai_drv; | ||
4029 | cmpnt->num_dai = num_dai; | ||
4030 | INIT_LIST_HEAD(&cmpnt->dai_list); | ||
4031 | 4098 | ||
4032 | ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai, | 4099 | if (!component->dapm_ptr) |
4033 | allow_single_dai); | 4100 | component->dapm_ptr = &component->dapm; |
4034 | if (ret < 0) { | 4101 | |
4035 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); | 4102 | dapm = component->dapm_ptr; |
4036 | goto error_component_name; | 4103 | dapm->dev = dev; |
4037 | } | 4104 | dapm->component = component; |
4105 | dapm->bias_level = SND_SOC_BIAS_OFF; | ||
4106 | if (driver->seq_notifier) | ||
4107 | dapm->seq_notifier = snd_soc_component_seq_notifier; | ||
4108 | if (driver->stream_event) | ||
4109 | dapm->stream_event = snd_soc_component_stream_event; | ||
4110 | |||
4111 | INIT_LIST_HEAD(&component->dai_list); | ||
4112 | mutex_init(&component->io_mutex); | ||
4113 | |||
4114 | return 0; | ||
4115 | } | ||
4038 | 4116 | ||
4117 | static void snd_soc_component_add_unlocked(struct snd_soc_component *component) | ||
4118 | { | ||
4119 | list_add(&component->list, &component_list); | ||
4120 | } | ||
4121 | |||
4122 | static void snd_soc_component_add(struct snd_soc_component *component) | ||
4123 | { | ||
4039 | mutex_lock(&client_mutex); | 4124 | mutex_lock(&client_mutex); |
4040 | list_add(&cmpnt->list, &component_list); | 4125 | snd_soc_component_add_unlocked(component); |
4041 | mutex_unlock(&client_mutex); | 4126 | mutex_unlock(&client_mutex); |
4127 | } | ||
4042 | 4128 | ||
4043 | dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); | 4129 | static void snd_soc_component_cleanup(struct snd_soc_component *component) |
4044 | 4130 | { | |
4045 | return ret; | 4131 | snd_soc_unregister_dais(component); |
4132 | kfree(component->name); | ||
4133 | } | ||
4046 | 4134 | ||
4047 | error_component_name: | 4135 | static void snd_soc_component_del_unlocked(struct snd_soc_component *component) |
4048 | kfree(cmpnt->name); | 4136 | { |
4137 | list_del(&component->list); | ||
4138 | } | ||
4049 | 4139 | ||
4050 | return ret; | 4140 | static void snd_soc_component_del(struct snd_soc_component *component) |
4141 | { | ||
4142 | mutex_lock(&client_mutex); | ||
4143 | snd_soc_component_del_unlocked(component); | ||
4144 | mutex_unlock(&client_mutex); | ||
4051 | } | 4145 | } |
4052 | 4146 | ||
4053 | int snd_soc_register_component(struct device *dev, | 4147 | int snd_soc_register_component(struct device *dev, |
@@ -4056,32 +4150,38 @@ int snd_soc_register_component(struct device *dev, | |||
4056 | int num_dai) | 4150 | int num_dai) |
4057 | { | 4151 | { |
4058 | struct snd_soc_component *cmpnt; | 4152 | struct snd_soc_component *cmpnt; |
4153 | int ret; | ||
4059 | 4154 | ||
4060 | cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); | 4155 | cmpnt = kzalloc(sizeof(*cmpnt), GFP_KERNEL); |
4061 | if (!cmpnt) { | 4156 | if (!cmpnt) { |
4062 | dev_err(dev, "ASoC: Failed to allocate memory\n"); | 4157 | dev_err(dev, "ASoC: Failed to allocate memory\n"); |
4063 | return -ENOMEM; | 4158 | return -ENOMEM; |
4064 | } | 4159 | } |
4065 | 4160 | ||
4161 | ret = snd_soc_component_initialize(cmpnt, cmpnt_drv, dev); | ||
4162 | if (ret) | ||
4163 | goto err_free; | ||
4164 | |||
4066 | cmpnt->ignore_pmdown_time = true; | 4165 | cmpnt->ignore_pmdown_time = true; |
4067 | cmpnt->registered_as_component = true; | 4166 | cmpnt->registered_as_component = true; |
4068 | 4167 | ||
4069 | return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL, | 4168 | ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, true); |
4070 | dai_drv, num_dai, true); | 4169 | if (ret < 0) { |
4071 | } | 4170 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); |
4072 | EXPORT_SYMBOL_GPL(snd_soc_register_component); | 4171 | goto err_cleanup; |
4172 | } | ||
4073 | 4173 | ||
4074 | static void __snd_soc_unregister_component(struct snd_soc_component *cmpnt) | 4174 | snd_soc_component_add(cmpnt); |
4075 | { | ||
4076 | snd_soc_unregister_dais(cmpnt); | ||
4077 | 4175 | ||
4078 | mutex_lock(&client_mutex); | 4176 | return 0; |
4079 | list_del(&cmpnt->list); | ||
4080 | mutex_unlock(&client_mutex); | ||
4081 | 4177 | ||
4082 | dev_dbg(cmpnt->dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); | 4178 | err_cleanup: |
4083 | kfree(cmpnt->name); | 4179 | snd_soc_component_cleanup(cmpnt); |
4180 | err_free: | ||
4181 | kfree(cmpnt); | ||
4182 | return ret; | ||
4084 | } | 4183 | } |
4184 | EXPORT_SYMBOL_GPL(snd_soc_register_component); | ||
4085 | 4185 | ||
4086 | /** | 4186 | /** |
4087 | * snd_soc_unregister_component - Unregister a component from the ASoC core | 4187 | * snd_soc_unregister_component - Unregister a component from the ASoC core |
@@ -4098,7 +4198,9 @@ void snd_soc_unregister_component(struct device *dev) | |||
4098 | return; | 4198 | return; |
4099 | 4199 | ||
4100 | found: | 4200 | found: |
4101 | __snd_soc_unregister_component(cmpnt); | 4201 | snd_soc_component_del(cmpnt); |
4202 | snd_soc_component_cleanup(cmpnt); | ||
4203 | kfree(cmpnt); | ||
4102 | } | 4204 | } |
4103 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); | 4205 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); |
4104 | 4206 | ||
@@ -4131,37 +4233,25 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, | |||
4131 | { | 4233 | { |
4132 | int ret; | 4234 | int ret; |
4133 | 4235 | ||
4134 | /* create platform component name */ | 4236 | ret = snd_soc_component_initialize(&platform->component, |
4135 | platform->name = fmt_single_name(dev, &platform->id); | 4237 | &platform_drv->component_driver, dev); |
4136 | if (platform->name == NULL) | 4238 | if (ret) |
4137 | return -ENOMEM; | 4239 | return ret; |
4138 | 4240 | ||
4139 | platform->dev = dev; | 4241 | platform->dev = dev; |
4140 | platform->driver = platform_drv; | 4242 | platform->driver = platform_drv; |
4141 | platform->dapm.dev = dev; | ||
4142 | platform->dapm.platform = platform; | ||
4143 | platform->dapm.component = &platform->component; | ||
4144 | platform->dapm.stream_event = platform_drv->stream_event; | ||
4145 | if (platform_drv->write) | 4243 | if (platform_drv->write) |
4146 | platform->component.write = snd_soc_platform_drv_write; | 4244 | platform->component.write = snd_soc_platform_drv_write; |
4147 | if (platform_drv->read) | 4245 | if (platform_drv->read) |
4148 | platform->component.read = snd_soc_platform_drv_read; | 4246 | platform->component.read = snd_soc_platform_drv_read; |
4149 | 4247 | ||
4150 | /* register component */ | ||
4151 | ret = __snd_soc_register_component(dev, &platform->component, | ||
4152 | &platform_drv->component_driver, | ||
4153 | NULL, NULL, 0, false); | ||
4154 | if (ret < 0) { | ||
4155 | dev_err(platform->component.dev, | ||
4156 | "ASoC: Failed to register component: %d\n", ret); | ||
4157 | return ret; | ||
4158 | } | ||
4159 | |||
4160 | mutex_lock(&client_mutex); | 4248 | mutex_lock(&client_mutex); |
4249 | snd_soc_component_add_unlocked(&platform->component); | ||
4161 | list_add(&platform->list, &platform_list); | 4250 | list_add(&platform->list, &platform_list); |
4162 | mutex_unlock(&client_mutex); | 4251 | mutex_unlock(&client_mutex); |
4163 | 4252 | ||
4164 | dev_dbg(dev, "ASoC: Registered platform '%s'\n", platform->name); | 4253 | dev_dbg(dev, "ASoC: Registered platform '%s'\n", |
4254 | platform->component.name); | ||
4165 | 4255 | ||
4166 | return 0; | 4256 | return 0; |
4167 | } | 4257 | } |
@@ -4198,15 +4288,16 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform); | |||
4198 | */ | 4288 | */ |
4199 | void snd_soc_remove_platform(struct snd_soc_platform *platform) | 4289 | void snd_soc_remove_platform(struct snd_soc_platform *platform) |
4200 | { | 4290 | { |
4201 | __snd_soc_unregister_component(&platform->component); | ||
4202 | 4291 | ||
4203 | mutex_lock(&client_mutex); | 4292 | mutex_lock(&client_mutex); |
4204 | list_del(&platform->list); | 4293 | list_del(&platform->list); |
4294 | snd_soc_component_del_unlocked(&platform->component); | ||
4205 | mutex_unlock(&client_mutex); | 4295 | mutex_unlock(&client_mutex); |
4206 | 4296 | ||
4297 | snd_soc_component_cleanup(&platform->component); | ||
4298 | |||
4207 | dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n", | 4299 | dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n", |
4208 | platform->name); | 4300 | platform->component.name); |
4209 | kfree(platform->name); | ||
4210 | } | 4301 | } |
4211 | EXPORT_SYMBOL_GPL(snd_soc_remove_platform); | 4302 | EXPORT_SYMBOL_GPL(snd_soc_remove_platform); |
4212 | 4303 | ||
@@ -4292,6 +4383,14 @@ static int snd_soc_codec_drv_read(struct snd_soc_component *component, | |||
4292 | return 0; | 4383 | return 0; |
4293 | } | 4384 | } |
4294 | 4385 | ||
4386 | static int snd_soc_codec_set_bias_level(struct snd_soc_dapm_context *dapm, | ||
4387 | enum snd_soc_bias_level level) | ||
4388 | { | ||
4389 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
4390 | |||
4391 | return codec->driver->set_bias_level(codec, level); | ||
4392 | } | ||
4393 | |||
4295 | /** | 4394 | /** |
4296 | * snd_soc_register_codec - Register a codec with the ASoC core | 4395 | * snd_soc_register_codec - Register a codec with the ASoC core |
4297 | * | 4396 | * |
@@ -4303,6 +4402,7 @@ int snd_soc_register_codec(struct device *dev, | |||
4303 | int num_dai) | 4402 | int num_dai) |
4304 | { | 4403 | { |
4305 | struct snd_soc_codec *codec; | 4404 | struct snd_soc_codec *codec; |
4405 | struct snd_soc_dai *dai; | ||
4306 | struct regmap *regmap; | 4406 | struct regmap *regmap; |
4307 | int ret, i; | 4407 | int ret, i; |
4308 | 4408 | ||
@@ -4312,24 +4412,23 @@ int snd_soc_register_codec(struct device *dev, | |||
4312 | if (codec == NULL) | 4412 | if (codec == NULL) |
4313 | return -ENOMEM; | 4413 | return -ENOMEM; |
4314 | 4414 | ||
4315 | /* create CODEC component name */ | 4415 | codec->component.dapm_ptr = &codec->dapm; |
4316 | codec->name = fmt_single_name(dev, &codec->id); | 4416 | |
4317 | if (codec->name == NULL) { | 4417 | ret = snd_soc_component_initialize(&codec->component, |
4318 | ret = -ENOMEM; | 4418 | &codec_drv->component_driver, dev); |
4319 | goto fail_codec; | 4419 | if (ret) |
4320 | } | 4420 | goto err_free; |
4321 | 4421 | ||
4322 | if (codec_drv->write) | 4422 | if (codec_drv->write) |
4323 | codec->component.write = snd_soc_codec_drv_write; | 4423 | codec->component.write = snd_soc_codec_drv_write; |
4324 | if (codec_drv->read) | 4424 | if (codec_drv->read) |
4325 | codec->component.read = snd_soc_codec_drv_read; | 4425 | codec->component.read = snd_soc_codec_drv_read; |
4326 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; | 4426 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; |
4327 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | ||
4328 | codec->dapm.dev = dev; | ||
4329 | codec->dapm.codec = codec; | 4427 | codec->dapm.codec = codec; |
4330 | codec->dapm.component = &codec->component; | 4428 | if (codec_drv->seq_notifier) |
4331 | codec->dapm.seq_notifier = codec_drv->seq_notifier; | 4429 | codec->dapm.seq_notifier = codec_drv->seq_notifier; |
4332 | codec->dapm.stream_event = codec_drv->stream_event; | 4430 | if (codec_drv->set_bias_level) |
4431 | codec->dapm.set_bias_level = snd_soc_codec_set_bias_level; | ||
4333 | codec->dev = dev; | 4432 | codec->dev = dev; |
4334 | codec->driver = codec_drv; | 4433 | codec->driver = codec_drv; |
4335 | codec->component.val_bytes = codec_drv->reg_word_size; | 4434 | codec->component.val_bytes = codec_drv->reg_word_size; |
@@ -4348,7 +4447,7 @@ int snd_soc_register_codec(struct device *dev, | |||
4348 | dev_err(codec->dev, | 4447 | dev_err(codec->dev, |
4349 | "Failed to set cache I/O:%d\n", | 4448 | "Failed to set cache I/O:%d\n", |
4350 | ret); | 4449 | ret); |
4351 | return ret; | 4450 | goto err_cleanup; |
4352 | } | 4451 | } |
4353 | } | 4452 | } |
4354 | } | 4453 | } |
@@ -4358,29 +4457,27 @@ int snd_soc_register_codec(struct device *dev, | |||
4358 | fixup_codec_formats(&dai_drv[i].capture); | 4457 | fixup_codec_formats(&dai_drv[i].capture); |
4359 | } | 4458 | } |
4360 | 4459 | ||
4361 | mutex_lock(&client_mutex); | 4460 | ret = snd_soc_register_dais(&codec->component, dai_drv, num_dai, false); |
4362 | list_add(&codec->list, &codec_list); | ||
4363 | mutex_unlock(&client_mutex); | ||
4364 | |||
4365 | /* register component */ | ||
4366 | ret = __snd_soc_register_component(dev, &codec->component, | ||
4367 | &codec_drv->component_driver, | ||
4368 | codec, dai_drv, num_dai, false); | ||
4369 | if (ret < 0) { | 4461 | if (ret < 0) { |
4370 | dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); | 4462 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); |
4371 | goto fail_codec_name; | 4463 | goto err_cleanup; |
4372 | } | 4464 | } |
4373 | 4465 | ||
4374 | dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", codec->name); | 4466 | list_for_each_entry(dai, &codec->component.dai_list, list) |
4375 | return 0; | 4467 | dai->codec = codec; |
4376 | 4468 | ||
4377 | fail_codec_name: | ||
4378 | mutex_lock(&client_mutex); | 4469 | mutex_lock(&client_mutex); |
4379 | list_del(&codec->list); | 4470 | snd_soc_component_add_unlocked(&codec->component); |
4471 | list_add(&codec->list, &codec_list); | ||
4380 | mutex_unlock(&client_mutex); | 4472 | mutex_unlock(&client_mutex); |
4381 | 4473 | ||
4382 | kfree(codec->name); | 4474 | dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", |
4383 | fail_codec: | 4475 | codec->component.name); |
4476 | return 0; | ||
4477 | |||
4478 | err_cleanup: | ||
4479 | snd_soc_component_cleanup(&codec->component); | ||
4480 | err_free: | ||
4384 | kfree(codec); | 4481 | kfree(codec); |
4385 | return ret; | 4482 | return ret; |
4386 | } | 4483 | } |
@@ -4402,16 +4499,17 @@ void snd_soc_unregister_codec(struct device *dev) | |||
4402 | return; | 4499 | return; |
4403 | 4500 | ||
4404 | found: | 4501 | found: |
4405 | __snd_soc_unregister_component(&codec->component); | ||
4406 | 4502 | ||
4407 | mutex_lock(&client_mutex); | 4503 | mutex_lock(&client_mutex); |
4408 | list_del(&codec->list); | 4504 | list_del(&codec->list); |
4505 | snd_soc_component_del_unlocked(&codec->component); | ||
4409 | mutex_unlock(&client_mutex); | 4506 | mutex_unlock(&client_mutex); |
4410 | 4507 | ||
4411 | dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name); | 4508 | dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", |
4509 | codec->component.name); | ||
4412 | 4510 | ||
4511 | snd_soc_component_cleanup(&codec->component); | ||
4413 | snd_soc_cache_exit(codec); | 4512 | snd_soc_cache_exit(codec); |
4414 | kfree(codec->name); | ||
4415 | kfree(codec); | 4513 | kfree(codec); |
4416 | } | 4514 | } |
4417 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | 4515 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); |
@@ -4420,9 +4518,16 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | |||
4420 | int snd_soc_of_parse_card_name(struct snd_soc_card *card, | 4518 | int snd_soc_of_parse_card_name(struct snd_soc_card *card, |
4421 | const char *propname) | 4519 | const char *propname) |
4422 | { | 4520 | { |
4423 | struct device_node *np = card->dev->of_node; | 4521 | struct device_node *np; |
4424 | int ret; | 4522 | int ret; |
4425 | 4523 | ||
4524 | if (!card->dev) { | ||
4525 | pr_err("card->dev is not set before calling %s\n", __func__); | ||
4526 | return -EINVAL; | ||
4527 | } | ||
4528 | |||
4529 | np = card->dev->of_node; | ||
4530 | |||
4426 | ret = of_property_read_string_index(np, propname, 0, &card->name); | 4531 | ret = of_property_read_string_index(np, propname, 0, &card->name); |
4427 | /* | 4532 | /* |
4428 | * EINVAL means the property does not exist. This is fine providing | 4533 | * EINVAL means the property does not exist. This is fine providing |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a74b9bf23d9f..8348352dc2c6 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -350,12 +350,27 @@ static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol, | |||
350 | } | 350 | } |
351 | 351 | ||
352 | /** | 352 | /** |
353 | * snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a | ||
354 | * kcontrol | ||
355 | * @kcontrol: The kcontrol | ||
356 | * | ||
357 | * Note: This function must only be used on kcontrols that are known to have | ||
358 | * been registered for a CODEC. Otherwise the behaviour is undefined. | ||
359 | */ | ||
360 | struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm( | ||
361 | struct snd_kcontrol *kcontrol) | ||
362 | { | ||
363 | return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->dapm; | ||
364 | } | ||
365 | EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_dapm); | ||
366 | |||
367 | /** | ||
353 | * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol | 368 | * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol |
354 | * @kcontrol: The kcontrol | 369 | * @kcontrol: The kcontrol |
355 | */ | 370 | */ |
356 | struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol) | 371 | struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol) |
357 | { | 372 | { |
358 | return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->codec; | 373 | return snd_soc_dapm_to_codec(snd_soc_dapm_kcontrol_dapm(kcontrol)); |
359 | } | 374 | } |
360 | EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec); | 375 | EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec); |
361 | 376 | ||
@@ -375,23 +390,38 @@ static void dapm_reset(struct snd_soc_card *card) | |||
375 | } | 390 | } |
376 | } | 391 | } |
377 | 392 | ||
378 | static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg, | 393 | static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm) |
394 | { | ||
395 | if (!dapm->component) | ||
396 | return NULL; | ||
397 | return dapm->component->name_prefix; | ||
398 | } | ||
399 | |||
400 | static int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg, | ||
379 | unsigned int *value) | 401 | unsigned int *value) |
380 | { | 402 | { |
381 | if (!w->dapm->component) | 403 | if (!dapm->component) |
382 | return -EIO; | 404 | return -EIO; |
383 | return snd_soc_component_read(w->dapm->component, reg, value); | 405 | return snd_soc_component_read(dapm->component, reg, value); |
384 | } | 406 | } |
385 | 407 | ||
386 | static int soc_widget_update_bits(struct snd_soc_dapm_widget *w, | 408 | static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm, |
387 | int reg, unsigned int mask, unsigned int value) | 409 | int reg, unsigned int mask, unsigned int value) |
388 | { | 410 | { |
389 | if (!w->dapm->component) | 411 | if (!dapm->component) |
390 | return -EIO; | 412 | return -EIO; |
391 | return snd_soc_component_update_bits_async(w->dapm->component, reg, | 413 | return snd_soc_component_update_bits_async(dapm->component, reg, |
392 | mask, value); | 414 | mask, value); |
393 | } | 415 | } |
394 | 416 | ||
417 | static int soc_dapm_test_bits(struct snd_soc_dapm_context *dapm, | ||
418 | int reg, unsigned int mask, unsigned int value) | ||
419 | { | ||
420 | if (!dapm->component) | ||
421 | return -EIO; | ||
422 | return snd_soc_component_test_bits(dapm->component, reg, mask, value); | ||
423 | } | ||
424 | |||
395 | static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm) | 425 | static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm) |
396 | { | 426 | { |
397 | if (dapm->component) | 427 | if (dapm->component) |
@@ -420,15 +450,10 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, | |||
420 | if (ret != 0) | 450 | if (ret != 0) |
421 | goto out; | 451 | goto out; |
422 | 452 | ||
423 | if (dapm->codec) { | 453 | if (dapm->set_bias_level) |
424 | if (dapm->codec->driver->set_bias_level) | 454 | ret = dapm->set_bias_level(dapm, level); |
425 | ret = dapm->codec->driver->set_bias_level(dapm->codec, | 455 | else if (!card || dapm != &card->dapm) |
426 | level); | ||
427 | else | ||
428 | dapm->bias_level = level; | ||
429 | } else if (!card || dapm != &card->dapm) { | ||
430 | dapm->bias_level = level; | 456 | dapm->bias_level = level; |
431 | } | ||
432 | 457 | ||
433 | if (ret != 0) | 458 | if (ret != 0) |
434 | goto out; | 459 | goto out; |
@@ -452,7 +477,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, | |||
452 | int i; | 477 | int i; |
453 | 478 | ||
454 | if (e->reg != SND_SOC_NOPM) { | 479 | if (e->reg != SND_SOC_NOPM) { |
455 | soc_widget_read(dest, e->reg, &val); | 480 | soc_dapm_read(dapm, e->reg, &val); |
456 | val = (val >> e->shift_l) & e->mask; | 481 | val = (val >> e->shift_l) & e->mask; |
457 | item = snd_soc_enum_val_to_item(e, val); | 482 | item = snd_soc_enum_val_to_item(e, val); |
458 | } else { | 483 | } else { |
@@ -496,7 +521,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, | |||
496 | unsigned int val; | 521 | unsigned int val; |
497 | 522 | ||
498 | if (reg != SND_SOC_NOPM) { | 523 | if (reg != SND_SOC_NOPM) { |
499 | soc_widget_read(w, reg, &val); | 524 | soc_dapm_read(w->dapm, reg, &val); |
500 | val = (val >> shift) & mask; | 525 | val = (val >> shift) & mask; |
501 | if (invert) | 526 | if (invert) |
502 | val = max - val; | 527 | val = max - val; |
@@ -570,11 +595,7 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
570 | const char *name; | 595 | const char *name; |
571 | int ret; | 596 | int ret; |
572 | 597 | ||
573 | if (dapm->codec) | 598 | prefix = soc_dapm_prefix(dapm); |
574 | prefix = dapm->codec->name_prefix; | ||
575 | else | ||
576 | prefix = NULL; | ||
577 | |||
578 | if (prefix) | 599 | if (prefix) |
579 | prefix_len = strlen(prefix) + 1; | 600 | prefix_len = strlen(prefix) + 1; |
580 | else | 601 | else |
@@ -1308,16 +1329,18 @@ static void dapm_seq_check_event(struct snd_soc_card *card, | |||
1308 | static void dapm_seq_run_coalesced(struct snd_soc_card *card, | 1329 | static void dapm_seq_run_coalesced(struct snd_soc_card *card, |
1309 | struct list_head *pending) | 1330 | struct list_head *pending) |
1310 | { | 1331 | { |
1332 | struct snd_soc_dapm_context *dapm; | ||
1311 | struct snd_soc_dapm_widget *w; | 1333 | struct snd_soc_dapm_widget *w; |
1312 | int reg; | 1334 | int reg; |
1313 | unsigned int value = 0; | 1335 | unsigned int value = 0; |
1314 | unsigned int mask = 0; | 1336 | unsigned int mask = 0; |
1315 | 1337 | ||
1316 | reg = list_first_entry(pending, struct snd_soc_dapm_widget, | 1338 | w = list_first_entry(pending, struct snd_soc_dapm_widget, power_list); |
1317 | power_list)->reg; | 1339 | reg = w->reg; |
1340 | dapm = w->dapm; | ||
1318 | 1341 | ||
1319 | list_for_each_entry(w, pending, power_list) { | 1342 | list_for_each_entry(w, pending, power_list) { |
1320 | WARN_ON(reg != w->reg); | 1343 | WARN_ON(reg != w->reg || dapm != w->dapm); |
1321 | w->power = w->new_power; | 1344 | w->power = w->new_power; |
1322 | 1345 | ||
1323 | mask |= w->mask << w->shift; | 1346 | mask |= w->mask << w->shift; |
@@ -1326,7 +1349,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card, | |||
1326 | else | 1349 | else |
1327 | value |= w->off_val << w->shift; | 1350 | value |= w->off_val << w->shift; |
1328 | 1351 | ||
1329 | pop_dbg(w->dapm->dev, card->pop_time, | 1352 | pop_dbg(dapm->dev, card->pop_time, |
1330 | "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", | 1353 | "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", |
1331 | w->name, reg, value, mask); | 1354 | w->name, reg, value, mask); |
1332 | 1355 | ||
@@ -1339,14 +1362,12 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card, | |||
1339 | /* Any widget will do, they should all be updating the | 1362 | /* Any widget will do, they should all be updating the |
1340 | * same register. | 1363 | * same register. |
1341 | */ | 1364 | */ |
1342 | w = list_first_entry(pending, struct snd_soc_dapm_widget, | ||
1343 | power_list); | ||
1344 | 1365 | ||
1345 | pop_dbg(w->dapm->dev, card->pop_time, | 1366 | pop_dbg(dapm->dev, card->pop_time, |
1346 | "pop test : Applying 0x%x/0x%x to %x in %dms\n", | 1367 | "pop test : Applying 0x%x/0x%x to %x in %dms\n", |
1347 | value, mask, reg, card->pop_time); | 1368 | value, mask, reg, card->pop_time); |
1348 | pop_wait(card->pop_time); | 1369 | pop_wait(card->pop_time); |
1349 | soc_widget_update_bits(w, reg, mask, value); | 1370 | soc_dapm_update_bits(dapm, reg, mask, value); |
1350 | } | 1371 | } |
1351 | 1372 | ||
1352 | list_for_each_entry(w, pending, power_list) { | 1373 | list_for_each_entry(w, pending, power_list) { |
@@ -1492,7 +1513,8 @@ static void dapm_widget_update(struct snd_soc_card *card) | |||
1492 | if (!w) | 1513 | if (!w) |
1493 | return; | 1514 | return; |
1494 | 1515 | ||
1495 | ret = soc_widget_update_bits(w, update->reg, update->mask, update->val); | 1516 | ret = soc_dapm_update_bits(w->dapm, update->reg, update->mask, |
1517 | update->val); | ||
1496 | if (ret < 0) | 1518 | if (ret < 0) |
1497 | dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n", | 1519 | dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n", |
1498 | w->name, ret); | 1520 | w->name, ret); |
@@ -2062,17 +2084,13 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, | |||
2062 | } | 2084 | } |
2063 | EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); | 2085 | EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); |
2064 | 2086 | ||
2065 | /* show dapm widget status in sys fs */ | 2087 | static ssize_t dapm_widget_show_codec(struct snd_soc_codec *codec, char *buf) |
2066 | static ssize_t dapm_widget_show(struct device *dev, | ||
2067 | struct device_attribute *attr, char *buf) | ||
2068 | { | 2088 | { |
2069 | struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev); | ||
2070 | struct snd_soc_codec *codec =rtd->codec; | ||
2071 | struct snd_soc_dapm_widget *w; | 2089 | struct snd_soc_dapm_widget *w; |
2072 | int count = 0; | 2090 | int count = 0; |
2073 | char *state = "not set"; | 2091 | char *state = "not set"; |
2074 | 2092 | ||
2075 | list_for_each_entry(w, &codec->card->widgets, list) { | 2093 | list_for_each_entry(w, &codec->component.card->widgets, list) { |
2076 | if (w->dapm != &codec->dapm) | 2094 | if (w->dapm != &codec->dapm) |
2077 | continue; | 2095 | continue; |
2078 | 2096 | ||
@@ -2120,6 +2138,21 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
2120 | return count; | 2138 | return count; |
2121 | } | 2139 | } |
2122 | 2140 | ||
2141 | /* show dapm widget status in sys fs */ | ||
2142 | static ssize_t dapm_widget_show(struct device *dev, | ||
2143 | struct device_attribute *attr, char *buf) | ||
2144 | { | ||
2145 | struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev); | ||
2146 | int i, count = 0; | ||
2147 | |||
2148 | for (i = 0; i < rtd->num_codecs; i++) { | ||
2149 | struct snd_soc_codec *codec = rtd->codec_dais[i]->codec; | ||
2150 | count += dapm_widget_show_codec(codec, buf + count); | ||
2151 | } | ||
2152 | |||
2153 | return count; | ||
2154 | } | ||
2155 | |||
2123 | static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); | 2156 | static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); |
2124 | 2157 | ||
2125 | int snd_soc_dapm_sys_add(struct device *dev) | 2158 | int snd_soc_dapm_sys_add(struct device *dev) |
@@ -2371,14 +2404,16 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
2371 | const char *source; | 2404 | const char *source; |
2372 | char prefixed_sink[80]; | 2405 | char prefixed_sink[80]; |
2373 | char prefixed_source[80]; | 2406 | char prefixed_source[80]; |
2407 | const char *prefix; | ||
2374 | int ret; | 2408 | int ret; |
2375 | 2409 | ||
2376 | if (dapm->codec && dapm->codec->name_prefix) { | 2410 | prefix = soc_dapm_prefix(dapm); |
2411 | if (prefix) { | ||
2377 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", | 2412 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", |
2378 | dapm->codec->name_prefix, route->sink); | 2413 | prefix, route->sink); |
2379 | sink = prefixed_sink; | 2414 | sink = prefixed_sink; |
2380 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", | 2415 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", |
2381 | dapm->codec->name_prefix, route->source); | 2416 | prefix, route->source); |
2382 | source = prefixed_source; | 2417 | source = prefixed_source; |
2383 | } else { | 2418 | } else { |
2384 | sink = route->sink; | 2419 | sink = route->sink; |
@@ -2439,6 +2474,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | |||
2439 | const char *source; | 2474 | const char *source; |
2440 | char prefixed_sink[80]; | 2475 | char prefixed_sink[80]; |
2441 | char prefixed_source[80]; | 2476 | char prefixed_source[80]; |
2477 | const char *prefix; | ||
2442 | 2478 | ||
2443 | if (route->control) { | 2479 | if (route->control) { |
2444 | dev_err(dapm->dev, | 2480 | dev_err(dapm->dev, |
@@ -2446,12 +2482,13 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | |||
2446 | return -EINVAL; | 2482 | return -EINVAL; |
2447 | } | 2483 | } |
2448 | 2484 | ||
2449 | if (dapm->codec && dapm->codec->name_prefix) { | 2485 | prefix = soc_dapm_prefix(dapm); |
2486 | if (prefix) { | ||
2450 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", | 2487 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", |
2451 | dapm->codec->name_prefix, route->sink); | 2488 | prefix, route->sink); |
2452 | sink = prefixed_sink; | 2489 | sink = prefixed_sink; |
2453 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", | 2490 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", |
2454 | dapm->codec->name_prefix, route->source); | 2491 | prefix, route->source); |
2455 | source = prefixed_source; | 2492 | source = prefixed_source; |
2456 | } else { | 2493 | } else { |
2457 | sink = route->sink; | 2494 | sink = route->sink; |
@@ -2670,7 +2707,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) | |||
2670 | 2707 | ||
2671 | /* Read the initial power state from the device */ | 2708 | /* Read the initial power state from the device */ |
2672 | if (w->reg >= 0) { | 2709 | if (w->reg >= 0) { |
2673 | soc_widget_read(w, w->reg, &val); | 2710 | soc_dapm_read(w->dapm, w->reg, &val); |
2674 | val = val >> w->shift; | 2711 | val = val >> w->shift; |
2675 | val &= w->mask; | 2712 | val &= w->mask; |
2676 | if (val == w->on_val) | 2713 | if (val == w->on_val) |
@@ -2701,8 +2738,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); | |||
2701 | int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | 2738 | int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, |
2702 | struct snd_ctl_elem_value *ucontrol) | 2739 | struct snd_ctl_elem_value *ucontrol) |
2703 | { | 2740 | { |
2704 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 2741 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
2705 | struct snd_soc_card *card = codec->card; | 2742 | struct snd_soc_card *card = dapm->card; |
2706 | struct soc_mixer_control *mc = | 2743 | struct soc_mixer_control *mc = |
2707 | (struct soc_mixer_control *)kcontrol->private_value; | 2744 | (struct soc_mixer_control *)kcontrol->private_value; |
2708 | int reg = mc->reg; | 2745 | int reg = mc->reg; |
@@ -2711,17 +2748,20 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
2711 | unsigned int mask = (1 << fls(max)) - 1; | 2748 | unsigned int mask = (1 << fls(max)) - 1; |
2712 | unsigned int invert = mc->invert; | 2749 | unsigned int invert = mc->invert; |
2713 | unsigned int val; | 2750 | unsigned int val; |
2751 | int ret = 0; | ||
2714 | 2752 | ||
2715 | if (snd_soc_volsw_is_stereo(mc)) | 2753 | if (snd_soc_volsw_is_stereo(mc)) |
2716 | dev_warn(codec->dapm.dev, | 2754 | dev_warn(dapm->dev, |
2717 | "ASoC: Control '%s' is stereo, which is not supported\n", | 2755 | "ASoC: Control '%s' is stereo, which is not supported\n", |
2718 | kcontrol->id.name); | 2756 | kcontrol->id.name); |
2719 | 2757 | ||
2720 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2758 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
2721 | if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) | 2759 | if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) { |
2722 | val = (snd_soc_read(codec, reg) >> shift) & mask; | 2760 | ret = soc_dapm_read(dapm, reg, &val); |
2723 | else | 2761 | val = (val >> shift) & mask; |
2762 | } else { | ||
2724 | val = dapm_kcontrol_get_value(kcontrol); | 2763 | val = dapm_kcontrol_get_value(kcontrol); |
2764 | } | ||
2725 | mutex_unlock(&card->dapm_mutex); | 2765 | mutex_unlock(&card->dapm_mutex); |
2726 | 2766 | ||
2727 | if (invert) | 2767 | if (invert) |
@@ -2729,7 +2769,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
2729 | else | 2769 | else |
2730 | ucontrol->value.integer.value[0] = val; | 2770 | ucontrol->value.integer.value[0] = val; |
2731 | 2771 | ||
2732 | return 0; | 2772 | return ret; |
2733 | } | 2773 | } |
2734 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); | 2774 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); |
2735 | 2775 | ||
@@ -2745,8 +2785,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); | |||
2745 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | 2785 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, |
2746 | struct snd_ctl_elem_value *ucontrol) | 2786 | struct snd_ctl_elem_value *ucontrol) |
2747 | { | 2787 | { |
2748 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 2788 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
2749 | struct snd_soc_card *card = codec->card; | 2789 | struct snd_soc_card *card = dapm->card; |
2750 | struct soc_mixer_control *mc = | 2790 | struct soc_mixer_control *mc = |
2751 | (struct soc_mixer_control *)kcontrol->private_value; | 2791 | (struct soc_mixer_control *)kcontrol->private_value; |
2752 | int reg = mc->reg; | 2792 | int reg = mc->reg; |
@@ -2755,12 +2795,12 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2755 | unsigned int mask = (1 << fls(max)) - 1; | 2795 | unsigned int mask = (1 << fls(max)) - 1; |
2756 | unsigned int invert = mc->invert; | 2796 | unsigned int invert = mc->invert; |
2757 | unsigned int val; | 2797 | unsigned int val; |
2758 | int connect, change; | 2798 | int connect, change, reg_change = 0; |
2759 | struct snd_soc_dapm_update update; | 2799 | struct snd_soc_dapm_update update; |
2760 | int ret = 0; | 2800 | int ret = 0; |
2761 | 2801 | ||
2762 | if (snd_soc_volsw_is_stereo(mc)) | 2802 | if (snd_soc_volsw_is_stereo(mc)) |
2763 | dev_warn(codec->dapm.dev, | 2803 | dev_warn(dapm->dev, |
2764 | "ASoC: Control '%s' is stereo, which is not supported\n", | 2804 | "ASoC: Control '%s' is stereo, which is not supported\n", |
2765 | kcontrol->id.name); | 2805 | kcontrol->id.name); |
2766 | 2806 | ||
@@ -2773,20 +2813,23 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2773 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2813 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
2774 | 2814 | ||
2775 | change = dapm_kcontrol_set_value(kcontrol, val); | 2815 | change = dapm_kcontrol_set_value(kcontrol, val); |
2776 | if (change) { | ||
2777 | if (reg != SND_SOC_NOPM) { | ||
2778 | mask = mask << shift; | ||
2779 | val = val << shift; | ||
2780 | |||
2781 | if (snd_soc_test_bits(codec, reg, mask, val)) { | ||
2782 | update.kcontrol = kcontrol; | ||
2783 | update.reg = reg; | ||
2784 | update.mask = mask; | ||
2785 | update.val = val; | ||
2786 | card->update = &update; | ||
2787 | } | ||
2788 | 2816 | ||
2817 | if (reg != SND_SOC_NOPM) { | ||
2818 | mask = mask << shift; | ||
2819 | val = val << shift; | ||
2820 | |||
2821 | reg_change = soc_dapm_test_bits(dapm, reg, mask, val); | ||
2822 | } | ||
2823 | |||
2824 | if (change || reg_change) { | ||
2825 | if (reg_change) { | ||
2826 | update.kcontrol = kcontrol; | ||
2827 | update.reg = reg; | ||
2828 | update.mask = mask; | ||
2829 | update.val = val; | ||
2830 | card->update = &update; | ||
2789 | } | 2831 | } |
2832 | change |= reg_change; | ||
2790 | 2833 | ||
2791 | ret = soc_dapm_mixer_update_power(card, kcontrol, connect); | 2834 | ret = soc_dapm_mixer_update_power(card, kcontrol, connect); |
2792 | 2835 | ||
@@ -2814,12 +2857,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | |||
2814 | int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | 2857 | int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, |
2815 | struct snd_ctl_elem_value *ucontrol) | 2858 | struct snd_ctl_elem_value *ucontrol) |
2816 | { | 2859 | { |
2817 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 2860 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
2818 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2861 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2819 | unsigned int reg_val, val; | 2862 | unsigned int reg_val, val; |
2863 | int ret = 0; | ||
2820 | 2864 | ||
2821 | if (e->reg != SND_SOC_NOPM) | 2865 | if (e->reg != SND_SOC_NOPM) |
2822 | reg_val = snd_soc_read(codec, e->reg); | 2866 | ret = soc_dapm_read(dapm, e->reg, ®_val); |
2823 | else | 2867 | else |
2824 | reg_val = dapm_kcontrol_get_value(kcontrol); | 2868 | reg_val = dapm_kcontrol_get_value(kcontrol); |
2825 | 2869 | ||
@@ -2831,7 +2875,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | |||
2831 | ucontrol->value.enumerated.item[1] = val; | 2875 | ucontrol->value.enumerated.item[1] = val; |
2832 | } | 2876 | } |
2833 | 2877 | ||
2834 | return 0; | 2878 | return ret; |
2835 | } | 2879 | } |
2836 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); | 2880 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); |
2837 | 2881 | ||
@@ -2847,8 +2891,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); | |||
2847 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | 2891 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, |
2848 | struct snd_ctl_elem_value *ucontrol) | 2892 | struct snd_ctl_elem_value *ucontrol) |
2849 | { | 2893 | { |
2850 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 2894 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
2851 | struct snd_soc_card *card = codec->card; | 2895 | struct snd_soc_card *card = dapm->card; |
2852 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2896 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2853 | unsigned int *item = ucontrol->value.enumerated.item; | 2897 | unsigned int *item = ucontrol->value.enumerated.item; |
2854 | unsigned int val, change; | 2898 | unsigned int val, change; |
@@ -2871,7 +2915,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2871 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2915 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
2872 | 2916 | ||
2873 | if (e->reg != SND_SOC_NOPM) | 2917 | if (e->reg != SND_SOC_NOPM) |
2874 | change = snd_soc_test_bits(codec, e->reg, mask, val); | 2918 | change = soc_dapm_test_bits(dapm, e->reg, mask, val); |
2875 | else | 2919 | else |
2876 | change = dapm_kcontrol_set_value(kcontrol, val); | 2920 | change = dapm_kcontrol_set_value(kcontrol, val); |
2877 | 2921 | ||
@@ -2968,6 +3012,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
2968 | const struct snd_soc_dapm_widget *widget) | 3012 | const struct snd_soc_dapm_widget *widget) |
2969 | { | 3013 | { |
2970 | struct snd_soc_dapm_widget *w; | 3014 | struct snd_soc_dapm_widget *w; |
3015 | const char *prefix; | ||
2971 | int ret; | 3016 | int ret; |
2972 | 3017 | ||
2973 | if ((w = dapm_cnew_widget(widget)) == NULL) | 3018 | if ((w = dapm_cnew_widget(widget)) == NULL) |
@@ -3008,9 +3053,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3008 | break; | 3053 | break; |
3009 | } | 3054 | } |
3010 | 3055 | ||
3011 | if (dapm->codec && dapm->codec->name_prefix) | 3056 | prefix = soc_dapm_prefix(dapm); |
3012 | w->name = kasprintf(GFP_KERNEL, "%s %s", | 3057 | if (prefix) |
3013 | dapm->codec->name_prefix, widget->name); | 3058 | w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name); |
3014 | else | 3059 | else |
3015 | w->name = kasprintf(GFP_KERNEL, "%s", widget->name); | 3060 | w->name = kasprintf(GFP_KERNEL, "%s", widget->name); |
3016 | 3061 | ||
@@ -3063,7 +3108,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3063 | 3108 | ||
3064 | w->dapm = dapm; | 3109 | w->dapm = dapm; |
3065 | w->codec = dapm->codec; | 3110 | w->codec = dapm->codec; |
3066 | w->platform = dapm->platform; | ||
3067 | INIT_LIST_HEAD(&w->sources); | 3111 | INIT_LIST_HEAD(&w->sources); |
3068 | INIT_LIST_HEAD(&w->sinks); | 3112 | INIT_LIST_HEAD(&w->sinks); |
3069 | INIT_LIST_HEAD(&w->list); | 3113 | INIT_LIST_HEAD(&w->list); |
@@ -3170,27 +3214,15 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, | |||
3170 | 3214 | ||
3171 | switch (event) { | 3215 | switch (event) { |
3172 | case SND_SOC_DAPM_PRE_PMU: | 3216 | case SND_SOC_DAPM_PRE_PMU: |
3173 | if (source->driver->ops && source->driver->ops->hw_params) { | 3217 | substream.stream = SNDRV_PCM_STREAM_CAPTURE; |
3174 | substream.stream = SNDRV_PCM_STREAM_CAPTURE; | 3218 | ret = soc_dai_hw_params(&substream, params, source); |
3175 | ret = source->driver->ops->hw_params(&substream, | 3219 | if (ret < 0) |
3176 | params, source); | 3220 | goto out; |
3177 | if (ret != 0) { | ||
3178 | dev_err(source->dev, | ||
3179 | "ASoC: hw_params() failed: %d\n", ret); | ||
3180 | goto out; | ||
3181 | } | ||
3182 | } | ||
3183 | 3221 | ||
3184 | if (sink->driver->ops && sink->driver->ops->hw_params) { | 3222 | substream.stream = SNDRV_PCM_STREAM_PLAYBACK; |
3185 | substream.stream = SNDRV_PCM_STREAM_PLAYBACK; | 3223 | ret = soc_dai_hw_params(&substream, params, sink); |
3186 | ret = sink->driver->ops->hw_params(&substream, params, | 3224 | if (ret < 0) |
3187 | sink); | 3225 | goto out; |
3188 | if (ret != 0) { | ||
3189 | dev_err(sink->dev, | ||
3190 | "ASoC: hw_params() failed: %d\n", ret); | ||
3191 | goto out; | ||
3192 | } | ||
3193 | } | ||
3194 | break; | 3226 | break; |
3195 | 3227 | ||
3196 | case SND_SOC_DAPM_POST_PMU: | 3228 | case SND_SOC_DAPM_POST_PMU: |
@@ -3362,25 +3394,15 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) | |||
3362 | return 0; | 3394 | return 0; |
3363 | } | 3395 | } |
3364 | 3396 | ||
3365 | void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) | 3397 | static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, |
3398 | struct snd_soc_pcm_runtime *rtd) | ||
3366 | { | 3399 | { |
3367 | struct snd_soc_pcm_runtime *rtd = card->rtd; | 3400 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
3368 | struct snd_soc_dapm_widget *sink, *source; | 3401 | struct snd_soc_dapm_widget *sink, *source; |
3369 | struct snd_soc_dai *cpu_dai, *codec_dai; | ||
3370 | int i; | 3402 | int i; |
3371 | 3403 | ||
3372 | /* for each BE DAI link... */ | 3404 | for (i = 0; i < rtd->num_codecs; i++) { |
3373 | for (i = 0; i < card->num_rtd; i++) { | 3405 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; |
3374 | rtd = &card->rtd[i]; | ||
3375 | cpu_dai = rtd->cpu_dai; | ||
3376 | codec_dai = rtd->codec_dai; | ||
3377 | |||
3378 | /* | ||
3379 | * dynamic FE links have no fixed DAI mapping. | ||
3380 | * CODEC<->CODEC links have no direct connection. | ||
3381 | */ | ||
3382 | if (rtd->dai_link->dynamic || rtd->dai_link->params) | ||
3383 | continue; | ||
3384 | 3406 | ||
3385 | /* there is no point in connecting BE DAI links with dummies */ | 3407 | /* there is no point in connecting BE DAI links with dummies */ |
3386 | if (snd_soc_dai_is_dummy(codec_dai) || | 3408 | if (snd_soc_dai_is_dummy(codec_dai) || |
@@ -3392,8 +3414,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) | |||
3392 | source = cpu_dai->playback_widget; | 3414 | source = cpu_dai->playback_widget; |
3393 | sink = codec_dai->playback_widget; | 3415 | sink = codec_dai->playback_widget; |
3394 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", | 3416 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", |
3395 | cpu_dai->codec->name, source->name, | 3417 | cpu_dai->component->name, source->name, |
3396 | codec_dai->platform->name, sink->name); | 3418 | codec_dai->component->name, sink->name); |
3397 | 3419 | ||
3398 | snd_soc_dapm_add_path(&card->dapm, source, sink, | 3420 | snd_soc_dapm_add_path(&card->dapm, source, sink, |
3399 | NULL, NULL); | 3421 | NULL, NULL); |
@@ -3404,8 +3426,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) | |||
3404 | source = codec_dai->capture_widget; | 3426 | source = codec_dai->capture_widget; |
3405 | sink = cpu_dai->capture_widget; | 3427 | sink = cpu_dai->capture_widget; |
3406 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", | 3428 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", |
3407 | codec_dai->codec->name, source->name, | 3429 | codec_dai->component->name, source->name, |
3408 | cpu_dai->platform->name, sink->name); | 3430 | cpu_dai->component->name, sink->name); |
3409 | 3431 | ||
3410 | snd_soc_dapm_add_path(&card->dapm, source, sink, | 3432 | snd_soc_dapm_add_path(&card->dapm, source, sink, |
3411 | NULL, NULL); | 3433 | NULL, NULL); |
@@ -3442,11 +3464,34 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, | |||
3442 | } | 3464 | } |
3443 | } | 3465 | } |
3444 | 3466 | ||
3467 | void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) | ||
3468 | { | ||
3469 | struct snd_soc_pcm_runtime *rtd = card->rtd; | ||
3470 | int i; | ||
3471 | |||
3472 | /* for each BE DAI link... */ | ||
3473 | for (i = 0; i < card->num_rtd; i++) { | ||
3474 | rtd = &card->rtd[i]; | ||
3475 | |||
3476 | /* | ||
3477 | * dynamic FE links have no fixed DAI mapping. | ||
3478 | * CODEC<->CODEC links have no direct connection. | ||
3479 | */ | ||
3480 | if (rtd->dai_link->dynamic || rtd->dai_link->params) | ||
3481 | continue; | ||
3482 | |||
3483 | dapm_connect_dai_link_widgets(card, rtd); | ||
3484 | } | ||
3485 | } | ||
3486 | |||
3445 | static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, | 3487 | static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, |
3446 | int event) | 3488 | int event) |
3447 | { | 3489 | { |
3490 | int i; | ||
3491 | |||
3448 | soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event); | 3492 | soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event); |
3449 | soc_dapm_dai_stream_event(rtd->codec_dai, stream, event); | 3493 | for (i = 0; i < rtd->num_codecs; i++) |
3494 | soc_dapm_dai_stream_event(rtd->codec_dais[i], stream, event); | ||
3450 | 3495 | ||
3451 | dapm_power_widgets(rtd->card, event); | 3496 | dapm_power_widgets(rtd->card, event); |
3452 | } | 3497 | } |
@@ -3755,36 +3800,31 @@ static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card, | |||
3755 | } | 3800 | } |
3756 | 3801 | ||
3757 | /** | 3802 | /** |
3758 | * snd_soc_dapm_auto_nc_codec_pins - call snd_soc_dapm_nc_pin for unused pins | 3803 | * snd_soc_dapm_auto_nc_pins - call snd_soc_dapm_nc_pin for unused pins |
3759 | * @codec: The codec whose pins should be processed | 3804 | * @card: The card whose pins should be processed |
3760 | * | 3805 | * |
3761 | * Automatically call snd_soc_dapm_nc_pin() for any external pins in the codec | 3806 | * Automatically call snd_soc_dapm_nc_pin() for any external pins in the card |
3762 | * which are unused. Pins are used if they are connected externally to the | 3807 | * which are unused. Pins are used if they are connected externally to a |
3763 | * codec, whether that be to some other device, or a loop-back connection to | 3808 | * component, whether that be to some other device, or a loop-back connection to |
3764 | * the codec itself. | 3809 | * the component itself. |
3765 | */ | 3810 | */ |
3766 | void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec) | 3811 | void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card) |
3767 | { | 3812 | { |
3768 | struct snd_soc_card *card = codec->card; | ||
3769 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
3770 | struct snd_soc_dapm_widget *w; | 3813 | struct snd_soc_dapm_widget *w; |
3771 | 3814 | ||
3772 | dev_dbg(codec->dev, "ASoC: Auto NC: DAPMs: card:%p codec:%p\n", | 3815 | dev_dbg(card->dev, "ASoC: Auto NC: DAPMs: card:%p\n", &card->dapm); |
3773 | &card->dapm, &codec->dapm); | ||
3774 | 3816 | ||
3775 | list_for_each_entry(w, &card->widgets, list) { | 3817 | list_for_each_entry(w, &card->widgets, list) { |
3776 | if (w->dapm != dapm) | ||
3777 | continue; | ||
3778 | switch (w->id) { | 3818 | switch (w->id) { |
3779 | case snd_soc_dapm_input: | 3819 | case snd_soc_dapm_input: |
3780 | case snd_soc_dapm_output: | 3820 | case snd_soc_dapm_output: |
3781 | case snd_soc_dapm_micbias: | 3821 | case snd_soc_dapm_micbias: |
3782 | dev_dbg(codec->dev, "ASoC: Auto NC: Checking widget %s\n", | 3822 | dev_dbg(card->dev, "ASoC: Auto NC: Checking widget %s\n", |
3783 | w->name); | 3823 | w->name); |
3784 | if (!snd_soc_dapm_widget_in_card_paths(card, w)) { | 3824 | if (!snd_soc_dapm_widget_in_card_paths(card, w)) { |
3785 | dev_dbg(codec->dev, | 3825 | dev_dbg(card->dev, |
3786 | "... Not in map; disabling\n"); | 3826 | "... Not in map; disabling\n"); |
3787 | snd_soc_dapm_nc_pin(dapm, w->name); | 3827 | snd_soc_dapm_nc_pin(w->dapm, w->name); |
3788 | } | 3828 | } |
3789 | break; | 3829 | break; |
3790 | default: | 3830 | default: |
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 5bace124ef43..6307f85e871b 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -119,7 +119,10 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea | |||
119 | struct snd_dmaengine_dai_dma_data *dma_data; | 119 | struct snd_dmaengine_dai_dma_data *dma_data; |
120 | struct dma_slave_caps dma_caps; | 120 | struct dma_slave_caps dma_caps; |
121 | struct snd_pcm_hardware hw; | 121 | struct snd_pcm_hardware hw; |
122 | int ret; | 122 | u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | |
123 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
124 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); | ||
125 | int i, ret; | ||
123 | 126 | ||
124 | if (pcm->config && pcm->config->pcm_hardware) | 127 | if (pcm->config && pcm->config->pcm_hardware) |
125 | return snd_soc_set_runtime_hwparams(substream, | 128 | return snd_soc_set_runtime_hwparams(substream, |
@@ -146,6 +149,38 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea | |||
146 | hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; | 149 | hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; |
147 | if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) | 150 | if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) |
148 | hw.info |= SNDRV_PCM_INFO_BATCH; | 151 | hw.info |= SNDRV_PCM_INFO_BATCH; |
152 | |||
153 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
154 | addr_widths = dma_caps.dstn_addr_widths; | ||
155 | else | ||
156 | addr_widths = dma_caps.src_addr_widths; | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * Prepare formats mask for valid/allowed sample types. If the dma does | ||
161 | * not have support for the given physical word size, it needs to be | ||
162 | * masked out so user space can not use the format which produces | ||
163 | * corrupted audio. | ||
164 | * In case the dma driver does not implement the slave_caps the default | ||
165 | * assumption is that it supports 1, 2 and 4 bytes widths. | ||
166 | */ | ||
167 | for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { | ||
168 | int bits = snd_pcm_format_physical_width(i); | ||
169 | |||
170 | /* Enable only samples with DMA supported physical widths */ | ||
171 | switch (bits) { | ||
172 | case 8: | ||
173 | case 16: | ||
174 | case 24: | ||
175 | case 32: | ||
176 | case 64: | ||
177 | if (addr_widths & (1 << (bits / 8))) | ||
178 | hw.formats |= (1LL << i); | ||
179 | break; | ||
180 | default: | ||
181 | /* Unsupported types */ | ||
182 | break; | ||
183 | } | ||
149 | } | 184 | } |
150 | 185 | ||
151 | return snd_soc_set_runtime_hwparams(substream, &hw); | 186 | return snd_soc_set_runtime_hwparams(substream, &hw); |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index d0d98810af91..ab47fea997a3 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -43,7 +43,7 @@ int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type, | |||
43 | INIT_LIST_HEAD(&jack->jack_zones); | 43 | INIT_LIST_HEAD(&jack->jack_zones); |
44 | BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); | 44 | BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); |
45 | 45 | ||
46 | return snd_jack_new(codec->card->snd_card, id, type, &jack->jack); | 46 | return snd_jack_new(codec->component.card->snd_card, id, type, &jack->jack); |
47 | } | 47 | } |
48 | EXPORT_SYMBOL_GPL(snd_soc_jack_new); | 48 | EXPORT_SYMBOL_GPL(snd_soc_jack_new); |
49 | 49 | ||
@@ -260,7 +260,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) | |||
260 | static irqreturn_t gpio_handler(int irq, void *data) | 260 | static irqreturn_t gpio_handler(int irq, void *data) |
261 | { | 261 | { |
262 | struct snd_soc_jack_gpio *gpio = data; | 262 | struct snd_soc_jack_gpio *gpio = data; |
263 | struct device *dev = gpio->jack->codec->card->dev; | 263 | struct device *dev = gpio->jack->codec->component.card->dev; |
264 | 264 | ||
265 | trace_snd_soc_jack_irq(gpio->name); | 265 | trace_snd_soc_jack_irq(gpio->name); |
266 | 266 | ||
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 54d18f22a33e..731fdb5b5f9b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Copyright (C) 2010 Texas Instruments Inc. | 7 | * Copyright (C) 2010 Texas Instruments Inc. |
8 | * | 8 | * |
9 | * Authors: Liam Girdwood <lrg@ti.com> | 9 | * Authors: Liam Girdwood <lrg@ti.com> |
10 | * Mark Brown <broonie@opensource.wolfsonmicro.com> | 10 | * Mark Brown <broonie@opensource.wolfsonmicro.com> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify it | 12 | * This program is free software; you can redistribute it and/or modify it |
13 | * under the terms of the GNU General Public License as published by the | 13 | * under the terms of the GNU General Public License as published by the |
@@ -47,22 +47,26 @@ | |||
47 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | 47 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) |
48 | { | 48 | { |
49 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 49 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
50 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 50 | int i; |
51 | 51 | ||
52 | lockdep_assert_held(&rtd->pcm_mutex); | 52 | lockdep_assert_held(&rtd->pcm_mutex); |
53 | 53 | ||
54 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 54 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
55 | cpu_dai->playback_active++; | 55 | cpu_dai->playback_active++; |
56 | codec_dai->playback_active++; | 56 | for (i = 0; i < rtd->num_codecs; i++) |
57 | rtd->codec_dais[i]->playback_active++; | ||
57 | } else { | 58 | } else { |
58 | cpu_dai->capture_active++; | 59 | cpu_dai->capture_active++; |
59 | codec_dai->capture_active++; | 60 | for (i = 0; i < rtd->num_codecs; i++) |
61 | rtd->codec_dais[i]->capture_active++; | ||
60 | } | 62 | } |
61 | 63 | ||
62 | cpu_dai->active++; | 64 | cpu_dai->active++; |
63 | codec_dai->active++; | ||
64 | cpu_dai->component->active++; | 65 | cpu_dai->component->active++; |
65 | codec_dai->component->active++; | 66 | for (i = 0; i < rtd->num_codecs; i++) { |
67 | rtd->codec_dais[i]->active++; | ||
68 | rtd->codec_dais[i]->component->active++; | ||
69 | } | ||
66 | } | 70 | } |
67 | 71 | ||
68 | /** | 72 | /** |
@@ -78,22 +82,26 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | |||
78 | void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) | 82 | void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) |
79 | { | 83 | { |
80 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 84 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
81 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 85 | int i; |
82 | 86 | ||
83 | lockdep_assert_held(&rtd->pcm_mutex); | 87 | lockdep_assert_held(&rtd->pcm_mutex); |
84 | 88 | ||
85 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 89 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
86 | cpu_dai->playback_active--; | 90 | cpu_dai->playback_active--; |
87 | codec_dai->playback_active--; | 91 | for (i = 0; i < rtd->num_codecs; i++) |
92 | rtd->codec_dais[i]->playback_active--; | ||
88 | } else { | 93 | } else { |
89 | cpu_dai->capture_active--; | 94 | cpu_dai->capture_active--; |
90 | codec_dai->capture_active--; | 95 | for (i = 0; i < rtd->num_codecs; i++) |
96 | rtd->codec_dais[i]->capture_active--; | ||
91 | } | 97 | } |
92 | 98 | ||
93 | cpu_dai->active--; | 99 | cpu_dai->active--; |
94 | codec_dai->active--; | ||
95 | cpu_dai->component->active--; | 100 | cpu_dai->component->active--; |
96 | codec_dai->component->active--; | 101 | for (i = 0; i < rtd->num_codecs; i++) { |
102 | rtd->codec_dais[i]->component->active--; | ||
103 | rtd->codec_dais[i]->active--; | ||
104 | } | ||
97 | } | 105 | } |
98 | 106 | ||
99 | /** | 107 | /** |
@@ -107,11 +115,16 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) | |||
107 | */ | 115 | */ |
108 | bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) | 116 | bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) |
109 | { | 117 | { |
118 | int i; | ||
119 | bool ignore = true; | ||
120 | |||
110 | if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time) | 121 | if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time) |
111 | return true; | 122 | return true; |
112 | 123 | ||
113 | return rtd->cpu_dai->component->ignore_pmdown_time && | 124 | for (i = 0; i < rtd->num_codecs; i++) |
114 | rtd->codec_dai->component->ignore_pmdown_time; | 125 | ignore &= rtd->codec_dais[i]->component->ignore_pmdown_time; |
126 | |||
127 | return rtd->cpu_dai->component->ignore_pmdown_time && ignore; | ||
115 | } | 128 | } |
116 | 129 | ||
117 | /** | 130 | /** |
@@ -222,8 +235,7 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
222 | { | 235 | { |
223 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 236 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
224 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 237 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
225 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 238 | unsigned int rate, channels, sample_bits, symmetry, i; |
226 | unsigned int rate, channels, sample_bits, symmetry; | ||
227 | 239 | ||
228 | rate = params_rate(params); | 240 | rate = params_rate(params); |
229 | channels = params_channels(params); | 241 | channels = params_channels(params); |
@@ -231,8 +243,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
231 | 243 | ||
232 | /* reject unmatched parameters when applying symmetry */ | 244 | /* reject unmatched parameters when applying symmetry */ |
233 | symmetry = cpu_dai->driver->symmetric_rates || | 245 | symmetry = cpu_dai->driver->symmetric_rates || |
234 | codec_dai->driver->symmetric_rates || | ||
235 | rtd->dai_link->symmetric_rates; | 246 | rtd->dai_link->symmetric_rates; |
247 | |||
248 | for (i = 0; i < rtd->num_codecs; i++) | ||
249 | symmetry |= rtd->codec_dais[i]->driver->symmetric_rates; | ||
250 | |||
236 | if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) { | 251 | if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) { |
237 | dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", | 252 | dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", |
238 | cpu_dai->rate, rate); | 253 | cpu_dai->rate, rate); |
@@ -240,8 +255,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
240 | } | 255 | } |
241 | 256 | ||
242 | symmetry = cpu_dai->driver->symmetric_channels || | 257 | symmetry = cpu_dai->driver->symmetric_channels || |
243 | codec_dai->driver->symmetric_channels || | ||
244 | rtd->dai_link->symmetric_channels; | 258 | rtd->dai_link->symmetric_channels; |
259 | |||
260 | for (i = 0; i < rtd->num_codecs; i++) | ||
261 | symmetry |= rtd->codec_dais[i]->driver->symmetric_channels; | ||
262 | |||
245 | if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) { | 263 | if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) { |
246 | dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", | 264 | dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", |
247 | cpu_dai->channels, channels); | 265 | cpu_dai->channels, channels); |
@@ -249,8 +267,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
249 | } | 267 | } |
250 | 268 | ||
251 | symmetry = cpu_dai->driver->symmetric_samplebits || | 269 | symmetry = cpu_dai->driver->symmetric_samplebits || |
252 | codec_dai->driver->symmetric_samplebits || | ||
253 | rtd->dai_link->symmetric_samplebits; | 270 | rtd->dai_link->symmetric_samplebits; |
271 | |||
272 | for (i = 0; i < rtd->num_codecs; i++) | ||
273 | symmetry |= rtd->codec_dais[i]->driver->symmetric_samplebits; | ||
274 | |||
254 | if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) { | 275 | if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) { |
255 | dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", | 276 | dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", |
256 | cpu_dai->sample_bits, sample_bits); | 277 | cpu_dai->sample_bits, sample_bits); |
@@ -264,15 +285,20 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) | |||
264 | { | 285 | { |
265 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 286 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
266 | struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver; | 287 | struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver; |
267 | struct snd_soc_dai_driver *codec_driver = rtd->codec_dai->driver; | ||
268 | struct snd_soc_dai_link *link = rtd->dai_link; | 288 | struct snd_soc_dai_link *link = rtd->dai_link; |
289 | unsigned int symmetry, i; | ||
269 | 290 | ||
270 | return cpu_driver->symmetric_rates || codec_driver->symmetric_rates || | 291 | symmetry = cpu_driver->symmetric_rates || link->symmetric_rates || |
271 | link->symmetric_rates || cpu_driver->symmetric_channels || | 292 | cpu_driver->symmetric_channels || link->symmetric_channels || |
272 | codec_driver->symmetric_channels || link->symmetric_channels || | 293 | cpu_driver->symmetric_samplebits || link->symmetric_samplebits; |
273 | cpu_driver->symmetric_samplebits || | 294 | |
274 | codec_driver->symmetric_samplebits || | 295 | for (i = 0; i < rtd->num_codecs; i++) |
275 | link->symmetric_samplebits; | 296 | symmetry = symmetry || |
297 | rtd->codec_dais[i]->driver->symmetric_rates || | ||
298 | rtd->codec_dais[i]->driver->symmetric_channels || | ||
299 | rtd->codec_dais[i]->driver->symmetric_samplebits; | ||
300 | |||
301 | return symmetry; | ||
276 | } | 302 | } |
277 | 303 | ||
278 | /* | 304 | /* |
@@ -284,15 +310,10 @@ static int sample_sizes[] = { | |||
284 | 24, 32, | 310 | 24, 32, |
285 | }; | 311 | }; |
286 | 312 | ||
287 | static void soc_pcm_apply_msb(struct snd_pcm_substream *substream, | 313 | static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits) |
288 | struct snd_soc_dai *dai) | ||
289 | { | 314 | { |
290 | int ret, i, bits; | 315 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
291 | 316 | int ret, i; | |
292 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
293 | bits = dai->driver->playback.sig_bits; | ||
294 | else | ||
295 | bits = dai->driver->capture.sig_bits; | ||
296 | 317 | ||
297 | if (!bits) | 318 | if (!bits) |
298 | return; | 319 | return; |
@@ -304,38 +325,105 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream, | |||
304 | ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0, | 325 | ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0, |
305 | sample_sizes[i], bits); | 326 | sample_sizes[i], bits); |
306 | if (ret != 0) | 327 | if (ret != 0) |
307 | dev_warn(dai->dev, | 328 | dev_warn(rtd->dev, |
308 | "ASoC: Failed to set MSB %d/%d: %d\n", | 329 | "ASoC: Failed to set MSB %d/%d: %d\n", |
309 | bits, sample_sizes[i], ret); | 330 | bits, sample_sizes[i], ret); |
310 | } | 331 | } |
311 | } | 332 | } |
312 | 333 | ||
313 | static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime, | 334 | static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) |
314 | struct snd_soc_pcm_stream *codec_stream, | 335 | { |
315 | struct snd_soc_pcm_stream *cpu_stream) | 336 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
337 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
338 | struct snd_soc_dai *codec_dai; | ||
339 | int i; | ||
340 | unsigned int bits = 0, cpu_bits; | ||
341 | |||
342 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
343 | for (i = 0; i < rtd->num_codecs; i++) { | ||
344 | codec_dai = rtd->codec_dais[i]; | ||
345 | if (codec_dai->driver->playback.sig_bits == 0) { | ||
346 | bits = 0; | ||
347 | break; | ||
348 | } | ||
349 | bits = max(codec_dai->driver->playback.sig_bits, bits); | ||
350 | } | ||
351 | cpu_bits = cpu_dai->driver->playback.sig_bits; | ||
352 | } else { | ||
353 | for (i = 0; i < rtd->num_codecs; i++) { | ||
354 | codec_dai = rtd->codec_dais[i]; | ||
355 | if (codec_dai->driver->playback.sig_bits == 0) { | ||
356 | bits = 0; | ||
357 | break; | ||
358 | } | ||
359 | bits = max(codec_dai->driver->capture.sig_bits, bits); | ||
360 | } | ||
361 | cpu_bits = cpu_dai->driver->capture.sig_bits; | ||
362 | } | ||
363 | |||
364 | soc_pcm_set_msb(substream, bits); | ||
365 | soc_pcm_set_msb(substream, cpu_bits); | ||
366 | } | ||
367 | |||
368 | static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) | ||
316 | { | 369 | { |
370 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
317 | struct snd_pcm_hardware *hw = &runtime->hw; | 371 | struct snd_pcm_hardware *hw = &runtime->hw; |
372 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
373 | struct snd_soc_dai_driver *cpu_dai_drv = rtd->cpu_dai->driver; | ||
374 | struct snd_soc_dai_driver *codec_dai_drv; | ||
375 | struct snd_soc_pcm_stream *codec_stream; | ||
376 | struct snd_soc_pcm_stream *cpu_stream; | ||
377 | unsigned int chan_min = 0, chan_max = UINT_MAX; | ||
378 | unsigned int rate_min = 0, rate_max = UINT_MAX; | ||
379 | unsigned int rates = UINT_MAX; | ||
380 | u64 formats = ULLONG_MAX; | ||
381 | int i; | ||
318 | 382 | ||
319 | hw->channels_min = max(codec_stream->channels_min, | 383 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
320 | cpu_stream->channels_min); | 384 | cpu_stream = &cpu_dai_drv->playback; |
321 | hw->channels_max = min(codec_stream->channels_max, | ||
322 | cpu_stream->channels_max); | ||
323 | if (hw->formats) | ||
324 | hw->formats &= codec_stream->formats & cpu_stream->formats; | ||
325 | else | 385 | else |
326 | hw->formats = codec_stream->formats & cpu_stream->formats; | 386 | cpu_stream = &cpu_dai_drv->capture; |
327 | hw->rates = snd_pcm_rate_mask_intersect(codec_stream->rates, | ||
328 | cpu_stream->rates); | ||
329 | 387 | ||
330 | hw->rate_min = 0; | 388 | /* first calculate min/max only for CODECs in the DAI link */ |
331 | hw->rate_max = UINT_MAX; | 389 | for (i = 0; i < rtd->num_codecs; i++) { |
390 | codec_dai_drv = rtd->codec_dais[i]->driver; | ||
391 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
392 | codec_stream = &codec_dai_drv->playback; | ||
393 | else | ||
394 | codec_stream = &codec_dai_drv->capture; | ||
395 | chan_min = max(chan_min, codec_stream->channels_min); | ||
396 | chan_max = min(chan_max, codec_stream->channels_max); | ||
397 | rate_min = max(rate_min, codec_stream->rate_min); | ||
398 | rate_max = min_not_zero(rate_max, codec_stream->rate_max); | ||
399 | formats &= codec_stream->formats; | ||
400 | rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates); | ||
401 | } | ||
402 | |||
403 | /* | ||
404 | * chan min/max cannot be enforced if there are multiple CODEC DAIs | ||
405 | * connected to a single CPU DAI, use CPU DAI's directly and let | ||
406 | * channel allocation be fixed up later | ||
407 | */ | ||
408 | if (rtd->num_codecs > 1) { | ||
409 | chan_min = cpu_stream->channels_min; | ||
410 | chan_max = cpu_stream->channels_max; | ||
411 | } | ||
412 | |||
413 | hw->channels_min = max(chan_min, cpu_stream->channels_min); | ||
414 | hw->channels_max = min(chan_max, cpu_stream->channels_max); | ||
415 | if (hw->formats) | ||
416 | hw->formats &= formats & cpu_stream->formats; | ||
417 | else | ||
418 | hw->formats = formats & cpu_stream->formats; | ||
419 | hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_stream->rates); | ||
332 | 420 | ||
333 | snd_pcm_limit_hw_rates(runtime); | 421 | snd_pcm_limit_hw_rates(runtime); |
334 | 422 | ||
335 | hw->rate_min = max(hw->rate_min, cpu_stream->rate_min); | 423 | hw->rate_min = max(hw->rate_min, cpu_stream->rate_min); |
336 | hw->rate_min = max(hw->rate_min, codec_stream->rate_min); | 424 | hw->rate_min = max(hw->rate_min, rate_min); |
337 | hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max); | 425 | hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max); |
338 | hw->rate_max = min_not_zero(hw->rate_max, codec_stream->rate_max); | 426 | hw->rate_max = min_not_zero(hw->rate_max, rate_max); |
339 | } | 427 | } |
340 | 428 | ||
341 | /* | 429 | /* |
@@ -349,15 +437,16 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
349 | struct snd_pcm_runtime *runtime = substream->runtime; | 437 | struct snd_pcm_runtime *runtime = substream->runtime; |
350 | struct snd_soc_platform *platform = rtd->platform; | 438 | struct snd_soc_platform *platform = rtd->platform; |
351 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 439 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
352 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 440 | struct snd_soc_dai *codec_dai; |
353 | struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; | 441 | const char *codec_dai_name = "multicodec"; |
354 | struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; | 442 | int i, ret = 0; |
355 | int ret = 0; | ||
356 | 443 | ||
357 | pinctrl_pm_select_default_state(cpu_dai->dev); | 444 | pinctrl_pm_select_default_state(cpu_dai->dev); |
358 | pinctrl_pm_select_default_state(codec_dai->dev); | 445 | for (i = 0; i < rtd->num_codecs; i++) |
446 | pinctrl_pm_select_default_state(rtd->codec_dais[i]->dev); | ||
359 | pm_runtime_get_sync(cpu_dai->dev); | 447 | pm_runtime_get_sync(cpu_dai->dev); |
360 | pm_runtime_get_sync(codec_dai->dev); | 448 | for (i = 0; i < rtd->num_codecs; i++) |
449 | pm_runtime_get_sync(rtd->codec_dais[i]->dev); | ||
361 | pm_runtime_get_sync(platform->dev); | 450 | pm_runtime_get_sync(platform->dev); |
362 | 451 | ||
363 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 452 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
@@ -376,18 +465,28 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
376 | ret = platform->driver->ops->open(substream); | 465 | ret = platform->driver->ops->open(substream); |
377 | if (ret < 0) { | 466 | if (ret < 0) { |
378 | dev_err(platform->dev, "ASoC: can't open platform" | 467 | dev_err(platform->dev, "ASoC: can't open platform" |
379 | " %s: %d\n", platform->name, ret); | 468 | " %s: %d\n", platform->component.name, ret); |
380 | goto platform_err; | 469 | goto platform_err; |
381 | } | 470 | } |
382 | } | 471 | } |
383 | 472 | ||
384 | if (codec_dai->driver->ops && codec_dai->driver->ops->startup) { | 473 | for (i = 0; i < rtd->num_codecs; i++) { |
385 | ret = codec_dai->driver->ops->startup(substream, codec_dai); | 474 | codec_dai = rtd->codec_dais[i]; |
386 | if (ret < 0) { | 475 | if (codec_dai->driver->ops && codec_dai->driver->ops->startup) { |
387 | dev_err(codec_dai->dev, "ASoC: can't open codec" | 476 | ret = codec_dai->driver->ops->startup(substream, |
388 | " %s: %d\n", codec_dai->name, ret); | 477 | codec_dai); |
389 | goto codec_dai_err; | 478 | if (ret < 0) { |
479 | dev_err(codec_dai->dev, | ||
480 | "ASoC: can't open codec %s: %d\n", | ||
481 | codec_dai->name, ret); | ||
482 | goto codec_dai_err; | ||
483 | } | ||
390 | } | 484 | } |
485 | |||
486 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
487 | codec_dai->tx_mask = 0; | ||
488 | else | ||
489 | codec_dai->rx_mask = 0; | ||
391 | } | 490 | } |
392 | 491 | ||
393 | if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { | 492 | if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { |
@@ -404,13 +503,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
404 | goto dynamic; | 503 | goto dynamic; |
405 | 504 | ||
406 | /* Check that the codec and cpu DAIs are compatible */ | 505 | /* Check that the codec and cpu DAIs are compatible */ |
407 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 506 | soc_pcm_init_runtime_hw(substream); |
408 | soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->playback, | 507 | |
409 | &cpu_dai_drv->playback); | 508 | if (rtd->num_codecs == 1) |
410 | } else { | 509 | codec_dai_name = rtd->codec_dai->name; |
411 | soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->capture, | ||
412 | &cpu_dai_drv->capture); | ||
413 | } | ||
414 | 510 | ||
415 | if (soc_pcm_has_symmetry(substream)) | 511 | if (soc_pcm_has_symmetry(substream)) |
416 | runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; | 512 | runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; |
@@ -418,23 +514,22 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
418 | ret = -EINVAL; | 514 | ret = -EINVAL; |
419 | if (!runtime->hw.rates) { | 515 | if (!runtime->hw.rates) { |
420 | printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n", | 516 | printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n", |
421 | codec_dai->name, cpu_dai->name); | 517 | codec_dai_name, cpu_dai->name); |
422 | goto config_err; | 518 | goto config_err; |
423 | } | 519 | } |
424 | if (!runtime->hw.formats) { | 520 | if (!runtime->hw.formats) { |
425 | printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n", | 521 | printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n", |
426 | codec_dai->name, cpu_dai->name); | 522 | codec_dai_name, cpu_dai->name); |
427 | goto config_err; | 523 | goto config_err; |
428 | } | 524 | } |
429 | if (!runtime->hw.channels_min || !runtime->hw.channels_max || | 525 | if (!runtime->hw.channels_min || !runtime->hw.channels_max || |
430 | runtime->hw.channels_min > runtime->hw.channels_max) { | 526 | runtime->hw.channels_min > runtime->hw.channels_max) { |
431 | printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n", | 527 | printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n", |
432 | codec_dai->name, cpu_dai->name); | 528 | codec_dai_name, cpu_dai->name); |
433 | goto config_err; | 529 | goto config_err; |
434 | } | 530 | } |
435 | 531 | ||
436 | soc_pcm_apply_msb(substream, codec_dai); | 532 | soc_pcm_apply_msb(substream); |
437 | soc_pcm_apply_msb(substream, cpu_dai); | ||
438 | 533 | ||
439 | /* Symmetry only applies if we've already got an active stream. */ | 534 | /* Symmetry only applies if we've already got an active stream. */ |
440 | if (cpu_dai->active) { | 535 | if (cpu_dai->active) { |
@@ -443,14 +538,17 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
443 | goto config_err; | 538 | goto config_err; |
444 | } | 539 | } |
445 | 540 | ||
446 | if (codec_dai->active) { | 541 | for (i = 0; i < rtd->num_codecs; i++) { |
447 | ret = soc_pcm_apply_symmetry(substream, codec_dai); | 542 | if (rtd->codec_dais[i]->active) { |
448 | if (ret != 0) | 543 | ret = soc_pcm_apply_symmetry(substream, |
449 | goto config_err; | 544 | rtd->codec_dais[i]); |
545 | if (ret != 0) | ||
546 | goto config_err; | ||
547 | } | ||
450 | } | 548 | } |
451 | 549 | ||
452 | pr_debug("ASoC: %s <-> %s info:\n", | 550 | pr_debug("ASoC: %s <-> %s info:\n", |
453 | codec_dai->name, cpu_dai->name); | 551 | codec_dai_name, cpu_dai->name); |
454 | pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates); | 552 | pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates); |
455 | pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min, | 553 | pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min, |
456 | runtime->hw.channels_max); | 554 | runtime->hw.channels_max); |
@@ -469,10 +567,15 @@ config_err: | |||
469 | rtd->dai_link->ops->shutdown(substream); | 567 | rtd->dai_link->ops->shutdown(substream); |
470 | 568 | ||
471 | machine_err: | 569 | machine_err: |
472 | if (codec_dai->driver->ops->shutdown) | 570 | i = rtd->num_codecs; |
473 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
474 | 571 | ||
475 | codec_dai_err: | 572 | codec_dai_err: |
573 | while (--i >= 0) { | ||
574 | codec_dai = rtd->codec_dais[i]; | ||
575 | if (codec_dai->driver->ops->shutdown) | ||
576 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
577 | } | ||
578 | |||
476 | if (platform->driver->ops && platform->driver->ops->close) | 579 | if (platform->driver->ops && platform->driver->ops->close) |
477 | platform->driver->ops->close(substream); | 580 | platform->driver->ops->close(substream); |
478 | 581 | ||
@@ -483,10 +586,13 @@ out: | |||
483 | mutex_unlock(&rtd->pcm_mutex); | 586 | mutex_unlock(&rtd->pcm_mutex); |
484 | 587 | ||
485 | pm_runtime_put(platform->dev); | 588 | pm_runtime_put(platform->dev); |
486 | pm_runtime_put(codec_dai->dev); | 589 | for (i = 0; i < rtd->num_codecs; i++) |
590 | pm_runtime_put(rtd->codec_dais[i]->dev); | ||
487 | pm_runtime_put(cpu_dai->dev); | 591 | pm_runtime_put(cpu_dai->dev); |
488 | if (!codec_dai->active) | 592 | for (i = 0; i < rtd->num_codecs; i++) { |
489 | pinctrl_pm_select_sleep_state(codec_dai->dev); | 593 | if (!rtd->codec_dais[i]->active) |
594 | pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev); | ||
595 | } | ||
490 | if (!cpu_dai->active) | 596 | if (!cpu_dai->active) |
491 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 597 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
492 | 598 | ||
@@ -502,7 +608,7 @@ static void close_delayed_work(struct work_struct *work) | |||
502 | { | 608 | { |
503 | struct snd_soc_pcm_runtime *rtd = | 609 | struct snd_soc_pcm_runtime *rtd = |
504 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); | 610 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); |
505 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 611 | struct snd_soc_dai *codec_dai = rtd->codec_dais[0]; |
506 | 612 | ||
507 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 613 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
508 | 614 | ||
@@ -531,7 +637,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
531 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 637 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
532 | struct snd_soc_platform *platform = rtd->platform; | 638 | struct snd_soc_platform *platform = rtd->platform; |
533 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 639 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
534 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 640 | struct snd_soc_dai *codec_dai; |
641 | int i; | ||
535 | 642 | ||
536 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 643 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
537 | 644 | ||
@@ -541,14 +648,20 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
541 | if (!cpu_dai->active) | 648 | if (!cpu_dai->active) |
542 | cpu_dai->rate = 0; | 649 | cpu_dai->rate = 0; |
543 | 650 | ||
544 | if (!codec_dai->active) | 651 | for (i = 0; i < rtd->num_codecs; i++) { |
545 | codec_dai->rate = 0; | 652 | codec_dai = rtd->codec_dais[i]; |
653 | if (!codec_dai->active) | ||
654 | codec_dai->rate = 0; | ||
655 | } | ||
546 | 656 | ||
547 | if (cpu_dai->driver->ops->shutdown) | 657 | if (cpu_dai->driver->ops->shutdown) |
548 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | 658 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
549 | 659 | ||
550 | if (codec_dai->driver->ops->shutdown) | 660 | for (i = 0; i < rtd->num_codecs; i++) { |
551 | codec_dai->driver->ops->shutdown(substream, codec_dai); | 661 | codec_dai = rtd->codec_dais[i]; |
662 | if (codec_dai->driver->ops->shutdown) | ||
663 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
664 | } | ||
552 | 665 | ||
553 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) | 666 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) |
554 | rtd->dai_link->ops->shutdown(substream); | 667 | rtd->dai_link->ops->shutdown(substream); |
@@ -578,10 +691,13 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
578 | mutex_unlock(&rtd->pcm_mutex); | 691 | mutex_unlock(&rtd->pcm_mutex); |
579 | 692 | ||
580 | pm_runtime_put(platform->dev); | 693 | pm_runtime_put(platform->dev); |
581 | pm_runtime_put(codec_dai->dev); | 694 | for (i = 0; i < rtd->num_codecs; i++) |
695 | pm_runtime_put(rtd->codec_dais[i]->dev); | ||
582 | pm_runtime_put(cpu_dai->dev); | 696 | pm_runtime_put(cpu_dai->dev); |
583 | if (!codec_dai->active) | 697 | for (i = 0; i < rtd->num_codecs; i++) { |
584 | pinctrl_pm_select_sleep_state(codec_dai->dev); | 698 | if (!rtd->codec_dais[i]->active) |
699 | pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev); | ||
700 | } | ||
585 | if (!cpu_dai->active) | 701 | if (!cpu_dai->active) |
586 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 702 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
587 | 703 | ||
@@ -598,8 +714,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
598 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 714 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
599 | struct snd_soc_platform *platform = rtd->platform; | 715 | struct snd_soc_platform *platform = rtd->platform; |
600 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 716 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
601 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 717 | struct snd_soc_dai *codec_dai; |
602 | int ret = 0; | 718 | int i, ret = 0; |
603 | 719 | ||
604 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 720 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
605 | 721 | ||
@@ -621,12 +737,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
621 | } | 737 | } |
622 | } | 738 | } |
623 | 739 | ||
624 | if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) { | 740 | for (i = 0; i < rtd->num_codecs; i++) { |
625 | ret = codec_dai->driver->ops->prepare(substream, codec_dai); | 741 | codec_dai = rtd->codec_dais[i]; |
626 | if (ret < 0) { | 742 | if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) { |
627 | dev_err(codec_dai->dev, "ASoC: DAI prepare error: %d\n", | 743 | ret = codec_dai->driver->ops->prepare(substream, |
628 | ret); | 744 | codec_dai); |
629 | goto out; | 745 | if (ret < 0) { |
746 | dev_err(codec_dai->dev, | ||
747 | "ASoC: DAI prepare error: %d\n", ret); | ||
748 | goto out; | ||
749 | } | ||
630 | } | 750 | } |
631 | } | 751 | } |
632 | 752 | ||
@@ -649,13 +769,44 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
649 | snd_soc_dapm_stream_event(rtd, substream->stream, | 769 | snd_soc_dapm_stream_event(rtd, substream->stream, |
650 | SND_SOC_DAPM_STREAM_START); | 770 | SND_SOC_DAPM_STREAM_START); |
651 | 771 | ||
652 | snd_soc_dai_digital_mute(codec_dai, 0, substream->stream); | 772 | for (i = 0; i < rtd->num_codecs; i++) |
773 | snd_soc_dai_digital_mute(rtd->codec_dais[i], 0, | ||
774 | substream->stream); | ||
653 | 775 | ||
654 | out: | 776 | out: |
655 | mutex_unlock(&rtd->pcm_mutex); | 777 | mutex_unlock(&rtd->pcm_mutex); |
656 | return ret; | 778 | return ret; |
657 | } | 779 | } |
658 | 780 | ||
781 | static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params, | ||
782 | unsigned int mask) | ||
783 | { | ||
784 | struct snd_interval *interval; | ||
785 | int channels = hweight_long(mask); | ||
786 | |||
787 | interval = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
788 | interval->min = channels; | ||
789 | interval->max = channels; | ||
790 | } | ||
791 | |||
792 | int soc_dai_hw_params(struct snd_pcm_substream *substream, | ||
793 | struct snd_pcm_hw_params *params, | ||
794 | struct snd_soc_dai *dai) | ||
795 | { | ||
796 | int ret; | ||
797 | |||
798 | if (dai->driver->ops && dai->driver->ops->hw_params) { | ||
799 | ret = dai->driver->ops->hw_params(substream, params, dai); | ||
800 | if (ret < 0) { | ||
801 | dev_err(dai->dev, "ASoC: can't set %s hw params: %d\n", | ||
802 | dai->name, ret); | ||
803 | return ret; | ||
804 | } | ||
805 | } | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
659 | /* | 810 | /* |
660 | * Called by ALSA when the hardware params are set by application. This | 811 | * Called by ALSA when the hardware params are set by application. This |
661 | * function can also be called multiple times and can allocate buffers | 812 | * function can also be called multiple times and can allocate buffers |
@@ -667,8 +818,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
667 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 818 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
668 | struct snd_soc_platform *platform = rtd->platform; | 819 | struct snd_soc_platform *platform = rtd->platform; |
669 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 820 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
670 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 821 | int i, ret = 0; |
671 | int ret = 0; | ||
672 | 822 | ||
673 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 823 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
674 | 824 | ||
@@ -685,29 +835,40 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
685 | } | 835 | } |
686 | } | 836 | } |
687 | 837 | ||
688 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_params) { | 838 | for (i = 0; i < rtd->num_codecs; i++) { |
689 | ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); | 839 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; |
690 | if (ret < 0) { | 840 | struct snd_pcm_hw_params codec_params; |
691 | dev_err(codec_dai->dev, "ASoC: can't set %s hw params:" | 841 | |
692 | " %d\n", codec_dai->name, ret); | 842 | /* copy params for each codec */ |
843 | codec_params = *params; | ||
844 | |||
845 | /* fixup params based on TDM slot masks */ | ||
846 | if (codec_dai->tx_mask) | ||
847 | soc_pcm_codec_params_fixup(&codec_params, | ||
848 | codec_dai->tx_mask); | ||
849 | if (codec_dai->rx_mask) | ||
850 | soc_pcm_codec_params_fixup(&codec_params, | ||
851 | codec_dai->rx_mask); | ||
852 | |||
853 | ret = soc_dai_hw_params(substream, &codec_params, codec_dai); | ||
854 | if(ret < 0) | ||
693 | goto codec_err; | 855 | goto codec_err; |
694 | } | ||
695 | } | ||
696 | 856 | ||
697 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_params) { | 857 | codec_dai->rate = params_rate(&codec_params); |
698 | ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai); | 858 | codec_dai->channels = params_channels(&codec_params); |
699 | if (ret < 0) { | 859 | codec_dai->sample_bits = snd_pcm_format_physical_width( |
700 | dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n", | 860 | params_format(&codec_params)); |
701 | cpu_dai->name, ret); | ||
702 | goto interface_err; | ||
703 | } | ||
704 | } | 861 | } |
705 | 862 | ||
863 | ret = soc_dai_hw_params(substream, params, cpu_dai); | ||
864 | if (ret < 0) | ||
865 | goto interface_err; | ||
866 | |||
706 | if (platform->driver->ops && platform->driver->ops->hw_params) { | 867 | if (platform->driver->ops && platform->driver->ops->hw_params) { |
707 | ret = platform->driver->ops->hw_params(substream, params); | 868 | ret = platform->driver->ops->hw_params(substream, params); |
708 | if (ret < 0) { | 869 | if (ret < 0) { |
709 | dev_err(platform->dev, "ASoC: %s hw params failed: %d\n", | 870 | dev_err(platform->dev, "ASoC: %s hw params failed: %d\n", |
710 | platform->name, ret); | 871 | platform->component.name, ret); |
711 | goto platform_err; | 872 | goto platform_err; |
712 | } | 873 | } |
713 | } | 874 | } |
@@ -718,11 +879,6 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
718 | cpu_dai->sample_bits = | 879 | cpu_dai->sample_bits = |
719 | snd_pcm_format_physical_width(params_format(params)); | 880 | snd_pcm_format_physical_width(params_format(params)); |
720 | 881 | ||
721 | codec_dai->rate = params_rate(params); | ||
722 | codec_dai->channels = params_channels(params); | ||
723 | codec_dai->sample_bits = | ||
724 | snd_pcm_format_physical_width(params_format(params)); | ||
725 | |||
726 | out: | 882 | out: |
727 | mutex_unlock(&rtd->pcm_mutex); | 883 | mutex_unlock(&rtd->pcm_mutex); |
728 | return ret; | 884 | return ret; |
@@ -732,10 +888,16 @@ platform_err: | |||
732 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | 888 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); |
733 | 889 | ||
734 | interface_err: | 890 | interface_err: |
735 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free) | 891 | i = rtd->num_codecs; |
736 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
737 | 892 | ||
738 | codec_err: | 893 | codec_err: |
894 | while (--i >= 0) { | ||
895 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
896 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free) | ||
897 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
898 | codec_dai->rate = 0; | ||
899 | } | ||
900 | |||
739 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) | 901 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) |
740 | rtd->dai_link->ops->hw_free(substream); | 902 | rtd->dai_link->ops->hw_free(substream); |
741 | 903 | ||
@@ -751,8 +913,9 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
751 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 913 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
752 | struct snd_soc_platform *platform = rtd->platform; | 914 | struct snd_soc_platform *platform = rtd->platform; |
753 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 915 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
754 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 916 | struct snd_soc_dai *codec_dai; |
755 | bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 917 | bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
918 | int i; | ||
756 | 919 | ||
757 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 920 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
758 | 921 | ||
@@ -763,16 +926,22 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
763 | cpu_dai->sample_bits = 0; | 926 | cpu_dai->sample_bits = 0; |
764 | } | 927 | } |
765 | 928 | ||
766 | if (codec_dai->active == 1) { | 929 | for (i = 0; i < rtd->num_codecs; i++) { |
767 | codec_dai->rate = 0; | 930 | codec_dai = rtd->codec_dais[i]; |
768 | codec_dai->channels = 0; | 931 | if (codec_dai->active == 1) { |
769 | codec_dai->sample_bits = 0; | 932 | codec_dai->rate = 0; |
933 | codec_dai->channels = 0; | ||
934 | codec_dai->sample_bits = 0; | ||
935 | } | ||
770 | } | 936 | } |
771 | 937 | ||
772 | /* apply codec digital mute */ | 938 | /* apply codec digital mute */ |
773 | if ((playback && codec_dai->playback_active == 1) || | 939 | for (i = 0; i < rtd->num_codecs; i++) { |
774 | (!playback && codec_dai->capture_active == 1)) | 940 | if ((playback && rtd->codec_dais[i]->playback_active == 1) || |
775 | snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); | 941 | (!playback && rtd->codec_dais[i]->capture_active == 1)) |
942 | snd_soc_dai_digital_mute(rtd->codec_dais[i], 1, | ||
943 | substream->stream); | ||
944 | } | ||
776 | 945 | ||
777 | /* free any machine hw params */ | 946 | /* free any machine hw params */ |
778 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) | 947 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) |
@@ -783,8 +952,11 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
783 | platform->driver->ops->hw_free(substream); | 952 | platform->driver->ops->hw_free(substream); |
784 | 953 | ||
785 | /* now free hw params for the DAIs */ | 954 | /* now free hw params for the DAIs */ |
786 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free) | 955 | for (i = 0; i < rtd->num_codecs; i++) { |
787 | codec_dai->driver->ops->hw_free(substream, codec_dai); | 956 | codec_dai = rtd->codec_dais[i]; |
957 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free) | ||
958 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
959 | } | ||
788 | 960 | ||
789 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free) | 961 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free) |
790 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | 962 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); |
@@ -798,13 +970,17 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
798 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 970 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
799 | struct snd_soc_platform *platform = rtd->platform; | 971 | struct snd_soc_platform *platform = rtd->platform; |
800 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 972 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
801 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 973 | struct snd_soc_dai *codec_dai; |
802 | int ret; | 974 | int i, ret; |
803 | 975 | ||
804 | if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) { | 976 | for (i = 0; i < rtd->num_codecs; i++) { |
805 | ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai); | 977 | codec_dai = rtd->codec_dais[i]; |
806 | if (ret < 0) | 978 | if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) { |
807 | return ret; | 979 | ret = codec_dai->driver->ops->trigger(substream, |
980 | cmd, codec_dai); | ||
981 | if (ret < 0) | ||
982 | return ret; | ||
983 | } | ||
808 | } | 984 | } |
809 | 985 | ||
810 | if (platform->driver->ops && platform->driver->ops->trigger) { | 986 | if (platform->driver->ops && platform->driver->ops->trigger) { |
@@ -834,14 +1010,18 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, | |||
834 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1010 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
835 | struct snd_soc_platform *platform = rtd->platform; | 1011 | struct snd_soc_platform *platform = rtd->platform; |
836 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1012 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
837 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 1013 | struct snd_soc_dai *codec_dai; |
838 | int ret; | 1014 | int i, ret; |
839 | 1015 | ||
840 | if (codec_dai->driver->ops && | 1016 | for (i = 0; i < rtd->num_codecs; i++) { |
841 | codec_dai->driver->ops->bespoke_trigger) { | 1017 | codec_dai = rtd->codec_dais[i]; |
842 | ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai); | 1018 | if (codec_dai->driver->ops && |
843 | if (ret < 0) | 1019 | codec_dai->driver->ops->bespoke_trigger) { |
844 | return ret; | 1020 | ret = codec_dai->driver->ops->bespoke_trigger(substream, |
1021 | cmd, codec_dai); | ||
1022 | if (ret < 0) | ||
1023 | return ret; | ||
1024 | } | ||
845 | } | 1025 | } |
846 | 1026 | ||
847 | if (platform->driver->bespoke_trigger) { | 1027 | if (platform->driver->bespoke_trigger) { |
@@ -867,10 +1047,12 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | |||
867 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1047 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
868 | struct snd_soc_platform *platform = rtd->platform; | 1048 | struct snd_soc_platform *platform = rtd->platform; |
869 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1049 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
870 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 1050 | struct snd_soc_dai *codec_dai; |
871 | struct snd_pcm_runtime *runtime = substream->runtime; | 1051 | struct snd_pcm_runtime *runtime = substream->runtime; |
872 | snd_pcm_uframes_t offset = 0; | 1052 | snd_pcm_uframes_t offset = 0; |
873 | snd_pcm_sframes_t delay = 0; | 1053 | snd_pcm_sframes_t delay = 0; |
1054 | snd_pcm_sframes_t codec_delay = 0; | ||
1055 | int i; | ||
874 | 1056 | ||
875 | if (platform->driver->ops && platform->driver->ops->pointer) | 1057 | if (platform->driver->ops && platform->driver->ops->pointer) |
876 | offset = platform->driver->ops->pointer(substream); | 1058 | offset = platform->driver->ops->pointer(substream); |
@@ -878,11 +1060,21 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | |||
878 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay) | 1060 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay) |
879 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); | 1061 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); |
880 | 1062 | ||
881 | if (codec_dai->driver->ops && codec_dai->driver->ops->delay) | 1063 | for (i = 0; i < rtd->num_codecs; i++) { |
882 | delay += codec_dai->driver->ops->delay(substream, codec_dai); | 1064 | codec_dai = rtd->codec_dais[i]; |
1065 | if (codec_dai->driver->ops && codec_dai->driver->ops->delay) | ||
1066 | codec_delay = max(codec_delay, | ||
1067 | codec_dai->driver->ops->delay(substream, | ||
1068 | codec_dai)); | ||
1069 | } | ||
1070 | delay += codec_delay; | ||
883 | 1071 | ||
1072 | /* | ||
1073 | * None of the existing platform drivers implement delay(), so | ||
1074 | * for now the codec_dai of first multicodec entry is used | ||
1075 | */ | ||
884 | if (platform->driver->delay) | 1076 | if (platform->driver->delay) |
885 | delay += platform->driver->delay(substream, codec_dai); | 1077 | delay += platform->driver->delay(substream, rtd->codec_dais[0]); |
886 | 1078 | ||
887 | runtime->delay = delay; | 1079 | runtime->delay = delay; |
888 | 1080 | ||
@@ -985,7 +1177,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, | |||
985 | struct snd_soc_dapm_widget *widget, int stream) | 1177 | struct snd_soc_dapm_widget *widget, int stream) |
986 | { | 1178 | { |
987 | struct snd_soc_pcm_runtime *be; | 1179 | struct snd_soc_pcm_runtime *be; |
988 | int i; | 1180 | int i, j; |
989 | 1181 | ||
990 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 1182 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
991 | for (i = 0; i < card->num_links; i++) { | 1183 | for (i = 0; i < card->num_links; i++) { |
@@ -994,9 +1186,14 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, | |||
994 | if (!be->dai_link->no_pcm) | 1186 | if (!be->dai_link->no_pcm) |
995 | continue; | 1187 | continue; |
996 | 1188 | ||
997 | if (be->cpu_dai->playback_widget == widget || | 1189 | if (be->cpu_dai->playback_widget == widget) |
998 | be->codec_dai->playback_widget == widget) | ||
999 | return be; | 1190 | return be; |
1191 | |||
1192 | for (j = 0; j < be->num_codecs; j++) { | ||
1193 | struct snd_soc_dai *dai = be->codec_dais[j]; | ||
1194 | if (dai->playback_widget == widget) | ||
1195 | return be; | ||
1196 | } | ||
1000 | } | 1197 | } |
1001 | } else { | 1198 | } else { |
1002 | 1199 | ||
@@ -1006,9 +1203,14 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, | |||
1006 | if (!be->dai_link->no_pcm) | 1203 | if (!be->dai_link->no_pcm) |
1007 | continue; | 1204 | continue; |
1008 | 1205 | ||
1009 | if (be->cpu_dai->capture_widget == widget || | 1206 | if (be->cpu_dai->capture_widget == widget) |
1010 | be->codec_dai->capture_widget == widget) | ||
1011 | return be; | 1207 | return be; |
1208 | |||
1209 | for (j = 0; j < be->num_codecs; j++) { | ||
1210 | struct snd_soc_dai *dai = be->codec_dais[j]; | ||
1211 | if (dai->capture_widget == widget) | ||
1212 | return be; | ||
1213 | } | ||
1012 | } | 1214 | } |
1013 | } | 1215 | } |
1014 | 1216 | ||
@@ -1071,6 +1273,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, | |||
1071 | 1273 | ||
1072 | /* Destroy any old FE <--> BE connections */ | 1274 | /* Destroy any old FE <--> BE connections */ |
1073 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1275 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { |
1276 | unsigned int i; | ||
1074 | 1277 | ||
1075 | /* is there a valid CPU DAI widget for this BE */ | 1278 | /* is there a valid CPU DAI widget for this BE */ |
1076 | widget = dai_get_widget(dpcm->be->cpu_dai, stream); | 1279 | widget = dai_get_widget(dpcm->be->cpu_dai, stream); |
@@ -1080,11 +1283,14 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, | |||
1080 | continue; | 1283 | continue; |
1081 | 1284 | ||
1082 | /* is there a valid CODEC DAI widget for this BE */ | 1285 | /* is there a valid CODEC DAI widget for this BE */ |
1083 | widget = dai_get_widget(dpcm->be->codec_dai, stream); | 1286 | for (i = 0; i < dpcm->be->num_codecs; i++) { |
1287 | struct snd_soc_dai *dai = dpcm->be->codec_dais[i]; | ||
1288 | widget = dai_get_widget(dai, stream); | ||
1084 | 1289 | ||
1085 | /* prune the BE if it's no longer in our active list */ | 1290 | /* prune the BE if it's no longer in our active list */ |
1086 | if (widget && widget_in_list(list, widget)) | 1291 | if (widget && widget_in_list(list, widget)) |
1087 | continue; | 1292 | continue; |
1293 | } | ||
1088 | 1294 | ||
1089 | dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n", | 1295 | dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n", |
1090 | stream ? "capture" : "playback", | 1296 | stream ? "capture" : "playback", |
@@ -2069,6 +2275,7 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card) | |||
2069 | dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK); | 2275 | dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK); |
2070 | } | 2276 | } |
2071 | 2277 | ||
2278 | dpcm_path_put(&list); | ||
2072 | capture: | 2279 | capture: |
2073 | /* skip if FE doesn't have capture capability */ | 2280 | /* skip if FE doesn't have capture capability */ |
2074 | if (!fe->cpu_dai->driver->capture.channels_min) | 2281 | if (!fe->cpu_dai->driver->capture.channels_min) |
@@ -2113,16 +2320,22 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute) | |||
2113 | list_for_each_entry(dpcm, clients, list_be) { | 2320 | list_for_each_entry(dpcm, clients, list_be) { |
2114 | 2321 | ||
2115 | struct snd_soc_pcm_runtime *be = dpcm->be; | 2322 | struct snd_soc_pcm_runtime *be = dpcm->be; |
2116 | struct snd_soc_dai *dai = be->codec_dai; | 2323 | int i; |
2117 | struct snd_soc_dai_driver *drv = dai->driver; | ||
2118 | 2324 | ||
2119 | if (be->dai_link->ignore_suspend) | 2325 | if (be->dai_link->ignore_suspend) |
2120 | continue; | 2326 | continue; |
2121 | 2327 | ||
2122 | dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name); | 2328 | for (i = 0; i < be->num_codecs; i++) { |
2329 | struct snd_soc_dai *dai = be->codec_dais[i]; | ||
2330 | struct snd_soc_dai_driver *drv = dai->driver; | ||
2331 | |||
2332 | dev_dbg(be->dev, "ASoC: BE digital mute %s\n", | ||
2333 | be->dai_link->name); | ||
2123 | 2334 | ||
2124 | if (drv->ops && drv->ops->digital_mute && dai->playback_active) | 2335 | if (drv->ops && drv->ops->digital_mute && |
2125 | drv->ops->digital_mute(dai, mute); | 2336 | dai->playback_active) |
2337 | drv->ops->digital_mute(dai, mute); | ||
2338 | } | ||
2126 | } | 2339 | } |
2127 | 2340 | ||
2128 | return 0; | 2341 | return 0; |
@@ -2187,22 +2400,27 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) | |||
2187 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | 2400 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) |
2188 | { | 2401 | { |
2189 | struct snd_soc_platform *platform = rtd->platform; | 2402 | struct snd_soc_platform *platform = rtd->platform; |
2190 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 2403 | struct snd_soc_dai *codec_dai; |
2191 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 2404 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
2192 | struct snd_pcm *pcm; | 2405 | struct snd_pcm *pcm; |
2193 | char new_name[64]; | 2406 | char new_name[64]; |
2194 | int ret = 0, playback = 0, capture = 0; | 2407 | int ret = 0, playback = 0, capture = 0; |
2408 | int i; | ||
2195 | 2409 | ||
2196 | if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) { | 2410 | if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) { |
2197 | playback = rtd->dai_link->dpcm_playback; | 2411 | playback = rtd->dai_link->dpcm_playback; |
2198 | capture = rtd->dai_link->dpcm_capture; | 2412 | capture = rtd->dai_link->dpcm_capture; |
2199 | } else { | 2413 | } else { |
2200 | if (codec_dai->driver->playback.channels_min && | 2414 | for (i = 0; i < rtd->num_codecs; i++) { |
2201 | cpu_dai->driver->playback.channels_min) | 2415 | codec_dai = rtd->codec_dais[i]; |
2202 | playback = 1; | 2416 | if (codec_dai->driver->playback.channels_min) |
2203 | if (codec_dai->driver->capture.channels_min && | 2417 | playback = 1; |
2204 | cpu_dai->driver->capture.channels_min) | 2418 | if (codec_dai->driver->capture.channels_min) |
2205 | capture = 1; | 2419 | capture = 1; |
2420 | } | ||
2421 | |||
2422 | capture = capture && cpu_dai->driver->capture.channels_min; | ||
2423 | playback = playback && cpu_dai->driver->playback.channels_min; | ||
2206 | } | 2424 | } |
2207 | 2425 | ||
2208 | if (rtd->dai_link->playback_only) { | 2426 | if (rtd->dai_link->playback_only) { |
@@ -2228,7 +2446,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2228 | rtd->dai_link->stream_name); | 2446 | rtd->dai_link->stream_name); |
2229 | else | 2447 | else |
2230 | snprintf(new_name, sizeof(new_name), "%s %s-%d", | 2448 | snprintf(new_name, sizeof(new_name), "%s %s-%d", |
2231 | rtd->dai_link->stream_name, codec_dai->name, num); | 2449 | rtd->dai_link->stream_name, |
2450 | (rtd->num_codecs > 1) ? | ||
2451 | "multicodec" : rtd->codec_dai->name, num); | ||
2232 | 2452 | ||
2233 | ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback, | 2453 | ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback, |
2234 | capture, &pcm); | 2454 | capture, &pcm); |
@@ -2301,8 +2521,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2301 | 2521 | ||
2302 | pcm->private_free = platform->driver->pcm_free; | 2522 | pcm->private_free = platform->driver->pcm_free; |
2303 | out: | 2523 | out: |
2304 | dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", codec_dai->name, | 2524 | dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", |
2305 | cpu_dai->name); | 2525 | (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, |
2526 | cpu_dai->name); | ||
2306 | return ret; | 2527 | return ret; |
2307 | } | 2528 | } |
2308 | 2529 | ||
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 02734bd4f09b..a83aff09dce2 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c | |||
@@ -41,8 +41,7 @@ static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream, | |||
41 | { | 41 | { |
42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
44 | struct snd_soc_codec *codec = codec_dai->codec; | 44 | struct snd_soc_card *card = rtd->card; |
45 | struct snd_soc_card *card = codec->card; | ||
46 | struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card); | 45 | struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card); |
47 | int srate, mclk; | 46 | int srate, mclk; |
48 | int err; | 47 | int err; |
@@ -105,7 +104,7 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) | |||
105 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 104 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
106 | struct snd_soc_codec *codec = codec_dai->codec; | 105 | struct snd_soc_codec *codec = codec_dai->codec; |
107 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 106 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
108 | struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card); | 107 | struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(rtd->card); |
109 | 108 | ||
110 | snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, | 109 | snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, |
111 | &tegra_alc5632_hs_jack); | 110 | &tegra_alc5632_hs_jack); |
diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c index ce73e1f62c4b..b86cd9936ef1 100644 --- a/sound/soc/tegra/tegra_max98090.c +++ b/sound/soc/tegra/tegra_max98090.c | |||
@@ -49,8 +49,7 @@ static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream, | |||
49 | { | 49 | { |
50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
51 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 51 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
52 | struct snd_soc_codec *codec = codec_dai->codec; | 52 | struct snd_soc_card *card = rtd->card; |
53 | struct snd_soc_card *card = codec->card; | ||
54 | struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card); | 53 | struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card); |
55 | int srate, mclk; | 54 | int srate, mclk; |
56 | int err; | 55 | int err; |
@@ -127,7 +126,7 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd) | |||
127 | { | 126 | { |
128 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 127 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
129 | struct snd_soc_codec *codec = codec_dai->codec; | 128 | struct snd_soc_codec *codec = codec_dai->codec; |
130 | struct tegra_max98090 *machine = snd_soc_card_get_drvdata(codec->card); | 129 | struct tegra_max98090 *machine = snd_soc_card_get_drvdata(rtd->card); |
131 | 130 | ||
132 | if (gpio_is_valid(machine->gpio_hp_det)) { | 131 | if (gpio_is_valid(machine->gpio_hp_det)) { |
133 | snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, | 132 | snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, |
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index 4feb16a99e02..a6898831fb9f 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c | |||
@@ -51,8 +51,7 @@ static int tegra_rt5640_asoc_hw_params(struct snd_pcm_substream *substream, | |||
51 | { | 51 | { |
52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
53 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 53 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
54 | struct snd_soc_codec *codec = codec_dai->codec; | 54 | struct snd_soc_card *card = rtd->card; |
55 | struct snd_soc_card *card = codec->card; | ||
56 | struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); | 55 | struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); |
57 | int srate, mclk; | 56 | int srate, mclk; |
58 | int err; | 57 | int err; |
@@ -110,7 +109,7 @@ static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd) | |||
110 | { | 109 | { |
111 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 110 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
112 | struct snd_soc_codec *codec = codec_dai->codec; | 111 | struct snd_soc_codec *codec = codec_dai->codec; |
113 | struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(codec->card); | 112 | struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(rtd->card); |
114 | 113 | ||
115 | snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, | 114 | snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, |
116 | &tegra_rt5640_hp_jack); | 115 | &tegra_rt5640_hp_jack); |
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 8e774d1a243c..769e28f6642e 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c | |||
@@ -55,8 +55,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream, | |||
55 | { | 55 | { |
56 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 56 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
57 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 57 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
58 | struct snd_soc_codec *codec = codec_dai->codec; | 58 | struct snd_soc_card *card = rtd->card; |
59 | struct snd_soc_card *card = codec->card; | ||
60 | struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); | 59 | struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); |
61 | int srate, mclk; | 60 | int srate, mclk; |
62 | int err; | 61 | int err; |
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 0939661df60b..86e05e938585 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c | |||
@@ -60,8 +60,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, | |||
60 | { | 60 | { |
61 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 61 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
62 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 62 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
63 | struct snd_soc_codec *codec = codec_dai->codec; | 63 | struct snd_soc_card *card = rtd->card; |
64 | struct snd_soc_card *card = codec->card; | ||
65 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | 64 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); |
66 | int srate, mclk; | 65 | int srate, mclk; |
67 | int err; | 66 | int err; |
@@ -173,7 +172,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) | |||
173 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 172 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
174 | struct snd_soc_codec *codec = codec_dai->codec; | 173 | struct snd_soc_codec *codec = codec_dai->codec; |
175 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 174 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
176 | struct snd_soc_card *card = codec->card; | 175 | struct snd_soc_card *card = rtd->card; |
177 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | 176 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); |
178 | 177 | ||
179 | if (gpio_is_valid(machine->gpio_hp_det)) { | 178 | if (gpio_is_valid(machine->gpio_hp_det)) { |
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 734bfcd21148..589d2d9b553a 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c | |||
@@ -50,8 +50,7 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, | |||
50 | { | 50 | { |
51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
52 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 52 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
53 | struct snd_soc_codec *codec = codec_dai->codec; | 53 | struct snd_soc_card *card = rtd->card; |
54 | struct snd_soc_card *card = codec->card; | ||
55 | struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); | 54 | struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); |
56 | int srate, mclk; | 55 | int srate, mclk; |
57 | int err; | 56 | int err; |