summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2016-05-27 11:16:53 -0400
committerTakashi Iwai <tiwai@suse.de>2016-05-27 11:16:53 -0400
commiteb4606e64a7d548f5d60a9583baa8104890b2c6e (patch)
tree2dc8e587fc79c207dab2fb74830963cc84dcf801 /sound
parent86c72d1ce91d804e4fa8d90b316a89597dd220f1 (diff)
parentbf65921380cd50b87618df550398e06581f4a361 (diff)
Merge tag 'asoc-v4.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v4.7 part 2 Really sorry about this late pull request. It looks like at the time I sent my pull request for v4.7 there was some conflict or other issue which caused my script to stop merging the ASoC branches at some point after the HDMI changes. It's all specific driver updates, including: - New drivers for MAX98371 and TAS5720. - SPI support for TLV320AIC32x4. - TDM support for STI Uniperf IPs. This code should all have been in -next prior to the merge window apart from some fixes, it dropped out on the 18th.
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/Kconfig38
-rw-r--r--sound/soc/codecs/Makefile11
-rw-r--r--sound/soc/codecs/ak4642.c3
-rw-r--r--sound/soc/codecs/max98371.c441
-rw-r--r--sound/soc/codecs/max98371.h67
-rw-r--r--sound/soc/codecs/rt298.c51
-rw-r--r--sound/soc/codecs/rt298.h2
-rw-r--r--sound/soc/codecs/rt5677.c24
-rw-r--r--sound/soc/codecs/tas571x.c141
-rw-r--r--sound/soc/codecs/tas571x.h22
-rw-r--r--sound/soc/codecs/tas5720.c620
-rw-r--r--sound/soc/codecs/tas5720.h90
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c10
-rw-r--r--sound/soc/codecs/tlv320aic32x4-i2c.c74
-rw-r--r--sound/soc/codecs/tlv320aic32x4-spi.c76
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c279
-rw-r--r--sound/soc/codecs/tlv320aic32x4.h7
-rw-r--r--sound/soc/codecs/twl6040.c16
-rw-r--r--sound/soc/codecs/wm8962.c9
-rw-r--r--sound/soc/codecs/wm8962.h6
-rw-r--r--sound/soc/generic/simple-card.c1
-rw-r--r--sound/soc/kirkwood/Kconfig1
-rw-r--r--sound/soc/mediatek/Kconfig1
-rw-r--r--sound/soc/mediatek/mt8173-rt5650-rt5676.c27
-rw-r--r--sound/soc/mediatek/mt8173-rt5650.c50
-rw-r--r--sound/soc/mediatek/mtk-afe-pcm.c2
-rw-r--r--sound/soc/omap/mcbsp.c8
-rw-r--r--sound/soc/omap/omap-pcm.c2
-rw-r--r--sound/soc/pxa/brownstone.c1
-rw-r--r--sound/soc/pxa/mioa701_wm9713.c1
-rw-r--r--sound/soc/pxa/mmp-pcm.c1
-rw-r--r--sound/soc/pxa/mmp-sspa.c1
-rw-r--r--sound/soc/pxa/palm27x.c1
-rw-r--r--sound/soc/pxa/pxa-ssp.c1
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c1
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c1
-rw-r--r--sound/soc/qcom/lpass-platform.c8
-rw-r--r--sound/soc/sh/rcar/adg.c8
-rw-r--r--sound/soc/sh/rcar/dma.c12
-rw-r--r--sound/soc/sh/rcar/rsnd.h13
-rw-r--r--sound/soc/sh/rcar/src.c4
-rw-r--r--sound/soc/soc-topology.c48
-rw-r--r--sound/soc/sti/sti_uniperif.c144
-rw-r--r--sound/soc/sti/uniperif.h220
-rw-r--r--sound/soc/sti/uniperif_player.c182
-rw-r--r--sound/soc/sti/uniperif_reader.c229
46 files changed, 2638 insertions, 317 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b3afae990e39..4d82a58ff6b0 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -43,6 +43,7 @@ config SND_SOC_ALL_CODECS
43 select SND_SOC_AK5386 43 select SND_SOC_AK5386
44 select SND_SOC_ALC5623 if I2C 44 select SND_SOC_ALC5623 if I2C
45 select SND_SOC_ALC5632 if I2C 45 select SND_SOC_ALC5632 if I2C
46 select SND_SOC_BT_SCO
46 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC 47 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
47 select SND_SOC_CS35L32 if I2C 48 select SND_SOC_CS35L32 if I2C
48 select SND_SOC_CS42L51_I2C if I2C 49 select SND_SOC_CS42L51_I2C if I2C
@@ -64,7 +65,6 @@ config SND_SOC_ALL_CODECS
64 select SND_SOC_DA732X if I2C 65 select SND_SOC_DA732X if I2C
65 select SND_SOC_DA9055 if I2C 66 select SND_SOC_DA9055 if I2C
66 select SND_SOC_DMIC 67 select SND_SOC_DMIC
67 select SND_SOC_BT_SCO
68 select SND_SOC_ES8328_SPI if SPI_MASTER 68 select SND_SOC_ES8328_SPI if SPI_MASTER
69 select SND_SOC_ES8328_I2C if I2C 69 select SND_SOC_ES8328_I2C if I2C
70 select SND_SOC_GTM601 70 select SND_SOC_GTM601
@@ -79,6 +79,7 @@ config SND_SOC_ALL_CODECS
79 select SND_SOC_MAX98090 if I2C 79 select SND_SOC_MAX98090 if I2C
80 select SND_SOC_MAX98095 if I2C 80 select SND_SOC_MAX98095 if I2C
81 select SND_SOC_MAX98357A if GPIOLIB 81 select SND_SOC_MAX98357A if GPIOLIB
82 select SND_SOC_MAX98371 if I2C
82 select SND_SOC_MAX9867 if I2C 83 select SND_SOC_MAX9867 if I2C
83 select SND_SOC_MAX98925 if I2C 84 select SND_SOC_MAX98925 if I2C
84 select SND_SOC_MAX98926 if I2C 85 select SND_SOC_MAX98926 if I2C
@@ -126,12 +127,14 @@ config SND_SOC_ALL_CODECS
126 select SND_SOC_TAS2552 if I2C 127 select SND_SOC_TAS2552 if I2C
127 select SND_SOC_TAS5086 if I2C 128 select SND_SOC_TAS5086 if I2C
128 select SND_SOC_TAS571X if I2C 129 select SND_SOC_TAS571X if I2C
130 select SND_SOC_TAS5720 if I2C
129 select SND_SOC_TFA9879 if I2C 131 select SND_SOC_TFA9879 if I2C
130 select SND_SOC_TLV320AIC23_I2C if I2C 132 select SND_SOC_TLV320AIC23_I2C if I2C
131 select SND_SOC_TLV320AIC23_SPI if SPI_MASTER 133 select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
132 select SND_SOC_TLV320AIC26 if SPI_MASTER 134 select SND_SOC_TLV320AIC26 if SPI_MASTER
133 select SND_SOC_TLV320AIC31XX if I2C 135 select SND_SOC_TLV320AIC31XX if I2C
134 select SND_SOC_TLV320AIC32X4 if I2C 136 select SND_SOC_TLV320AIC32X4_I2C if I2C
137 select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER
135 select SND_SOC_TLV320AIC3X if I2C 138 select SND_SOC_TLV320AIC3X if I2C
136 select SND_SOC_TPA6130A2 if I2C 139 select SND_SOC_TPA6130A2 if I2C
137 select SND_SOC_TLV320DAC33 if I2C 140 select SND_SOC_TLV320DAC33 if I2C
@@ -367,6 +370,9 @@ config SND_SOC_ALC5623
367config SND_SOC_ALC5632 370config SND_SOC_ALC5632
368 tristate 371 tristate
369 372
373config SND_SOC_BT_SCO
374 tristate
375
370config SND_SOC_CQ0093VC 376config SND_SOC_CQ0093VC
371 tristate 377 tristate
372 378
@@ -473,9 +479,6 @@ config SND_SOC_DA732X
473config SND_SOC_DA9055 479config SND_SOC_DA9055
474 tristate 480 tristate
475 481
476config SND_SOC_BT_SCO
477 tristate
478
479config SND_SOC_DMIC 482config SND_SOC_DMIC
480 tristate 483 tristate
481 484
@@ -529,6 +532,9 @@ config SND_SOC_MAX98095
529config SND_SOC_MAX98357A 532config SND_SOC_MAX98357A
530 tristate 533 tristate
531 534
535config SND_SOC_MAX98371
536 tristate
537
532config SND_SOC_MAX9867 538config SND_SOC_MAX9867
533 tristate 539 tristate
534 540
@@ -748,9 +754,16 @@ config SND_SOC_TAS5086
748 depends on I2C 754 depends on I2C
749 755
750config SND_SOC_TAS571X 756config SND_SOC_TAS571X
751 tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers" 757 tristate "Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 power amplifiers"
752 depends on I2C 758 depends on I2C
753 759
760config SND_SOC_TAS5720
761 tristate "Texas Instruments TAS5720 Mono Audio amplifier"
762 depends on I2C
763 help
764 Enable support for Texas Instruments TAS5720L/M high-efficiency mono
765 Class-D audio power amplifiers.
766
754config SND_SOC_TFA9879 767config SND_SOC_TFA9879
755 tristate "NXP Semiconductors TFA9879 amplifier" 768 tristate "NXP Semiconductors TFA9879 amplifier"
756 depends on I2C 769 depends on I2C
@@ -780,6 +793,16 @@ config SND_SOC_TLV320AIC31XX
780config SND_SOC_TLV320AIC32X4 793config SND_SOC_TLV320AIC32X4
781 tristate 794 tristate
782 795
796config SND_SOC_TLV320AIC32X4_I2C
797 tristate
798 depends on I2C
799 select SND_SOC_TLV320AIC32X4
800
801config SND_SOC_TLV320AIC32X4_SPI
802 tristate
803 depends on SPI_MASTER
804 select SND_SOC_TLV320AIC32X4
805
783config SND_SOC_TLV320AIC3X 806config SND_SOC_TLV320AIC3X
784 tristate "Texas Instruments TLV320AIC3x CODECs" 807 tristate "Texas Instruments TLV320AIC3x CODECs"
785 depends on I2C 808 depends on I2C
@@ -920,7 +943,8 @@ config SND_SOC_WM8955
920 tristate 943 tristate
921 944
922config SND_SOC_WM8960 945config SND_SOC_WM8960
923 tristate 946 tristate "Wolfson Microelectronics WM8960 CODEC"
947 depends on I2C
924 948
925config SND_SOC_WM8961 949config SND_SOC_WM8961
926 tristate 950 tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index b7b99416537f..0f548fd34ca3 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -32,6 +32,7 @@ snd-soc-ak4642-objs := ak4642.o
32snd-soc-ak4671-objs := ak4671.o 32snd-soc-ak4671-objs := ak4671.o
33snd-soc-ak5386-objs := ak5386.o 33snd-soc-ak5386-objs := ak5386.o
34snd-soc-arizona-objs := arizona.o 34snd-soc-arizona-objs := arizona.o
35snd-soc-bt-sco-objs := bt-sco.o
35snd-soc-cq93vc-objs := cq93vc.o 36snd-soc-cq93vc-objs := cq93vc.o
36snd-soc-cs35l32-objs := cs35l32.o 37snd-soc-cs35l32-objs := cs35l32.o
37snd-soc-cs42l51-objs := cs42l51.o 38snd-soc-cs42l51-objs := cs42l51.o
@@ -55,7 +56,6 @@ snd-soc-da7218-objs := da7218.o
55snd-soc-da7219-objs := da7219.o da7219-aad.o 56snd-soc-da7219-objs := da7219.o da7219-aad.o
56snd-soc-da732x-objs := da732x.o 57snd-soc-da732x-objs := da732x.o
57snd-soc-da9055-objs := da9055.o 58snd-soc-da9055-objs := da9055.o
58snd-soc-bt-sco-objs := bt-sco.o
59snd-soc-dmic-objs := dmic.o 59snd-soc-dmic-objs := dmic.o
60snd-soc-es8328-objs := es8328.o 60snd-soc-es8328-objs := es8328.o
61snd-soc-es8328-i2c-objs := es8328-i2c.o 61snd-soc-es8328-i2c-objs := es8328-i2c.o
@@ -74,6 +74,7 @@ snd-soc-max98088-objs := max98088.o
74snd-soc-max98090-objs := max98090.o 74snd-soc-max98090-objs := max98090.o
75snd-soc-max98095-objs := max98095.o 75snd-soc-max98095-objs := max98095.o
76snd-soc-max98357a-objs := max98357a.o 76snd-soc-max98357a-objs := max98357a.o
77snd-soc-max98371-objs := max98371.o
77snd-soc-max9867-objs := max9867.o 78snd-soc-max9867-objs := max9867.o
78snd-soc-max98925-objs := max98925.o 79snd-soc-max98925-objs := max98925.o
79snd-soc-max98926-objs := max98926.o 80snd-soc-max98926-objs := max98926.o
@@ -131,6 +132,7 @@ snd-soc-stac9766-objs := stac9766.o
131snd-soc-sti-sas-objs := sti-sas.o 132snd-soc-sti-sas-objs := sti-sas.o
132snd-soc-tas5086-objs := tas5086.o 133snd-soc-tas5086-objs := tas5086.o
133snd-soc-tas571x-objs := tas571x.o 134snd-soc-tas571x-objs := tas571x.o
135snd-soc-tas5720-objs := tas5720.o
134snd-soc-tfa9879-objs := tfa9879.o 136snd-soc-tfa9879-objs := tfa9879.o
135snd-soc-tlv320aic23-objs := tlv320aic23.o 137snd-soc-tlv320aic23-objs := tlv320aic23.o
136snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o 138snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
@@ -138,6 +140,8 @@ snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
138snd-soc-tlv320aic26-objs := tlv320aic26.o 140snd-soc-tlv320aic26-objs := tlv320aic26.o
139snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o 141snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o
140snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o 142snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
143snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o
144snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o
141snd-soc-tlv320aic3x-objs := tlv320aic3x.o 145snd-soc-tlv320aic3x-objs := tlv320aic3x.o
142snd-soc-tlv320dac33-objs := tlv320dac33.o 146snd-soc-tlv320dac33-objs := tlv320dac33.o
143snd-soc-ts3a227e-objs := ts3a227e.o 147snd-soc-ts3a227e-objs := ts3a227e.o
@@ -243,6 +247,7 @@ obj-$(CONFIG_SND_SOC_AK5386) += snd-soc-ak5386.o
243obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o 247obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
244obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o 248obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
245obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o 249obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
250obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o
246obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o 251obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
247obj-$(CONFIG_SND_SOC_CS35L32) += snd-soc-cs35l32.o 252obj-$(CONFIG_SND_SOC_CS35L32) += snd-soc-cs35l32.o
248obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o 253obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
@@ -266,7 +271,6 @@ obj-$(CONFIG_SND_SOC_DA7218) += snd-soc-da7218.o
266obj-$(CONFIG_SND_SOC_DA7219) += snd-soc-da7219.o 271obj-$(CONFIG_SND_SOC_DA7219) += snd-soc-da7219.o
267obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o 272obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o
268obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o 273obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o
269obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o
270obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o 274obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
271obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o 275obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
272obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o 276obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
@@ -339,6 +343,7 @@ obj-$(CONFIG_SND_SOC_STI_SAS) += snd-soc-sti-sas.o
339obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o 343obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o
340obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o 344obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
341obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o 345obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o
346obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o
342obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o 347obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
343obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 348obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
344obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o 349obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
@@ -346,6 +351,8 @@ obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o
346obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 351obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
347obj-$(CONFIG_SND_SOC_TLV320AIC31XX) += snd-soc-tlv320aic31xx.o 352obj-$(CONFIG_SND_SOC_TLV320AIC31XX) += snd-soc-tlv320aic31xx.o
348obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o 353obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o
354obj-$(CONFIG_SND_SOC_TLV320AIC32X4_I2C) += snd-soc-tlv320aic32x4-i2c.o
355obj-$(CONFIG_SND_SOC_TLV320AIC32X4_SPI) += snd-soc-tlv320aic32x4-spi.o
349obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 356obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
350obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o 357obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
351obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o 358obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 1ee8506c06c7..4d8b9e49e8d6 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -560,6 +560,7 @@ static const struct regmap_config ak4642_regmap = {
560 .max_register = FIL1_3, 560 .max_register = FIL1_3,
561 .reg_defaults = ak4642_reg, 561 .reg_defaults = ak4642_reg,
562 .num_reg_defaults = NUM_AK4642_REG_DEFAULTS, 562 .num_reg_defaults = NUM_AK4642_REG_DEFAULTS,
563 .cache_type = REGCACHE_RBTREE,
563}; 564};
564 565
565static const struct regmap_config ak4643_regmap = { 566static const struct regmap_config ak4643_regmap = {
@@ -568,6 +569,7 @@ static const struct regmap_config ak4643_regmap = {
568 .max_register = SPK_MS, 569 .max_register = SPK_MS,
569 .reg_defaults = ak4643_reg, 570 .reg_defaults = ak4643_reg,
570 .num_reg_defaults = ARRAY_SIZE(ak4643_reg), 571 .num_reg_defaults = ARRAY_SIZE(ak4643_reg),
572 .cache_type = REGCACHE_RBTREE,
571}; 573};
572 574
573static const struct regmap_config ak4648_regmap = { 575static const struct regmap_config ak4648_regmap = {
@@ -576,6 +578,7 @@ static const struct regmap_config ak4648_regmap = {
576 .max_register = EQ_FBEQE, 578 .max_register = EQ_FBEQE,
577 .reg_defaults = ak4648_reg, 579 .reg_defaults = ak4648_reg,
578 .num_reg_defaults = ARRAY_SIZE(ak4648_reg), 580 .num_reg_defaults = ARRAY_SIZE(ak4648_reg),
581 .cache_type = REGCACHE_RBTREE,
579}; 582};
580 583
581static const struct ak4642_drvdata ak4642_drvdata = { 584static const struct ak4642_drvdata ak4642_drvdata = {
diff --git a/sound/soc/codecs/max98371.c b/sound/soc/codecs/max98371.c
new file mode 100644
index 000000000000..cf0a39bb631a
--- /dev/null
+++ b/sound/soc/codecs/max98371.c
@@ -0,0 +1,441 @@
1/*
2 * max98371.c -- ALSA SoC Stereo MAX98371 driver
3 *
4 * Copyright 2015-16 Maxim Integrated Products
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/i2c.h>
12#include <linux/module.h>
13#include <linux/regmap.h>
14#include <linux/slab.h>
15#include <sound/pcm.h>
16#include <sound/pcm_params.h>
17#include <sound/soc.h>
18#include <sound/tlv.h>
19#include "max98371.h"
20
21static const char *const monomix_text[] = {
22 "Left", "Right", "LeftRightDiv2",
23};
24
25static const char *const hpf_cutoff_txt[] = {
26 "Disable", "DC Block", "50Hz",
27 "100Hz", "200Hz", "400Hz", "800Hz",
28};
29
30static SOC_ENUM_SINGLE_DECL(max98371_monomix, MAX98371_MONOMIX_CFG, 0,
31 monomix_text);
32
33static SOC_ENUM_SINGLE_DECL(max98371_hpf_cutoff, MAX98371_HPF, 0,
34 hpf_cutoff_txt);
35
36static const DECLARE_TLV_DB_RANGE(max98371_dht_min_gain,
37 0, 1, TLV_DB_SCALE_ITEM(537, 66, 0),
38 2, 3, TLV_DB_SCALE_ITEM(677, 82, 0),
39 4, 5, TLV_DB_SCALE_ITEM(852, 104, 0),
40 6, 7, TLV_DB_SCALE_ITEM(1072, 131, 0),
41 8, 9, TLV_DB_SCALE_ITEM(1350, 165, 0),
42 10, 11, TLV_DB_SCALE_ITEM(1699, 101, 0),
43);
44
45static const DECLARE_TLV_DB_RANGE(max98371_dht_max_gain,
46 0, 1, TLV_DB_SCALE_ITEM(537, 66, 0),
47 2, 3, TLV_DB_SCALE_ITEM(677, 82, 0),
48 4, 5, TLV_DB_SCALE_ITEM(852, 104, 0),
49 6, 7, TLV_DB_SCALE_ITEM(1072, 131, 0),
50 8, 9, TLV_DB_SCALE_ITEM(1350, 165, 0),
51 10, 11, TLV_DB_SCALE_ITEM(1699, 208, 0),
52);
53
54static const DECLARE_TLV_DB_RANGE(max98371_dht_rot_gain,
55 0, 1, TLV_DB_SCALE_ITEM(-50, -50, 0),
56 2, 6, TLV_DB_SCALE_ITEM(-100, -100, 0),
57 7, 8, TLV_DB_SCALE_ITEM(-800, -200, 0),
58 9, 11, TLV_DB_SCALE_ITEM(-1200, -300, 0),
59 12, 13, TLV_DB_SCALE_ITEM(-2000, -200, 0),
60 14, 15, TLV_DB_SCALE_ITEM(-2500, -500, 0),
61);
62
63static const struct reg_default max98371_reg[] = {
64 { 0x01, 0x00 },
65 { 0x02, 0x00 },
66 { 0x03, 0x00 },
67 { 0x04, 0x00 },
68 { 0x05, 0x00 },
69 { 0x06, 0x00 },
70 { 0x07, 0x00 },
71 { 0x08, 0x00 },
72 { 0x09, 0x00 },
73 { 0x0A, 0x00 },
74 { 0x10, 0x06 },
75 { 0x11, 0x08 },
76 { 0x14, 0x80 },
77 { 0x15, 0x00 },
78 { 0x16, 0x00 },
79 { 0x18, 0x00 },
80 { 0x19, 0x00 },
81 { 0x1C, 0x00 },
82 { 0x1D, 0x00 },
83 { 0x1E, 0x00 },
84 { 0x1F, 0x00 },
85 { 0x20, 0x00 },
86 { 0x21, 0x00 },
87 { 0x22, 0x00 },
88 { 0x23, 0x00 },
89 { 0x24, 0x00 },
90 { 0x25, 0x00 },
91 { 0x26, 0x00 },
92 { 0x27, 0x00 },
93 { 0x28, 0x00 },
94 { 0x29, 0x00 },
95 { 0x2A, 0x00 },
96 { 0x2B, 0x00 },
97 { 0x2C, 0x00 },
98 { 0x2D, 0x00 },
99 { 0x2E, 0x0B },
100 { 0x31, 0x00 },
101 { 0x32, 0x18 },
102 { 0x33, 0x00 },
103 { 0x34, 0x00 },
104 { 0x36, 0x00 },
105 { 0x37, 0x00 },
106 { 0x38, 0x00 },
107 { 0x39, 0x00 },
108 { 0x3A, 0x00 },
109 { 0x3B, 0x00 },
110 { 0x3C, 0x00 },
111 { 0x3D, 0x00 },
112 { 0x3E, 0x00 },
113 { 0x3F, 0x00 },
114 { 0x40, 0x00 },
115 { 0x41, 0x00 },
116 { 0x42, 0x00 },
117 { 0x43, 0x00 },
118 { 0x4A, 0x00 },
119 { 0x4B, 0x00 },
120 { 0x4C, 0x00 },
121 { 0x4D, 0x00 },
122 { 0x4E, 0x00 },
123 { 0x50, 0x00 },
124 { 0x51, 0x00 },
125 { 0x55, 0x00 },
126 { 0x58, 0x00 },
127 { 0x59, 0x00 },
128 { 0x5C, 0x00 },
129 { 0xFF, 0x43 },
130};
131
132static bool max98371_volatile_register(struct device *dev, unsigned int reg)
133{
134 switch (reg) {
135 case MAX98371_IRQ_CLEAR1:
136 case MAX98371_IRQ_CLEAR2:
137 case MAX98371_IRQ_CLEAR3:
138 case MAX98371_VERSION:
139 return true;
140 default:
141 return false;
142 }
143}
144
145static bool max98371_readable_register(struct device *dev, unsigned int reg)
146{
147 switch (reg) {
148 case MAX98371_SOFT_RESET:
149 return false;
150 default:
151 return true;
152 }
153};
154
155static const DECLARE_TLV_DB_RANGE(max98371_gain_tlv,
156 0, 7, TLV_DB_SCALE_ITEM(0, 50, 0),
157 8, 10, TLV_DB_SCALE_ITEM(400, 100, 0)
158);
159
160static const DECLARE_TLV_DB_RANGE(max98371_noload_gain_tlv,
161 0, 11, TLV_DB_SCALE_ITEM(950, 100, 0),
162);
163
164static const DECLARE_TLV_DB_SCALE(digital_tlv, -6300, 50, 1);
165
166static const struct snd_kcontrol_new max98371_snd_controls[] = {
167 SOC_SINGLE_TLV("Speaker Volume", MAX98371_GAIN,
168 MAX98371_GAIN_SHIFT, (1<<MAX98371_GAIN_WIDTH)-1, 0,
169 max98371_gain_tlv),
170 SOC_SINGLE_TLV("Digital Volume", MAX98371_DIGITAL_GAIN, 0,
171 (1<<MAX98371_DIGITAL_GAIN_WIDTH)-1, 1, digital_tlv),
172 SOC_SINGLE_TLV("Speaker DHT Max Volume", MAX98371_GAIN,
173 0, (1<<MAX98371_DHT_MAX_WIDTH)-1, 0,
174 max98371_dht_max_gain),
175 SOC_SINGLE_TLV("Speaker DHT Min Volume", MAX98371_DHT_GAIN,
176 0, (1<<MAX98371_DHT_GAIN_WIDTH)-1, 0,
177 max98371_dht_min_gain),
178 SOC_SINGLE_TLV("Speaker DHT Rotation Volume", MAX98371_DHT_GAIN,
179 0, (1<<MAX98371_DHT_ROT_WIDTH)-1, 0,
180 max98371_dht_rot_gain),
181 SOC_SINGLE("DHT Attack Step", MAX98371_DHT, MAX98371_DHT_STEP, 3, 0),
182 SOC_SINGLE("DHT Attack Rate", MAX98371_DHT, 0, 7, 0),
183 SOC_ENUM("Monomix Select", max98371_monomix),
184 SOC_ENUM("HPF Cutoff", max98371_hpf_cutoff),
185};
186
187static int max98371_dai_set_fmt(struct snd_soc_dai *codec_dai,
188 unsigned int fmt)
189{
190 struct snd_soc_codec *codec = codec_dai->codec;
191 struct max98371_priv *max98371 = snd_soc_codec_get_drvdata(codec);
192 unsigned int val = 0;
193
194 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
195 case SND_SOC_DAIFMT_CBS_CFS:
196 break;
197 default:
198 dev_err(codec->dev, "DAI clock mode unsupported");
199 return -EINVAL;
200 }
201
202 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
203 case SND_SOC_DAIFMT_I2S:
204 val |= 0;
205 break;
206 case SND_SOC_DAIFMT_RIGHT_J:
207 val |= MAX98371_DAI_RIGHT;
208 break;
209 case SND_SOC_DAIFMT_LEFT_J:
210 val |= MAX98371_DAI_LEFT;
211 break;
212 default:
213 dev_err(codec->dev, "DAI wrong mode unsupported");
214 return -EINVAL;
215 }
216 regmap_update_bits(max98371->regmap, MAX98371_FMT,
217 MAX98371_FMT_MODE_MASK, val);
218 return 0;
219}
220
221static int max98371_dai_hw_params(struct snd_pcm_substream *substream,
222 struct snd_pcm_hw_params *params,
223 struct snd_soc_dai *dai)
224{
225 struct snd_soc_codec *codec = dai->codec;
226 struct max98371_priv *max98371 = snd_soc_codec_get_drvdata(codec);
227 int blr_clk_ratio, ch_size, channels = params_channels(params);
228 int rate = params_rate(params);
229
230 switch (params_format(params)) {
231 case SNDRV_PCM_FORMAT_S8:
232 regmap_update_bits(max98371->regmap, MAX98371_FMT,
233 MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_16);
234 ch_size = 8;
235 break;
236 case SNDRV_PCM_FORMAT_S16_LE:
237 regmap_update_bits(max98371->regmap, MAX98371_FMT,
238 MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_16);
239 ch_size = 16;
240 break;
241 case SNDRV_PCM_FORMAT_S24_LE:
242 regmap_update_bits(max98371->regmap, MAX98371_FMT,
243 MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_32);
244 ch_size = 24;
245 break;
246 case SNDRV_PCM_FORMAT_S32_LE:
247 regmap_update_bits(max98371->regmap, MAX98371_FMT,
248 MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_32);
249 ch_size = 32;
250 break;
251 default:
252 return -EINVAL;
253 }
254
255 /* BCLK/LRCLK ratio calculation */
256 blr_clk_ratio = channels * ch_size;
257 switch (blr_clk_ratio) {
258 case 32:
259 regmap_update_bits(max98371->regmap,
260 MAX98371_DAI_CLK,
261 MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_32);
262 break;
263 case 48:
264 regmap_update_bits(max98371->regmap,
265 MAX98371_DAI_CLK,
266 MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_48);
267 break;
268 case 64:
269 regmap_update_bits(max98371->regmap,
270 MAX98371_DAI_CLK,
271 MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_64);
272 break;
273 default:
274 return -EINVAL;
275 }
276
277 switch (rate) {
278 case 32000:
279 regmap_update_bits(max98371->regmap,
280 MAX98371_SPK_SR,
281 MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_32);
282 break;
283 case 44100:
284 regmap_update_bits(max98371->regmap,
285 MAX98371_SPK_SR,
286 MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_44);
287 break;
288 case 48000:
289 regmap_update_bits(max98371->regmap,
290 MAX98371_SPK_SR,
291 MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_48);
292 break;
293 case 88200:
294 regmap_update_bits(max98371->regmap,
295 MAX98371_SPK_SR,
296 MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_88);
297 break;
298 case 96000:
299 regmap_update_bits(max98371->regmap,
300 MAX98371_SPK_SR,
301 MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_96);
302 break;
303 default:
304 return -EINVAL;
305 }
306
307 /* enabling both the RX channels*/
308 regmap_update_bits(max98371->regmap, MAX98371_MONOMIX_SRC,
309 MAX98371_MONOMIX_SRC_MASK, MONOMIX_RX_0_1);
310 regmap_update_bits(max98371->regmap, MAX98371_DAI_CHANNEL,
311 MAX98371_CHANNEL_MASK, MAX98371_CHANNEL_MASK);
312 return 0;
313}
314
315static const struct snd_soc_dapm_widget max98371_dapm_widgets[] = {
316 SND_SOC_DAPM_DAC("DAC", NULL, MAX98371_SPK_ENABLE, 0, 0),
317 SND_SOC_DAPM_SUPPLY("Global Enable", MAX98371_GLOBAL_ENABLE,
318 0, 0, NULL, 0),
319 SND_SOC_DAPM_OUTPUT("SPK_OUT"),
320};
321
322static const struct snd_soc_dapm_route max98371_audio_map[] = {
323 {"DAC", NULL, "HiFi Playback"},
324 {"SPK_OUT", NULL, "DAC"},
325 {"SPK_OUT", NULL, "Global Enable"},
326};
327
328#define MAX98371_RATES SNDRV_PCM_RATE_8000_48000
329#define MAX98371_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
330 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE)
331
332static const struct snd_soc_dai_ops max98371_dai_ops = {
333 .set_fmt = max98371_dai_set_fmt,
334 .hw_params = max98371_dai_hw_params,
335};
336
337static struct snd_soc_dai_driver max98371_dai[] = {
338 {
339 .name = "max98371-aif1",
340 .playback = {
341 .stream_name = "HiFi Playback",
342 .channels_min = 1,
343 .channels_max = 2,
344 .rates = SNDRV_PCM_RATE_8000_48000,
345 .formats = MAX98371_FORMATS,
346 },
347 .ops = &max98371_dai_ops,
348 }
349};
350
351static const struct snd_soc_codec_driver max98371_codec = {
352 .controls = max98371_snd_controls,
353 .num_controls = ARRAY_SIZE(max98371_snd_controls),
354 .dapm_routes = max98371_audio_map,
355 .num_dapm_routes = ARRAY_SIZE(max98371_audio_map),
356 .dapm_widgets = max98371_dapm_widgets,
357 .num_dapm_widgets = ARRAY_SIZE(max98371_dapm_widgets),
358};
359
360static const struct regmap_config max98371_regmap = {
361 .reg_bits = 8,
362 .val_bits = 8,
363 .max_register = MAX98371_VERSION,
364 .reg_defaults = max98371_reg,
365 .num_reg_defaults = ARRAY_SIZE(max98371_reg),
366 .volatile_reg = max98371_volatile_register,
367 .readable_reg = max98371_readable_register,
368 .cache_type = REGCACHE_RBTREE,
369};
370
371static int max98371_i2c_probe(struct i2c_client *i2c,
372 const struct i2c_device_id *id)
373{
374 struct max98371_priv *max98371;
375 int ret, reg;
376
377 max98371 = devm_kzalloc(&i2c->dev,
378 sizeof(*max98371), GFP_KERNEL);
379 if (!max98371)
380 return -ENOMEM;
381
382 i2c_set_clientdata(i2c, max98371);
383 max98371->regmap = devm_regmap_init_i2c(i2c, &max98371_regmap);
384 if (IS_ERR(max98371->regmap)) {
385 ret = PTR_ERR(max98371->regmap);
386 dev_err(&i2c->dev,
387 "Failed to allocate regmap: %d\n", ret);
388 return ret;
389 }
390
391 ret = regmap_read(max98371->regmap, MAX98371_VERSION, &reg);
392 if (ret < 0) {
393 dev_info(&i2c->dev, "device error %d\n", ret);
394 return ret;
395 }
396 dev_info(&i2c->dev, "device version %x\n", reg);
397
398 ret = snd_soc_register_codec(&i2c->dev, &max98371_codec,
399 max98371_dai, ARRAY_SIZE(max98371_dai));
400 if (ret < 0) {
401 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
402 return ret;
403 }
404 return ret;
405}
406
407static int max98371_i2c_remove(struct i2c_client *client)
408{
409 snd_soc_unregister_codec(&client->dev);
410 return 0;
411}
412
413static const struct i2c_device_id max98371_i2c_id[] = {
414 { "max98371", 0 },
415};
416
417MODULE_DEVICE_TABLE(i2c, max98371_i2c_id);
418
419static const struct of_device_id max98371_of_match[] = {
420 { .compatible = "maxim,max98371", },
421 { }
422};
423MODULE_DEVICE_TABLE(of, max98371_of_match);
424
425static struct i2c_driver max98371_i2c_driver = {
426 .driver = {
427 .name = "max98371",
428 .owner = THIS_MODULE,
429 .pm = NULL,
430 .of_match_table = of_match_ptr(max98371_of_match),
431 },
432 .probe = max98371_i2c_probe,
433 .remove = max98371_i2c_remove,
434 .id_table = max98371_i2c_id,
435};
436
437module_i2c_driver(max98371_i2c_driver);
438
439MODULE_AUTHOR("anish kumar <yesanishhere@gmail.com>");
440MODULE_DESCRIPTION("ALSA SoC MAX98371 driver");
441MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98371.h b/sound/soc/codecs/max98371.h
new file mode 100644
index 000000000000..9f6330964d98
--- /dev/null
+++ b/sound/soc/codecs/max98371.h
@@ -0,0 +1,67 @@
1/*
2 * max98371.h -- MAX98371 ALSA SoC Audio driver
3 *
4 * Copyright 2011-2012 Maxim Integrated Products
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef _MAX98371_H
12#define _MAX98371_H
13
14#define MAX98371_IRQ_CLEAR1 0x01
15#define MAX98371_IRQ_CLEAR2 0x02
16#define MAX98371_IRQ_CLEAR3 0x03
17#define MAX98371_DAI_CLK 0x10
18#define MAX98371_DAI_BSEL_MASK 0xF
19#define MAX98371_DAI_BSEL_32 2
20#define MAX98371_DAI_BSEL_48 3
21#define MAX98371_DAI_BSEL_64 4
22#define MAX98371_SPK_SR 0x11
23#define MAX98371_SPK_SR_MASK 0xF
24#define MAX98371_SPK_SR_32 6
25#define MAX98371_SPK_SR_44 7
26#define MAX98371_SPK_SR_48 8
27#define MAX98371_SPK_SR_88 10
28#define MAX98371_SPK_SR_96 11
29#define MAX98371_DAI_CHANNEL 0x15
30#define MAX98371_CHANNEL_MASK 0x3
31#define MAX98371_MONOMIX_SRC 0x18
32#define MAX98371_MONOMIX_CFG 0x19
33#define MAX98371_HPF 0x1C
34#define MAX98371_MONOMIX_SRC_MASK 0xFF
35#define MONOMIX_RX_0_1 ((0x1)<<(4))
36#define M98371_DAI_CHANNEL_I2S 0x3
37#define MAX98371_DIGITAL_GAIN 0x2D
38#define MAX98371_DIGITAL_GAIN_WIDTH 0x7
39#define MAX98371_GAIN 0x2E
40#define MAX98371_GAIN_SHIFT 0x4
41#define MAX98371_GAIN_WIDTH 0x4
42#define MAX98371_DHT_MAX_WIDTH 4
43#define MAX98371_FMT 0x14
44#define MAX98371_CHANSZ_WIDTH 6
45#define MAX98371_FMT_MASK ((0x3)<<(MAX98371_CHANSZ_WIDTH))
46#define MAX98371_FMT_MODE_MASK ((0x7)<<(3))
47#define MAX98371_DAI_LEFT ((0x1)<<(3))
48#define MAX98371_DAI_RIGHT ((0x2)<<(3))
49#define MAX98371_DAI_CHANSZ_16 ((1)<<(MAX98371_CHANSZ_WIDTH))
50#define MAX98371_DAI_CHANSZ_24 ((2)<<(MAX98371_CHANSZ_WIDTH))
51#define MAX98371_DAI_CHANSZ_32 ((3)<<(MAX98371_CHANSZ_WIDTH))
52#define MAX98371_DHT 0x32
53#define MAX98371_DHT_STEP 0x3
54#define MAX98371_DHT_GAIN 0x31
55#define MAX98371_DHT_GAIN_WIDTH 0x4
56#define MAX98371_DHT_ROT_WIDTH 0x4
57#define MAX98371_SPK_ENABLE 0x4A
58#define MAX98371_GLOBAL_ENABLE 0x50
59#define MAX98371_SOFT_RESET 0x51
60#define MAX98371_VERSION 0xFF
61
62
63struct max98371_priv {
64 struct regmap *regmap;
65 struct snd_soc_codec *codec;
66};
67#endif
diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c
index a1aaffc20862..f80cfe4d2ef2 100644
--- a/sound/soc/codecs/rt298.c
+++ b/sound/soc/codecs/rt298.c
@@ -276,6 +276,8 @@ static int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic)
276 } else { 276 } else {
277 *mic = false; 277 *mic = false;
278 regmap_write(rt298->regmap, RT298_SET_MIC1, 0x20); 278 regmap_write(rt298->regmap, RT298_SET_MIC1, 0x20);
279 regmap_update_bits(rt298->regmap,
280 RT298_CBJ_CTRL1, 0x0400, 0x0000);
279 } 281 }
280 } else { 282 } else {
281 regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf); 283 regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf);
@@ -482,6 +484,26 @@ static int rt298_adc_event(struct snd_soc_dapm_widget *w,
482 snd_soc_update_bits(codec, 484 snd_soc_update_bits(codec,
483 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), 485 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0),
484 0x7080, 0x7000); 486 0x7080, 0x7000);
487 /* If MCLK doesn't exist, reset AD filter */
488 if (!(snd_soc_read(codec, RT298_VAD_CTRL) & 0x200)) {
489 pr_info("NO MCLK\n");
490 switch (nid) {
491 case RT298_ADC_IN1:
492 snd_soc_update_bits(codec,
493 RT298_D_FILTER_CTRL, 0x2, 0x2);
494 mdelay(10);
495 snd_soc_update_bits(codec,
496 RT298_D_FILTER_CTRL, 0x2, 0x0);
497 break;
498 case RT298_ADC_IN2:
499 snd_soc_update_bits(codec,
500 RT298_D_FILTER_CTRL, 0x4, 0x4);
501 mdelay(10);
502 snd_soc_update_bits(codec,
503 RT298_D_FILTER_CTRL, 0x4, 0x0);
504 break;
505 }
506 }
485 break; 507 break;
486 case SND_SOC_DAPM_PRE_PMD: 508 case SND_SOC_DAPM_PRE_PMD:
487 snd_soc_update_bits(codec, 509 snd_soc_update_bits(codec,
@@ -520,30 +542,12 @@ static int rt298_mic1_event(struct snd_soc_dapm_widget *w,
520 return 0; 542 return 0;
521} 543}
522 544
523static int rt298_vref_event(struct snd_soc_dapm_widget *w,
524 struct snd_kcontrol *kcontrol, int event)
525{
526 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
527
528 switch (event) {
529 case SND_SOC_DAPM_PRE_PMU:
530 snd_soc_update_bits(codec,
531 RT298_CBJ_CTRL1, 0x0400, 0x0000);
532 mdelay(50);
533 break;
534 default:
535 return 0;
536 }
537
538 return 0;
539}
540
541static const struct snd_soc_dapm_widget rt298_dapm_widgets[] = { 545static const struct snd_soc_dapm_widget rt298_dapm_widgets[] = {
542 546
543 SND_SOC_DAPM_SUPPLY_S("HV", 1, RT298_POWER_CTRL1, 547 SND_SOC_DAPM_SUPPLY_S("HV", 1, RT298_POWER_CTRL1,
544 12, 1, NULL, 0), 548 12, 1, NULL, 0),
545 SND_SOC_DAPM_SUPPLY("VREF", RT298_POWER_CTRL1, 549 SND_SOC_DAPM_SUPPLY("VREF", RT298_POWER_CTRL1,
546 0, 1, rt298_vref_event, SND_SOC_DAPM_PRE_PMU), 550 0, 1, NULL, 0),
547 SND_SOC_DAPM_SUPPLY_S("BG_MBIAS", 1, RT298_POWER_CTRL2, 551 SND_SOC_DAPM_SUPPLY_S("BG_MBIAS", 1, RT298_POWER_CTRL2,
548 1, 0, NULL, 0), 552 1, 0, NULL, 0),
549 SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT298_POWER_CTRL2, 553 SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT298_POWER_CTRL2,
@@ -934,18 +938,9 @@ static int rt298_set_bias_level(struct snd_soc_codec *codec,
934 } 938 }
935 break; 939 break;
936 940
937 case SND_SOC_BIAS_ON:
938 mdelay(30);
939 snd_soc_update_bits(codec,
940 RT298_CBJ_CTRL1, 0x0400, 0x0400);
941
942 break;
943
944 case SND_SOC_BIAS_STANDBY: 941 case SND_SOC_BIAS_STANDBY:
945 snd_soc_write(codec, 942 snd_soc_write(codec,
946 RT298_SET_AUDIO_POWER, AC_PWRST_D3); 943 RT298_SET_AUDIO_POWER, AC_PWRST_D3);
947 snd_soc_update_bits(codec,
948 RT298_CBJ_CTRL1, 0x0400, 0x0000);
949 break; 944 break;
950 945
951 default: 946 default:
diff --git a/sound/soc/codecs/rt298.h b/sound/soc/codecs/rt298.h
index d66f8847b676..3638f3d61209 100644
--- a/sound/soc/codecs/rt298.h
+++ b/sound/soc/codecs/rt298.h
@@ -137,6 +137,7 @@
137#define RT298_A_BIAS_CTRL2 0x02 137#define RT298_A_BIAS_CTRL2 0x02
138#define RT298_POWER_CTRL1 0x03 138#define RT298_POWER_CTRL1 0x03
139#define RT298_A_BIAS_CTRL3 0x04 139#define RT298_A_BIAS_CTRL3 0x04
140#define RT298_D_FILTER_CTRL 0x05
140#define RT298_POWER_CTRL2 0x08 141#define RT298_POWER_CTRL2 0x08
141#define RT298_I2S_CTRL1 0x09 142#define RT298_I2S_CTRL1 0x09
142#define RT298_I2S_CTRL2 0x0a 143#define RT298_I2S_CTRL2 0x0a
@@ -148,6 +149,7 @@
148#define RT298_IRQ_CTRL 0x33 149#define RT298_IRQ_CTRL 0x33
149#define RT298_WIND_FILTER_CTRL 0x46 150#define RT298_WIND_FILTER_CTRL 0x46
150#define RT298_PLL_CTRL1 0x49 151#define RT298_PLL_CTRL1 0x49
152#define RT298_VAD_CTRL 0x4e
151#define RT298_CBJ_CTRL1 0x4f 153#define RT298_CBJ_CTRL1 0x4f
152#define RT298_CBJ_CTRL2 0x50 154#define RT298_CBJ_CTRL2 0x50
153#define RT298_PLL_CTRL 0x63 155#define RT298_PLL_CTRL 0x63
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
index 33e290b703df..b3f1db5bae4a 100644
--- a/sound/soc/codecs/rt5677.c
+++ b/sound/soc/codecs/rt5677.c
@@ -1241,60 +1241,46 @@ static int rt5677_dmic_use_asrc(struct snd_soc_dapm_widget *source,
1241 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); 1241 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
1242 asrc_setting = (asrc_setting & RT5677_AD_STO1_CLK_SEL_MASK) >> 1242 asrc_setting = (asrc_setting & RT5677_AD_STO1_CLK_SEL_MASK) >>
1243 RT5677_AD_STO1_CLK_SEL_SFT; 1243 RT5677_AD_STO1_CLK_SEL_SFT;
1244 if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
1245 asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
1246 return 1;
1247 break; 1244 break;
1248 1245
1249 case 10: 1246 case 10:
1250 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); 1247 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
1251 asrc_setting = (asrc_setting & RT5677_AD_STO2_CLK_SEL_MASK) >> 1248 asrc_setting = (asrc_setting & RT5677_AD_STO2_CLK_SEL_MASK) >>
1252 RT5677_AD_STO2_CLK_SEL_SFT; 1249 RT5677_AD_STO2_CLK_SEL_SFT;
1253 if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
1254 asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
1255 return 1;
1256 break; 1250 break;
1257 1251
1258 case 9: 1252 case 9:
1259 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); 1253 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
1260 asrc_setting = (asrc_setting & RT5677_AD_STO3_CLK_SEL_MASK) >> 1254 asrc_setting = (asrc_setting & RT5677_AD_STO3_CLK_SEL_MASK) >>
1261 RT5677_AD_STO3_CLK_SEL_SFT; 1255 RT5677_AD_STO3_CLK_SEL_SFT;
1262 if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
1263 asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
1264 return 1;
1265 break; 1256 break;
1266 1257
1267 case 8: 1258 case 8:
1268 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); 1259 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
1269 asrc_setting = (asrc_setting & RT5677_AD_STO4_CLK_SEL_MASK) >> 1260 asrc_setting = (asrc_setting & RT5677_AD_STO4_CLK_SEL_MASK) >>
1270 RT5677_AD_STO4_CLK_SEL_SFT; 1261 RT5677_AD_STO4_CLK_SEL_SFT;
1271 if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
1272 asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
1273 return 1;
1274 break; 1262 break;
1275 1263
1276 case 7: 1264 case 7:
1277 regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting); 1265 regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting);
1278 asrc_setting = (asrc_setting & RT5677_AD_MONOL_CLK_SEL_MASK) >> 1266 asrc_setting = (asrc_setting & RT5677_AD_MONOL_CLK_SEL_MASK) >>
1279 RT5677_AD_MONOL_CLK_SEL_SFT; 1267 RT5677_AD_MONOL_CLK_SEL_SFT;
1280 if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
1281 asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
1282 return 1;
1283 break; 1268 break;
1284 1269
1285 case 6: 1270 case 6:
1286 regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting); 1271 regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting);
1287 asrc_setting = (asrc_setting & RT5677_AD_MONOR_CLK_SEL_MASK) >> 1272 asrc_setting = (asrc_setting & RT5677_AD_MONOR_CLK_SEL_MASK) >>
1288 RT5677_AD_MONOR_CLK_SEL_SFT; 1273 RT5677_AD_MONOR_CLK_SEL_SFT;
1289 if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
1290 asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
1291 return 1;
1292 break; 1274 break;
1293 1275
1294 default: 1276 default:
1295 break; 1277 return 0;
1296 } 1278 }
1297 1279
1280 if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
1281 asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
1282 return 1;
1283
1298 return 0; 1284 return 0;
1299} 1285}
1300 1286
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
index 39307ad41a34..b8d19b77bde9 100644
--- a/sound/soc/codecs/tas571x.c
+++ b/sound/soc/codecs/tas571x.c
@@ -4,6 +4,9 @@
4 * Copyright (C) 2015 Google, Inc. 4 * Copyright (C) 2015 Google, Inc.
5 * Copyright (c) 2013 Daniel Mack <zonque@gmail.com> 5 * Copyright (c) 2013 Daniel Mack <zonque@gmail.com>
6 * 6 *
7 * TAS5721 support:
8 * Copyright (C) 2016 Petr Kulhavy, Barix AG <petr@barix.com>
9 *
7 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or 12 * the Free Software Foundation; either version 2 of the License, or
@@ -57,6 +60,10 @@ static int tas571x_register_size(struct tas571x_private *priv, unsigned int reg)
57 case TAS571X_CH1_VOL_REG: 60 case TAS571X_CH1_VOL_REG:
58 case TAS571X_CH2_VOL_REG: 61 case TAS571X_CH2_VOL_REG:
59 return priv->chip->vol_reg_size; 62 return priv->chip->vol_reg_size;
63 case TAS571X_INPUT_MUX_REG:
64 case TAS571X_CH4_SRC_SELECT_REG:
65 case TAS571X_PWM_MUX_REG:
66 return 4;
60 default: 67 default:
61 return 1; 68 return 1;
62 } 69 }
@@ -167,6 +174,23 @@ static int tas571x_hw_params(struct snd_pcm_substream *substream,
167 TAS571X_SDI_FMT_MASK, val); 174 TAS571X_SDI_FMT_MASK, val);
168} 175}
169 176
177static int tas571x_mute(struct snd_soc_dai *dai, int mute)
178{
179 struct snd_soc_codec *codec = dai->codec;
180 u8 sysctl2;
181 int ret;
182
183 sysctl2 = mute ? TAS571X_SYS_CTRL_2_SDN_MASK : 0;
184
185 ret = snd_soc_update_bits(codec,
186 TAS571X_SYS_CTRL_2_REG,
187 TAS571X_SYS_CTRL_2_SDN_MASK,
188 sysctl2);
189 usleep_range(1000, 2000);
190
191 return ret;
192}
193
170static int tas571x_set_bias_level(struct snd_soc_codec *codec, 194static int tas571x_set_bias_level(struct snd_soc_codec *codec,
171 enum snd_soc_bias_level level) 195 enum snd_soc_bias_level level)
172{ 196{
@@ -214,6 +238,7 @@ static int tas571x_set_bias_level(struct snd_soc_codec *codec,
214static const struct snd_soc_dai_ops tas571x_dai_ops = { 238static const struct snd_soc_dai_ops tas571x_dai_ops = {
215 .set_fmt = tas571x_set_dai_fmt, 239 .set_fmt = tas571x_set_dai_fmt,
216 .hw_params = tas571x_hw_params, 240 .hw_params = tas571x_hw_params,
241 .digital_mute = tas571x_mute,
217}; 242};
218 243
219static const char *const tas5711_supply_names[] = { 244static const char *const tas5711_supply_names[] = {
@@ -241,6 +266,26 @@ static const struct snd_kcontrol_new tas5711_controls[] = {
241 1, 1), 266 1, 1),
242}; 267};
243 268
269static const struct regmap_range tas571x_readonly_regs_range[] = {
270 regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_DEV_ID_REG),
271};
272
273static const struct regmap_range tas571x_volatile_regs_range[] = {
274 regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_ERR_STATUS_REG),
275 regmap_reg_range(TAS571X_OSC_TRIM_REG, TAS571X_OSC_TRIM_REG),
276};
277
278static const struct regmap_access_table tas571x_write_regs = {
279 .no_ranges = tas571x_readonly_regs_range,
280 .n_no_ranges = ARRAY_SIZE(tas571x_readonly_regs_range),
281};
282
283static const struct regmap_access_table tas571x_volatile_regs = {
284 .yes_ranges = tas571x_volatile_regs_range,
285 .n_yes_ranges = ARRAY_SIZE(tas571x_volatile_regs_range),
286
287};
288
244static const struct reg_default tas5711_reg_defaults[] = { 289static const struct reg_default tas5711_reg_defaults[] = {
245 { 0x04, 0x05 }, 290 { 0x04, 0x05 },
246 { 0x05, 0x40 }, 291 { 0x05, 0x40 },
@@ -260,6 +305,8 @@ static const struct regmap_config tas5711_regmap_config = {
260 .reg_defaults = tas5711_reg_defaults, 305 .reg_defaults = tas5711_reg_defaults,
261 .num_reg_defaults = ARRAY_SIZE(tas5711_reg_defaults), 306 .num_reg_defaults = ARRAY_SIZE(tas5711_reg_defaults),
262 .cache_type = REGCACHE_RBTREE, 307 .cache_type = REGCACHE_RBTREE,
308 .wr_table = &tas571x_write_regs,
309 .volatile_table = &tas571x_volatile_regs,
263}; 310};
264 311
265static const struct tas571x_chip tas5711_chip = { 312static const struct tas571x_chip tas5711_chip = {
@@ -314,6 +361,8 @@ static const struct regmap_config tas5717_regmap_config = {
314 .reg_defaults = tas5717_reg_defaults, 361 .reg_defaults = tas5717_reg_defaults,
315 .num_reg_defaults = ARRAY_SIZE(tas5717_reg_defaults), 362 .num_reg_defaults = ARRAY_SIZE(tas5717_reg_defaults),
316 .cache_type = REGCACHE_RBTREE, 363 .cache_type = REGCACHE_RBTREE,
364 .wr_table = &tas571x_write_regs,
365 .volatile_table = &tas571x_volatile_regs,
317}; 366};
318 367
319/* This entry is reused for tas5719 as the software interface is identical. */ 368/* This entry is reused for tas5719 as the software interface is identical. */
@@ -326,6 +375,77 @@ static const struct tas571x_chip tas5717_chip = {
326 .vol_reg_size = 2, 375 .vol_reg_size = 2,
327}; 376};
328 377
378static const char *const tas5721_supply_names[] = {
379 "AVDD",
380 "DVDD",
381 "DRVDD",
382 "PVDD",
383};
384
385static const struct snd_kcontrol_new tas5721_controls[] = {
386 SOC_SINGLE_TLV("Master Volume",
387 TAS571X_MVOL_REG,
388 0, 0xff, 1, tas5711_volume_tlv),
389 SOC_DOUBLE_R_TLV("Speaker Volume",
390 TAS571X_CH1_VOL_REG,
391 TAS571X_CH2_VOL_REG,
392 0, 0xff, 1, tas5711_volume_tlv),
393 SOC_DOUBLE("Speaker Switch",
394 TAS571X_SOFT_MUTE_REG,
395 TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
396 1, 1),
397};
398
399static const struct reg_default tas5721_reg_defaults[] = {
400 {TAS571X_CLK_CTRL_REG, 0x6c},
401 {TAS571X_DEV_ID_REG, 0x00},
402 {TAS571X_ERR_STATUS_REG, 0x00},
403 {TAS571X_SYS_CTRL_1_REG, 0xa0},
404 {TAS571X_SDI_REG, 0x05},
405 {TAS571X_SYS_CTRL_2_REG, 0x40},
406 {TAS571X_SOFT_MUTE_REG, 0x00},
407 {TAS571X_MVOL_REG, 0xff},
408 {TAS571X_CH1_VOL_REG, 0x30},
409 {TAS571X_CH2_VOL_REG, 0x30},
410 {TAS571X_CH3_VOL_REG, 0x30},
411 {TAS571X_VOL_CFG_REG, 0x91},
412 {TAS571X_MODULATION_LIMIT_REG, 0x02},
413 {TAS571X_IC_DELAY_CH1_REG, 0xac},
414 {TAS571X_IC_DELAY_CH2_REG, 0x54},
415 {TAS571X_IC_DELAY_CH3_REG, 0xac},
416 {TAS571X_IC_DELAY_CH4_REG, 0x54},
417 {TAS571X_PWM_CH_SDN_GROUP_REG, 0x30},
418 {TAS571X_START_STOP_PERIOD_REG, 0x0f},
419 {TAS571X_OSC_TRIM_REG, 0x82},
420 {TAS571X_BKND_ERR_REG, 0x02},
421 {TAS571X_INPUT_MUX_REG, 0x17772},
422 {TAS571X_CH4_SRC_SELECT_REG, 0x4303},
423 {TAS571X_PWM_MUX_REG, 0x1021345},
424};
425
426static const struct regmap_config tas5721_regmap_config = {
427 .reg_bits = 8,
428 .val_bits = 32,
429 .max_register = 0xff,
430 .reg_read = tas571x_reg_read,
431 .reg_write = tas571x_reg_write,
432 .reg_defaults = tas5721_reg_defaults,
433 .num_reg_defaults = ARRAY_SIZE(tas5721_reg_defaults),
434 .cache_type = REGCACHE_RBTREE,
435 .wr_table = &tas571x_write_regs,
436 .volatile_table = &tas571x_volatile_regs,
437};
438
439
440static const struct tas571x_chip tas5721_chip = {
441 .supply_names = tas5721_supply_names,
442 .num_supply_names = ARRAY_SIZE(tas5721_supply_names),
443 .controls = tas5711_controls,
444 .num_controls = ARRAY_SIZE(tas5711_controls),
445 .regmap_config = &tas5721_regmap_config,
446 .vol_reg_size = 1,
447};
448
329static const struct snd_soc_dapm_widget tas571x_dapm_widgets[] = { 449static const struct snd_soc_dapm_widget tas571x_dapm_widgets[] = {
330 SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), 450 SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
331 SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), 451 SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
@@ -386,11 +506,10 @@ static int tas571x_i2c_probe(struct i2c_client *client,
386 i2c_set_clientdata(client, priv); 506 i2c_set_clientdata(client, priv);
387 507
388 of_id = of_match_device(tas571x_of_match, dev); 508 of_id = of_match_device(tas571x_of_match, dev);
389 if (!of_id) { 509 if (of_id)
390 dev_err(dev, "Unknown device type\n"); 510 priv->chip = of_id->data;
391 return -EINVAL; 511 else
392 } 512 priv->chip = (void *) id->driver_data;
393 priv->chip = of_id->data;
394 513
395 priv->mclk = devm_clk_get(dev, "mclk"); 514 priv->mclk = devm_clk_get(dev, "mclk");
396 if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) { 515 if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) {
@@ -445,10 +564,6 @@ static int tas571x_i2c_probe(struct i2c_client *client,
445 if (ret) 564 if (ret)
446 return ret; 565 return ret;
447 566
448 ret = regmap_update_bits(priv->regmap, TAS571X_SYS_CTRL_2_REG,
449 TAS571X_SYS_CTRL_2_SDN_MASK, 0);
450 if (ret)
451 return ret;
452 567
453 memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver)); 568 memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver));
454 priv->codec_driver.controls = priv->chip->controls; 569 priv->codec_driver.controls = priv->chip->controls;
@@ -486,14 +601,16 @@ static const struct of_device_id tas571x_of_match[] = {
486 { .compatible = "ti,tas5711", .data = &tas5711_chip, }, 601 { .compatible = "ti,tas5711", .data = &tas5711_chip, },
487 { .compatible = "ti,tas5717", .data = &tas5717_chip, }, 602 { .compatible = "ti,tas5717", .data = &tas5717_chip, },
488 { .compatible = "ti,tas5719", .data = &tas5717_chip, }, 603 { .compatible = "ti,tas5719", .data = &tas5717_chip, },
604 { .compatible = "ti,tas5721", .data = &tas5721_chip, },
489 { } 605 { }
490}; 606};
491MODULE_DEVICE_TABLE(of, tas571x_of_match); 607MODULE_DEVICE_TABLE(of, tas571x_of_match);
492 608
493static const struct i2c_device_id tas571x_i2c_id[] = { 609static const struct i2c_device_id tas571x_i2c_id[] = {
494 { "tas5711", 0 }, 610 { "tas5711", (kernel_ulong_t) &tas5711_chip },
495 { "tas5717", 0 }, 611 { "tas5717", (kernel_ulong_t) &tas5717_chip },
496 { "tas5719", 0 }, 612 { "tas5719", (kernel_ulong_t) &tas5717_chip },
613 { "tas5721", (kernel_ulong_t) &tas5721_chip },
497 { } 614 { }
498}; 615};
499MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id); 616MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id);
diff --git a/sound/soc/codecs/tas571x.h b/sound/soc/codecs/tas571x.h
index 0aee471232cd..cf800c364f0f 100644
--- a/sound/soc/codecs/tas571x.h
+++ b/sound/soc/codecs/tas571x.h
@@ -13,6 +13,10 @@
13#define _TAS571X_H 13#define _TAS571X_H
14 14
15/* device registers */ 15/* device registers */
16#define TAS571X_CLK_CTRL_REG 0x00
17#define TAS571X_DEV_ID_REG 0x01
18#define TAS571X_ERR_STATUS_REG 0x02
19#define TAS571X_SYS_CTRL_1_REG 0x03
16#define TAS571X_SDI_REG 0x04 20#define TAS571X_SDI_REG 0x04
17#define TAS571X_SDI_FMT_MASK 0x0f 21#define TAS571X_SDI_FMT_MASK 0x0f
18 22
@@ -27,7 +31,25 @@
27#define TAS571X_MVOL_REG 0x07 31#define TAS571X_MVOL_REG 0x07
28#define TAS571X_CH1_VOL_REG 0x08 32#define TAS571X_CH1_VOL_REG 0x08
29#define TAS571X_CH2_VOL_REG 0x09 33#define TAS571X_CH2_VOL_REG 0x09
34#define TAS571X_CH3_VOL_REG 0x0a
35#define TAS571X_VOL_CFG_REG 0x0e
36#define TAS571X_MODULATION_LIMIT_REG 0x10
37#define TAS571X_IC_DELAY_CH1_REG 0x11
38#define TAS571X_IC_DELAY_CH2_REG 0x12
39#define TAS571X_IC_DELAY_CH3_REG 0x13
40#define TAS571X_IC_DELAY_CH4_REG 0x14
30 41
42#define TAS571X_PWM_CH_SDN_GROUP_REG 0x19 /* N/A on TAS5717, TAS5719 */
43#define TAS571X_PWM_CH1_SDN_MASK (1<<0)
44#define TAS571X_PWM_CH2_SDN_SHIFT (1<<1)
45#define TAS571X_PWM_CH3_SDN_SHIFT (1<<2)
46#define TAS571X_PWM_CH4_SDN_SHIFT (1<<3)
47
48#define TAS571X_START_STOP_PERIOD_REG 0x1a
31#define TAS571X_OSC_TRIM_REG 0x1b 49#define TAS571X_OSC_TRIM_REG 0x1b
50#define TAS571X_BKND_ERR_REG 0x1c
51#define TAS571X_INPUT_MUX_REG 0x20
52#define TAS571X_CH4_SRC_SELECT_REG 0x21
53#define TAS571X_PWM_MUX_REG 0x25
32 54
33#endif /* _TAS571X_H */ 55#endif /* _TAS571X_H */
diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c
new file mode 100644
index 000000000000..f54fb46b77c2
--- /dev/null
+++ b/sound/soc/codecs/tas5720.c
@@ -0,0 +1,620 @@
1/*
2 * tas5720.c - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier
3 *
4 * Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com
5 *
6 * Author: Andreas Dannenberg <dannenberg@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
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#include <linux/module.h>
19#include <linux/errno.h>
20#include <linux/device.h>
21#include <linux/i2c.h>
22#include <linux/pm_runtime.h>
23#include <linux/regmap.h>
24#include <linux/slab.h>
25#include <linux/regulator/consumer.h>
26#include <linux/delay.h>
27
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/soc.h>
31#include <sound/soc-dapm.h>
32#include <sound/tlv.h>
33
34#include "tas5720.h"
35
36/* Define how often to check (and clear) the fault status register (in ms) */
37#define TAS5720_FAULT_CHECK_INTERVAL 200
38
39static const char * const tas5720_supply_names[] = {
40 "dvdd", /* Digital power supply. Connect to 3.3-V supply. */
41 "pvdd", /* Class-D amp and analog power supply (connected). */
42};
43
44#define TAS5720_NUM_SUPPLIES ARRAY_SIZE(tas5720_supply_names)
45
46struct tas5720_data {
47 struct snd_soc_codec *codec;
48 struct regmap *regmap;
49 struct i2c_client *tas5720_client;
50 struct regulator_bulk_data supplies[TAS5720_NUM_SUPPLIES];
51 struct delayed_work fault_check_work;
52 unsigned int last_fault;
53};
54
55static int tas5720_hw_params(struct snd_pcm_substream *substream,
56 struct snd_pcm_hw_params *params,
57 struct snd_soc_dai *dai)
58{
59 struct snd_soc_codec *codec = dai->codec;
60 unsigned int rate = params_rate(params);
61 bool ssz_ds;
62 int ret;
63
64 switch (rate) {
65 case 44100:
66 case 48000:
67 ssz_ds = false;
68 break;
69 case 88200:
70 case 96000:
71 ssz_ds = true;
72 break;
73 default:
74 dev_err(codec->dev, "unsupported sample rate: %u\n", rate);
75 return -EINVAL;
76 }
77
78 ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG,
79 TAS5720_SSZ_DS, ssz_ds);
80 if (ret < 0) {
81 dev_err(codec->dev, "error setting sample rate: %d\n", ret);
82 return ret;
83 }
84
85 return 0;
86}
87
88static int tas5720_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
89{
90 struct snd_soc_codec *codec = dai->codec;
91 u8 serial_format;
92 int ret;
93
94 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
95 dev_vdbg(codec->dev, "DAI Format master is not found\n");
96 return -EINVAL;
97 }
98
99 switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK |
100 SND_SOC_DAIFMT_INV_MASK)) {
101 case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF):
102 /* 1st data bit occur one BCLK cycle after the frame sync */
103 serial_format = TAS5720_SAIF_I2S;
104 break;
105 case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF):
106 /*
107 * Note that although the TAS5720 does not have a dedicated DSP
108 * mode it doesn't care about the LRCLK duty cycle during TDM
109 * operation. Therefore we can use the device's I2S mode with
110 * its delaying of the 1st data bit to receive DSP_A formatted
111 * data. See device datasheet for additional details.
112 */
113 serial_format = TAS5720_SAIF_I2S;
114 break;
115 case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF):
116 /*
117 * Similar to DSP_A, we can use the fact that the TAS5720 does
118 * not care about the LRCLK duty cycle during TDM to receive
119 * DSP_B formatted data in LEFTJ mode (no delaying of the 1st
120 * data bit).
121 */
122 serial_format = TAS5720_SAIF_LEFTJ;
123 break;
124 case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF):
125 /* No delay after the frame sync */
126 serial_format = TAS5720_SAIF_LEFTJ;
127 break;
128 default:
129 dev_vdbg(codec->dev, "DAI Format is not found\n");
130 return -EINVAL;
131 }
132
133 ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG,
134 TAS5720_SAIF_FORMAT_MASK,
135 serial_format);
136 if (ret < 0) {
137 dev_err(codec->dev, "error setting SAIF format: %d\n", ret);
138 return ret;
139 }
140
141 return 0;
142}
143
144static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai,
145 unsigned int tx_mask, unsigned int rx_mask,
146 int slots, int slot_width)
147{
148 struct snd_soc_codec *codec = dai->codec;
149 unsigned int first_slot;
150 int ret;
151
152 if (!tx_mask) {
153 dev_err(codec->dev, "tx masks must not be 0\n");
154 return -EINVAL;
155 }
156
157 /*
158 * Determine the first slot that is being requested. We will only
159 * use the first slot that is found since the TAS5720 is a mono
160 * amplifier.
161 */
162 first_slot = __ffs(tx_mask);
163
164 if (first_slot > 7) {
165 dev_err(codec->dev, "slot selection out of bounds (%u)\n",
166 first_slot);
167 return -EINVAL;
168 }
169
170 /* Enable manual TDM slot selection (instead of I2C ID based) */
171 ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG,
172 TAS5720_TDM_CFG_SRC, TAS5720_TDM_CFG_SRC);
173 if (ret < 0)
174 goto error_snd_soc_update_bits;
175
176 /* Configure the TDM slot to process audio from */
177 ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG,
178 TAS5720_TDM_SLOT_SEL_MASK, first_slot);
179 if (ret < 0)
180 goto error_snd_soc_update_bits;
181
182 return 0;
183
184error_snd_soc_update_bits:
185 dev_err(codec->dev, "error configuring TDM mode: %d\n", ret);
186 return ret;
187}
188
189static int tas5720_mute(struct snd_soc_dai *dai, int mute)
190{
191 struct snd_soc_codec *codec = dai->codec;
192 int ret;
193
194 ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG,
195 TAS5720_MUTE, mute ? TAS5720_MUTE : 0);
196 if (ret < 0) {
197 dev_err(codec->dev, "error (un-)muting device: %d\n", ret);
198 return ret;
199 }
200
201 return 0;
202}
203
204static void tas5720_fault_check_work(struct work_struct *work)
205{
206 struct tas5720_data *tas5720 = container_of(work, struct tas5720_data,
207 fault_check_work.work);
208 struct device *dev = tas5720->codec->dev;
209 unsigned int curr_fault;
210 int ret;
211
212 ret = regmap_read(tas5720->regmap, TAS5720_FAULT_REG, &curr_fault);
213 if (ret < 0) {
214 dev_err(dev, "failed to read FAULT register: %d\n", ret);
215 goto out;
216 }
217
218 /* Check/handle all errors except SAIF clock errors */
219 curr_fault &= TAS5720_OCE | TAS5720_DCE | TAS5720_OTE;
220
221 /*
222 * Only flag errors once for a given occurrence. This is needed as
223 * the TAS5720 will take time clearing the fault condition internally
224 * during which we don't want to bombard the system with the same
225 * error message over and over.
226 */
227 if ((curr_fault & TAS5720_OCE) && !(tas5720->last_fault & TAS5720_OCE))
228 dev_crit(dev, "experienced an over current hardware fault\n");
229
230 if ((curr_fault & TAS5720_DCE) && !(tas5720->last_fault & TAS5720_DCE))
231 dev_crit(dev, "experienced a DC detection fault\n");
232
233 if ((curr_fault & TAS5720_OTE) && !(tas5720->last_fault & TAS5720_OTE))
234 dev_crit(dev, "experienced an over temperature fault\n");
235
236 /* Store current fault value so we can detect any changes next time */
237 tas5720->last_fault = curr_fault;
238
239 if (!curr_fault)
240 goto out;
241
242 /*
243 * Periodically toggle SDZ (shutdown bit) H->L->H to clear any latching
244 * faults as long as a fault condition persists. Always going through
245 * the full sequence no matter the first return value to minimizes
246 * chances for the device to end up in shutdown mode.
247 */
248 ret = regmap_write_bits(tas5720->regmap, TAS5720_POWER_CTRL_REG,
249 TAS5720_SDZ, 0);
250 if (ret < 0)
251 dev_err(dev, "failed to write POWER_CTRL register: %d\n", ret);
252
253 ret = regmap_write_bits(tas5720->regmap, TAS5720_POWER_CTRL_REG,
254 TAS5720_SDZ, TAS5720_SDZ);
255 if (ret < 0)
256 dev_err(dev, "failed to write POWER_CTRL register: %d\n", ret);
257
258out:
259 /* Schedule the next fault check at the specified interval */
260 schedule_delayed_work(&tas5720->fault_check_work,
261 msecs_to_jiffies(TAS5720_FAULT_CHECK_INTERVAL));
262}
263
264static int tas5720_codec_probe(struct snd_soc_codec *codec)
265{
266 struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec);
267 unsigned int device_id;
268 int ret;
269
270 tas5720->codec = codec;
271
272 ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies),
273 tas5720->supplies);
274 if (ret != 0) {
275 dev_err(codec->dev, "failed to enable supplies: %d\n", ret);
276 return ret;
277 }
278
279 ret = regmap_read(tas5720->regmap, TAS5720_DEVICE_ID_REG, &device_id);
280 if (ret < 0) {
281 dev_err(codec->dev, "failed to read device ID register: %d\n",
282 ret);
283 goto probe_fail;
284 }
285
286 if (device_id != TAS5720_DEVICE_ID) {
287 dev_err(codec->dev, "wrong device ID. expected: %u read: %u\n",
288 TAS5720_DEVICE_ID, device_id);
289 ret = -ENODEV;
290 goto probe_fail;
291 }
292
293 /* Set device to mute */
294 ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG,
295 TAS5720_MUTE, TAS5720_MUTE);
296 if (ret < 0)
297 goto error_snd_soc_update_bits;
298
299 /*
300 * Enter shutdown mode - our default when not playing audio - to
301 * minimize current consumption. On the TAS5720 there is no real down
302 * side doing so as all device registers are preserved and the wakeup
303 * of the codec is rather quick which we do using a dapm widget.
304 */
305 ret = snd_soc_update_bits(codec, TAS5720_POWER_CTRL_REG,
306 TAS5720_SDZ, 0);
307 if (ret < 0)
308 goto error_snd_soc_update_bits;
309
310 INIT_DELAYED_WORK(&tas5720->fault_check_work, tas5720_fault_check_work);
311
312 return 0;
313
314error_snd_soc_update_bits:
315 dev_err(codec->dev, "error configuring device registers: %d\n", ret);
316
317probe_fail:
318 regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies),
319 tas5720->supplies);
320 return ret;
321}
322
323static int tas5720_codec_remove(struct snd_soc_codec *codec)
324{
325 struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec);
326 int ret;
327
328 cancel_delayed_work_sync(&tas5720->fault_check_work);
329
330 ret = regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies),
331 tas5720->supplies);
332 if (ret < 0)
333 dev_err(codec->dev, "failed to disable supplies: %d\n", ret);
334
335 return ret;
336};
337
338static int tas5720_dac_event(struct snd_soc_dapm_widget *w,
339 struct snd_kcontrol *kcontrol, int event)
340{
341 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
342 struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec);
343 int ret;
344
345 if (event & SND_SOC_DAPM_POST_PMU) {
346 /* Take TAS5720 out of shutdown mode */
347 ret = snd_soc_update_bits(codec, TAS5720_POWER_CTRL_REG,
348 TAS5720_SDZ, TAS5720_SDZ);
349 if (ret < 0) {
350 dev_err(codec->dev, "error waking codec: %d\n", ret);
351 return ret;
352 }
353
354 /*
355 * Observe codec shutdown-to-active time. The datasheet only
356 * lists a nominal value however just use-it as-is without
357 * additional padding to minimize the delay introduced in
358 * starting to play audio (actually there is other setup done
359 * by the ASoC framework that will provide additional delays,
360 * so we should always be safe).
361 */
362 msleep(25);
363
364 /* Turn on TAS5720 periodic fault checking/handling */
365 tas5720->last_fault = 0;
366 schedule_delayed_work(&tas5720->fault_check_work,
367 msecs_to_jiffies(TAS5720_FAULT_CHECK_INTERVAL));
368 } else if (event & SND_SOC_DAPM_PRE_PMD) {
369 /* Disable TAS5720 periodic fault checking/handling */
370 cancel_delayed_work_sync(&tas5720->fault_check_work);
371
372 /* Place TAS5720 in shutdown mode to minimize current draw */
373 ret = snd_soc_update_bits(codec, TAS5720_POWER_CTRL_REG,
374 TAS5720_SDZ, 0);
375 if (ret < 0) {
376 dev_err(codec->dev, "error shutting down codec: %d\n",
377 ret);
378 return ret;
379 }
380 }
381
382 return 0;
383}
384
385#ifdef CONFIG_PM
386static int tas5720_suspend(struct snd_soc_codec *codec)
387{
388 struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec);
389 int ret;
390
391 regcache_cache_only(tas5720->regmap, true);
392 regcache_mark_dirty(tas5720->regmap);
393
394 ret = regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies),
395 tas5720->supplies);
396 if (ret < 0)
397 dev_err(codec->dev, "failed to disable supplies: %d\n", ret);
398
399 return ret;
400}
401
402static int tas5720_resume(struct snd_soc_codec *codec)
403{
404 struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec);
405 int ret;
406
407 ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies),
408 tas5720->supplies);
409 if (ret < 0) {
410 dev_err(codec->dev, "failed to enable supplies: %d\n", ret);
411 return ret;
412 }
413
414 regcache_cache_only(tas5720->regmap, false);
415
416 ret = regcache_sync(tas5720->regmap);
417 if (ret < 0) {
418 dev_err(codec->dev, "failed to sync regcache: %d\n", ret);
419 return ret;
420 }
421
422 return 0;
423}
424#else
425#define tas5720_suspend NULL
426#define tas5720_resume NULL
427#endif
428
429static bool tas5720_is_volatile_reg(struct device *dev, unsigned int reg)
430{
431 switch (reg) {
432 case TAS5720_DEVICE_ID_REG:
433 case TAS5720_FAULT_REG:
434 return true;
435 default:
436 return false;
437 }
438}
439
440static const struct regmap_config tas5720_regmap_config = {
441 .reg_bits = 8,
442 .val_bits = 8,
443
444 .max_register = TAS5720_MAX_REG,
445 .cache_type = REGCACHE_RBTREE,
446 .volatile_reg = tas5720_is_volatile_reg,
447};
448
449/*
450 * DAC analog gain. There are four discrete values to select from, ranging
451 * from 19.2 dB to 26.3dB.
452 */
453static const DECLARE_TLV_DB_RANGE(dac_analog_tlv,
454 0x0, 0x0, TLV_DB_SCALE_ITEM(1920, 0, 0),
455 0x1, 0x1, TLV_DB_SCALE_ITEM(2070, 0, 0),
456 0x2, 0x2, TLV_DB_SCALE_ITEM(2350, 0, 0),
457 0x3, 0x3, TLV_DB_SCALE_ITEM(2630, 0, 0),
458);
459
460/*
461 * DAC digital volumes. From -103.5 to 24 dB in 0.5 dB steps. Note that
462 * setting the gain below -100 dB (register value <0x7) is effectively a MUTE
463 * as per device datasheet.
464 */
465static DECLARE_TLV_DB_SCALE(dac_tlv, -10350, 50, 0);
466
467static const struct snd_kcontrol_new tas5720_snd_controls[] = {
468 SOC_SINGLE_TLV("Speaker Driver Playback Volume",
469 TAS5720_VOLUME_CTRL_REG, 0, 0xff, 0, dac_tlv),
470 SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG,
471 TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv),
472};
473
474static const struct snd_soc_dapm_widget tas5720_dapm_widgets[] = {
475 SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
476 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas5720_dac_event,
477 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
478 SND_SOC_DAPM_OUTPUT("OUT")
479};
480
481static const struct snd_soc_dapm_route tas5720_audio_map[] = {
482 { "DAC", NULL, "DAC IN" },
483 { "OUT", NULL, "DAC" },
484};
485
486static struct snd_soc_codec_driver soc_codec_dev_tas5720 = {
487 .probe = tas5720_codec_probe,
488 .remove = tas5720_codec_remove,
489 .suspend = tas5720_suspend,
490 .resume = tas5720_resume,
491
492 .controls = tas5720_snd_controls,
493 .num_controls = ARRAY_SIZE(tas5720_snd_controls),
494 .dapm_widgets = tas5720_dapm_widgets,
495 .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets),
496 .dapm_routes = tas5720_audio_map,
497 .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map),
498};
499
500/* PCM rates supported by the TAS5720 driver */
501#define TAS5720_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
502 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
503
504/* Formats supported by TAS5720 driver */
505#define TAS5720_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\
506 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
507
508static struct snd_soc_dai_ops tas5720_speaker_dai_ops = {
509 .hw_params = tas5720_hw_params,
510 .set_fmt = tas5720_set_dai_fmt,
511 .set_tdm_slot = tas5720_set_dai_tdm_slot,
512 .digital_mute = tas5720_mute,
513};
514
515/*
516 * TAS5720 DAI structure
517 *
518 * Note that were are advertising .playback.channels_max = 2 despite this being
519 * a mono amplifier. The reason for that is that some serial ports such as TI's
520 * McASP module have a minimum number of channels (2) that they can output.
521 * Advertising more channels than we have will allow us to interface with such
522 * a serial port without really any negative side effects as the TAS5720 will
523 * simply ignore any extra channel(s) asides from the one channel that is
524 * configured to be played back.
525 */
526static struct snd_soc_dai_driver tas5720_dai[] = {
527 {
528 .name = "tas5720-amplifier",
529 .playback = {
530 .stream_name = "Playback",
531 .channels_min = 1,
532 .channels_max = 2,
533 .rates = TAS5720_RATES,
534 .formats = TAS5720_FORMATS,
535 },
536 .ops = &tas5720_speaker_dai_ops,
537 },
538};
539
540static int tas5720_probe(struct i2c_client *client,
541 const struct i2c_device_id *id)
542{
543 struct device *dev = &client->dev;
544 struct tas5720_data *data;
545 int ret;
546 int i;
547
548 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
549 if (!data)
550 return -ENOMEM;
551
552 data->tas5720_client = client;
553 data->regmap = devm_regmap_init_i2c(client, &tas5720_regmap_config);
554 if (IS_ERR(data->regmap)) {
555 ret = PTR_ERR(data->regmap);
556 dev_err(dev, "failed to allocate register map: %d\n", ret);
557 return ret;
558 }
559
560 for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
561 data->supplies[i].supply = tas5720_supply_names[i];
562
563 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies),
564 data->supplies);
565 if (ret != 0) {
566 dev_err(dev, "failed to request supplies: %d\n", ret);
567 return ret;
568 }
569
570 dev_set_drvdata(dev, data);
571
572 ret = snd_soc_register_codec(&client->dev,
573 &soc_codec_dev_tas5720,
574 tas5720_dai, ARRAY_SIZE(tas5720_dai));
575 if (ret < 0) {
576 dev_err(dev, "failed to register codec: %d\n", ret);
577 return ret;
578 }
579
580 return 0;
581}
582
583static int tas5720_remove(struct i2c_client *client)
584{
585 struct device *dev = &client->dev;
586
587 snd_soc_unregister_codec(dev);
588
589 return 0;
590}
591
592static const struct i2c_device_id tas5720_id[] = {
593 { "tas5720", 0 },
594 { }
595};
596MODULE_DEVICE_TABLE(i2c, tas5720_id);
597
598#if IS_ENABLED(CONFIG_OF)
599static const struct of_device_id tas5720_of_match[] = {
600 { .compatible = "ti,tas5720", },
601 { },
602};
603MODULE_DEVICE_TABLE(of, tas5720_of_match);
604#endif
605
606static struct i2c_driver tas5720_i2c_driver = {
607 .driver = {
608 .name = "tas5720",
609 .of_match_table = of_match_ptr(tas5720_of_match),
610 },
611 .probe = tas5720_probe,
612 .remove = tas5720_remove,
613 .id_table = tas5720_id,
614};
615
616module_i2c_driver(tas5720_i2c_driver);
617
618MODULE_AUTHOR("Andreas Dannenberg <dannenberg@ti.com>");
619MODULE_DESCRIPTION("TAS5720 Audio amplifier driver");
620MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tas5720.h b/sound/soc/codecs/tas5720.h
new file mode 100644
index 000000000000..3d077c779b12
--- /dev/null
+++ b/sound/soc/codecs/tas5720.h
@@ -0,0 +1,90 @@
1/*
2 * tas5720.h - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier
3 *
4 * Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com
5 *
6 * Author: Andreas Dannenberg <dannenberg@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
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#ifndef __TAS5720_H__
19#define __TAS5720_H__
20
21/* Register Address Map */
22#define TAS5720_DEVICE_ID_REG 0x00
23#define TAS5720_POWER_CTRL_REG 0x01
24#define TAS5720_DIGITAL_CTRL1_REG 0x02
25#define TAS5720_DIGITAL_CTRL2_REG 0x03
26#define TAS5720_VOLUME_CTRL_REG 0x04
27#define TAS5720_ANALOG_CTRL_REG 0x06
28#define TAS5720_FAULT_REG 0x08
29#define TAS5720_DIGITAL_CLIP2_REG 0x10
30#define TAS5720_DIGITAL_CLIP1_REG 0x11
31#define TAS5720_MAX_REG TAS5720_DIGITAL_CLIP1_REG
32
33/* TAS5720_DEVICE_ID_REG */
34#define TAS5720_DEVICE_ID 0x01
35
36/* TAS5720_POWER_CTRL_REG */
37#define TAS5720_DIG_CLIP_MASK GENMASK(7, 2)
38#define TAS5720_SLEEP BIT(1)
39#define TAS5720_SDZ BIT(0)
40
41/* TAS5720_DIGITAL_CTRL1_REG */
42#define TAS5720_HPF_BYPASS BIT(7)
43#define TAS5720_TDM_CFG_SRC BIT(6)
44#define TAS5720_SSZ_DS BIT(3)
45#define TAS5720_SAIF_RIGHTJ_24BIT (0x0)
46#define TAS5720_SAIF_RIGHTJ_20BIT (0x1)
47#define TAS5720_SAIF_RIGHTJ_18BIT (0x2)
48#define TAS5720_SAIF_RIGHTJ_16BIT (0x3)
49#define TAS5720_SAIF_I2S (0x4)
50#define TAS5720_SAIF_LEFTJ (0x5)
51#define TAS5720_SAIF_FORMAT_MASK GENMASK(2, 0)
52
53/* TAS5720_DIGITAL_CTRL2_REG */
54#define TAS5720_MUTE BIT(4)
55#define TAS5720_TDM_SLOT_SEL_MASK GENMASK(2, 0)
56
57/* TAS5720_ANALOG_CTRL_REG */
58#define TAS5720_PWM_RATE_6_3_FSYNC (0x0 << 4)
59#define TAS5720_PWM_RATE_8_4_FSYNC (0x1 << 4)
60#define TAS5720_PWM_RATE_10_5_FSYNC (0x2 << 4)
61#define TAS5720_PWM_RATE_12_6_FSYNC (0x3 << 4)
62#define TAS5720_PWM_RATE_14_7_FSYNC (0x4 << 4)
63#define TAS5720_PWM_RATE_16_8_FSYNC (0x5 << 4)
64#define TAS5720_PWM_RATE_20_10_FSYNC (0x6 << 4)
65#define TAS5720_PWM_RATE_24_12_FSYNC (0x7 << 4)
66#define TAS5720_PWM_RATE_MASK GENMASK(6, 4)
67#define TAS5720_ANALOG_GAIN_19_2DBV (0x0 << 2)
68#define TAS5720_ANALOG_GAIN_20_7DBV (0x1 << 2)
69#define TAS5720_ANALOG_GAIN_23_5DBV (0x2 << 2)
70#define TAS5720_ANALOG_GAIN_26_3DBV (0x3 << 2)
71#define TAS5720_ANALOG_GAIN_MASK GENMASK(3, 2)
72#define TAS5720_ANALOG_GAIN_SHIFT (0x2)
73
74/* TAS5720_FAULT_REG */
75#define TAS5720_OC_THRESH_100PCT (0x0 << 4)
76#define TAS5720_OC_THRESH_75PCT (0x1 << 4)
77#define TAS5720_OC_THRESH_50PCT (0x2 << 4)
78#define TAS5720_OC_THRESH_25PCT (0x3 << 4)
79#define TAS5720_OC_THRESH_MASK GENMASK(5, 4)
80#define TAS5720_CLKE BIT(3)
81#define TAS5720_OCE BIT(2)
82#define TAS5720_DCE BIT(1)
83#define TAS5720_OTE BIT(0)
84#define TAS5720_FAULT_MASK GENMASK(3, 0)
85
86/* TAS5720_DIGITAL_CLIP1_REG */
87#define TAS5720_CLIP1_MASK GENMASK(7, 2)
88#define TAS5720_CLIP1_SHIFT (0x2)
89
90#endif /* __TAS5720_H__ */
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index ee4def4f819f..3c5e1df01c19 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -28,6 +28,7 @@
28#include <linux/i2c.h> 28#include <linux/i2c.h>
29#include <linux/gpio.h> 29#include <linux/gpio.h>
30#include <linux/regulator/consumer.h> 30#include <linux/regulator/consumer.h>
31#include <linux/acpi.h>
31#include <linux/of.h> 32#include <linux/of.h>
32#include <linux/of_gpio.h> 33#include <linux/of_gpio.h>
33#include <linux/slab.h> 34#include <linux/slab.h>
@@ -1280,10 +1281,19 @@ static const struct i2c_device_id aic31xx_i2c_id[] = {
1280}; 1281};
1281MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); 1282MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id);
1282 1283
1284#ifdef CONFIG_ACPI
1285static const struct acpi_device_id aic31xx_acpi_match[] = {
1286 { "10TI3100", 0 },
1287 { }
1288};
1289MODULE_DEVICE_TABLE(acpi, aic31xx_acpi_match);
1290#endif
1291
1283static struct i2c_driver aic31xx_i2c_driver = { 1292static struct i2c_driver aic31xx_i2c_driver = {
1284 .driver = { 1293 .driver = {
1285 .name = "tlv320aic31xx-codec", 1294 .name = "tlv320aic31xx-codec",
1286 .of_match_table = of_match_ptr(tlv320aic31xx_of_match), 1295 .of_match_table = of_match_ptr(tlv320aic31xx_of_match),
1296 .acpi_match_table = ACPI_PTR(aic31xx_acpi_match),
1287 }, 1297 },
1288 .probe = aic31xx_i2c_probe, 1298 .probe = aic31xx_i2c_probe,
1289 .remove = aic31xx_i2c_remove, 1299 .remove = aic31xx_i2c_remove,
diff --git a/sound/soc/codecs/tlv320aic32x4-i2c.c b/sound/soc/codecs/tlv320aic32x4-i2c.c
new file mode 100644
index 000000000000..59606cf3008f
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic32x4-i2c.c
@@ -0,0 +1,74 @@
1/*
2 * linux/sound/soc/codecs/tlv320aic32x4-i2c.c
3 *
4 * Copyright 2011 NW Digital Radio
5 *
6 * Author: Jeremy McDermond <nh6z@nh6z.net>
7 *
8 * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */
20
21#include <linux/i2c.h>
22#include <linux/module.h>
23#include <linux/of.h>
24#include <linux/regmap.h>
25#include <sound/soc.h>
26
27#include "tlv320aic32x4.h"
28
29static int aic32x4_i2c_probe(struct i2c_client *i2c,
30 const struct i2c_device_id *id)
31{
32 struct regmap *regmap;
33 struct regmap_config config;
34
35 config = aic32x4_regmap_config;
36 config.reg_bits = 8;
37 config.val_bits = 8;
38
39 regmap = devm_regmap_init_i2c(i2c, &config);
40 return aic32x4_probe(&i2c->dev, regmap);
41}
42
43static int aic32x4_i2c_remove(struct i2c_client *i2c)
44{
45 return aic32x4_remove(&i2c->dev);
46}
47
48static const struct i2c_device_id aic32x4_i2c_id[] = {
49 { "tlv320aic32x4", 0 },
50 { /* sentinel */ }
51};
52MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id);
53
54static const struct of_device_id aic32x4_of_id[] = {
55 { .compatible = "ti,tlv320aic32x4", },
56 { /* senitel */ }
57};
58MODULE_DEVICE_TABLE(of, aic32x4_of_id);
59
60static struct i2c_driver aic32x4_i2c_driver = {
61 .driver = {
62 .name = "tlv320aic32x4",
63 .of_match_table = aic32x4_of_id,
64 },
65 .probe = aic32x4_i2c_probe,
66 .remove = aic32x4_i2c_remove,
67 .id_table = aic32x4_i2c_id,
68};
69
70module_i2c_driver(aic32x4_i2c_driver);
71
72MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver I2C");
73MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
74MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic32x4-spi.c b/sound/soc/codecs/tlv320aic32x4-spi.c
new file mode 100644
index 000000000000..724fcdd491b2
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic32x4-spi.c
@@ -0,0 +1,76 @@
1/*
2 * linux/sound/soc/codecs/tlv320aic32x4-spi.c
3 *
4 * Copyright 2011 NW Digital Radio
5 *
6 * Author: Jeremy McDermond <nh6z@nh6z.net>
7 *
8 * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */
20
21#include <linux/spi/spi.h>
22#include <linux/module.h>
23#include <linux/of.h>
24#include <linux/regmap.h>
25#include <sound/soc.h>
26
27#include "tlv320aic32x4.h"
28
29static int aic32x4_spi_probe(struct spi_device *spi)
30{
31 struct regmap *regmap;
32 struct regmap_config config;
33
34 config = aic32x4_regmap_config;
35 config.reg_bits = 7;
36 config.pad_bits = 1;
37 config.val_bits = 8;
38 config.read_flag_mask = 0x01;
39
40 regmap = devm_regmap_init_spi(spi, &config);
41 return aic32x4_probe(&spi->dev, regmap);
42}
43
44static int aic32x4_spi_remove(struct spi_device *spi)
45{
46 return aic32x4_remove(&spi->dev);
47}
48
49static const struct spi_device_id aic32x4_spi_id[] = {
50 { "tlv320aic32x4", 0 },
51 { /* sentinel */ }
52};
53MODULE_DEVICE_TABLE(spi, aic32x4_spi_id);
54
55static const struct of_device_id aic32x4_of_id[] = {
56 { .compatible = "ti,tlv320aic32x4", },
57 { /* senitel */ }
58};
59MODULE_DEVICE_TABLE(of, aic32x4_of_id);
60
61static struct spi_driver aic32x4_spi_driver = {
62 .driver = {
63 .name = "tlv320aic32x4",
64 .owner = THIS_MODULE,
65 .of_match_table = aic32x4_of_id,
66 },
67 .probe = aic32x4_spi_probe,
68 .remove = aic32x4_spi_remove,
69 .id_table = aic32x4_spi_id,
70};
71
72module_spi_driver(aic32x4_spi_driver);
73
74MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver SPI");
75MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
76MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index f2d3191961e1..85d4978d0384 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -30,7 +30,6 @@
30#include <linux/pm.h> 30#include <linux/pm.h>
31#include <linux/gpio.h> 31#include <linux/gpio.h>
32#include <linux/of_gpio.h> 32#include <linux/of_gpio.h>
33#include <linux/i2c.h>
34#include <linux/cdev.h> 33#include <linux/cdev.h>
35#include <linux/slab.h> 34#include <linux/slab.h>
36#include <linux/clk.h> 35#include <linux/clk.h>
@@ -160,7 +159,10 @@ static const struct aic32x4_rate_divs aic32x4_divs[] = {
160 /* 48k rate */ 159 /* 48k rate */
161 {AIC32X4_FREQ_12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4}, 160 {AIC32X4_FREQ_12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4},
162 {AIC32X4_FREQ_24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4}, 161 {AIC32X4_FREQ_24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4},
163 {AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4} 162 {AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4},
163
164 /* 96k rate */
165 {AIC32X4_FREQ_25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1},
164}; 166};
165 167
166static const struct snd_kcontrol_new hpl_output_mixer_controls[] = { 168static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
@@ -181,16 +183,71 @@ static const struct snd_kcontrol_new lor_output_mixer_controls[] = {
181 SOC_DAPM_SINGLE("R_DAC Switch", AIC32X4_LORROUTE, 3, 1, 0), 183 SOC_DAPM_SINGLE("R_DAC Switch", AIC32X4_LORROUTE, 3, 1, 0),
182}; 184};
183 185
184static const struct snd_kcontrol_new left_input_mixer_controls[] = { 186static const char * const resistor_text[] = {
185 SOC_DAPM_SINGLE("IN1_L P Switch", AIC32X4_LMICPGAPIN, 6, 1, 0), 187 "Off", "10 kOhm", "20 kOhm", "40 kOhm",
186 SOC_DAPM_SINGLE("IN2_L P Switch", AIC32X4_LMICPGAPIN, 4, 1, 0),
187 SOC_DAPM_SINGLE("IN3_L P Switch", AIC32X4_LMICPGAPIN, 2, 1, 0),
188}; 188};
189 189
190static const struct snd_kcontrol_new right_input_mixer_controls[] = { 190/* Left mixer pins */
191 SOC_DAPM_SINGLE("IN1_R P Switch", AIC32X4_RMICPGAPIN, 6, 1, 0), 191static SOC_ENUM_SINGLE_DECL(in1l_lpga_p_enum, AIC32X4_LMICPGAPIN, 6, resistor_text);
192 SOC_DAPM_SINGLE("IN2_R P Switch", AIC32X4_RMICPGAPIN, 4, 1, 0), 192static SOC_ENUM_SINGLE_DECL(in2l_lpga_p_enum, AIC32X4_LMICPGAPIN, 4, resistor_text);
193 SOC_DAPM_SINGLE("IN3_R P Switch", AIC32X4_RMICPGAPIN, 2, 1, 0), 193static SOC_ENUM_SINGLE_DECL(in3l_lpga_p_enum, AIC32X4_LMICPGAPIN, 2, resistor_text);
194static SOC_ENUM_SINGLE_DECL(in1r_lpga_p_enum, AIC32X4_LMICPGAPIN, 0, resistor_text);
195
196static SOC_ENUM_SINGLE_DECL(cml_lpga_n_enum, AIC32X4_LMICPGANIN, 6, resistor_text);
197static SOC_ENUM_SINGLE_DECL(in2r_lpga_n_enum, AIC32X4_LMICPGANIN, 4, resistor_text);
198static SOC_ENUM_SINGLE_DECL(in3r_lpga_n_enum, AIC32X4_LMICPGANIN, 2, resistor_text);
199
200static const struct snd_kcontrol_new in1l_to_lmixer_controls[] = {
201 SOC_DAPM_ENUM("IN1_L L+ Switch", in1l_lpga_p_enum),
202};
203static const struct snd_kcontrol_new in2l_to_lmixer_controls[] = {
204 SOC_DAPM_ENUM("IN2_L L+ Switch", in2l_lpga_p_enum),
205};
206static const struct snd_kcontrol_new in3l_to_lmixer_controls[] = {
207 SOC_DAPM_ENUM("IN3_L L+ Switch", in3l_lpga_p_enum),
208};
209static const struct snd_kcontrol_new in1r_to_lmixer_controls[] = {
210 SOC_DAPM_ENUM("IN1_R L+ Switch", in1r_lpga_p_enum),
211};
212static const struct snd_kcontrol_new cml_to_lmixer_controls[] = {
213 SOC_DAPM_ENUM("CM_L L- Switch", cml_lpga_n_enum),
214};
215static const struct snd_kcontrol_new in2r_to_lmixer_controls[] = {
216 SOC_DAPM_ENUM("IN2_R L- Switch", in2r_lpga_n_enum),
217};
218static const struct snd_kcontrol_new in3r_to_lmixer_controls[] = {
219 SOC_DAPM_ENUM("IN3_R L- Switch", in3r_lpga_n_enum),
220};
221
222/* Right mixer pins */
223static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, resistor_text);
224static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, resistor_text);
225static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, resistor_text);
226static SOC_ENUM_SINGLE_DECL(in2l_rpga_p_enum, AIC32X4_RMICPGAPIN, 0, resistor_text);
227static SOC_ENUM_SINGLE_DECL(cmr_rpga_n_enum, AIC32X4_RMICPGANIN, 6, resistor_text);
228static SOC_ENUM_SINGLE_DECL(in1l_rpga_n_enum, AIC32X4_RMICPGANIN, 4, resistor_text);
229static SOC_ENUM_SINGLE_DECL(in3l_rpga_n_enum, AIC32X4_RMICPGANIN, 2, resistor_text);
230
231static const struct snd_kcontrol_new in1r_to_rmixer_controls[] = {
232 SOC_DAPM_ENUM("IN1_R R+ Switch", in1r_rpga_p_enum),
233};
234static const struct snd_kcontrol_new in2r_to_rmixer_controls[] = {
235 SOC_DAPM_ENUM("IN2_R R+ Switch", in2r_rpga_p_enum),
236};
237static const struct snd_kcontrol_new in3r_to_rmixer_controls[] = {
238 SOC_DAPM_ENUM("IN3_R R+ Switch", in3r_rpga_p_enum),
239};
240static const struct snd_kcontrol_new in2l_to_rmixer_controls[] = {
241 SOC_DAPM_ENUM("IN2_L R+ Switch", in2l_rpga_p_enum),
242};
243static const struct snd_kcontrol_new cmr_to_rmixer_controls[] = {
244 SOC_DAPM_ENUM("CM_R R- Switch", cmr_rpga_n_enum),
245};
246static const struct snd_kcontrol_new in1l_to_rmixer_controls[] = {
247 SOC_DAPM_ENUM("IN1_L R- Switch", in1l_rpga_n_enum),
248};
249static const struct snd_kcontrol_new in3l_to_rmixer_controls[] = {
250 SOC_DAPM_ENUM("IN3_L R- Switch", in3l_rpga_n_enum),
194}; 251};
195 252
196static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { 253static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
@@ -214,14 +271,39 @@ static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
214 &lor_output_mixer_controls[0], 271 &lor_output_mixer_controls[0],
215 ARRAY_SIZE(lor_output_mixer_controls)), 272 ARRAY_SIZE(lor_output_mixer_controls)),
216 SND_SOC_DAPM_PGA("LOR Power", AIC32X4_OUTPWRCTL, 2, 0, NULL, 0), 273 SND_SOC_DAPM_PGA("LOR Power", AIC32X4_OUTPWRCTL, 2, 0, NULL, 0),
217 SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0, 274
218 &left_input_mixer_controls[0],
219 ARRAY_SIZE(left_input_mixer_controls)),
220 SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0,
221 &right_input_mixer_controls[0],
222 ARRAY_SIZE(right_input_mixer_controls)),
223 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", AIC32X4_ADCSETUP, 7, 0),
224 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", AIC32X4_ADCSETUP, 6, 0), 275 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", AIC32X4_ADCSETUP, 6, 0),
276 SND_SOC_DAPM_MUX("IN1_R to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
277 in1r_to_rmixer_controls),
278 SND_SOC_DAPM_MUX("IN2_R to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
279 in2r_to_rmixer_controls),
280 SND_SOC_DAPM_MUX("IN3_R to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
281 in3r_to_rmixer_controls),
282 SND_SOC_DAPM_MUX("IN2_L to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
283 in2l_to_rmixer_controls),
284 SND_SOC_DAPM_MUX("CM_R to Right Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
285 cmr_to_rmixer_controls),
286 SND_SOC_DAPM_MUX("IN1_L to Right Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
287 in1l_to_rmixer_controls),
288 SND_SOC_DAPM_MUX("IN3_L to Right Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
289 in3l_to_rmixer_controls),
290
291 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", AIC32X4_ADCSETUP, 7, 0),
292 SND_SOC_DAPM_MUX("IN1_L to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
293 in1l_to_lmixer_controls),
294 SND_SOC_DAPM_MUX("IN2_L to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
295 in2l_to_lmixer_controls),
296 SND_SOC_DAPM_MUX("IN3_L to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
297 in3l_to_lmixer_controls),
298 SND_SOC_DAPM_MUX("IN1_R to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0,
299 in1r_to_lmixer_controls),
300 SND_SOC_DAPM_MUX("CM_L to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
301 cml_to_lmixer_controls),
302 SND_SOC_DAPM_MUX("IN2_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
303 in2r_to_lmixer_controls),
304 SND_SOC_DAPM_MUX("IN3_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
305 in3r_to_lmixer_controls),
306
225 SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0), 307 SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0),
226 308
227 SND_SOC_DAPM_OUTPUT("HPL"), 309 SND_SOC_DAPM_OUTPUT("HPL"),
@@ -261,19 +343,77 @@ static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = {
261 {"LOR Power", NULL, "LOR Output Mixer"}, 343 {"LOR Power", NULL, "LOR Output Mixer"},
262 {"LOR", NULL, "LOR Power"}, 344 {"LOR", NULL, "LOR Power"},
263 345
264 /* Left input */
265 {"Left Input Mixer", "IN1_L P Switch", "IN1_L"},
266 {"Left Input Mixer", "IN2_L P Switch", "IN2_L"},
267 {"Left Input Mixer", "IN3_L P Switch", "IN3_L"},
268
269 {"Left ADC", NULL, "Left Input Mixer"},
270
271 /* Right Input */ 346 /* Right Input */
272 {"Right Input Mixer", "IN1_R P Switch", "IN1_R"}, 347 {"Right ADC", NULL, "IN1_R to Right Mixer Positive Resistor"},
273 {"Right Input Mixer", "IN2_R P Switch", "IN2_R"}, 348 {"IN1_R to Right Mixer Positive Resistor", "10 kOhm", "IN1_R"},
274 {"Right Input Mixer", "IN3_R P Switch", "IN3_R"}, 349 {"IN1_R to Right Mixer Positive Resistor", "20 kOhm", "IN1_R"},
275 350 {"IN1_R to Right Mixer Positive Resistor", "40 kOhm", "IN1_R"},
276 {"Right ADC", NULL, "Right Input Mixer"}, 351
352 {"Right ADC", NULL, "IN2_R to Right Mixer Positive Resistor"},
353 {"IN2_R to Right Mixer Positive Resistor", "10 kOhm", "IN2_R"},
354 {"IN2_R to Right Mixer Positive Resistor", "20 kOhm", "IN2_R"},
355 {"IN2_R to Right Mixer Positive Resistor", "40 kOhm", "IN2_R"},
356
357 {"Right ADC", NULL, "IN3_R to Right Mixer Positive Resistor"},
358 {"IN3_R to Right Mixer Positive Resistor", "10 kOhm", "IN3_R"},
359 {"IN3_R to Right Mixer Positive Resistor", "20 kOhm", "IN3_R"},
360 {"IN3_R to Right Mixer Positive Resistor", "40 kOhm", "IN3_R"},
361
362 {"Right ADC", NULL, "IN2_L to Right Mixer Positive Resistor"},
363 {"IN2_L to Right Mixer Positive Resistor", "10 kOhm", "IN2_L"},
364 {"IN2_L to Right Mixer Positive Resistor", "20 kOhm", "IN2_L"},
365 {"IN2_L to Right Mixer Positive Resistor", "40 kOhm", "IN2_L"},
366
367 {"Right ADC", NULL, "CM_R to Right Mixer Negative Resistor"},
368 {"CM_R to Right Mixer Negative Resistor", "10 kOhm", "CM_R"},
369 {"CM_R to Right Mixer Negative Resistor", "20 kOhm", "CM_R"},
370 {"CM_R to Right Mixer Negative Resistor", "40 kOhm", "CM_R"},
371
372 {"Right ADC", NULL, "IN1_L to Right Mixer Negative Resistor"},
373 {"IN1_L to Right Mixer Negative Resistor", "10 kOhm", "IN1_L"},
374 {"IN1_L to Right Mixer Negative Resistor", "20 kOhm", "IN1_L"},
375 {"IN1_L to Right Mixer Negative Resistor", "40 kOhm", "IN1_L"},
376
377 {"Right ADC", NULL, "IN3_L to Right Mixer Negative Resistor"},
378 {"IN3_L to Right Mixer Negative Resistor", "10 kOhm", "IN3_L"},
379 {"IN3_L to Right Mixer Negative Resistor", "20 kOhm", "IN3_L"},
380 {"IN3_L to Right Mixer Negative Resistor", "40 kOhm", "IN3_L"},
381
382 /* Left Input */
383 {"Left ADC", NULL, "IN1_L to Left Mixer Positive Resistor"},
384 {"IN1_L to Left Mixer Positive Resistor", "10 kOhm", "IN1_L"},
385 {"IN1_L to Left Mixer Positive Resistor", "20 kOhm", "IN1_L"},
386 {"IN1_L to Left Mixer Positive Resistor", "40 kOhm", "IN1_L"},
387
388 {"Left ADC", NULL, "IN2_L to Left Mixer Positive Resistor"},
389 {"IN2_L to Left Mixer Positive Resistor", "10 kOhm", "IN2_L"},
390 {"IN2_L to Left Mixer Positive Resistor", "20 kOhm", "IN2_L"},
391 {"IN2_L to Left Mixer Positive Resistor", "40 kOhm", "IN2_L"},
392
393 {"Left ADC", NULL, "IN3_L to Left Mixer Positive Resistor"},
394 {"IN3_L to Left Mixer Positive Resistor", "10 kOhm", "IN3_L"},
395 {"IN3_L to Left Mixer Positive Resistor", "20 kOhm", "IN3_L"},
396 {"IN3_L to Left Mixer Positive Resistor", "40 kOhm", "IN3_L"},
397
398 {"Left ADC", NULL, "IN1_R to Left Mixer Positive Resistor"},
399 {"IN1_R to Left Mixer Positive Resistor", "10 kOhm", "IN1_R"},
400 {"IN1_R to Left Mixer Positive Resistor", "20 kOhm", "IN1_R"},
401 {"IN1_R to Left Mixer Positive Resistor", "40 kOhm", "IN1_R"},
402
403 {"Left ADC", NULL, "CM_L to Left Mixer Negative Resistor"},
404 {"CM_L to Left Mixer Negative Resistor", "10 kOhm", "CM_L"},
405 {"CM_L to Left Mixer Negative Resistor", "20 kOhm", "CM_L"},
406 {"CM_L to Left Mixer Negative Resistor", "40 kOhm", "CM_L"},
407
408 {"Left ADC", NULL, "IN2_R to Left Mixer Negative Resistor"},
409 {"IN2_R to Left Mixer Negative Resistor", "10 kOhm", "IN2_R"},
410 {"IN2_R to Left Mixer Negative Resistor", "20 kOhm", "IN2_R"},
411 {"IN2_R to Left Mixer Negative Resistor", "40 kOhm", "IN2_R"},
412
413 {"Left ADC", NULL, "IN3_R to Left Mixer Negative Resistor"},
414 {"IN3_R to Left Mixer Negative Resistor", "10 kOhm", "IN3_R"},
415 {"IN3_R to Left Mixer Negative Resistor", "20 kOhm", "IN3_R"},
416 {"IN3_R to Left Mixer Negative Resistor", "40 kOhm", "IN3_R"},
277}; 417};
278 418
279static const struct regmap_range_cfg aic32x4_regmap_pages[] = { 419static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
@@ -287,14 +427,12 @@ static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
287 }, 427 },
288}; 428};
289 429
290static const struct regmap_config aic32x4_regmap = { 430const struct regmap_config aic32x4_regmap_config = {
291 .reg_bits = 8,
292 .val_bits = 8,
293
294 .max_register = AIC32X4_RMICPGAVOL, 431 .max_register = AIC32X4_RMICPGAVOL,
295 .ranges = aic32x4_regmap_pages, 432 .ranges = aic32x4_regmap_pages,
296 .num_ranges = ARRAY_SIZE(aic32x4_regmap_pages), 433 .num_ranges = ARRAY_SIZE(aic32x4_regmap_pages),
297}; 434};
435EXPORT_SYMBOL(aic32x4_regmap_config);
298 436
299static inline int aic32x4_get_divs(int mclk, int rate) 437static inline int aic32x4_get_divs(int mclk, int rate)
300{ 438{
@@ -567,7 +705,7 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
567 return 0; 705 return 0;
568} 706}
569 707
570#define AIC32X4_RATES SNDRV_PCM_RATE_8000_48000 708#define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000
571#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ 709#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
572 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) 710 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
573 711
@@ -596,7 +734,7 @@ static struct snd_soc_dai_driver aic32x4_dai = {
596 .symmetric_rates = 1, 734 .symmetric_rates = 1,
597}; 735};
598 736
599static int aic32x4_probe(struct snd_soc_codec *codec) 737static int aic32x4_codec_probe(struct snd_soc_codec *codec)
600{ 738{
601 struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); 739 struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
602 u32 tmp_reg; 740 u32 tmp_reg;
@@ -655,7 +793,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
655} 793}
656 794
657static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { 795static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
658 .probe = aic32x4_probe, 796 .probe = aic32x4_codec_probe,
659 .set_bias_level = aic32x4_set_bias_level, 797 .set_bias_level = aic32x4_set_bias_level,
660 .suspend_bias_off = true, 798 .suspend_bias_off = true,
661 799
@@ -777,24 +915,22 @@ error_ldo:
777 return ret; 915 return ret;
778} 916}
779 917
780static int aic32x4_i2c_probe(struct i2c_client *i2c, 918int aic32x4_probe(struct device *dev, struct regmap *regmap)
781 const struct i2c_device_id *id)
782{ 919{
783 struct aic32x4_pdata *pdata = i2c->dev.platform_data;
784 struct aic32x4_priv *aic32x4; 920 struct aic32x4_priv *aic32x4;
785 struct device_node *np = i2c->dev.of_node; 921 struct aic32x4_pdata *pdata = dev->platform_data;
922 struct device_node *np = dev->of_node;
786 int ret; 923 int ret;
787 924
788 aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), 925 if (IS_ERR(regmap))
926 return PTR_ERR(regmap);
927
928 aic32x4 = devm_kzalloc(dev, sizeof(struct aic32x4_priv),
789 GFP_KERNEL); 929 GFP_KERNEL);
790 if (aic32x4 == NULL) 930 if (aic32x4 == NULL)
791 return -ENOMEM; 931 return -ENOMEM;
792 932
793 aic32x4->regmap = devm_regmap_init_i2c(i2c, &aic32x4_regmap); 933 dev_set_drvdata(dev, aic32x4);
794 if (IS_ERR(aic32x4->regmap))
795 return PTR_ERR(aic32x4->regmap);
796
797 i2c_set_clientdata(i2c, aic32x4);
798 934
799 if (pdata) { 935 if (pdata) {
800 aic32x4->power_cfg = pdata->power_cfg; 936 aic32x4->power_cfg = pdata->power_cfg;
@@ -804,7 +940,7 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c,
804 } else if (np) { 940 } else if (np) {
805 ret = aic32x4_parse_dt(aic32x4, np); 941 ret = aic32x4_parse_dt(aic32x4, np);
806 if (ret) { 942 if (ret) {
807 dev_err(&i2c->dev, "Failed to parse DT node\n"); 943 dev_err(dev, "Failed to parse DT node\n");
808 return ret; 944 return ret;
809 } 945 }
810 } else { 946 } else {
@@ -814,71 +950,48 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c,
814 aic32x4->rstn_gpio = -1; 950 aic32x4->rstn_gpio = -1;
815 } 951 }
816 952
817 aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk"); 953 aic32x4->mclk = devm_clk_get(dev, "mclk");
818 if (IS_ERR(aic32x4->mclk)) { 954 if (IS_ERR(aic32x4->mclk)) {
819 dev_err(&i2c->dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); 955 dev_err(dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n");
820 return PTR_ERR(aic32x4->mclk); 956 return PTR_ERR(aic32x4->mclk);
821 } 957 }
822 958
823 if (gpio_is_valid(aic32x4->rstn_gpio)) { 959 if (gpio_is_valid(aic32x4->rstn_gpio)) {
824 ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, 960 ret = devm_gpio_request_one(dev, aic32x4->rstn_gpio,
825 GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); 961 GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
826 if (ret != 0) 962 if (ret != 0)
827 return ret; 963 return ret;
828 } 964 }
829 965
830 ret = aic32x4_setup_regulators(&i2c->dev, aic32x4); 966 ret = aic32x4_setup_regulators(dev, aic32x4);
831 if (ret) { 967 if (ret) {
832 dev_err(&i2c->dev, "Failed to setup regulators\n"); 968 dev_err(dev, "Failed to setup regulators\n");
833 return ret; 969 return ret;
834 } 970 }
835 971
836 ret = snd_soc_register_codec(&i2c->dev, 972 ret = snd_soc_register_codec(dev,
837 &soc_codec_dev_aic32x4, &aic32x4_dai, 1); 973 &soc_codec_dev_aic32x4, &aic32x4_dai, 1);
838 if (ret) { 974 if (ret) {
839 dev_err(&i2c->dev, "Failed to register codec\n"); 975 dev_err(dev, "Failed to register codec\n");
840 aic32x4_disable_regulators(aic32x4); 976 aic32x4_disable_regulators(aic32x4);
841 return ret; 977 return ret;
842 } 978 }
843 979
844 i2c_set_clientdata(i2c, aic32x4);
845
846 return 0; 980 return 0;
847} 981}
982EXPORT_SYMBOL(aic32x4_probe);
848 983
849static int aic32x4_i2c_remove(struct i2c_client *client) 984int aic32x4_remove(struct device *dev)
850{ 985{
851 struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client); 986 struct aic32x4_priv *aic32x4 = dev_get_drvdata(dev);
852 987
853 aic32x4_disable_regulators(aic32x4); 988 aic32x4_disable_regulators(aic32x4);
854 989
855 snd_soc_unregister_codec(&client->dev); 990 snd_soc_unregister_codec(dev);
991
856 return 0; 992 return 0;
857} 993}
858 994EXPORT_SYMBOL(aic32x4_remove);
859static const struct i2c_device_id aic32x4_i2c_id[] = {
860 { "tlv320aic32x4", 0 },
861 { }
862};
863MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id);
864
865static const struct of_device_id aic32x4_of_id[] = {
866 { .compatible = "ti,tlv320aic32x4", },
867 { /* senitel */ }
868};
869MODULE_DEVICE_TABLE(of, aic32x4_of_id);
870
871static struct i2c_driver aic32x4_i2c_driver = {
872 .driver = {
873 .name = "tlv320aic32x4",
874 .of_match_table = aic32x4_of_id,
875 },
876 .probe = aic32x4_i2c_probe,
877 .remove = aic32x4_i2c_remove,
878 .id_table = aic32x4_i2c_id,
879};
880
881module_i2c_driver(aic32x4_i2c_driver);
882 995
883MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); 996MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver");
884MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); 997MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
diff --git a/sound/soc/codecs/tlv320aic32x4.h b/sound/soc/codecs/tlv320aic32x4.h
index 995f033a855d..a197dd51addc 100644
--- a/sound/soc/codecs/tlv320aic32x4.h
+++ b/sound/soc/codecs/tlv320aic32x4.h
@@ -10,6 +10,13 @@
10#ifndef _TLV320AIC32X4_H 10#ifndef _TLV320AIC32X4_H
11#define _TLV320AIC32X4_H 11#define _TLV320AIC32X4_H
12 12
13struct device;
14struct regmap_config;
15
16extern const struct regmap_config aic32x4_regmap_config;
17int aic32x4_probe(struct device *dev, struct regmap *regmap);
18int aic32x4_remove(struct device *dev);
19
13/* tlv320aic32x4 register space (in decimal to match datasheet) */ 20/* tlv320aic32x4 register space (in decimal to match datasheet) */
14 21
15#define AIC32X4_PAGE1 128 22#define AIC32X4_PAGE1 128
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index bc3de2e844e6..1f7081043566 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -824,7 +824,7 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
824{ 824{
825 struct twl6040 *twl6040 = codec->control_data; 825 struct twl6040 *twl6040 = codec->control_data;
826 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 826 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
827 int ret; 827 int ret = 0;
828 828
829 switch (level) { 829 switch (level) {
830 case SND_SOC_BIAS_ON: 830 case SND_SOC_BIAS_ON:
@@ -832,12 +832,16 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
832 case SND_SOC_BIAS_PREPARE: 832 case SND_SOC_BIAS_PREPARE:
833 break; 833 break;
834 case SND_SOC_BIAS_STANDBY: 834 case SND_SOC_BIAS_STANDBY:
835 if (priv->codec_powered) 835 if (priv->codec_powered) {
836 /* Select low power PLL in standby */
837 ret = twl6040_set_pll(twl6040, TWL6040_SYSCLK_SEL_LPPLL,
838 32768, 19200000);
836 break; 839 break;
840 }
837 841
838 ret = twl6040_power(twl6040, 1); 842 ret = twl6040_power(twl6040, 1);
839 if (ret) 843 if (ret)
840 return ret; 844 break;
841 845
842 priv->codec_powered = 1; 846 priv->codec_powered = 1;
843 847
@@ -853,7 +857,7 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
853 break; 857 break;
854 } 858 }
855 859
856 return 0; 860 return ret;
857} 861}
858 862
859static int twl6040_startup(struct snd_pcm_substream *substream, 863static int twl6040_startup(struct snd_pcm_substream *substream,
@@ -983,9 +987,9 @@ static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id i
983 if (mute) { 987 if (mute) {
984 /* Power down drivers and DACs */ 988 /* Power down drivers and DACs */
985 hflctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | 989 hflctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA |
986 TWL6040_HFDRVENA); 990 TWL6040_HFDRVENA | TWL6040_HFSWENA);
987 hfrctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | 991 hfrctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA |
988 TWL6040_HFDRVENA); 992 TWL6040_HFDRVENA | TWL6040_HFSWENA);
989 } 993 }
990 994
991 twl6040_reg_write(twl6040, TWL6040_REG_HFLCTL, hflctl); 995 twl6040_reg_write(twl6040, TWL6040_REG_HFLCTL, hflctl);
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 720a14e0687d..0100e28f40dc 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3798,9 +3798,8 @@ static int wm8962_runtime_resume(struct device *dev)
3798 ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies), 3798 ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
3799 wm8962->supplies); 3799 wm8962->supplies);
3800 if (ret != 0) { 3800 if (ret != 0) {
3801 dev_err(dev, 3801 dev_err(dev, "Failed to enable supplies: %d\n", ret);
3802 "Failed to enable supplies: %d\n", ret); 3802 goto disable_clock;
3803 return ret;
3804 } 3803 }
3805 3804
3806 regcache_cache_only(wm8962->regmap, false); 3805 regcache_cache_only(wm8962->regmap, false);
@@ -3838,6 +3837,10 @@ static int wm8962_runtime_resume(struct device *dev)
3838 msleep(5); 3837 msleep(5);
3839 3838
3840 return 0; 3839 return 0;
3840
3841disable_clock:
3842 clk_disable_unprepare(wm8962->pdata.mclk);
3843 return ret;
3841} 3844}
3842 3845
3843static int wm8962_runtime_suspend(struct device *dev) 3846static int wm8962_runtime_suspend(struct device *dev)
diff --git a/sound/soc/codecs/wm8962.h b/sound/soc/codecs/wm8962.h
index 910aafd09d21..e63a318a3015 100644
--- a/sound/soc/codecs/wm8962.h
+++ b/sound/soc/codecs/wm8962.h
@@ -16,9 +16,9 @@
16#include <asm/types.h> 16#include <asm/types.h>
17#include <sound/soc.h> 17#include <sound/soc.h>
18 18
19#define WM8962_SYSCLK_MCLK 1 19#define WM8962_SYSCLK_MCLK 0
20#define WM8962_SYSCLK_FLL 2 20#define WM8962_SYSCLK_FLL 1
21#define WM8962_SYSCLK_PLL3 3 21#define WM8962_SYSCLK_PLL3 2
22 22
23#define WM8962_FLL 1 23#define WM8962_FLL 1
24 24
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 2389ab47e25f..466492b7d4f5 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -643,6 +643,7 @@ MODULE_DEVICE_TABLE(of, asoc_simple_of_match);
643static struct platform_driver asoc_simple_card = { 643static struct platform_driver asoc_simple_card = {
644 .driver = { 644 .driver = {
645 .name = "asoc-simple-card", 645 .name = "asoc-simple-card",
646 .pm = &snd_soc_pm_ops,
646 .of_match_table = asoc_simple_of_match, 647 .of_match_table = asoc_simple_of_match,
647 }, 648 },
648 .probe = asoc_simple_card_probe, 649 .probe = asoc_simple_card_probe,
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig
index 132bb83f8e99..bc3c7b5ac752 100644
--- a/sound/soc/kirkwood/Kconfig
+++ b/sound/soc/kirkwood/Kconfig
@@ -1,6 +1,7 @@
1config SND_KIRKWOOD_SOC 1config 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_DOVE || ARCH_MVEBU || COMPILE_TEST 3 depends on ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST
4 depends on HAS_DMA
4 help 5 help
5 Say Y or M if you want to add support for codecs attached to 6 Say Y or M if you want to add support for codecs attached to
6 the Kirkwood I2S interface. You will also need to select the 7 the Kirkwood I2S interface. You will also need to select the
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index f7e789e97fbc..3abf51c07851 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -43,6 +43,7 @@ config SND_SOC_MT8173_RT5650_RT5676
43 depends on SND_SOC_MEDIATEK && I2C 43 depends on SND_SOC_MEDIATEK && I2C
44 select SND_SOC_RT5645 44 select SND_SOC_RT5645
45 select SND_SOC_RT5677 45 select SND_SOC_RT5677
46 select SND_SOC_HDMI_CODEC
46 help 47 help
47 This adds ASoC driver for Mediatek MT8173 boards 48 This adds ASoC driver for Mediatek MT8173 boards
48 with the RT5650 and RT5676 codecs. 49 with the RT5650 and RT5676 codecs.
diff --git a/sound/soc/mediatek/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173-rt5650-rt5676.c
index 5c4c58c69c51..bb593926c62d 100644
--- a/sound/soc/mediatek/mt8173-rt5650-rt5676.c
+++ b/sound/soc/mediatek/mt8173-rt5650-rt5676.c
@@ -134,7 +134,9 @@ static struct snd_soc_dai_link_component mt8173_rt5650_rt5676_codecs[] = {
134enum { 134enum {
135 DAI_LINK_PLAYBACK, 135 DAI_LINK_PLAYBACK,
136 DAI_LINK_CAPTURE, 136 DAI_LINK_CAPTURE,
137 DAI_LINK_HDMI,
137 DAI_LINK_CODEC_I2S, 138 DAI_LINK_CODEC_I2S,
139 DAI_LINK_HDMI_I2S,
138 DAI_LINK_INTERCODEC 140 DAI_LINK_INTERCODEC
139}; 141};
140 142
@@ -161,6 +163,16 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
161 .dynamic = 1, 163 .dynamic = 1,
162 .dpcm_capture = 1, 164 .dpcm_capture = 1,
163 }, 165 },
166 [DAI_LINK_HDMI] = {
167 .name = "HDMI",
168 .stream_name = "HDMI PCM",
169 .cpu_dai_name = "HDMI",
170 .codec_name = "snd-soc-dummy",
171 .codec_dai_name = "snd-soc-dummy-dai",
172 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
173 .dynamic = 1,
174 .dpcm_playback = 1,
175 },
164 176
165 /* Back End DAI links */ 177 /* Back End DAI links */
166 [DAI_LINK_CODEC_I2S] = { 178 [DAI_LINK_CODEC_I2S] = {
@@ -177,6 +189,13 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
177 .dpcm_playback = 1, 189 .dpcm_playback = 1,
178 .dpcm_capture = 1, 190 .dpcm_capture = 1,
179 }, 191 },
192 [DAI_LINK_HDMI_I2S] = {
193 .name = "HDMI BE",
194 .cpu_dai_name = "HDMIO",
195 .no_pcm = 1,
196 .codec_dai_name = "i2s-hifi",
197 .dpcm_playback = 1,
198 },
180 /* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */ 199 /* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */
181 [DAI_LINK_INTERCODEC] = { 200 [DAI_LINK_INTERCODEC] = {
182 .name = "rt5650_rt5676 intercodec", 201 .name = "rt5650_rt5676 intercodec",
@@ -251,6 +270,14 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev)
251 mt8173_rt5650_rt5676_dais[DAI_LINK_INTERCODEC].codec_of_node = 270 mt8173_rt5650_rt5676_dais[DAI_LINK_INTERCODEC].codec_of_node =
252 mt8173_rt5650_rt5676_codecs[1].of_node; 271 mt8173_rt5650_rt5676_codecs[1].of_node;
253 272
273 mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codec_of_node =
274 of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 2);
275 if (!mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codec_of_node) {
276 dev_err(&pdev->dev,
277 "Property 'audio-codec' missing or invalid\n");
278 return -EINVAL;
279 }
280
254 card->dev = &pdev->dev; 281 card->dev = &pdev->dev;
255 platform_set_drvdata(pdev, card); 282 platform_set_drvdata(pdev, card);
256 283
diff --git a/sound/soc/mediatek/mt8173-rt5650.c b/sound/soc/mediatek/mt8173-rt5650.c
index bb09bb1b7f1c..a27a6673dbe3 100644
--- a/sound/soc/mediatek/mt8173-rt5650.c
+++ b/sound/soc/mediatek/mt8173-rt5650.c
@@ -85,12 +85,29 @@ static int mt8173_rt5650_init(struct snd_soc_pcm_runtime *runtime)
85{ 85{
86 struct snd_soc_card *card = runtime->card; 86 struct snd_soc_card *card = runtime->card;
87 struct snd_soc_codec *codec = runtime->codec_dais[0]->codec; 87 struct snd_soc_codec *codec = runtime->codec_dais[0]->codec;
88 const char *codec_capture_dai = runtime->codec_dais[1]->name;
88 int ret; 89 int ret;
89 90
90 rt5645_sel_asrc_clk_src(codec, 91 rt5645_sel_asrc_clk_src(codec,
91 RT5645_DA_STEREO_FILTER | 92 RT5645_DA_STEREO_FILTER,
92 RT5645_AD_STEREO_FILTER,
93 RT5645_CLK_SEL_I2S1_ASRC); 93 RT5645_CLK_SEL_I2S1_ASRC);
94
95 if (!strcmp(codec_capture_dai, "rt5645-aif1")) {
96 rt5645_sel_asrc_clk_src(codec,
97 RT5645_AD_STEREO_FILTER,
98 RT5645_CLK_SEL_I2S1_ASRC);
99 } else if (!strcmp(codec_capture_dai, "rt5645-aif2")) {
100 rt5645_sel_asrc_clk_src(codec,
101 RT5645_AD_STEREO_FILTER,
102 RT5645_CLK_SEL_I2S2_ASRC);
103 } else {
104 dev_warn(card->dev,
105 "Only one dai codec found in DTS, enabled rt5645 AD filter\n");
106 rt5645_sel_asrc_clk_src(codec,
107 RT5645_AD_STEREO_FILTER,
108 RT5645_CLK_SEL_I2S1_ASRC);
109 }
110
94 /* enable jack detection */ 111 /* enable jack detection */
95 ret = snd_soc_card_jack_new(card, "Headset Jack", 112 ret = snd_soc_card_jack_new(card, "Headset Jack",
96 SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | 113 SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
@@ -110,6 +127,11 @@ static int mt8173_rt5650_init(struct snd_soc_pcm_runtime *runtime)
110 127
111static struct snd_soc_dai_link_component mt8173_rt5650_codecs[] = { 128static struct snd_soc_dai_link_component mt8173_rt5650_codecs[] = {
112 { 129 {
130 /* Playback */
131 .dai_name = "rt5645-aif1",
132 },
133 {
134 /* Capture */
113 .dai_name = "rt5645-aif1", 135 .dai_name = "rt5645-aif1",
114 }, 136 },
115}; 137};
@@ -149,7 +171,7 @@ static struct snd_soc_dai_link mt8173_rt5650_dais[] = {
149 .cpu_dai_name = "I2S", 171 .cpu_dai_name = "I2S",
150 .no_pcm = 1, 172 .no_pcm = 1,
151 .codecs = mt8173_rt5650_codecs, 173 .codecs = mt8173_rt5650_codecs,
152 .num_codecs = 1, 174 .num_codecs = 2,
153 .init = mt8173_rt5650_init, 175 .init = mt8173_rt5650_init,
154 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 176 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
155 SND_SOC_DAIFMT_CBS_CFS, 177 SND_SOC_DAIFMT_CBS_CFS,
@@ -177,6 +199,8 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev)
177{ 199{
178 struct snd_soc_card *card = &mt8173_rt5650_card; 200 struct snd_soc_card *card = &mt8173_rt5650_card;
179 struct device_node *platform_node; 201 struct device_node *platform_node;
202 struct device_node *np;
203 const char *codec_capture_dai;
180 int i, ret; 204 int i, ret;
181 205
182 platform_node = of_parse_phandle(pdev->dev.of_node, 206 platform_node = of_parse_phandle(pdev->dev.of_node,
@@ -199,6 +223,26 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev)
199 "Property 'audio-codec' missing or invalid\n"); 223 "Property 'audio-codec' missing or invalid\n");
200 return -EINVAL; 224 return -EINVAL;
201 } 225 }
226 mt8173_rt5650_codecs[1].of_node = mt8173_rt5650_codecs[0].of_node;
227
228 if (of_find_node_by_name(platform_node, "codec-capture")) {
229 np = of_get_child_by_name(pdev->dev.of_node, "codec-capture");
230 if (!np) {
231 dev_err(&pdev->dev,
232 "%s: Can't find codec-capture DT node\n",
233 __func__);
234 return -EINVAL;
235 }
236 ret = snd_soc_of_get_dai_name(np, &codec_capture_dai);
237 if (ret < 0) {
238 dev_err(&pdev->dev,
239 "%s codec_capture_dai name fail %d\n",
240 __func__, ret);
241 return ret;
242 }
243 mt8173_rt5650_codecs[1].dai_name = codec_capture_dai;
244 }
245
202 card->dev = &pdev->dev; 246 card->dev = &pdev->dev;
203 platform_set_drvdata(pdev, card); 247 platform_set_drvdata(pdev, card);
204 248
diff --git a/sound/soc/mediatek/mtk-afe-pcm.c b/sound/soc/mediatek/mtk-afe-pcm.c
index f1c58a2c12fb..2b5df2ef51a3 100644
--- a/sound/soc/mediatek/mtk-afe-pcm.c
+++ b/sound/soc/mediatek/mtk-afe-pcm.c
@@ -123,6 +123,7 @@
123#define AFE_TDM_CON1_WLEN_32BIT (0x2 << 8) 123#define AFE_TDM_CON1_WLEN_32BIT (0x2 << 8)
124#define AFE_TDM_CON1_MSB_ALIGNED (0x1 << 4) 124#define AFE_TDM_CON1_MSB_ALIGNED (0x1 << 4)
125#define AFE_TDM_CON1_1_BCK_DELAY (0x1 << 3) 125#define AFE_TDM_CON1_1_BCK_DELAY (0x1 << 3)
126#define AFE_TDM_CON1_LRCK_INV (0x1 << 2)
126#define AFE_TDM_CON1_BCK_INV (0x1 << 1) 127#define AFE_TDM_CON1_BCK_INV (0x1 << 1)
127#define AFE_TDM_CON1_EN (0x1 << 0) 128#define AFE_TDM_CON1_EN (0x1 << 0)
128 129
@@ -449,6 +450,7 @@ static int mtk_afe_hdmi_prepare(struct snd_pcm_substream *substream,
449 runtime->rate * runtime->channels * 32); 450 runtime->rate * runtime->channels * 32);
450 451
451 val = AFE_TDM_CON1_BCK_INV | 452 val = AFE_TDM_CON1_BCK_INV |
453 AFE_TDM_CON1_LRCK_INV |
452 AFE_TDM_CON1_1_BCK_DELAY | 454 AFE_TDM_CON1_1_BCK_DELAY |
453 AFE_TDM_CON1_MSB_ALIGNED | /* I2S mode */ 455 AFE_TDM_CON1_MSB_ALIGNED | /* I2S mode */
454 AFE_TDM_CON1_WLEN_32BIT | 456 AFE_TDM_CON1_WLEN_32BIT |
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index c7563e230c7d..4a16e778966b 100644
--- a/sound/soc/omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -260,6 +260,10 @@ static void omap_st_on(struct omap_mcbsp *mcbsp)
260 if (mcbsp->pdata->enable_st_clock) 260 if (mcbsp->pdata->enable_st_clock)
261 mcbsp->pdata->enable_st_clock(mcbsp->id, 1); 261 mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
262 262
263 /* Disable Sidetone clock auto-gating for normal operation */
264 w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
265 MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE));
266
263 /* Enable McBSP Sidetone */ 267 /* Enable McBSP Sidetone */
264 w = MCBSP_READ(mcbsp, SSELCR); 268 w = MCBSP_READ(mcbsp, SSELCR);
265 MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN); 269 MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN);
@@ -279,6 +283,10 @@ static void omap_st_off(struct omap_mcbsp *mcbsp)
279 w = MCBSP_READ(mcbsp, SSELCR); 283 w = MCBSP_READ(mcbsp, SSELCR);
280 MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN)); 284 MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
281 285
286 /* Enable Sidetone clock auto-gating to reduce power consumption */
287 w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
288 MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w | ST_AUTOIDLE);
289
282 if (mcbsp->pdata->enable_st_clock) 290 if (mcbsp->pdata->enable_st_clock)
283 mcbsp->pdata->enable_st_clock(mcbsp->id, 0); 291 mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
284} 292}
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 99381a27295b..a84f677234f0 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -82,6 +82,8 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
82 struct dma_chan *chan; 82 struct dma_chan *chan;
83 int err = 0; 83 int err = 0;
84 84
85 memset(&config, 0x00, sizeof(config));
86
85 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 87 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
86 88
87 /* return if this is a bufferless transfer e.g. 89 /* return if this is a bufferless transfer e.g.
diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c
index ec522e94b0e2..b6cb9950f05d 100644
--- a/sound/soc/pxa/brownstone.c
+++ b/sound/soc/pxa/brownstone.c
@@ -133,3 +133,4 @@ module_platform_driver(mmp_driver);
133MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); 133MODULE_AUTHOR("Leo Yan <leoy@marvell.com>");
134MODULE_DESCRIPTION("ALSA SoC Brownstone"); 134MODULE_DESCRIPTION("ALSA SoC Brownstone");
135MODULE_LICENSE("GPL"); 135MODULE_LICENSE("GPL");
136MODULE_ALIAS("platform:brownstone-audio");
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index 5c8f9db50a47..d1661fa6ee08 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -207,3 +207,4 @@ module_platform_driver(mioa701_wm9713_driver);
207MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)"); 207MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)");
208MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701"); 208MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701");
209MODULE_LICENSE("GPL"); 209MODULE_LICENSE("GPL");
210MODULE_ALIAS("platform:mioa701-wm9713");
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
index 51e790d006f5..96df9b2d8fc4 100644
--- a/sound/soc/pxa/mmp-pcm.c
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -248,3 +248,4 @@ module_platform_driver(mmp_pcm_driver);
248MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); 248MODULE_AUTHOR("Leo Yan <leoy@marvell.com>");
249MODULE_DESCRIPTION("MMP Soc Audio DMA module"); 249MODULE_DESCRIPTION("MMP Soc Audio DMA module");
250MODULE_LICENSE("GPL"); 250MODULE_LICENSE("GPL");
251MODULE_ALIAS("platform:mmp-pcm-audio");
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index eca60c29791a..ca8b23f8c525 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -482,3 +482,4 @@ module_platform_driver(asoc_mmp_sspa_driver);
482MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); 482MODULE_AUTHOR("Leo Yan <leoy@marvell.com>");
483MODULE_DESCRIPTION("MMP SSPA SoC Interface"); 483MODULE_DESCRIPTION("MMP SSPA SoC Interface");
484MODULE_LICENSE("GPL"); 484MODULE_LICENSE("GPL");
485MODULE_ALIAS("platform:mmp-sspa-dai");
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 4e74d9573f03..bcc81e920a67 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -161,3 +161,4 @@ module_platform_driver(palm27x_wm9712_driver);
161MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); 161MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
162MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive"); 162MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive");
163MODULE_LICENSE("GPL"); 163MODULE_LICENSE("GPL");
164MODULE_ALIAS("platform:palm27x-asoc");
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index da03fad1b9cd..3cad990dad2c 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -833,3 +833,4 @@ module_platform_driver(asoc_ssp_driver);
833MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 833MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
834MODULE_DESCRIPTION("PXA SSP/PCM SoC Interface"); 834MODULE_DESCRIPTION("PXA SSP/PCM SoC Interface");
835MODULE_LICENSE("GPL"); 835MODULE_LICENSE("GPL");
836MODULE_ALIAS("platform:pxa-ssp-dai");
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index f3de615aacd7..9615e6de1306 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -287,3 +287,4 @@ module_platform_driver(pxa2xx_ac97_driver);
287MODULE_AUTHOR("Nicolas Pitre"); 287MODULE_AUTHOR("Nicolas Pitre");
288MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); 288MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
289MODULE_LICENSE("GPL"); 289MODULE_LICENSE("GPL");
290MODULE_ALIAS("platform:pxa2xx-ac97");
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 9f390398d518..410d48b93031 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -117,3 +117,4 @@ module_platform_driver(pxa_pcm_driver);
117MODULE_AUTHOR("Nicolas Pitre"); 117MODULE_AUTHOR("Nicolas Pitre");
118MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); 118MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
119MODULE_LICENSE("GPL"); 119MODULE_LICENSE("GPL");
120MODULE_ALIAS("platform:pxa-pcm-audio");
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index 6e8665430bd5..db000c6987a1 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -474,7 +474,7 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
474 struct lpass_data *drvdata = 474 struct lpass_data *drvdata =
475 snd_soc_platform_get_drvdata(soc_runtime->platform); 475 snd_soc_platform_get_drvdata(soc_runtime->platform);
476 struct lpass_variant *v = drvdata->variant; 476 struct lpass_variant *v = drvdata->variant;
477 int ret; 477 int ret = -EINVAL;
478 struct lpass_pcm_data *data; 478 struct lpass_pcm_data *data;
479 size_t size = lpass_platform_pcm_hardware.buffer_bytes_max; 479 size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
480 480
@@ -491,7 +491,7 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
491 data->rdma_ch = v->alloc_dma_channel(drvdata, 491 data->rdma_ch = v->alloc_dma_channel(drvdata,
492 SNDRV_PCM_STREAM_PLAYBACK); 492 SNDRV_PCM_STREAM_PLAYBACK);
493 493
494 if (IS_ERR_VALUE(data->rdma_ch)) 494 if (data->rdma_ch < 0)
495 return data->rdma_ch; 495 return data->rdma_ch;
496 496
497 drvdata->substream[data->rdma_ch] = psubstream; 497 drvdata->substream[data->rdma_ch] = psubstream;
@@ -518,8 +518,10 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
518 data->wrdma_ch = v->alloc_dma_channel(drvdata, 518 data->wrdma_ch = v->alloc_dma_channel(drvdata,
519 SNDRV_PCM_STREAM_CAPTURE); 519 SNDRV_PCM_STREAM_CAPTURE);
520 520
521 if (IS_ERR_VALUE(data->wrdma_ch)) 521 if (data->wrdma_ch < 0) {
522 ret = data->wrdma_ch;
522 goto capture_alloc_err; 523 goto capture_alloc_err;
524 }
523 525
524 drvdata->substream[data->wrdma_ch] = csubstream; 526 drvdata->substream[data->wrdma_ch] = csubstream;
525 527
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index 606399de684d..49354d17ea55 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -492,9 +492,7 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
492 */ 492 */
493 if (!count) { 493 if (!count) {
494 clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT], 494 clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT],
495 parent_clk_name, 495 parent_clk_name, 0, req_rate);
496 (parent_clk_name) ?
497 0 : CLK_IS_ROOT, req_rate);
498 if (!IS_ERR(clk)) { 496 if (!IS_ERR(clk)) {
499 adg->clkout[CLKOUT] = clk; 497 adg->clkout[CLKOUT] = clk;
500 of_clk_add_provider(np, of_clk_src_simple_get, clk); 498 of_clk_add_provider(np, of_clk_src_simple_get, clk);
@@ -506,9 +504,7 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
506 else { 504 else {
507 for (i = 0; i < CLKOUTMAX; i++) { 505 for (i = 0; i < CLKOUTMAX; i++) {
508 clk = clk_register_fixed_rate(dev, clkout_name[i], 506 clk = clk_register_fixed_rate(dev, clkout_name[i],
509 parent_clk_name, 507 parent_clk_name, 0,
510 (parent_clk_name) ?
511 0 : CLK_IS_ROOT,
512 req_rate); 508 req_rate);
513 if (!IS_ERR(clk)) { 509 if (!IS_ERR(clk)) {
514 adg->onecell.clks = adg->clkout; 510 adg->onecell.clks = adg->clkout;
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index 7658e8fd7bdc..6bc93cbb3049 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -316,11 +316,15 @@ static u32 rsnd_dmapp_get_id(struct rsnd_dai_stream *io,
316 size = ARRAY_SIZE(gen2_id_table_cmd); 316 size = ARRAY_SIZE(gen2_id_table_cmd);
317 } 317 }
318 318
319 if (!entry) 319 if ((!entry) || (size <= id)) {
320 return 0xFF; 320 struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io));
321 321
322 if (size <= id) 322 dev_err(dev, "unknown connection (%s[%d])\n",
323 return 0xFF; 323 rsnd_mod_name(mod), rsnd_mod_id(mod));
324
325 /* use non-prohibited SRS number as error */
326 return 0x00; /* SSI00 */
327 }
324 328
325 return entry[id]; 329 return entry[id];
326} 330}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index fc89a67258ca..a8f61d79333b 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -276,8 +276,9 @@ struct rsnd_mod {
276/* 276/*
277 * status 277 * status
278 * 278 *
279 * 0xH0000CB0 279 * 0xH0000CBA
280 * 280 *
281 * A 0: probe 1: remove
281 * B 0: init 1: quit 282 * B 0: init 1: quit
282 * C 0: start 1: stop 283 * C 0: start 1: stop
283 * 284 *
@@ -287,19 +288,19 @@ struct rsnd_mod {
287 * H 0: fallback 288 * H 0: fallback
288 * H 0: hw_params 289 * H 0: hw_params
289 */ 290 */
291#define __rsnd_mod_shift_probe 0
292#define __rsnd_mod_shift_remove 0
290#define __rsnd_mod_shift_init 4 293#define __rsnd_mod_shift_init 4
291#define __rsnd_mod_shift_quit 4 294#define __rsnd_mod_shift_quit 4
292#define __rsnd_mod_shift_start 8 295#define __rsnd_mod_shift_start 8
293#define __rsnd_mod_shift_stop 8 296#define __rsnd_mod_shift_stop 8
294#define __rsnd_mod_shift_probe 28 /* always called */
295#define __rsnd_mod_shift_remove 28 /* always called */
296#define __rsnd_mod_shift_irq 28 /* always called */ 297#define __rsnd_mod_shift_irq 28 /* always called */
297#define __rsnd_mod_shift_pcm_new 28 /* always called */ 298#define __rsnd_mod_shift_pcm_new 28 /* always called */
298#define __rsnd_mod_shift_fallback 28 /* always called */ 299#define __rsnd_mod_shift_fallback 28 /* always called */
299#define __rsnd_mod_shift_hw_params 28 /* always called */ 300#define __rsnd_mod_shift_hw_params 28 /* always called */
300 301
301#define __rsnd_mod_add_probe 0 302#define __rsnd_mod_add_probe 1
302#define __rsnd_mod_add_remove 0 303#define __rsnd_mod_add_remove -1
303#define __rsnd_mod_add_init 1 304#define __rsnd_mod_add_init 1
304#define __rsnd_mod_add_quit -1 305#define __rsnd_mod_add_quit -1
305#define __rsnd_mod_add_start 1 306#define __rsnd_mod_add_start 1
@@ -310,7 +311,7 @@ struct rsnd_mod {
310#define __rsnd_mod_add_hw_params 0 311#define __rsnd_mod_add_hw_params 0
311 312
312#define __rsnd_mod_call_probe 0 313#define __rsnd_mod_call_probe 0
313#define __rsnd_mod_call_remove 0 314#define __rsnd_mod_call_remove 1
314#define __rsnd_mod_call_init 0 315#define __rsnd_mod_call_init 0
315#define __rsnd_mod_call_quit 1 316#define __rsnd_mod_call_quit 1
316#define __rsnd_mod_call_start 0 317#define __rsnd_mod_call_start 0
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 15d6ffe8be74..e39f916d0f2f 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -572,6 +572,9 @@ int rsnd_src_probe(struct rsnd_priv *priv)
572 572
573 i = 0; 573 i = 0;
574 for_each_child_of_node(node, np) { 574 for_each_child_of_node(node, np) {
575 if (!of_device_is_available(np))
576 goto skip;
577
575 src = rsnd_src_get(priv, i); 578 src = rsnd_src_get(priv, i);
576 579
577 snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d", 580 snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
@@ -595,6 +598,7 @@ int rsnd_src_probe(struct rsnd_priv *priv)
595 if (ret) 598 if (ret)
596 goto rsnd_src_probe_done; 599 goto rsnd_src_probe_done;
597 600
601skip:
598 i++; 602 i++;
599 } 603 }
600 604
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 1cf94d7fb9f4..ee7f15aa46fc 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -1023,6 +1023,11 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
1023 1023
1024 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; 1024 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
1025 1025
1026 if (control_hdr->size != sizeof(*control_hdr)) {
1027 dev_err(tplg->dev, "ASoC: invalid control size\n");
1028 return -EINVAL;
1029 }
1030
1026 switch (control_hdr->ops.info) { 1031 switch (control_hdr->ops.info) {
1027 case SND_SOC_TPLG_CTL_VOLSW: 1032 case SND_SOC_TPLG_CTL_VOLSW:
1028 case SND_SOC_TPLG_CTL_STROBE: 1033 case SND_SOC_TPLG_CTL_STROBE:
@@ -1476,6 +1481,8 @@ widget:
1476 widget->dobj.type = SND_SOC_DOBJ_WIDGET; 1481 widget->dobj.type = SND_SOC_DOBJ_WIDGET;
1477 widget->dobj.ops = tplg->ops; 1482 widget->dobj.ops = tplg->ops;
1478 widget->dobj.index = tplg->index; 1483 widget->dobj.index = tplg->index;
1484 kfree(template.sname);
1485 kfree(template.name);
1479 list_add(&widget->dobj.list, &tplg->comp->dobj_list); 1486 list_add(&widget->dobj.list, &tplg->comp->dobj_list);
1480 return 0; 1487 return 0;
1481 1488
@@ -1499,10 +1506,17 @@ static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg,
1499 1506
1500 for (i = 0; i < count; i++) { 1507 for (i = 0; i < count; i++) {
1501 widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; 1508 widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;
1509 if (widget->size != sizeof(*widget)) {
1510 dev_err(tplg->dev, "ASoC: invalid widget size\n");
1511 return -EINVAL;
1512 }
1513
1502 ret = soc_tplg_dapm_widget_create(tplg, widget); 1514 ret = soc_tplg_dapm_widget_create(tplg, widget);
1503 if (ret < 0) 1515 if (ret < 0) {
1504 dev_err(tplg->dev, "ASoC: failed to load widget %s\n", 1516 dev_err(tplg->dev, "ASoC: failed to load widget %s\n",
1505 widget->name); 1517 widget->name);
1518 return ret;
1519 }
1506 } 1520 }
1507 1521
1508 return 0; 1522 return 0;
@@ -1586,6 +1600,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
1586 return snd_soc_register_dai(tplg->comp, dai_drv); 1600 return snd_soc_register_dai(tplg->comp, dai_drv);
1587} 1601}
1588 1602
1603/* create the FE DAI link */
1589static int soc_tplg_link_create(struct soc_tplg *tplg, 1604static int soc_tplg_link_create(struct soc_tplg *tplg,
1590 struct snd_soc_tplg_pcm *pcm) 1605 struct snd_soc_tplg_pcm *pcm)
1591{ 1606{
@@ -1598,6 +1613,16 @@ static int soc_tplg_link_create(struct soc_tplg *tplg,
1598 1613
1599 link->name = pcm->pcm_name; 1614 link->name = pcm->pcm_name;
1600 link->stream_name = pcm->pcm_name; 1615 link->stream_name = pcm->pcm_name;
1616 link->id = pcm->pcm_id;
1617
1618 link->cpu_dai_name = pcm->dai_name;
1619 link->codec_name = "snd-soc-dummy";
1620 link->codec_dai_name = "snd-soc-dummy-dai";
1621
1622 /* enable DPCM */
1623 link->dynamic = 1;
1624 link->dpcm_playback = pcm->playback;
1625 link->dpcm_capture = pcm->capture;
1601 1626
1602 /* pass control to component driver for optional further init */ 1627 /* pass control to component driver for optional further init */
1603 ret = soc_tplg_dai_link_load(tplg, link); 1628 ret = soc_tplg_dai_link_load(tplg, link);
@@ -1639,8 +1664,6 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
1639 if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) 1664 if (tplg->pass != SOC_TPLG_PASS_PCM_DAI)
1640 return 0; 1665 return 0;
1641 1666
1642 pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
1643
1644 if (soc_tplg_check_elem_count(tplg, 1667 if (soc_tplg_check_elem_count(tplg,
1645 sizeof(struct snd_soc_tplg_pcm), count, 1668 sizeof(struct snd_soc_tplg_pcm), count,
1646 hdr->payload_size, "PCM DAI")) { 1669 hdr->payload_size, "PCM DAI")) {
@@ -1650,7 +1673,13 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
1650 } 1673 }
1651 1674
1652 /* create the FE DAIs and DAI links */ 1675 /* create the FE DAIs and DAI links */
1676 pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
1653 for (i = 0; i < count; i++) { 1677 for (i = 0; i < count; i++) {
1678 if (pcm->size != sizeof(*pcm)) {
1679 dev_err(tplg->dev, "ASoC: invalid pcm size\n");
1680 return -EINVAL;
1681 }
1682
1654 soc_tplg_pcm_create(tplg, pcm); 1683 soc_tplg_pcm_create(tplg, pcm);
1655 pcm++; 1684 pcm++;
1656 } 1685 }
@@ -1670,6 +1699,11 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg,
1670 return 0; 1699 return 0;
1671 1700
1672 manifest = (struct snd_soc_tplg_manifest *)tplg->pos; 1701 manifest = (struct snd_soc_tplg_manifest *)tplg->pos;
1702 if (manifest->size != sizeof(*manifest)) {
1703 dev_err(tplg->dev, "ASoC: invalid manifest size\n");
1704 return -EINVAL;
1705 }
1706
1673 tplg->pos += sizeof(struct snd_soc_tplg_manifest); 1707 tplg->pos += sizeof(struct snd_soc_tplg_manifest);
1674 1708
1675 if (tplg->comp && tplg->ops && tplg->ops->manifest) 1709 if (tplg->comp && tplg->ops && tplg->ops->manifest)
@@ -1686,6 +1720,14 @@ static int soc_valid_header(struct soc_tplg *tplg,
1686 if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size) 1720 if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size)
1687 return 0; 1721 return 0;
1688 1722
1723 if (hdr->size != sizeof(*hdr)) {
1724 dev_err(tplg->dev,
1725 "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n",
1726 hdr->type, soc_tplg_get_hdr_offset(tplg),
1727 tplg->fw->size);
1728 return -EINVAL;
1729 }
1730
1689 /* big endian firmware objects not supported atm */ 1731 /* big endian firmware objects not supported atm */
1690 if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) { 1732 if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) {
1691 dev_err(tplg->dev, 1733 dev_err(tplg->dev,
diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c
index 39bcefe5eea0..488ef4ed8fba 100644
--- a/sound/soc/sti/sti_uniperif.c
+++ b/sound/soc/sti/sti_uniperif.c
@@ -11,6 +11,142 @@
11#include "uniperif.h" 11#include "uniperif.h"
12 12
13/* 13/*
14 * User frame size shall be 2, 4, 6 or 8 32-bits words length
15 * (i.e. 8, 16, 24 or 32 bytes)
16 * This constraint comes from allowed values for
17 * UNIPERIF_I2S_FMT_NUM_CH register
18 */
19#define UNIPERIF_MAX_FRAME_SZ 0x20
20#define UNIPERIF_ALLOWED_FRAME_SZ (0x08 | 0x10 | 0x18 | UNIPERIF_MAX_FRAME_SZ)
21
22int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
23 unsigned int rx_mask, int slots,
24 int slot_width)
25{
26 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
27 struct uniperif *uni = priv->dai_data.uni;
28 int i, frame_size, avail_slots;
29
30 if (!UNIPERIF_TYPE_IS_TDM(uni)) {
31 dev_err(uni->dev, "cpu dai not in tdm mode\n");
32 return -EINVAL;
33 }
34
35 /* store info in unip context */
36 uni->tdm_slot.slots = slots;
37 uni->tdm_slot.slot_width = slot_width;
38 /* unip is unidirectionnal */
39 uni->tdm_slot.mask = (tx_mask != 0) ? tx_mask : rx_mask;
40
41 /* number of available timeslots */
42 for (i = 0, avail_slots = 0; i < uni->tdm_slot.slots; i++) {
43 if ((uni->tdm_slot.mask >> i) & 0x01)
44 avail_slots++;
45 }
46 uni->tdm_slot.avail_slots = avail_slots;
47
48 /* frame size in bytes */
49 frame_size = uni->tdm_slot.avail_slots * uni->tdm_slot.slot_width / 8;
50
51 /* check frame size is allowed */
52 if ((frame_size > UNIPERIF_MAX_FRAME_SZ) ||
53 (frame_size & ~(int)UNIPERIF_ALLOWED_FRAME_SZ)) {
54 dev_err(uni->dev, "frame size not allowed: %d bytes\n",
55 frame_size);
56 return -EINVAL;
57 }
58
59 return 0;
60}
61
62int sti_uniperiph_fix_tdm_chan(struct snd_pcm_hw_params *params,
63 struct snd_pcm_hw_rule *rule)
64{
65 struct uniperif *uni = rule->private;
66 struct snd_interval t;
67
68 t.min = uni->tdm_slot.avail_slots;
69 t.max = uni->tdm_slot.avail_slots;
70 t.openmin = 0;
71 t.openmax = 0;
72 t.integer = 0;
73
74 return snd_interval_refine(hw_param_interval(params, rule->var), &t);
75}
76
77int sti_uniperiph_fix_tdm_format(struct snd_pcm_hw_params *params,
78 struct snd_pcm_hw_rule *rule)
79{
80 struct uniperif *uni = rule->private;
81 struct snd_mask *maskp = hw_param_mask(params, rule->var);
82 u64 format;
83
84 switch (uni->tdm_slot.slot_width) {
85 case 16:
86 format = SNDRV_PCM_FMTBIT_S16_LE;
87 break;
88 case 32:
89 format = SNDRV_PCM_FMTBIT_S32_LE;
90 break;
91 default:
92 dev_err(uni->dev, "format not supported: %d bits\n",
93 uni->tdm_slot.slot_width);
94 return -EINVAL;
95 }
96
97 maskp->bits[0] &= (u_int32_t)format;
98 maskp->bits[1] &= (u_int32_t)(format >> 32);
99 /* clear remaining indexes */
100 memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX - 64) / 8);
101
102 if (!maskp->bits[0] && !maskp->bits[1])
103 return -EINVAL;
104
105 return 0;
106}
107
108int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni,
109 unsigned int *word_pos)
110{
111 int slot_width = uni->tdm_slot.slot_width / 8;
112 int slots_num = uni->tdm_slot.slots;
113 unsigned int slots_mask = uni->tdm_slot.mask;
114 int i, j, k;
115 unsigned int word16_pos[4];
116
117 /* word16_pos:
118 * word16_pos[0] = WORDX_LSB
119 * word16_pos[1] = WORDX_MSB,
120 * word16_pos[2] = WORDX+1_LSB
121 * word16_pos[3] = WORDX+1_MSB
122 */
123
124 /* set unip word position */
125 for (i = 0, j = 0, k = 0; (i < slots_num) && (k < WORD_MAX); i++) {
126 if ((slots_mask >> i) & 0x01) {
127 word16_pos[j] = i * slot_width;
128
129 if (slot_width == 4) {
130 word16_pos[j + 1] = word16_pos[j] + 2;
131 j++;
132 }
133 j++;
134
135 if (j > 3) {
136 word_pos[k] = word16_pos[1] |
137 (word16_pos[0] << 8) |
138 (word16_pos[3] << 16) |
139 (word16_pos[2] << 24);
140 j = 0;
141 k++;
142 }
143 }
144 }
145
146 return 0;
147}
148
149/*
14 * sti_uniperiph_dai_create_ctrl 150 * sti_uniperiph_dai_create_ctrl
15 * This function is used to create Ctrl associated to DAI but also pcm device. 151 * This function is used to create Ctrl associated to DAI but also pcm device.
16 * Request is done by front end to associate ctrl with pcm device id 152 * Request is done by front end to associate ctrl with pcm device id
@@ -45,10 +181,16 @@ int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream,
45 struct snd_pcm_hw_params *params, 181 struct snd_pcm_hw_params *params,
46 struct snd_soc_dai *dai) 182 struct snd_soc_dai *dai)
47{ 183{
184 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
185 struct uniperif *uni = priv->dai_data.uni;
48 struct snd_dmaengine_dai_dma_data *dma_data; 186 struct snd_dmaengine_dai_dma_data *dma_data;
49 int transfer_size; 187 int transfer_size;
50 188
51 transfer_size = params_channels(params) * UNIPERIF_FIFO_FRAMES; 189 if (uni->info->type == SND_ST_UNIPERIF_TYPE_TDM)
190 /* transfer size = user frame size (in 32-bits FIFO cell) */
191 transfer_size = snd_soc_params_to_frame_size(params) / 32;
192 else
193 transfer_size = params_channels(params) * UNIPERIF_FIFO_FRAMES;
52 194
53 dma_data = snd_soc_dai_get_dma_data(dai, substream); 195 dma_data = snd_soc_dai_get_dma_data(dai, substream);
54 dma_data->maxburst = transfer_size; 196 dma_data->maxburst = transfer_size;
diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h
index f0fd5a9944e9..eb9933c62ad6 100644
--- a/sound/soc/sti/uniperif.h
+++ b/sound/soc/sti/uniperif.h
@@ -25,7 +25,7 @@
25 writel_relaxed((((value) & mask) << shift), ip->base + offset) 25 writel_relaxed((((value) & mask) << shift), ip->base + offset)
26 26
27/* 27/*
28 * AUD_UNIPERIF_SOFT_RST reg 28 * UNIPERIF_SOFT_RST reg
29 */ 29 */
30 30
31#define UNIPERIF_SOFT_RST_OFFSET(ip) 0x0000 31#define UNIPERIF_SOFT_RST_OFFSET(ip) 0x0000
@@ -50,7 +50,7 @@
50 UNIPERIF_SOFT_RST_SOFT_RST_MASK(ip)) 50 UNIPERIF_SOFT_RST_SOFT_RST_MASK(ip))
51 51
52/* 52/*
53 * AUD_UNIPERIF_FIFO_DATA reg 53 * UNIPERIF_FIFO_DATA reg
54 */ 54 */
55 55
56#define UNIPERIF_FIFO_DATA_OFFSET(ip) 0x0004 56#define UNIPERIF_FIFO_DATA_OFFSET(ip) 0x0004
@@ -58,7 +58,7 @@
58 writel_relaxed(value, ip->base + UNIPERIF_FIFO_DATA_OFFSET(ip)) 58 writel_relaxed(value, ip->base + UNIPERIF_FIFO_DATA_OFFSET(ip))
59 59
60/* 60/*
61 * AUD_UNIPERIF_CHANNEL_STA_REGN reg 61 * UNIPERIF_CHANNEL_STA_REGN reg
62 */ 62 */
63 63
64#define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n)) 64#define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n))
@@ -105,7 +105,7 @@
105 writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG5_OFFSET(ip)) 105 writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG5_OFFSET(ip))
106 106
107/* 107/*
108 * AUD_UNIPERIF_ITS reg 108 * UNIPERIF_ITS reg
109 */ 109 */
110 110
111#define UNIPERIF_ITS_OFFSET(ip) 0x000C 111#define UNIPERIF_ITS_OFFSET(ip) 0x000C
@@ -143,7 +143,7 @@
143 0 : (BIT(UNIPERIF_ITS_UNDERFLOW_REC_FAILED_SHIFT(ip)))) 143 0 : (BIT(UNIPERIF_ITS_UNDERFLOW_REC_FAILED_SHIFT(ip))))
144 144
145/* 145/*
146 * AUD_UNIPERIF_ITS_BCLR reg 146 * UNIPERIF_ITS_BCLR reg
147 */ 147 */
148 148
149/* FIFO_ERROR */ 149/* FIFO_ERROR */
@@ -160,7 +160,7 @@
160 writel_relaxed(value, ip->base + UNIPERIF_ITS_BCLR_OFFSET(ip)) 160 writel_relaxed(value, ip->base + UNIPERIF_ITS_BCLR_OFFSET(ip))
161 161
162/* 162/*
163 * AUD_UNIPERIF_ITM reg 163 * UNIPERIF_ITM reg
164 */ 164 */
165 165
166#define UNIPERIF_ITM_OFFSET(ip) 0x0018 166#define UNIPERIF_ITM_OFFSET(ip) 0x0018
@@ -188,7 +188,7 @@
188 0 : (BIT(UNIPERIF_ITM_UNDERFLOW_REC_FAILED_SHIFT(ip)))) 188 0 : (BIT(UNIPERIF_ITM_UNDERFLOW_REC_FAILED_SHIFT(ip))))
189 189
190/* 190/*
191 * AUD_UNIPERIF_ITM_BCLR reg 191 * UNIPERIF_ITM_BCLR reg
192 */ 192 */
193 193
194#define UNIPERIF_ITM_BCLR_OFFSET(ip) 0x001c 194#define UNIPERIF_ITM_BCLR_OFFSET(ip) 0x001c
@@ -213,7 +213,7 @@
213 UNIPERIF_ITM_BCLR_DMA_ERROR_MASK(ip)) 213 UNIPERIF_ITM_BCLR_DMA_ERROR_MASK(ip))
214 214
215/* 215/*
216 * AUD_UNIPERIF_ITM_BSET reg 216 * UNIPERIF_ITM_BSET reg
217 */ 217 */
218 218
219#define UNIPERIF_ITM_BSET_OFFSET(ip) 0x0020 219#define UNIPERIF_ITM_BSET_OFFSET(ip) 0x0020
@@ -767,7 +767,7 @@
767 SET_UNIPERIF_REG(ip, \ 767 SET_UNIPERIF_REG(ip, \
768 UNIPERIF_CTRL_OFFSET(ip), \ 768 UNIPERIF_CTRL_OFFSET(ip), \
769 UNIPERIF_CTRL_READER_OUT_SEL_SHIFT(ip), \ 769 UNIPERIF_CTRL_READER_OUT_SEL_SHIFT(ip), \
770 CORAUD_UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip), 1) 770 UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip), 1)
771 771
772/* UNDERFLOW_REC_WINDOW */ 772/* UNDERFLOW_REC_WINDOW */
773#define UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_SHIFT(ip) 20 773#define UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_SHIFT(ip) 20
@@ -1046,7 +1046,7 @@
1046 UNIPERIF_STATUS_1_UNDERFLOW_DURATION_MASK(ip), value) 1046 UNIPERIF_STATUS_1_UNDERFLOW_DURATION_MASK(ip), value)
1047 1047
1048/* 1048/*
1049 * AUD_UNIPERIF_CHANNEL_STA_REGN reg 1049 * UNIPERIF_CHANNEL_STA_REGN reg
1050 */ 1050 */
1051 1051
1052#define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n)) 1052#define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n))
@@ -1057,7 +1057,7 @@
1057 UNIPERIF_CHANNEL_STA_REGN(ip, n)) 1057 UNIPERIF_CHANNEL_STA_REGN(ip, n))
1058 1058
1059/* 1059/*
1060 * AUD_UNIPERIF_USER_VALIDITY reg 1060 * UNIPERIF_USER_VALIDITY reg
1061 */ 1061 */
1062 1062
1063#define UNIPERIF_USER_VALIDITY_OFFSET(ip) 0x0090 1063#define UNIPERIF_USER_VALIDITY_OFFSET(ip) 0x0090
@@ -1101,12 +1101,136 @@
1101 UNIPERIF_DBG_STANDBY_LEFT_SP_MASK(ip), value) 1101 UNIPERIF_DBG_STANDBY_LEFT_SP_MASK(ip), value)
1102 1102
1103/* 1103/*
1104 * UNIPERIF_TDM_ENABLE
1105 */
1106#define UNIPERIF_TDM_ENABLE_OFFSET(ip) 0x0118
1107#define GET_UNIPERIF_TDM_ENABLE(ip) \
1108 readl_relaxed(ip->base + UNIPERIF_TDM_ENABLE_OFFSET(ip))
1109#define SET_UNIPERIF_TDM_ENABLE(ip, value) \
1110 writel_relaxed(value, ip->base + UNIPERIF_TDM_ENABLE_OFFSET(ip))
1111
1112/* TDM_ENABLE */
1113#define UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip) 0x0
1114#define UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip) 0x1
1115#define GET_UNIPERIF_TDM_ENABLE_EN_TDM(ip) \
1116 GET_UNIPERIF_REG(ip, \
1117 UNIPERIF_TDM_ENABLE_OFFSET(ip), \
1118 UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \
1119 UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip))
1120#define SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(ip) \
1121 SET_UNIPERIF_REG(ip, \
1122 UNIPERIF_TDM_ENABLE_OFFSET(ip), \
1123 UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \
1124 UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip), 1)
1125#define SET_UNIPERIF_TDM_ENABLE_TDM_DISABLE(ip) \
1126 SET_UNIPERIF_REG(ip, \
1127 UNIPERIF_TDM_ENABLE_OFFSET(ip), \
1128 UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \
1129 UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip), 0)
1130
1131/*
1132 * UNIPERIF_TDM_FS_REF_FREQ
1133 */
1134#define UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip) 0x011c
1135#define GET_UNIPERIF_TDM_FS_REF_FREQ(ip) \
1136 readl_relaxed(ip->base + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip))
1137#define SET_UNIPERIF_TDM_FS_REF_FREQ(ip, value) \
1138 writel_relaxed(value, ip->base + \
1139 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip))
1140
1141/* REF_FREQ */
1142#define UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip) 0x0
1143#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip) 0
1144#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip) 1
1145#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip) 2
1146#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip) 3
1147#define UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip) 0x3
1148#define GET_UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ(ip) \
1149 GET_UNIPERIF_REG(ip, \
1150 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \
1151 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \
1152 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip))
1153#define SET_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip) \
1154 SET_UNIPERIF_REG(ip, \
1155 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \
1156 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \
1157 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \
1158 VALUE_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip))
1159#define SET_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip) \
1160 SET_UNIPERIF_REG(ip, \
1161 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \
1162 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \
1163 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \
1164 VALUE_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip))
1165#define SET_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip) \
1166 SET_UNIPERIF_REG(ip, \
1167 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \
1168 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \
1169 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \
1170 VALUE_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip))
1171#define SET_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip) \
1172 SET_UNIPERIF_REG(ip, \
1173 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \
1174 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \
1175 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \
1176 VALUE_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip))
1177
1178/*
1179 * UNIPERIF_TDM_FS_REF_DIV
1180 */
1181#define UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip) 0x0120
1182#define GET_UNIPERIF_TDM_FS_REF_DIV(ip) \
1183 readl_relaxed(ip->base + UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip))
1184#define SET_UNIPERIF_TDM_FS_REF_DIV(ip, value) \
1185 writel_relaxed(value, ip->base + \
1186 UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip))
1187
1188/* NUM_TIMESLOT */
1189#define UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip) 0x0
1190#define UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip) 0xff
1191#define GET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(ip) \
1192 GET_UNIPERIF_REG(ip, \
1193 UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip), \
1194 UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip), \
1195 UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip))
1196#define SET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(ip, value) \
1197 SET_UNIPERIF_REG(ip, \
1198 UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip), \
1199 UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip), \
1200 UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip), value)
1201
1202/*
1203 * UNIPERIF_TDM_WORD_POS_X_Y
1204 * 32 bits of UNIPERIF_TDM_WORD_POS_X_Y register shall be set in 1 shot
1205 */
1206#define UNIPERIF_TDM_WORD_POS_1_2_OFFSET(ip) 0x013c
1207#define UNIPERIF_TDM_WORD_POS_3_4_OFFSET(ip) 0x0140
1208#define UNIPERIF_TDM_WORD_POS_5_6_OFFSET(ip) 0x0144
1209#define UNIPERIF_TDM_WORD_POS_7_8_OFFSET(ip) 0x0148
1210#define GET_UNIPERIF_TDM_WORD_POS(ip, words) \
1211 readl_relaxed(ip->base + UNIPERIF_TDM_WORD_POS_##words##_OFFSET(ip))
1212#define SET_UNIPERIF_TDM_WORD_POS(ip, words, value) \
1213 writel_relaxed(value, ip->base + \
1214 UNIPERIF_TDM_WORD_POS_##words##_OFFSET(ip))
1215/*
1104 * uniperipheral IP capabilities 1216 * uniperipheral IP capabilities
1105 */ 1217 */
1106 1218
1107#define UNIPERIF_FIFO_SIZE 70 /* FIFO is 70 cells deep */ 1219#define UNIPERIF_FIFO_SIZE 70 /* FIFO is 70 cells deep */
1108#define UNIPERIF_FIFO_FRAMES 4 /* FDMA trigger limit in frames */ 1220#define UNIPERIF_FIFO_FRAMES 4 /* FDMA trigger limit in frames */
1109 1221
1222#define UNIPERIF_TYPE_IS_HDMI(p) \
1223 ((p)->info->type == SND_ST_UNIPERIF_TYPE_HDMI)
1224#define UNIPERIF_TYPE_IS_PCM(p) \
1225 ((p)->info->type == SND_ST_UNIPERIF_TYPE_PCM)
1226#define UNIPERIF_TYPE_IS_SPDIF(p) \
1227 ((p)->info->type == SND_ST_UNIPERIF_TYPE_SPDIF)
1228#define UNIPERIF_TYPE_IS_IEC958(p) \
1229 (UNIPERIF_TYPE_IS_HDMI(p) || \
1230 UNIPERIF_TYPE_IS_SPDIF(p))
1231#define UNIPERIF_TYPE_IS_TDM(p) \
1232 ((p)->info->type == SND_ST_UNIPERIF_TYPE_TDM)
1233
1110/* 1234/*
1111 * Uniperipheral IP revisions 1235 * Uniperipheral IP revisions
1112 */ 1236 */
@@ -1125,10 +1249,11 @@ enum uniperif_version {
1125}; 1249};
1126 1250
1127enum uniperif_type { 1251enum uniperif_type {
1128 SND_ST_UNIPERIF_PLAYER_TYPE_NONE, 1252 SND_ST_UNIPERIF_TYPE_NONE,
1129 SND_ST_UNIPERIF_PLAYER_TYPE_HDMI, 1253 SND_ST_UNIPERIF_TYPE_HDMI,
1130 SND_ST_UNIPERIF_PLAYER_TYPE_PCM, 1254 SND_ST_UNIPERIF_TYPE_PCM,
1131 SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF 1255 SND_ST_UNIPERIF_TYPE_SPDIF,
1256 SND_ST_UNIPERIF_TYPE_TDM
1132}; 1257};
1133 1258
1134enum uniperif_state { 1259enum uniperif_state {
@@ -1145,9 +1270,17 @@ enum uniperif_iec958_encoding_mode {
1145 UNIPERIF_IEC958_ENCODING_MODE_ENCODED 1270 UNIPERIF_IEC958_ENCODING_MODE_ENCODED
1146}; 1271};
1147 1272
1273enum uniperif_word_pos {
1274 WORD_1_2,
1275 WORD_3_4,
1276 WORD_5_6,
1277 WORD_7_8,
1278 WORD_MAX
1279};
1280
1148struct uniperif_info { 1281struct uniperif_info {
1149 int id; /* instance value of the uniperipheral IP */ 1282 int id; /* instance value of the uniperipheral IP */
1150 enum uniperif_type player_type; 1283 enum uniperif_type type;
1151 int underflow_enabled; /* Underflow recovery mode */ 1284 int underflow_enabled; /* Underflow recovery mode */
1152}; 1285};
1153 1286
@@ -1156,12 +1289,20 @@ struct uniperif_iec958_settings {
1156 struct snd_aes_iec958 iec958; 1289 struct snd_aes_iec958 iec958;
1157}; 1290};
1158 1291
1292struct dai_tdm_slot {
1293 unsigned int mask;
1294 int slots;
1295 int slot_width;
1296 unsigned int avail_slots;
1297};
1298
1159struct uniperif { 1299struct uniperif {
1160 /* System information */ 1300 /* System information */
1161 struct uniperif_info *info; 1301 struct uniperif_info *info;
1162 struct device *dev; 1302 struct device *dev;
1163 int ver; /* IP version, used by register access macros */ 1303 int ver; /* IP version, used by register access macros */
1164 struct regmap_field *clk_sel; 1304 struct regmap_field *clk_sel;
1305 struct regmap_field *valid_sel;
1165 1306
1166 /* capabilities */ 1307 /* capabilities */
1167 const struct snd_pcm_hardware *hw; 1308 const struct snd_pcm_hardware *hw;
@@ -1192,6 +1333,7 @@ struct uniperif {
1192 1333
1193 /* dai properties */ 1334 /* dai properties */
1194 unsigned int daifmt; 1335 unsigned int daifmt;
1336 struct dai_tdm_slot tdm_slot;
1195 1337
1196 /* DAI callbacks */ 1338 /* DAI callbacks */
1197 const struct snd_soc_dai_ops *dai_ops; 1339 const struct snd_soc_dai_ops *dai_ops;
@@ -1209,6 +1351,28 @@ struct sti_uniperiph_data {
1209 struct sti_uniperiph_dai dai_data; 1351 struct sti_uniperiph_dai dai_data;
1210}; 1352};
1211 1353
1354static const struct snd_pcm_hardware uni_tdm_hw = {
1355 .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
1356 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP |
1357 SNDRV_PCM_INFO_MMAP_VALID,
1358
1359 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE,
1360
1361 .rates = SNDRV_PCM_RATE_CONTINUOUS,
1362 .rate_min = 8000,
1363 .rate_max = 48000,
1364
1365 .channels_min = 1,
1366 .channels_max = 32,
1367
1368 .periods_min = 2,
1369 .periods_max = 10,
1370
1371 .period_bytes_min = 128,
1372 .period_bytes_max = 64 * PAGE_SIZE,
1373 .buffer_bytes_max = 256 * PAGE_SIZE
1374};
1375
1212/* uniperiph player*/ 1376/* uniperiph player*/
1213int uni_player_init(struct platform_device *pdev, 1377int uni_player_init(struct platform_device *pdev,
1214 struct uniperif *uni_player); 1378 struct uniperif *uni_player);
@@ -1226,4 +1390,28 @@ int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream,
1226 struct snd_pcm_hw_params *params, 1390 struct snd_pcm_hw_params *params,
1227 struct snd_soc_dai *dai); 1391 struct snd_soc_dai *dai);
1228 1392
1393static inline int sti_uniperiph_get_user_frame_size(
1394 struct snd_pcm_runtime *runtime)
1395{
1396 return (runtime->channels * snd_pcm_format_width(runtime->format) / 8);
1397}
1398
1399static inline int sti_uniperiph_get_unip_tdm_frame_size(struct uniperif *uni)
1400{
1401 return (uni->tdm_slot.slots * uni->tdm_slot.slot_width / 8);
1402}
1403
1404int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
1405 unsigned int rx_mask, int slots,
1406 int slot_width);
1407
1408int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni,
1409 unsigned int *word_pos);
1410
1411int sti_uniperiph_fix_tdm_chan(struct snd_pcm_hw_params *params,
1412 struct snd_pcm_hw_rule *rule);
1413
1414int sti_uniperiph_fix_tdm_format(struct snd_pcm_hw_params *params,
1415 struct snd_pcm_hw_rule *rule);
1416
1229#endif 1417#endif
diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c
index 7aca6b92f718..ee1c7c245bc7 100644
--- a/sound/soc/sti/uniperif_player.c
+++ b/sound/soc/sti/uniperif_player.c
@@ -21,23 +21,14 @@
21 21
22/* sys config registers definitions */ 22/* sys config registers definitions */
23#define SYS_CFG_AUDIO_GLUE 0xA4 23#define SYS_CFG_AUDIO_GLUE 0xA4
24#define SYS_CFG_AUDI0_GLUE_PCM_CLKX 8
25 24
26/* 25/*
27 * Driver specific types. 26 * Driver specific types.
28 */ 27 */
29#define UNIPERIF_PLAYER_TYPE_IS_HDMI(p) \
30 ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_HDMI)
31#define UNIPERIF_PLAYER_TYPE_IS_PCM(p) \
32 ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_PCM)
33#define UNIPERIF_PLAYER_TYPE_IS_SPDIF(p) \
34 ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF)
35#define UNIPERIF_PLAYER_TYPE_IS_IEC958(p) \
36 (UNIPERIF_PLAYER_TYPE_IS_HDMI(p) || \
37 UNIPERIF_PLAYER_TYPE_IS_SPDIF(p))
38 28
39#define UNIPERIF_PLAYER_CLK_ADJ_MIN -999999 29#define UNIPERIF_PLAYER_CLK_ADJ_MIN -999999
40#define UNIPERIF_PLAYER_CLK_ADJ_MAX 1000000 30#define UNIPERIF_PLAYER_CLK_ADJ_MAX 1000000
31#define UNIPERIF_PLAYER_I2S_OUT 1 /* player id connected to I2S/TDM TX bus */
41 32
42/* 33/*
43 * Note: snd_pcm_hardware is linked to DMA controller but is declared here to 34 * Note: snd_pcm_hardware is linked to DMA controller but is declared here to
@@ -444,18 +435,11 @@ static int uni_player_prepare_pcm(struct uniperif *player,
444 435
445 /* Force slot width to 32 in I2S mode (HW constraint) */ 436 /* Force slot width to 32 in I2S mode (HW constraint) */
446 if ((player->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == 437 if ((player->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
447 SND_SOC_DAIFMT_I2S) { 438 SND_SOC_DAIFMT_I2S)
448 slot_width = 32; 439 slot_width = 32;
449 } else { 440 else
450 switch (runtime->format) { 441 slot_width = snd_pcm_format_width(runtime->format);
451 case SNDRV_PCM_FORMAT_S16_LE: 442
452 slot_width = 16;
453 break;
454 default:
455 slot_width = 32;
456 break;
457 }
458 }
459 output_frame_size = slot_width * runtime->channels; 443 output_frame_size = slot_width * runtime->channels;
460 444
461 clk_div = player->mclk / runtime->rate; 445 clk_div = player->mclk / runtime->rate;
@@ -530,7 +514,6 @@ static int uni_player_prepare_pcm(struct uniperif *player,
530 SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player); 514 SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player);
531 515
532 SET_UNIPERIF_I2S_FMT_ORDER_MSB(player); 516 SET_UNIPERIF_I2S_FMT_ORDER_MSB(player);
533 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(player);
534 517
535 /* No iec958 formatting as outputting to DAC */ 518 /* No iec958 formatting as outputting to DAC */
536 SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player); 519 SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player);
@@ -538,6 +521,55 @@ static int uni_player_prepare_pcm(struct uniperif *player,
538 return 0; 521 return 0;
539} 522}
540 523
524static int uni_player_prepare_tdm(struct uniperif *player,
525 struct snd_pcm_runtime *runtime)
526{
527 int tdm_frame_size; /* unip tdm frame size in bytes */
528 int user_frame_size; /* user tdm frame size in bytes */
529 /* default unip TDM_WORD_POS_X_Y */
530 unsigned int word_pos[4] = {
531 0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A};
532 int freq, ret;
533
534 tdm_frame_size =
535 sti_uniperiph_get_unip_tdm_frame_size(player);
536 user_frame_size =
537 sti_uniperiph_get_user_frame_size(runtime);
538
539 /* fix 16/0 format */
540 SET_UNIPERIF_CONFIG_MEM_FMT_16_0(player);
541 SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(player);
542
543 /* number of words inserted on the TDM line */
544 SET_UNIPERIF_I2S_FMT_NUM_CH(player, user_frame_size / 4 / 2);
545
546 SET_UNIPERIF_I2S_FMT_ORDER_MSB(player);
547 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(player);
548
549 /* Enable the tdm functionality */
550 SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(player);
551
552 /* number of 8 bits timeslots avail in unip tdm frame */
553 SET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(player, tdm_frame_size);
554
555 /* set the timeslot allocation for words in FIFO */
556 sti_uniperiph_get_tdm_word_pos(player, word_pos);
557 SET_UNIPERIF_TDM_WORD_POS(player, 1_2, word_pos[WORD_1_2]);
558 SET_UNIPERIF_TDM_WORD_POS(player, 3_4, word_pos[WORD_3_4]);
559 SET_UNIPERIF_TDM_WORD_POS(player, 5_6, word_pos[WORD_5_6]);
560 SET_UNIPERIF_TDM_WORD_POS(player, 7_8, word_pos[WORD_7_8]);
561
562 /* set unip clk rate (not done vai set_sysclk ops) */
563 freq = runtime->rate * tdm_frame_size * 8;
564 mutex_lock(&player->ctrl_lock);
565 ret = uni_player_clk_set_rate(player, freq);
566 if (!ret)
567 player->mclk = freq;
568 mutex_unlock(&player->ctrl_lock);
569
570 return 0;
571}
572
541/* 573/*
542 * ALSA uniperipheral iec958 controls 574 * ALSA uniperipheral iec958 controls
543 */ 575 */
@@ -668,11 +700,29 @@ static int uni_player_startup(struct snd_pcm_substream *substream,
668{ 700{
669 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 701 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
670 struct uniperif *player = priv->dai_data.uni; 702 struct uniperif *player = priv->dai_data.uni;
703 int ret;
704
671 player->substream = substream; 705 player->substream = substream;
672 706
673 player->clk_adj = 0; 707 player->clk_adj = 0;
674 708
675 return 0; 709 if (!UNIPERIF_TYPE_IS_TDM(player))
710 return 0;
711
712 /* refine hw constraint in tdm mode */
713 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
714 SNDRV_PCM_HW_PARAM_CHANNELS,
715 sti_uniperiph_fix_tdm_chan,
716 player, SNDRV_PCM_HW_PARAM_CHANNELS,
717 -1);
718 if (ret < 0)
719 return ret;
720
721 return snd_pcm_hw_rule_add(substream->runtime, 0,
722 SNDRV_PCM_HW_PARAM_FORMAT,
723 sti_uniperiph_fix_tdm_format,
724 player, SNDRV_PCM_HW_PARAM_FORMAT,
725 -1);
676} 726}
677 727
678static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id, 728static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id,
@@ -682,7 +732,7 @@ static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id,
682 struct uniperif *player = priv->dai_data.uni; 732 struct uniperif *player = priv->dai_data.uni;
683 int ret; 733 int ret;
684 734
685 if (dir == SND_SOC_CLOCK_IN) 735 if (UNIPERIF_TYPE_IS_TDM(player) || (dir == SND_SOC_CLOCK_IN))
686 return 0; 736 return 0;
687 737
688 if (clk_id != 0) 738 if (clk_id != 0)
@@ -714,7 +764,13 @@ static int uni_player_prepare(struct snd_pcm_substream *substream,
714 } 764 }
715 765
716 /* Calculate transfer size (in fifo cells and bytes) for frame count */ 766 /* Calculate transfer size (in fifo cells and bytes) for frame count */
717 transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; 767 if (player->info->type == SND_ST_UNIPERIF_TYPE_TDM) {
768 /* transfer size = user frame size (in 32 bits FIFO cell) */
769 transfer_size =
770 sti_uniperiph_get_user_frame_size(runtime) / 4;
771 } else {
772 transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES;
773 }
718 774
719 /* Calculate number of empty cells available before asserting DREQ */ 775 /* Calculate number of empty cells available before asserting DREQ */
720 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) { 776 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) {
@@ -738,16 +794,19 @@ static int uni_player_prepare(struct snd_pcm_substream *substream,
738 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(player, trigger_limit); 794 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(player, trigger_limit);
739 795
740 /* Uniperipheral setup depends on player type */ 796 /* Uniperipheral setup depends on player type */
741 switch (player->info->player_type) { 797 switch (player->info->type) {
742 case SND_ST_UNIPERIF_PLAYER_TYPE_HDMI: 798 case SND_ST_UNIPERIF_TYPE_HDMI:
743 ret = uni_player_prepare_iec958(player, runtime); 799 ret = uni_player_prepare_iec958(player, runtime);
744 break; 800 break;
745 case SND_ST_UNIPERIF_PLAYER_TYPE_PCM: 801 case SND_ST_UNIPERIF_TYPE_PCM:
746 ret = uni_player_prepare_pcm(player, runtime); 802 ret = uni_player_prepare_pcm(player, runtime);
747 break; 803 break;
748 case SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF: 804 case SND_ST_UNIPERIF_TYPE_SPDIF:
749 ret = uni_player_prepare_iec958(player, runtime); 805 ret = uni_player_prepare_iec958(player, runtime);
750 break; 806 break;
807 case SND_ST_UNIPERIF_TYPE_TDM:
808 ret = uni_player_prepare_tdm(player, runtime);
809 break;
751 default: 810 default:
752 dev_err(player->dev, "invalid player type"); 811 dev_err(player->dev, "invalid player type");
753 return -EINVAL; 812 return -EINVAL;
@@ -852,8 +911,8 @@ static int uni_player_start(struct uniperif *player)
852 * will not take affect and hang the player. 911 * will not take affect and hang the player.
853 */ 912 */
854 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) 913 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
855 if (UNIPERIF_PLAYER_TYPE_IS_IEC958(player)) 914 if (UNIPERIF_TYPE_IS_IEC958(player))
856 SET_UNIPERIF_CTRL_SPDIF_FMT_ON(player); 915 SET_UNIPERIF_CTRL_SPDIF_FMT_ON(player);
857 916
858 /* Force channel status update (no update if clk disable) */ 917 /* Force channel status update (no update if clk disable) */
859 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) 918 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
@@ -954,27 +1013,30 @@ static void uni_player_shutdown(struct snd_pcm_substream *substream,
954 player->substream = NULL; 1013 player->substream = NULL;
955} 1014}
956 1015
957static int uni_player_parse_dt_clk_glue(struct platform_device *pdev, 1016static int uni_player_parse_dt_audio_glue(struct platform_device *pdev,
958 struct uniperif *player) 1017 struct uniperif *player)
959{ 1018{
960 int bit_offset;
961 struct device_node *node = pdev->dev.of_node; 1019 struct device_node *node = pdev->dev.of_node;
962 struct regmap *regmap; 1020 struct regmap *regmap;
963 1021 struct reg_field regfield[2] = {
964 bit_offset = SYS_CFG_AUDI0_GLUE_PCM_CLKX + player->info->id; 1022 /* PCM_CLK_SEL */
1023 REG_FIELD(SYS_CFG_AUDIO_GLUE,
1024 8 + player->info->id,
1025 8 + player->info->id),
1026 /* PCMP_VALID_SEL */
1027 REG_FIELD(SYS_CFG_AUDIO_GLUE, 0, 1)
1028 };
965 1029
966 regmap = syscon_regmap_lookup_by_phandle(node, "st,syscfg"); 1030 regmap = syscon_regmap_lookup_by_phandle(node, "st,syscfg");
967 1031
968 if (regmap) { 1032 if (!regmap) {
969 struct reg_field regfield =
970 REG_FIELD(SYS_CFG_AUDIO_GLUE, bit_offset, bit_offset);
971
972 player->clk_sel = regmap_field_alloc(regmap, regfield);
973 } else {
974 dev_err(&pdev->dev, "sti-audio-clk-glue syscf not found\n"); 1033 dev_err(&pdev->dev, "sti-audio-clk-glue syscf not found\n");
975 return -EINVAL; 1034 return -EINVAL;
976 } 1035 }
977 1036
1037 player->clk_sel = regmap_field_alloc(regmap, regfield[0]);
1038 player->valid_sel = regmap_field_alloc(regmap, regfield[1]);
1039
978 return 0; 1040 return 0;
979} 1041}
980 1042
@@ -1012,19 +1074,21 @@ static int uni_player_parse_dt(struct platform_device *pdev,
1012 } 1074 }
1013 1075
1014 if (strcasecmp(mode, "hdmi") == 0) 1076 if (strcasecmp(mode, "hdmi") == 0)
1015 info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_HDMI; 1077 info->type = SND_ST_UNIPERIF_TYPE_HDMI;
1016 else if (strcasecmp(mode, "pcm") == 0) 1078 else if (strcasecmp(mode, "pcm") == 0)
1017 info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_PCM; 1079 info->type = SND_ST_UNIPERIF_TYPE_PCM;
1018 else if (strcasecmp(mode, "spdif") == 0) 1080 else if (strcasecmp(mode, "spdif") == 0)
1019 info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF; 1081 info->type = SND_ST_UNIPERIF_TYPE_SPDIF;
1082 else if (strcasecmp(mode, "tdm") == 0)
1083 info->type = SND_ST_UNIPERIF_TYPE_TDM;
1020 else 1084 else
1021 info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_NONE; 1085 info->type = SND_ST_UNIPERIF_TYPE_NONE;
1022 1086
1023 /* Save the info structure */ 1087 /* Save the info structure */
1024 player->info = info; 1088 player->info = info;
1025 1089
1026 /* Get the PCM_CLK_SEL bit from audio-glue-ctrl SoC register */ 1090 /* Get PCM_CLK_SEL & PCMP_VALID_SEL from audio-glue-ctrl SoC reg */
1027 if (uni_player_parse_dt_clk_glue(pdev, player)) 1091 if (uni_player_parse_dt_audio_glue(pdev, player))
1028 return -EINVAL; 1092 return -EINVAL;
1029 1093
1030 return 0; 1094 return 0;
@@ -1037,7 +1101,8 @@ static const struct snd_soc_dai_ops uni_player_dai_ops = {
1037 .trigger = uni_player_trigger, 1101 .trigger = uni_player_trigger,
1038 .hw_params = sti_uniperiph_dai_hw_params, 1102 .hw_params = sti_uniperiph_dai_hw_params,
1039 .set_fmt = sti_uniperiph_dai_set_fmt, 1103 .set_fmt = sti_uniperiph_dai_set_fmt,
1040 .set_sysclk = uni_player_set_sysclk 1104 .set_sysclk = uni_player_set_sysclk,
1105 .set_tdm_slot = sti_uniperiph_set_tdm_slot
1041}; 1106};
1042 1107
1043int uni_player_init(struct platform_device *pdev, 1108int uni_player_init(struct platform_device *pdev,
@@ -1047,7 +1112,6 @@ int uni_player_init(struct platform_device *pdev,
1047 1112
1048 player->dev = &pdev->dev; 1113 player->dev = &pdev->dev;
1049 player->state = UNIPERIF_STATE_STOPPED; 1114 player->state = UNIPERIF_STATE_STOPPED;
1050 player->hw = &uni_player_pcm_hw;
1051 player->dai_ops = &uni_player_dai_ops; 1115 player->dai_ops = &uni_player_dai_ops;
1052 1116
1053 ret = uni_player_parse_dt(pdev, player); 1117 ret = uni_player_parse_dt(pdev, player);
@@ -1057,6 +1121,11 @@ int uni_player_init(struct platform_device *pdev,
1057 return ret; 1121 return ret;
1058 } 1122 }
1059 1123
1124 if (UNIPERIF_TYPE_IS_TDM(player))
1125 player->hw = &uni_tdm_hw;
1126 else
1127 player->hw = &uni_player_pcm_hw;
1128
1060 /* Get uniperif resource */ 1129 /* Get uniperif resource */
1061 player->clk = of_clk_get(pdev->dev.of_node, 0); 1130 player->clk = of_clk_get(pdev->dev.of_node, 0);
1062 if (IS_ERR(player->clk)) 1131 if (IS_ERR(player->clk))
@@ -1073,6 +1142,17 @@ int uni_player_init(struct platform_device *pdev,
1073 } 1142 }
1074 } 1143 }
1075 1144
1145 /* connect to I2S/TDM TX bus */
1146 if (player->valid_sel &&
1147 (player->info->id == UNIPERIF_PLAYER_I2S_OUT)) {
1148 ret = regmap_field_write(player->valid_sel, player->info->id);
1149 if (ret) {
1150 dev_err(player->dev,
1151 "%s: unable to connect to tdm bus", __func__);
1152 return ret;
1153 }
1154 }
1155
1076 ret = devm_request_irq(&pdev->dev, player->irq, 1156 ret = devm_request_irq(&pdev->dev, player->irq,
1077 uni_player_irq_handler, IRQF_SHARED, 1157 uni_player_irq_handler, IRQF_SHARED,
1078 dev_name(&pdev->dev), player); 1158 dev_name(&pdev->dev), player);
@@ -1087,7 +1167,7 @@ int uni_player_init(struct platform_device *pdev,
1087 SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player); 1167 SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player);
1088 SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(player); 1168 SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(player);
1089 1169
1090 if (UNIPERIF_PLAYER_TYPE_IS_IEC958(player)) { 1170 if (UNIPERIF_TYPE_IS_IEC958(player)) {
1091 /* Set default iec958 status bits */ 1171 /* Set default iec958 status bits */
1092 1172
1093 /* Consumer, PCM, copyright, 2ch, mode 0 */ 1173 /* Consumer, PCM, copyright, 2ch, mode 0 */
diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c
index 8a0eb2050169..eb74a328c928 100644
--- a/sound/soc/sti/uniperif_reader.c
+++ b/sound/soc/sti/uniperif_reader.c
@@ -73,55 +73,10 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
73 return ret; 73 return ret;
74} 74}
75 75
76static int uni_reader_prepare(struct snd_pcm_substream *substream, 76static int uni_reader_prepare_pcm(struct snd_pcm_runtime *runtime,
77 struct snd_soc_dai *dai) 77 struct uniperif *reader)
78{ 78{
79 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
80 struct uniperif *reader = priv->dai_data.uni;
81 struct snd_pcm_runtime *runtime = substream->runtime;
82 int transfer_size, trigger_limit;
83 int slot_width; 79 int slot_width;
84 int count = 10;
85
86 /* The reader should be stopped */
87 if (reader->state != UNIPERIF_STATE_STOPPED) {
88 dev_err(reader->dev, "%s: invalid reader state %d", __func__,
89 reader->state);
90 return -EINVAL;
91 }
92
93 /* Calculate transfer size (in fifo cells and bytes) for frame count */
94 transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES;
95
96 /* Calculate number of empty cells available before asserting DREQ */
97 if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
98 trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size;
99 else
100 /*
101 * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0
102 * FDMA_TRIGGER_LIMIT also controls when the state switches
103 * from OFF or STANDBY to AUDIO DATA.
104 */
105 trigger_limit = transfer_size;
106
107 /* Trigger limit must be an even number */
108 if ((!trigger_limit % 2) ||
109 (trigger_limit != 1 && transfer_size % 2) ||
110 (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) {
111 dev_err(reader->dev, "invalid trigger limit %d", trigger_limit);
112 return -EINVAL;
113 }
114
115 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit);
116
117 switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) {
118 case SND_SOC_DAIFMT_IB_IF:
119 case SND_SOC_DAIFMT_NB_IF:
120 SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader);
121 break;
122 default:
123 SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader);
124 }
125 80
126 /* Force slot width to 32 in I2S mode */ 81 /* Force slot width to 32 in I2S mode */
127 if ((reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) 82 if ((reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK)
@@ -173,6 +128,109 @@ static int uni_reader_prepare(struct snd_pcm_substream *substream,
173 return -EINVAL; 128 return -EINVAL;
174 } 129 }
175 130
131 /* Number of channels must be even */
132 if ((runtime->channels % 2) || (runtime->channels < 2) ||
133 (runtime->channels > 10)) {
134 dev_err(reader->dev, "%s: invalid nb of channels", __func__);
135 return -EINVAL;
136 }
137
138 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2);
139 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader);
140
141 return 0;
142}
143
144static int uni_reader_prepare_tdm(struct snd_pcm_runtime *runtime,
145 struct uniperif *reader)
146{
147 int frame_size; /* user tdm frame size in bytes */
148 /* default unip TDM_WORD_POS_X_Y */
149 unsigned int word_pos[4] = {
150 0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A};
151
152 frame_size = sti_uniperiph_get_user_frame_size(runtime);
153
154 /* fix 16/0 format */
155 SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader);
156 SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader);
157
158 /* number of words inserted on the TDM line */
159 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, frame_size / 4 / 2);
160
161 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader);
162 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader);
163 SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(reader);
164
165 /*
166 * set the timeslots allocation for words in FIFO
167 *
168 * HW bug: (LSB word < MSB word) => this config is not possible
169 * So if we want (LSB word < MSB) word, then it shall be
170 * handled by user
171 */
172 sti_uniperiph_get_tdm_word_pos(reader, word_pos);
173 SET_UNIPERIF_TDM_WORD_POS(reader, 1_2, word_pos[WORD_1_2]);
174 SET_UNIPERIF_TDM_WORD_POS(reader, 3_4, word_pos[WORD_3_4]);
175 SET_UNIPERIF_TDM_WORD_POS(reader, 5_6, word_pos[WORD_5_6]);
176 SET_UNIPERIF_TDM_WORD_POS(reader, 7_8, word_pos[WORD_7_8]);
177
178 return 0;
179}
180
181static int uni_reader_prepare(struct snd_pcm_substream *substream,
182 struct snd_soc_dai *dai)
183{
184 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
185 struct uniperif *reader = priv->dai_data.uni;
186 struct snd_pcm_runtime *runtime = substream->runtime;
187 int transfer_size, trigger_limit, ret;
188 int count = 10;
189
190 /* The reader should be stopped */
191 if (reader->state != UNIPERIF_STATE_STOPPED) {
192 dev_err(reader->dev, "%s: invalid reader state %d", __func__,
193 reader->state);
194 return -EINVAL;
195 }
196
197 /* Calculate transfer size (in fifo cells and bytes) for frame count */
198 if (reader->info->type == SND_ST_UNIPERIF_TYPE_TDM) {
199 /* transfer size = unip frame size (in 32 bits FIFO cell) */
200 transfer_size =
201 sti_uniperiph_get_user_frame_size(runtime) / 4;
202 } else {
203 transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES;
204 }
205
206 /* Calculate number of empty cells available before asserting DREQ */
207 if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
208 trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size;
209 else
210 /*
211 * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0
212 * FDMA_TRIGGER_LIMIT also controls when the state switches
213 * from OFF or STANDBY to AUDIO DATA.
214 */
215 trigger_limit = transfer_size;
216
217 /* Trigger limit must be an even number */
218 if ((!trigger_limit % 2) ||
219 (trigger_limit != 1 && transfer_size % 2) ||
220 (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) {
221 dev_err(reader->dev, "invalid trigger limit %d", trigger_limit);
222 return -EINVAL;
223 }
224
225 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit);
226
227 if (UNIPERIF_TYPE_IS_TDM(reader))
228 ret = uni_reader_prepare_tdm(runtime, reader);
229 else
230 ret = uni_reader_prepare_pcm(runtime, reader);
231 if (ret)
232 return ret;
233
176 switch (reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) { 234 switch (reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) {
177 case SND_SOC_DAIFMT_I2S: 235 case SND_SOC_DAIFMT_I2S:
178 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); 236 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader);
@@ -191,21 +249,26 @@ static int uni_reader_prepare(struct snd_pcm_substream *substream,
191 return -EINVAL; 249 return -EINVAL;
192 } 250 }
193 251
194 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); 252 /* Data clocking (changing) on the rising/falling edge */
195 253 switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) {
196 /* Data clocking (changing) on the rising edge */ 254 case SND_SOC_DAIFMT_NB_NF:
197 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); 255 SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader);
198 256 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader);
199 /* Number of channels must be even */ 257 break;
200 258 case SND_SOC_DAIFMT_NB_IF:
201 if ((runtime->channels % 2) || (runtime->channels < 2) || 259 SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader);
202 (runtime->channels > 10)) { 260 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader);
203 dev_err(reader->dev, "%s: invalid nb of channels", __func__); 261 break;
204 return -EINVAL; 262 case SND_SOC_DAIFMT_IB_NF:
263 SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader);
264 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader);
265 break;
266 case SND_SOC_DAIFMT_IB_IF:
267 SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader);
268 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader);
269 break;
205 } 270 }
206 271
207 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2);
208
209 /* Clear any pending interrupts */ 272 /* Clear any pending interrupts */
210 SET_UNIPERIF_ITS_BCLR(reader, GET_UNIPERIF_ITS(reader)); 273 SET_UNIPERIF_ITS_BCLR(reader, GET_UNIPERIF_ITS(reader));
211 274
@@ -293,6 +356,32 @@ static int uni_reader_trigger(struct snd_pcm_substream *substream,
293 } 356 }
294} 357}
295 358
359static int uni_reader_startup(struct snd_pcm_substream *substream,
360 struct snd_soc_dai *dai)
361{
362 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
363 struct uniperif *reader = priv->dai_data.uni;
364 int ret;
365
366 if (!UNIPERIF_TYPE_IS_TDM(reader))
367 return 0;
368
369 /* refine hw constraint in tdm mode */
370 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
371 SNDRV_PCM_HW_PARAM_CHANNELS,
372 sti_uniperiph_fix_tdm_chan,
373 reader, SNDRV_PCM_HW_PARAM_CHANNELS,
374 -1);
375 if (ret < 0)
376 return ret;
377
378 return snd_pcm_hw_rule_add(substream->runtime, 0,
379 SNDRV_PCM_HW_PARAM_FORMAT,
380 sti_uniperiph_fix_tdm_format,
381 reader, SNDRV_PCM_HW_PARAM_FORMAT,
382 -1);
383}
384
296static void uni_reader_shutdown(struct snd_pcm_substream *substream, 385static void uni_reader_shutdown(struct snd_pcm_substream *substream,
297 struct snd_soc_dai *dai) 386 struct snd_soc_dai *dai)
298{ 387{
@@ -310,6 +399,7 @@ static int uni_reader_parse_dt(struct platform_device *pdev,
310{ 399{
311 struct uniperif_info *info; 400 struct uniperif_info *info;
312 struct device_node *node = pdev->dev.of_node; 401 struct device_node *node = pdev->dev.of_node;
402 const char *mode;
313 403
314 /* Allocate memory for the info structure */ 404 /* Allocate memory for the info structure */
315 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); 405 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
@@ -322,6 +412,17 @@ static int uni_reader_parse_dt(struct platform_device *pdev,
322 return -EINVAL; 412 return -EINVAL;
323 } 413 }
324 414
415 /* Read the device mode property */
416 if (of_property_read_string(node, "st,mode", &mode)) {
417 dev_err(&pdev->dev, "uniperipheral mode not defined");
418 return -EINVAL;
419 }
420
421 if (strcasecmp(mode, "tdm") == 0)
422 info->type = SND_ST_UNIPERIF_TYPE_TDM;
423 else
424 info->type = SND_ST_UNIPERIF_TYPE_PCM;
425
325 /* Save the info structure */ 426 /* Save the info structure */
326 reader->info = info; 427 reader->info = info;
327 428
@@ -329,11 +430,13 @@ static int uni_reader_parse_dt(struct platform_device *pdev,
329} 430}
330 431
331static const struct snd_soc_dai_ops uni_reader_dai_ops = { 432static const struct snd_soc_dai_ops uni_reader_dai_ops = {
433 .startup = uni_reader_startup,
332 .shutdown = uni_reader_shutdown, 434 .shutdown = uni_reader_shutdown,
333 .prepare = uni_reader_prepare, 435 .prepare = uni_reader_prepare,
334 .trigger = uni_reader_trigger, 436 .trigger = uni_reader_trigger,
335 .hw_params = sti_uniperiph_dai_hw_params, 437 .hw_params = sti_uniperiph_dai_hw_params,
336 .set_fmt = sti_uniperiph_dai_set_fmt, 438 .set_fmt = sti_uniperiph_dai_set_fmt,
439 .set_tdm_slot = sti_uniperiph_set_tdm_slot
337}; 440};
338 441
339int uni_reader_init(struct platform_device *pdev, 442int uni_reader_init(struct platform_device *pdev,
@@ -343,7 +446,6 @@ int uni_reader_init(struct platform_device *pdev,
343 446
344 reader->dev = &pdev->dev; 447 reader->dev = &pdev->dev;
345 reader->state = UNIPERIF_STATE_STOPPED; 448 reader->state = UNIPERIF_STATE_STOPPED;
346 reader->hw = &uni_reader_pcm_hw;
347 reader->dai_ops = &uni_reader_dai_ops; 449 reader->dai_ops = &uni_reader_dai_ops;
348 450
349 ret = uni_reader_parse_dt(pdev, reader); 451 ret = uni_reader_parse_dt(pdev, reader);
@@ -352,6 +454,11 @@ int uni_reader_init(struct platform_device *pdev,
352 return ret; 454 return ret;
353 } 455 }
354 456
457 if (UNIPERIF_TYPE_IS_TDM(reader))
458 reader->hw = &uni_tdm_hw;
459 else
460 reader->hw = &uni_reader_pcm_hw;
461
355 ret = devm_request_irq(&pdev->dev, reader->irq, 462 ret = devm_request_irq(&pdev->dev, reader->irq,
356 uni_reader_irq_handler, IRQF_SHARED, 463 uni_reader_irq_handler, IRQF_SHARED,
357 dev_name(&pdev->dev), reader); 464 dev_name(&pdev->dev), reader);