summaryrefslogtreecommitdiff
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/Kconfig627
-rw-r--r--sound/soc/codecs/Makefile4
-rw-r--r--sound/soc/codecs/ak4104.c3
-rw-r--r--sound/soc/codecs/cros_ec_codec.c25
-rw-r--r--sound/soc/codecs/cs4270.c3
-rw-r--r--sound/soc/codecs/cs4271.c4
-rw-r--r--sound/soc/codecs/cs47l15.c13
-rw-r--r--sound/soc/codecs/cs47l35.c12
-rw-r--r--sound/soc/codecs/cs47l85.c9
-rw-r--r--sound/soc/codecs/cs47l90.c9
-rw-r--r--sound/soc/codecs/cs47l92.c14
-rw-r--r--sound/soc/codecs/hdmi-codec.c2
-rw-r--r--sound/soc/codecs/madera.c13
-rw-r--r--sound/soc/codecs/madera.h4
-rw-r--r--sound/soc/codecs/max98357a.c36
-rw-r--r--sound/soc/codecs/mt6660.c79
-rw-r--r--sound/soc/codecs/rk3328_codec.c31
-rw-r--r--sound/soc/codecs/rl6231.c1
-rw-r--r--sound/soc/codecs/rl6231.h2
-rw-r--r--sound/soc/codecs/rt1015.c10
-rw-r--r--sound/soc/codecs/rt5659.c2
-rw-r--r--sound/soc/codecs/rt5682-sdw.c333
-rw-r--r--sound/soc/codecs/rt5682-sdw.h20
-rw-r--r--sound/soc/codecs/rt5682.c1268
-rw-r--r--sound/soc/codecs/rt5682.h98
-rw-r--r--sound/soc/codecs/tas2562.c119
-rw-r--r--sound/soc/codecs/tas2562.h12
-rw-r--r--sound/soc/codecs/tlv320adcx140.c922
-rw-r--r--sound/soc/codecs/tlv320adcx140.h131
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c6
-rw-r--r--sound/soc/codecs/wcd934x.c23
-rw-r--r--sound/soc/codecs/wm0010.c2
-rw-r--r--sound/soc/codecs/wm_adsp.c98
33 files changed, 3387 insertions, 548 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 7e90f5d83097..6aee70ed43df 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -14,262 +14,264 @@ menu "CODEC drivers"
config SND_SOC_ALL_CODECS
tristate "Build all ASoC CODEC drivers"
depends on COMPILE_TEST
- select SND_SOC_88PM860X if MFD_88PM860X
- select SND_SOC_L3
- select SND_SOC_AB8500_CODEC if ABX500_CORE
- select SND_SOC_AC97_CODEC
- select SND_SOC_AD1836 if SPI_MASTER
- select SND_SOC_AD193X_SPI if SPI_MASTER
- select SND_SOC_AD193X_I2C if I2C
- select SND_SOC_AD1980 if SND_SOC_AC97_BUS
- select SND_SOC_AD73311
- select SND_SOC_ADAU1373 if I2C
- select SND_SOC_ADAU1761_I2C if I2C
- select SND_SOC_ADAU1761_SPI if SPI
- select SND_SOC_ADAU1781_I2C if I2C
- select SND_SOC_ADAU1781_SPI if SPI
- select SND_SOC_ADAV801 if SPI_MASTER
- select SND_SOC_ADAV803 if I2C
- select SND_SOC_ADAU1977_SPI if SPI_MASTER
- select SND_SOC_ADAU1977_I2C if I2C
- select SND_SOC_ADAU1701 if I2C
- select SND_SOC_ADAU7002
- select SND_SOC_ADAU7118_I2C if I2C
- select SND_SOC_ADAU7118_HW
- select SND_SOC_ADS117X
- select SND_SOC_AK4104 if SPI_MASTER
- select SND_SOC_AK4118 if I2C
- select SND_SOC_AK4458 if I2C
- select SND_SOC_AK4535 if I2C
- select SND_SOC_AK4554
- select SND_SOC_AK4613 if I2C
- select SND_SOC_AK4641 if I2C
- select SND_SOC_AK4642 if I2C
- select SND_SOC_AK4671 if I2C
- select SND_SOC_AK5386
- select SND_SOC_AK5558 if I2C
- select SND_SOC_ALC5623 if I2C
- select SND_SOC_ALC5632 if I2C
- select SND_SOC_BT_SCO
- select SND_SOC_BD28623
- select SND_SOC_CQ0093VC
- select SND_SOC_CROS_EC_CODEC if CROS_EC
- select SND_SOC_CS35L32 if I2C
- select SND_SOC_CS35L33 if I2C
- select SND_SOC_CS35L34 if I2C
- select SND_SOC_CS35L35 if I2C
- select SND_SOC_CS35L36 if I2C
- select SND_SOC_CS42L42 if I2C
- select SND_SOC_CS42L51_I2C if I2C
- select SND_SOC_CS42L52 if I2C && INPUT
- select SND_SOC_CS42L56 if I2C && INPUT
- select SND_SOC_CS42L73 if I2C
- select SND_SOC_CS4265 if I2C
- select SND_SOC_CS4270 if I2C
- select SND_SOC_CS4271_I2C if I2C
- select SND_SOC_CS4271_SPI if SPI_MASTER
- select SND_SOC_CS42XX8_I2C if I2C
- select SND_SOC_CS43130 if I2C
- select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI
- select SND_SOC_CS4349 if I2C
- select SND_SOC_CS47L15 if MFD_CS47L15
- select SND_SOC_CS47L24 if MFD_CS47L24
- select SND_SOC_CS47L35 if MFD_CS47L35
- select SND_SOC_CS47L85 if MFD_CS47L85
- select SND_SOC_CS47L90 if MFD_CS47L90
- select SND_SOC_CS47L92 if MFD_CS47L92
- select SND_SOC_CS53L30 if I2C
- select SND_SOC_CX20442 if TTY
- select SND_SOC_CX2072X if I2C
- select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI
- select SND_SOC_DA7213 if I2C
- select SND_SOC_DA7218 if I2C
- select SND_SOC_DA7219 if I2C
- select SND_SOC_DA732X if I2C
- select SND_SOC_DA9055 if I2C
- select SND_SOC_DMIC if GPIOLIB
- select SND_SOC_ES8316 if I2C
- select SND_SOC_ES8328_SPI if SPI_MASTER
- select SND_SOC_ES8328_I2C if I2C
- select SND_SOC_ES7134
- select SND_SOC_ES7241
- select SND_SOC_GTM601
- select SND_SOC_HDAC_HDMI
- select SND_SOC_HDAC_HDA
- select SND_SOC_ICS43432
- select SND_SOC_INNO_RK3036
- select SND_SOC_ISABELLE if I2C
- select SND_SOC_JZ4740_CODEC
- select SND_SOC_JZ4725B_CODEC
- select SND_SOC_JZ4770_CODEC
- select SND_SOC_LM4857 if I2C
- select SND_SOC_LM49453 if I2C
- select SND_SOC_LOCHNAGAR_SC if MFD_LOCHNAGAR
- select SND_SOC_MAX98088 if I2C
- select SND_SOC_MAX98090 if I2C
- select SND_SOC_MAX98095 if I2C
- select SND_SOC_MAX98357A if GPIOLIB
- select SND_SOC_MAX98371 if I2C
- select SND_SOC_MAX98504 if I2C
- select SND_SOC_MAX9867 if I2C
- select SND_SOC_MAX98925 if I2C
- select SND_SOC_MAX98926 if I2C
- select SND_SOC_MAX98927 if I2C
- select SND_SOC_MAX98373 if I2C
- select SND_SOC_MAX9850 if I2C
- select SND_SOC_MAX9860 if I2C
- select SND_SOC_MAX9759
- select SND_SOC_MAX9768 if I2C
- select SND_SOC_MAX9877 if I2C
- select SND_SOC_MC13783 if MFD_MC13XXX
- select SND_SOC_ML26124 if I2C
- select SND_SOC_MT6351 if MTK_PMIC_WRAP
- select SND_SOC_MT6358 if MTK_PMIC_WRAP
- select SND_SOC_MT6660 if I2C
- select SND_SOC_NAU8540 if I2C
- select SND_SOC_NAU8810 if I2C
- select SND_SOC_NAU8822 if I2C
- select SND_SOC_NAU8824 if I2C
- select SND_SOC_NAU8825 if I2C
- select SND_SOC_HDMI_CODEC
- select SND_SOC_PCM1681 if I2C
- select SND_SOC_PCM1789_I2C if I2C
- select SND_SOC_PCM179X_I2C if I2C
- select SND_SOC_PCM179X_SPI if SPI_MASTER
- select SND_SOC_PCM186X_I2C if I2C
- select SND_SOC_PCM186X_SPI if SPI_MASTER
- select SND_SOC_PCM3008
- select SND_SOC_PCM3060_I2C if I2C
- select SND_SOC_PCM3060_SPI if SPI_MASTER
- select SND_SOC_PCM3168A_I2C if I2C
- select SND_SOC_PCM3168A_SPI if SPI_MASTER
- select SND_SOC_PCM5102A
- select SND_SOC_PCM512x_I2C if I2C
- select SND_SOC_PCM512x_SPI if SPI_MASTER
- select SND_SOC_RK3328
- select SND_SOC_RT274 if I2C
- select SND_SOC_RT286 if I2C
- select SND_SOC_RT298 if I2C
- select SND_SOC_RT1011 if I2C
- select SND_SOC_RT1015 if I2C
- select SND_SOC_RT1305 if I2C
- select SND_SOC_RT1308 if I2C
- select SND_SOC_RT5514 if I2C
- select SND_SOC_RT5616 if I2C
- select SND_SOC_RT5631 if I2C
- select SND_SOC_RT5640 if I2C
- select SND_SOC_RT5645 if I2C
- select SND_SOC_RT5651 if I2C
- select SND_SOC_RT5659 if I2C
- select SND_SOC_RT5660 if I2C
- select SND_SOC_RT5663 if I2C
- select SND_SOC_RT5665 if I2C
- select SND_SOC_RT5668 if I2C
- select SND_SOC_RT5670 if I2C
- select SND_SOC_RT5677 if I2C && SPI_MASTER
- select SND_SOC_RT5682 if I2C
- select SND_SOC_RT700_SDW if SOUNDWIRE
- select SND_SOC_RT711_SDW if SOUNDWIRE
- select SND_SOC_RT715_SDW if SOUNDWIRE
- select SND_SOC_RT1308_SDW if SOUNDWIRE
- select SND_SOC_SGTL5000 if I2C
- select SND_SOC_SI476X if MFD_SI476X_CORE
- select SND_SOC_SIMPLE_AMPLIFIER
- select SND_SOC_SIRF_AUDIO_CODEC
- select SND_SOC_SPDIF
- select SND_SOC_SSM2305
- select SND_SOC_SSM2518 if I2C
- select SND_SOC_SSM2602_SPI if SPI_MASTER
- select SND_SOC_SSM2602_I2C if I2C
- select SND_SOC_SSM4567 if I2C
- select SND_SOC_STA32X if I2C
- select SND_SOC_STA350 if I2C
- select SND_SOC_STA529 if I2C
- select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
- select SND_SOC_STI_SAS
- select SND_SOC_TAS2552 if I2C
- select SND_SOC_TAS2562 if I2C
- select SND_SOC_TAS2770 if I2C
- select SND_SOC_TAS5086 if I2C
- select SND_SOC_TAS571X if I2C
- select SND_SOC_TAS5720 if I2C
- select SND_SOC_TAS6424 if I2C
- select SND_SOC_TDA7419 if I2C
- select SND_SOC_TFA9879 if I2C
- select SND_SOC_TLV320AIC23_I2C if I2C
- select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
- select SND_SOC_TLV320AIC26 if SPI_MASTER
- select SND_SOC_TLV320AIC31XX if I2C
- select SND_SOC_TLV320AIC32X4_I2C if I2C && COMMON_CLK
- select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER && COMMON_CLK
- select SND_SOC_TLV320AIC3X if I2C
- select SND_SOC_TPA6130A2 if I2C
- select SND_SOC_TLV320DAC33 if I2C
- select SND_SOC_TSCS42XX if I2C
- select SND_SOC_TSCS454 if I2C
- select SND_SOC_TS3A227E if I2C
- select SND_SOC_TWL4030 if TWL4030_CORE
- select SND_SOC_TWL6040 if TWL6040_CORE
- select SND_SOC_UDA1334 if GPIOLIB
- select SND_SOC_UDA134X
- select SND_SOC_UDA1380 if I2C
- select SND_SOC_WCD9335 if SLIMBUS
- select SND_SOC_WCD934X if MFD_WCD934X && COMMON_CLK
- select SND_SOC_WL1273 if MFD_WL1273_CORE
- select SND_SOC_WM0010 if SPI_MASTER
- select SND_SOC_WM1250_EV1 if I2C
- select SND_SOC_WM2000 if I2C
- select SND_SOC_WM2200 if I2C
- select SND_SOC_WM5100 if I2C
- select SND_SOC_WM5102 if MFD_WM5102
- select SND_SOC_WM5110 if MFD_WM5110
- select SND_SOC_WM8350 if MFD_WM8350
- select SND_SOC_WM8400 if MFD_WM8400
- select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8523 if I2C
- select SND_SOC_WM8524 if GPIOLIB
- select SND_SOC_WM8580 if I2C
- select SND_SOC_WM8711 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8727
- select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8737 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8741 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8770 if SPI_MASTER
- select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8782
- select SND_SOC_WM8804_I2C if I2C
- select SND_SOC_WM8804_SPI if SPI_MASTER
- select SND_SOC_WM8900 if I2C
- select SND_SOC_WM8903 if I2C
- select SND_SOC_WM8904 if I2C
- select SND_SOC_WM8940 if I2C
- select SND_SOC_WM8955 if I2C
- select SND_SOC_WM8960 if I2C
- select SND_SOC_WM8961 if I2C
- select SND_SOC_WM8962 if I2C && INPUT
- select SND_SOC_WM8971 if I2C
- select SND_SOC_WM8974 if I2C
- select SND_SOC_WM8978 if I2C
- select SND_SOC_WM8983 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8990 if I2C
- select SND_SOC_WM8991 if I2C
- select SND_SOC_WM8993 if I2C
- select SND_SOC_WM8994 if MFD_WM8994
- select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI
- select SND_SOC_WM8996 if I2C
- select SND_SOC_WM8997 if MFD_WM8997
- select SND_SOC_WM8998 if MFD_WM8998
- select SND_SOC_WM9081 if I2C
- select SND_SOC_WM9090 if I2C
- select SND_SOC_WM9705 if (SND_SOC_AC97_BUS || SND_SOC_AC97_BUS_NEW)
- select SND_SOC_WM9712 if (SND_SOC_AC97_BUS || SND_SOC_AC97_BUS_NEW)
- select SND_SOC_WM9713 if (SND_SOC_AC97_BUS || SND_SOC_AC97_BUS_NEW)
- select SND_SOC_WSA881X if SOUNDWIRE
+ imply SND_SOC_88PM860X
+ imply SND_SOC_L3
+ imply SND_SOC_AB8500_CODEC
+ imply SND_SOC_AC97_CODEC
+ imply SND_SOC_AD1836
+ imply SND_SOC_AD193X_SPI
+ imply SND_SOC_AD193X_I2C
+ imply SND_SOC_AD1980
+ imply SND_SOC_AD73311
+ imply SND_SOC_ADAU1373
+ imply SND_SOC_ADAU1761_I2C
+ imply SND_SOC_ADAU1761_SPI
+ imply SND_SOC_ADAU1781_I2C
+ imply SND_SOC_ADAU1781_SPI
+ imply SND_SOC_ADAV801
+ imply SND_SOC_ADAV803
+ imply SND_SOC_ADAU1977_SPI
+ imply SND_SOC_ADAU1977_I2C
+ imply SND_SOC_ADAU1701
+ imply SND_SOC_ADAU7002
+ imply SND_SOC_ADAU7118_I2C
+ imply SND_SOC_ADAU7118_HW
+ imply SND_SOC_ADS117X
+ imply SND_SOC_AK4104
+ imply SND_SOC_AK4118
+ imply SND_SOC_AK4458
+ imply SND_SOC_AK4535
+ imply SND_SOC_AK4554
+ imply SND_SOC_AK4613
+ imply SND_SOC_AK4641
+ imply SND_SOC_AK4642
+ imply SND_SOC_AK4671
+ imply SND_SOC_AK5386
+ imply SND_SOC_AK5558
+ imply SND_SOC_ALC5623
+ imply SND_SOC_ALC5632
+ imply SND_SOC_BT_SCO
+ imply SND_SOC_BD28623
+ imply SND_SOC_CQ0093VC
+ imply SND_SOC_CROS_EC_CODEC
+ imply SND_SOC_CS35L32
+ imply SND_SOC_CS35L33
+ imply SND_SOC_CS35L34
+ imply SND_SOC_CS35L35
+ imply SND_SOC_CS35L36
+ imply SND_SOC_CS42L42
+ imply SND_SOC_CS42L51_I2C
+ imply SND_SOC_CS42L52
+ imply SND_SOC_CS42L56
+ imply SND_SOC_CS42L73
+ imply SND_SOC_CS4265
+ imply SND_SOC_CS4270
+ imply SND_SOC_CS4271_I2C
+ imply SND_SOC_CS4271_SPI
+ imply SND_SOC_CS42XX8_I2C
+ imply SND_SOC_CS43130
+ imply SND_SOC_CS4341
+ imply SND_SOC_CS4349
+ imply SND_SOC_CS47L15
+ imply SND_SOC_CS47L24
+ imply SND_SOC_CS47L35
+ imply SND_SOC_CS47L85
+ imply SND_SOC_CS47L90
+ imply SND_SOC_CS47L92
+ imply SND_SOC_CS53L30
+ imply SND_SOC_CX20442
+ imply SND_SOC_CX2072X
+ imply SND_SOC_DA7210
+ imply SND_SOC_DA7213
+ imply SND_SOC_DA7218
+ imply SND_SOC_DA7219
+ imply SND_SOC_DA732X
+ imply SND_SOC_DA9055
+ imply SND_SOC_DMIC
+ imply SND_SOC_ES8316
+ imply SND_SOC_ES8328_SPI
+ imply SND_SOC_ES8328_I2C
+ imply SND_SOC_ES7134
+ imply SND_SOC_ES7241
+ imply SND_SOC_GTM601
+ imply SND_SOC_HDAC_HDMI
+ imply SND_SOC_HDAC_HDA
+ imply SND_SOC_ICS43432
+ imply SND_SOC_INNO_RK3036
+ imply SND_SOC_ISABELLE
+ imply SND_SOC_JZ4740_CODEC
+ imply SND_SOC_JZ4725B_CODEC
+ imply SND_SOC_JZ4770_CODEC
+ imply SND_SOC_LM4857
+ imply SND_SOC_LM49453
+ imply SND_SOC_LOCHNAGAR_SC
+ imply SND_SOC_MAX98088
+ imply SND_SOC_MAX98090
+ imply SND_SOC_MAX98095
+ imply SND_SOC_MAX98357A
+ imply SND_SOC_MAX98371
+ imply SND_SOC_MAX98504
+ imply SND_SOC_MAX9867
+ imply SND_SOC_MAX98925
+ imply SND_SOC_MAX98926
+ imply SND_SOC_MAX98927
+ imply SND_SOC_MAX98373
+ imply SND_SOC_MAX9850
+ imply SND_SOC_MAX9860
+ imply SND_SOC_MAX9759
+ imply SND_SOC_MAX9768
+ imply SND_SOC_MAX9877
+ imply SND_SOC_MC13783
+ imply SND_SOC_ML26124
+ imply SND_SOC_MT6351
+ imply SND_SOC_MT6358
+ imply SND_SOC_MT6660
+ imply SND_SOC_NAU8540
+ imply SND_SOC_NAU8810
+ imply SND_SOC_NAU8822
+ imply SND_SOC_NAU8824
+ imply SND_SOC_NAU8825
+ imply SND_SOC_HDMI_CODEC
+ imply SND_SOC_PCM1681
+ imply SND_SOC_PCM1789_I2C
+ imply SND_SOC_PCM179X_I2C
+ imply SND_SOC_PCM179X_SPI
+ imply SND_SOC_PCM186X_I2C
+ imply SND_SOC_PCM186X_SPI
+ imply SND_SOC_PCM3008
+ imply SND_SOC_PCM3060_I2C
+ imply SND_SOC_PCM3060_SPI
+ imply SND_SOC_PCM3168A_I2C
+ imply SND_SOC_PCM3168A_SPI
+ imply SND_SOC_PCM5102A
+ imply SND_SOC_PCM512x_I2C
+ imply SND_SOC_PCM512x_SPI
+ imply SND_SOC_RK3328
+ imply SND_SOC_RT274
+ imply SND_SOC_RT286
+ imply SND_SOC_RT298
+ imply SND_SOC_RT1011
+ imply SND_SOC_RT1015
+ imply SND_SOC_RT1305
+ imply SND_SOC_RT1308
+ imply SND_SOC_RT5514
+ imply SND_SOC_RT5616
+ imply SND_SOC_RT5631
+ imply SND_SOC_RT5640
+ imply SND_SOC_RT5645
+ imply SND_SOC_RT5651
+ imply SND_SOC_RT5659
+ imply SND_SOC_RT5660
+ imply SND_SOC_RT5663
+ imply SND_SOC_RT5665
+ imply SND_SOC_RT5668
+ imply SND_SOC_RT5670
+ imply SND_SOC_RT5677
+ imply SND_SOC_RT5682
+ imply SND_SOC_RT5682_SDW
+ imply SND_SOC_RT700_SDW
+ imply SND_SOC_RT711_SDW
+ imply SND_SOC_RT715_SDW
+ imply SND_SOC_RT1308_SDW
+ imply SND_SOC_SGTL5000
+ imply SND_SOC_SI476X
+ imply SND_SOC_SIMPLE_AMPLIFIER
+ imply SND_SOC_SIRF_AUDIO_CODEC
+ imply SND_SOC_SPDIF
+ imply SND_SOC_SSM2305
+ imply SND_SOC_SSM2518
+ imply SND_SOC_SSM2602_SPI
+ imply SND_SOC_SSM2602_I2C
+ imply SND_SOC_SSM4567
+ imply SND_SOC_STA32X
+ imply SND_SOC_STA350
+ imply SND_SOC_STA529
+ imply SND_SOC_STAC9766
+ imply SND_SOC_STI_SAS
+ imply SND_SOC_TAS2552
+ imply SND_SOC_TAS2562
+ imply SND_SOC_TAS2770
+ imply SND_SOC_TAS5086
+ imply SND_SOC_TAS571X
+ imply SND_SOC_TAS5720
+ imply SND_SOC_TAS6424
+ imply SND_SOC_TDA7419
+ imply SND_SOC_TFA9879
+ imply SND_SOC_TLV320ADCX140
+ imply SND_SOC_TLV320AIC23_I2C
+ imply SND_SOC_TLV320AIC23_SPI
+ imply SND_SOC_TLV320AIC26
+ imply SND_SOC_TLV320AIC31XX
+ imply SND_SOC_TLV320AIC32X4_I2C
+ imply SND_SOC_TLV320AIC32X4_SPI
+ imply SND_SOC_TLV320AIC3X
+ imply SND_SOC_TPA6130A2
+ imply SND_SOC_TLV320DAC33
+ imply SND_SOC_TSCS42XX
+ imply SND_SOC_TSCS454
+ imply SND_SOC_TS3A227E
+ imply SND_SOC_TWL4030
+ imply SND_SOC_TWL6040
+ imply SND_SOC_UDA1334
+ imply SND_SOC_UDA134X
+ imply SND_SOC_UDA1380
+ imply SND_SOC_WCD9335
+ imply SND_SOC_WCD934X
+ imply SND_SOC_WL1273
+ imply SND_SOC_WM0010
+ imply SND_SOC_WM1250_EV1
+ imply SND_SOC_WM2000
+ imply SND_SOC_WM2200
+ imply SND_SOC_WM5100
+ imply SND_SOC_WM5102
+ imply SND_SOC_WM5110
+ imply SND_SOC_WM8350
+ imply SND_SOC_WM8400
+ imply SND_SOC_WM8510
+ imply SND_SOC_WM8523
+ imply SND_SOC_WM8524
+ imply SND_SOC_WM8580
+ imply SND_SOC_WM8711
+ imply SND_SOC_WM8727
+ imply SND_SOC_WM8728
+ imply SND_SOC_WM8731
+ imply SND_SOC_WM8737
+ imply SND_SOC_WM8741
+ imply SND_SOC_WM8750
+ imply SND_SOC_WM8753
+ imply SND_SOC_WM8770
+ imply SND_SOC_WM8776
+ imply SND_SOC_WM8782
+ imply SND_SOC_WM8804_I2C
+ imply SND_SOC_WM8804_SPI
+ imply SND_SOC_WM8900
+ imply SND_SOC_WM8903
+ imply SND_SOC_WM8904
+ imply SND_SOC_WM8940
+ imply SND_SOC_WM8955
+ imply SND_SOC_WM8960
+ imply SND_SOC_WM8961
+ imply SND_SOC_WM8962
+ imply SND_SOC_WM8971
+ imply SND_SOC_WM8974
+ imply SND_SOC_WM8978
+ imply SND_SOC_WM8983
+ imply SND_SOC_WM8985
+ imply SND_SOC_WM8988
+ imply SND_SOC_WM8990
+ imply SND_SOC_WM8991
+ imply SND_SOC_WM8993
+ imply SND_SOC_WM8994
+ imply SND_SOC_WM8995
+ imply SND_SOC_WM8996
+ imply SND_SOC_WM8997
+ imply SND_SOC_WM8998
+ imply SND_SOC_WM9081
+ imply SND_SOC_WM9090
+ imply SND_SOC_WM9705
+ imply SND_SOC_WM9712
+ imply SND_SOC_WM9713
+ imply SND_SOC_WSA881X
help
Normally ASoC codec drivers are only built if a machine driver which
uses them is also built since they are only usable with a machine
@@ -283,6 +285,7 @@ config SND_SOC_ALL_CODECS
config SND_SOC_88PM860X
tristate
+ depends on MFD_88PM860X
config SND_SOC_ARIZONA
tristate
@@ -318,6 +321,7 @@ config SND_SOC_WM_ADSP
config SND_SOC_AB8500_CODEC
tristate
+ depends on ABX500_CORE
config SND_SOC_AC97_CODEC
tristate "Build generic ASoC AC97 CODEC driver"
@@ -326,21 +330,25 @@ config SND_SOC_AC97_CODEC
config SND_SOC_AD1836
tristate
+ depends on SPI_MASTER
config SND_SOC_AD193X
tristate
config SND_SOC_AD193X_SPI
tristate
+ depends on SPI_MASTER
select SND_SOC_AD193X
config SND_SOC_AD193X_I2C
tristate
+ depends on I2C
select SND_SOC_AD193X
config SND_SOC_AD1980
- select REGMAP_AC97
tristate
+ depends on SND_SOC_AC97_BUS
+ select REGMAP_AC97
config SND_SOC_AD73311
tristate
@@ -350,6 +358,7 @@ config SND_SOC_ADAU_UTILS
config SND_SOC_ADAU1373
tristate
+ depends on I2C
select SND_SOC_ADAU_UTILS
config SND_SOC_ADAU1701
@@ -384,11 +393,13 @@ config SND_SOC_ADAU1781
config SND_SOC_ADAU1781_I2C
tristate
+ depends on I2C
select SND_SOC_ADAU1781
select REGMAP_I2C
config SND_SOC_ADAU1781_SPI
tristate
+ depends on SPI_MASTER
select SND_SOC_ADAU1781
select REGMAP_SPI
@@ -397,11 +408,13 @@ config SND_SOC_ADAU1977
config SND_SOC_ADAU1977_SPI
tristate
+ depends on SPI_MASTER
select SND_SOC_ADAU1977
select REGMAP_SPI
config SND_SOC_ADAU1977_I2C
tristate
+ depends on I2C
select SND_SOC_ADAU1977
select REGMAP_I2C
@@ -440,10 +453,12 @@ config SND_SOC_ADAV80X
config SND_SOC_ADAV801
tristate
+ depends on SPI_MASTER
select SND_SOC_ADAV80X
config SND_SOC_ADAV803
tristate
+ depends on I2C
select SND_SOC_ADAV80X
config SND_SOC_ADS117X
@@ -465,6 +480,7 @@ config SND_SOC_AK4458
config SND_SOC_AK4535
tristate
+ depends on I2C
config SND_SOC_AK4554
tristate "AKM AK4554 CODEC"
@@ -475,6 +491,7 @@ config SND_SOC_AK4613
config SND_SOC_AK4641
tristate
+ depends on I2C
config SND_SOC_AK4642
tristate "AKM AK4642 CODEC"
@@ -482,6 +499,7 @@ config SND_SOC_AK4642
config SND_SOC_AK4671
tristate
+ depends on I2C
config SND_SOC_AK5386
tristate "AKM AK5638 CODEC"
@@ -497,6 +515,7 @@ config SND_SOC_ALC5623
config SND_SOC_ALC5632
tristate
+ depends on I2C
config SND_SOC_BD28623
tristate "ROHM BD28623 CODEC"
@@ -631,6 +650,7 @@ config SND_SOC_CS47L15
config SND_SOC_CS47L24
tristate
+ depends on MFD_CS47L24
config SND_SOC_CS47L35
tristate
@@ -697,6 +717,7 @@ config SND_SOC_L3
config SND_SOC_DA7210
tristate
+ depends on I2C
config SND_SOC_DA7213
tristate "Dialog DA7213 CODEC"
@@ -704,15 +725,19 @@ config SND_SOC_DA7213
config SND_SOC_DA7218
tristate
+ depends on I2C
config SND_SOC_DA7219
tristate
+ depends on I2C
config SND_SOC_DA732X
tristate
+ depends on I2C
config SND_SOC_DA9055
tristate
+ depends on I2C
config SND_SOC_DMIC
tristate "Generic Digital Microphone CODEC"
@@ -772,9 +797,11 @@ config SND_SOC_INNO_RK3036
config SND_SOC_ISABELLE
tristate
+ depends on I2C
config SND_SOC_LM49453
tristate
+ depends on I2C
config SND_SOC_LOCHNAGAR_SC
tristate "Lochnagar Sound Card"
@@ -801,17 +828,20 @@ config SND_SOC_MAX98088
depends on I2C
config SND_SOC_MAX98090
- tristate
+ tristate
+ depends on I2C
config SND_SOC_MAX98095
- tristate
+ tristate
+ depends on I2C
config SND_SOC_MAX98357A
tristate "Maxim MAX98357A CODEC"
depends on GPIOLIB
config SND_SOC_MAX98371
- tristate
+ tristate
+ depends on I2C
config SND_SOC_MAX98504
tristate "Maxim MAX98504 speaker amplifier"
@@ -822,10 +852,12 @@ config SND_SOC_MAX9867
depends on I2C
config SND_SOC_MAX98925
- tristate
+ tristate
+ depends on I2C
config SND_SOC_MAX98926
tristate
+ depends on I2C
config SND_SOC_MAX98927
tristate "Maxim Integrated MAX98927 Speaker Amplifier"
@@ -837,6 +869,7 @@ config SND_SOC_MAX98373
config SND_SOC_MAX9850
tristate
+ depends on I2C
config SND_SOC_MAX9860
tristate "Maxim MAX9860 Mono Audio Voice Codec"
@@ -1015,26 +1048,32 @@ config SND_SOC_RT298
config SND_SOC_RT1011
tristate
+ depends on I2C
config SND_SOC_RT1015
tristate
+ depends on I2C
config SND_SOC_RT1305
tristate
+ depends on I2C
config SND_SOC_RT1308
tristate
+ depends on I2C
config SND_SOC_RT1308_SDW
tristate "Realtek RT1308 Codec - SDW"
- depends on SOUNDWIRE
+ depends on I2C && SOUNDWIRE
select REGMAP_SOUNDWIRE
config SND_SOC_RT5514
tristate
+ depends on I2C
config SND_SOC_RT5514_SPI
tristate
+ depends on SPI_MASTER
config SND_SOC_RT5514_SPI_BUILTIN
bool # force RT5514_SPI to be built-in to avoid link errors
@@ -1050,33 +1089,43 @@ config SND_SOC_RT5631
config SND_SOC_RT5640
tristate
+ depends on I2C
config SND_SOC_RT5645
tristate
+ depends on I2C
config SND_SOC_RT5651
tristate
+ depends on I2C
config SND_SOC_RT5659
tristate
+ depends on I2C
config SND_SOC_RT5660
tristate
+ depends on I2C
config SND_SOC_RT5663
tristate
+ depends on I2C
config SND_SOC_RT5665
tristate
+ depends on I2C
config SND_SOC_RT5668
tristate
+ depends on I2C
config SND_SOC_RT5670
tristate
+ depends on I2C
config SND_SOC_RT5677
tristate
+ depends on I2C
select REGMAP_I2C
select REGMAP_IRQ
@@ -1086,6 +1135,13 @@ config SND_SOC_RT5677_SPI
config SND_SOC_RT5682
tristate
+ depends on I2C
+
+config SND_SOC_RT5682_SDW
+ tristate "Realtek RT5682 Codec - SDW"
+ depends on SOUNDWIRE
+ select SND_SOC_RT5682
+ select REGMAP_SOUNDWIRE
config SND_SOC_RT700
tristate
@@ -1153,6 +1209,7 @@ config SND_SOC_SSM2305
config SND_SOC_SSM2518
tristate
+ depends on I2C
config SND_SOC_SSM2602
tristate
@@ -1184,9 +1241,11 @@ config SND_SOC_STA350
config SND_SOC_STA529
tristate
+ depends on I2C
config SND_SOC_STAC9766
tristate
+ depends on SND_SOC_AC97_BUS
config SND_SOC_STI_SAS
tristate "codec Audio support for STI SAS codec"
@@ -1281,6 +1340,15 @@ config SND_SOC_TLV320AIC3X
config SND_SOC_TLV320DAC33
tristate
+ depends on I2C
+
+config SND_SOC_TLV320ADCX140
+ tristate "Texas Instruments TLV320ADCX140 CODEC family"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Add support for Texas Instruments tlv320adc3140, tlv320adc5140 and
+ tlv320adc6140 quad channel ADCs.
config SND_SOC_TS3A227E
tristate "TI Headset/Mic detect and keypress chip"
@@ -1301,11 +1369,13 @@ config SND_SOC_TSCS454
Add support for Tempo Semiconductor's TSCS454 audio CODEC.
config SND_SOC_TWL4030
- select MFD_TWL4030_AUDIO
tristate
+ depends on TWL4030_CORE
+ select MFD_TWL4030_AUDIO
config SND_SOC_TWL6040
tristate
+ depends on TWL6040_CORE
config SND_SOC_UDA1334
tristate "NXP UDA1334 DAC"
@@ -1345,30 +1415,40 @@ config SND_SOC_WL1273
config SND_SOC_WM0010
tristate
+ depends on SPI_MASTER
config SND_SOC_WM1250_EV1
tristate
+ depends on I2C
config SND_SOC_WM2000
tristate
+ depends on I2C
config SND_SOC_WM2200
tristate
+ depends on I2C
config SND_SOC_WM5100
tristate
+ depends on I2C
config SND_SOC_WM5102
tristate
+ depends on MFD_WM5102
config SND_SOC_WM5110
tristate
+ depends on MFD_WM5110
config SND_SOC_WM8350
tristate
+ depends on MFD_WM8350
config SND_SOC_WM8400
tristate
+ # FIXME nothing selects SND_SOC_WM8400??
+ depends on MFD_WM8400
config SND_SOC_WM8510
tristate "Wolfson Microelectronics WM8510 CODEC"
@@ -1456,9 +1536,11 @@ config SND_SOC_WM8904
config SND_SOC_WM8940
tristate
+ depends on I2C
config SND_SOC_WM8955
tristate
+ depends on I2C
config SND_SOC_WM8960
tristate "Wolfson Microelectronics WM8960 CODEC"
@@ -1466,6 +1548,7 @@ config SND_SOC_WM8960
config SND_SOC_WM8961
tristate
+ depends on I2C
config SND_SOC_WM8962
tristate "Wolfson Microelectronics WM8962 CODEC"
@@ -1473,6 +1556,7 @@ config SND_SOC_WM8962
config SND_SOC_WM8971
tristate
+ depends on I2C
config SND_SOC_WM8974
tristate "Wolfson Microelectronics WM8974 codec"
@@ -1484,6 +1568,7 @@ config SND_SOC_WM8978
config SND_SOC_WM8983
tristate
+ depends on I2C
config SND_SOC_WM8985
tristate "Wolfson Microelectronics WM8985 and WM8758 codec driver"
@@ -1494,12 +1579,15 @@ config SND_SOC_WM8988
config SND_SOC_WM8990
tristate
+ depends on I2C
config SND_SOC_WM8991
tristate
+ depends on I2C
config SND_SOC_WM8993
tristate
+ depends on I2C
config SND_SOC_WM8994
tristate
@@ -1509,12 +1597,15 @@ config SND_SOC_WM8995
config SND_SOC_WM8996
tristate
+ depends on I2C
config SND_SOC_WM8997
tristate
+ depends on MFD_WM8997
config SND_SOC_WM8998
tristate
+ depends on MFD_WM8998
config SND_SOC_WM9081
tristate
@@ -1522,19 +1613,23 @@ config SND_SOC_WM9081
config SND_SOC_WM9090
tristate
+ depends on I2C
config SND_SOC_WM9705
tristate
+ depends on SND_SOC_AC97_BUS
select REGMAP_AC97
select AC97_BUS_COMPAT if AC97_BUS_NEW
config SND_SOC_WM9712
tristate
+ depends on SND_SOC_AC97_BUS
select REGMAP_AC97
select AC97_BUS_COMPAT if AC97_BUS_NEW
config SND_SOC_WM9713
tristate
+ depends on SND_SOC_AC97_BUS
select REGMAP_AC97
select AC97_BUS_COMPAT if AC97_BUS_NEW
@@ -1555,6 +1650,7 @@ config SND_SOC_ZX_AUD96P22
# Amp
config SND_SOC_LM4857
tristate
+ depends on I2C
config SND_SOC_MAX9759
tristate "Maxim MAX9759 speaker Amplifier"
@@ -1562,15 +1658,19 @@ config SND_SOC_MAX9759
config SND_SOC_MAX9768
tristate
+ depends on I2C
config SND_SOC_MAX9877
tristate
+ depends on I2C
config SND_SOC_MC13783
tristate
+ depends on MFD_MC13XXX
config SND_SOC_ML26124
tristate
+ depends on I2C
config SND_SOC_MT6351
tristate "MediaTek MT6351 Codec"
@@ -1608,6 +1708,7 @@ config SND_SOC_NAU8824
config SND_SOC_NAU8825
tristate
+ depends on I2C
config SND_SOC_TPA6130A2
tristate "Texas Instruments TPA6130A2 headphone amplifier"
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index ba1b4b3fa2da..03533157cda6 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -177,6 +177,7 @@ snd-soc-rt5670-objs := rt5670.o
snd-soc-rt5677-objs := rt5677.o
snd-soc-rt5677-spi-objs := rt5677-spi.o
snd-soc-rt5682-objs := rt5682.o
+snd-soc-rt5682-sdw-objs := rt5682-sdw.o
snd-soc-rt700-objs := rt700.o rt700-sdw.o
snd-soc-rt711-objs := rt711.o rt711-sdw.o
snd-soc-rt715-objs := rt715.o rt715-sdw.o
@@ -218,6 +219,7 @@ snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o
snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
snd-soc-tlv320dac33-objs := tlv320dac33.o
+snd-soc-tlv320adcx140-objs := tlv320adcx140.o
snd-soc-tscs42xx-objs := tscs42xx.o
snd-soc-tscs454-objs := tscs454.o
snd-soc-ts3a227e-objs := ts3a227e.o
@@ -476,6 +478,7 @@ obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o
obj-$(CONFIG_SND_SOC_RT5682) += snd-soc-rt5682.o
+obj-$(CONFIG_SND_SOC_RT5682_SDW) += snd-soc-rt5682-sdw.o
obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o
obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o
obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o
@@ -516,6 +519,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC32X4_I2C) += snd-soc-tlv320aic32x4-i2c.o
obj-$(CONFIG_SND_SOC_TLV320AIC32X4_SPI) += snd-soc-tlv320aic32x4-spi.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
+obj-$(CONFIG_SND_SOC_TLV320ADCX140) += snd-soc-tlv320adcx140.o
obj-$(CONFIG_SND_SOC_TSCS42XX) += snd-soc-tscs42xx.o
obj-$(CONFIG_SND_SOC_TSCS454) += snd-soc-tscs454.o
obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index e8c5fda82e08..979cfb165eed 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -295,8 +295,7 @@ static int ak4104_spi_probe(struct spi_device *spi)
reset_gpiod = devm_gpiod_get_optional(&spi->dev, "reset",
GPIOD_OUT_HIGH);
- if (IS_ERR(reset_gpiod) &&
- PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
+ if (PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
return -EPROBE_DEFER;
/* read the 'reserved' register - according to the datasheet, it
diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
index 6a24f570c5e8..d3dc42aa6825 100644
--- a/sound/soc/codecs/cros_ec_codec.c
+++ b/sound/soc/codecs/cros_ec_codec.c
@@ -45,6 +45,9 @@ struct cros_ec_codec_priv {
/* DMIC */
atomic_t dmic_probed;
+ /* I2S_RX */
+ uint32_t i2s_rx_bclk_ratio;
+
/* WoV */
bool wov_enabled;
uint8_t *wov_audio_shm_p;
@@ -259,6 +262,7 @@ static int i2s_rx_hw_params(struct snd_pcm_substream *substream,
snd_soc_component_get_drvdata(component);
struct ec_param_ec_codec_i2s_rx p;
enum ec_codec_i2s_rx_sample_depth depth;
+ uint32_t bclk;
int ret;
if (params_rate(params) != 48000)
@@ -284,15 +288,29 @@ static int i2s_rx_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
- dev_dbg(component->dev, "set bclk to %u\n",
- snd_soc_params_to_bclk(params));
+ if (priv->i2s_rx_bclk_ratio)
+ bclk = params_rate(params) * priv->i2s_rx_bclk_ratio;
+ else
+ bclk = snd_soc_params_to_bclk(params);
+
+ dev_dbg(component->dev, "set bclk to %u\n", bclk);
p.cmd = EC_CODEC_I2S_RX_SET_BCLK;
- p.set_bclk_param.bclk = snd_soc_params_to_bclk(params);
+ p.set_bclk_param.bclk = bclk;
return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
(uint8_t *)&p, sizeof(p), NULL, 0);
}
+static int i2s_rx_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+{
+ struct snd_soc_component *component = dai->component;
+ struct cros_ec_codec_priv *priv =
+ snd_soc_component_get_drvdata(component);
+
+ priv->i2s_rx_bclk_ratio = ratio;
+ return 0;
+}
+
static int i2s_rx_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_component *component = dai->component;
@@ -340,6 +358,7 @@ static int i2s_rx_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
static const struct snd_soc_dai_ops i2s_rx_dai_ops = {
.hw_params = i2s_rx_hw_params,
.set_fmt = i2s_rx_set_fmt,
+ .set_bclk_ratio = i2s_rx_set_bclk_ratio,
};
static int i2s_rx_event(struct snd_soc_dapm_widget *w,
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 793a14d58667..5f25b9f872bd 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -681,8 +681,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
reset_gpiod = devm_gpiod_get_optional(&i2c_client->dev, "reset",
GPIOD_OUT_HIGH);
- if (IS_ERR(reset_gpiod) &&
- PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
+ if (PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
return -EPROBE_DEFER;
cs4270->regmap = devm_regmap_init_i2c(i2c_client, &cs4270_regmap);
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index 04b86a51e055..62f412d6f9f2 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -356,9 +356,9 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
*/
if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
- !dai->capture_active) ||
+ !dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]) ||
(substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
- !dai->playback_active)) {
+ !dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK])) {
ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
CS4271_MODE2_PDN,
CS4271_MODE2_PDN);
diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c
index 513e2875e4c6..e8840dc142ef 100644
--- a/sound/soc/codecs/cs47l15.c
+++ b/sound/soc/codecs/cs47l15.c
@@ -531,6 +531,7 @@ SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"),
SND_SOC_DAPM_OUTPUT("DSP Trigger Out"),
SND_SOC_DAPM_DEMUX("HPOUT1 Demux", SND_SOC_NOPM, 0, 0, &cs47l15_outdemux),
+SND_SOC_DAPM_MUX("HPOUT1 Mono Mux", SND_SOC_NOPM, 0, 0, &cs47l15_outdemux),
SND_SOC_DAPM_PGA("PWM1 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM1_ENA_SHIFT,
0, NULL, 0),
@@ -1086,6 +1087,9 @@ static const struct snd_soc_dapm_route cs47l15_dapm_routes[] = {
{ "AEC2 Loopback", "HPOUT1R", "OUT1R" },
{ "HPOUT1 Demux", NULL, "OUT1L" },
{ "HPOUT1 Demux", NULL, "OUT1R" },
+
+ { "OUT1R", NULL, "HPOUT1 Mono Mux" },
+
{ "HPOUTL", "HPOUT", "HPOUT1 Demux" },
{ "HPOUTR", "HPOUT", "HPOUT1 Demux" },
{ "EPOUTP", "EPOUT", "HPOUT1 Demux" },
@@ -1263,6 +1267,11 @@ static irqreturn_t cs47l15_adsp2_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static const struct snd_soc_dapm_route cs47l15_mono_routes[] = {
+ { "HPOUT1 Mono Mux", "HPOUT", "OUT1L" },
+ { "HPOUT1 Mono Mux", "EPOUT", "OUT1L" },
+};
+
static int cs47l15_component_probe(struct snd_soc_component *component)
{
struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component);
@@ -1279,7 +1288,9 @@ static int cs47l15_component_probe(struct snd_soc_component *component)
if (ret)
return ret;
- ret = madera_init_outputs(component, CS47L15_MONO_OUTPUTS);
+ ret = madera_init_outputs(component, cs47l15_mono_routes,
+ ARRAY_SIZE(cs47l15_mono_routes),
+ CS47L15_MONO_OUTPUTS);
if (ret)
return ret;
diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c
index ba7aa6b31205..3d48a0d9ecc5 100644
--- a/sound/soc/codecs/cs47l35.c
+++ b/sound/soc/codecs/cs47l35.c
@@ -633,6 +633,7 @@ SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"),
SND_SOC_DAPM_OUTPUT("DSP Trigger Out"),
SND_SOC_DAPM_DEMUX("HPOUT1 Demux", SND_SOC_NOPM, 0, 0, &cs47l35_outdemux),
+SND_SOC_DAPM_MUX("HPOUT1 Mono Mux", SND_SOC_NOPM, 0, 0, &cs47l35_outdemux),
SND_SOC_DAPM_PGA("PWM1 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM1_ENA_SHIFT,
0, NULL, 0),
@@ -1311,6 +1312,8 @@ static const struct snd_soc_dapm_route cs47l35_dapm_routes[] = {
{ "SPKOUTN", NULL, "OUT4L" },
{ "SPKOUTP", NULL, "OUT4L" },
+ { "OUT1R", NULL, "HPOUT1 Mono Mux" },
+
{ "HPOUTL", "HPOUT", "HPOUT1 Demux" },
{ "HPOUTR", "HPOUT", "HPOUT1 Demux" },
{ "EPOUTP", "EPOUT", "HPOUT1 Demux" },
@@ -1554,6 +1557,11 @@ static irqreturn_t cs47l35_adsp2_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static const struct snd_soc_dapm_route cs47l35_mono_routes[] = {
+ { "HPOUT1 Mono Mux", "HPOUT", "OUT1L" },
+ { "HPOUT1 Mono Mux", "EPOUT", "OUT1L" },
+};
+
static int cs47l35_component_probe(struct snd_soc_component *component)
{
struct cs47l35 *cs47l35 = snd_soc_component_get_drvdata(component);
@@ -1570,7 +1578,9 @@ static int cs47l35_component_probe(struct snd_soc_component *component)
if (ret)
return ret;
- ret = madera_init_outputs(component, CS47L35_MONO_OUTPUTS);
+ ret = madera_init_outputs(component, cs47l35_mono_routes,
+ ARRAY_SIZE(cs47l35_mono_routes),
+ CS47L35_MONO_OUTPUTS);
if (ret)
return ret;
diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c
index f85581a97bdc..bef3471f482d 100644
--- a/sound/soc/codecs/cs47l85.c
+++ b/sound/soc/codecs/cs47l85.c
@@ -2008,12 +2008,18 @@ static const struct snd_soc_dapm_route cs47l85_dapm_routes[] = {
{ "IN3R", NULL, "IN3R Mode" },
{ "IN4L", NULL, "DMICCLK4" },
+ { "IN4L", NULL, "DMICDAT4" },
+ { "IN4R", NULL, "DMICCLK4" },
{ "IN4R", NULL, "DMICDAT4" },
{ "IN5L", NULL, "DMICCLK5" },
+ { "IN5L", NULL, "DMICDAT5" },
+ { "IN5R", NULL, "DMICCLK5" },
{ "IN5R", NULL, "DMICDAT5" },
{ "IN6L", NULL, "DMICCLK6" },
+ { "IN6L", NULL, "DMICDAT6" },
+ { "IN6R", NULL, "DMICCLK6" },
{ "IN6R", NULL, "DMICDAT6" },
MADERA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
@@ -2510,7 +2516,8 @@ static int cs47l85_component_probe(struct snd_soc_component *component)
if (ret)
return ret;
- ret = madera_init_outputs(component, CS47L85_MONO_OUTPUTS);
+ ret = madera_init_outputs(component, NULL, CS47L85_MONO_OUTPUTS,
+ CS47L85_MONO_OUTPUTS);
if (ret)
return ret;
diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c
index c3b6f4d41005..266eade82764 100644
--- a/sound/soc/codecs/cs47l90.c
+++ b/sound/soc/codecs/cs47l90.c
@@ -1938,12 +1938,18 @@ static const struct snd_soc_dapm_route cs47l90_dapm_routes[] = {
{ "IN2R", NULL, "IN2R Mode" },
{ "IN3L", NULL, "DMICCLK3" },
+ { "IN3L", NULL, "DMICDAT3" },
+ { "IN3R", NULL, "DMICCLK3" },
{ "IN3R", NULL, "DMICDAT3" },
{ "IN4L", NULL, "DMICCLK4" },
+ { "IN4L", NULL, "DMICDAT4" },
+ { "IN4R", NULL, "DMICCLK4" },
{ "IN4R", NULL, "DMICDAT4" },
{ "IN5L", NULL, "DMICCLK5" },
+ { "IN5L", NULL, "DMICDAT5" },
+ { "IN5R", NULL, "DMICCLK5" },
{ "IN5R", NULL, "DMICDAT5" },
MADERA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
@@ -2421,7 +2427,8 @@ static int cs47l90_component_probe(struct snd_soc_component *component)
if (ret)
return ret;
- ret = madera_init_outputs(component, CS47L90_MONO_OUTPUTS);
+ ret = madera_init_outputs(component, NULL, CS47L90_MONO_OUTPUTS,
+ CS47L90_MONO_OUTPUTS);
if (ret)
return ret;
diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c
index cbffcd84766d..942040fd354f 100644
--- a/sound/soc/codecs/cs47l92.c
+++ b/sound/soc/codecs/cs47l92.c
@@ -778,6 +778,7 @@ SND_SOC_DAPM_MUX("IN2L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]),
SND_SOC_DAPM_MUX("IN2R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]),
SND_SOC_DAPM_DEMUX("OUT3 Demux", SND_SOC_NOPM, 0, 0, &cs47l92_outdemux),
+SND_SOC_DAPM_MUX("OUT3 Mono Mux", SND_SOC_NOPM, 0, 0, &cs47l92_outdemux),
SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"),
SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"),
@@ -1632,6 +1633,8 @@ static const struct snd_soc_dapm_route cs47l92_dapm_routes[] = {
{ "OUT3 Demux", NULL, "OUT3L" },
{ "OUT3 Demux", NULL, "OUT3R" },
+ { "OUT3R", NULL, "OUT3 Mono Mux" },
+
{ "HPOUT3L", "HPOUT3", "OUT3 Demux" },
{ "HPOUT3R", "HPOUT3", "OUT3 Demux" },
{ "HPOUT4L", "HPOUT4", "OUT3 Demux" },
@@ -1865,6 +1868,13 @@ static irqreturn_t cs47l92_adsp2_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static const struct snd_soc_dapm_route cs47l92_mono_routes[] = {
+ { "OUT1R", NULL, "OUT1L" },
+ { "OUT2R", NULL, "OUT2L" },
+ { "OUT3 Mono Mux", "HPOUT3", "OUT3L" },
+ { "OUT3 Mono Mux", "HPOUT4", "OUT3L" },
+};
+
static int cs47l92_component_probe(struct snd_soc_component *component)
{
struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component);
@@ -1881,7 +1891,9 @@ static int cs47l92_component_probe(struct snd_soc_component *component)
if (ret)
return ret;
- ret = madera_init_outputs(component, CS47L92_MONO_OUTPUTS);
+ ret = madera_init_outputs(component, cs47l92_mono_routes,
+ ARRAY_SIZE(cs47l92_mono_routes),
+ CS47L92_MONO_OUTPUTS);
if (ret)
return ret;
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index bc2903d27e6e..f005751da2cc 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -293,7 +293,7 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
- uinfo->count = FIELD_SIZEOF(struct hdmi_codec_priv, eld);
+ uinfo->count = sizeof_field(struct hdmi_codec_priv, eld);
return 0;
}
diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c
index 7eccff62c3e1..40de9d7811d1 100644
--- a/sound/soc/codecs/madera.c
+++ b/sound/soc/codecs/madera.c
@@ -1212,7 +1212,9 @@ static const struct snd_soc_dapm_route madera_mono_routes[] = {
{ "OUT6R", NULL, "OUT6L" },
};
-int madera_init_outputs(struct snd_soc_component *component, int n_mono_routes)
+int madera_init_outputs(struct snd_soc_component *component,
+ const struct snd_soc_dapm_route *routes,
+ int n_mono_routes, int n_real)
{
struct snd_soc_dapm_context *dapm =
snd_soc_component_get_dapm(component);
@@ -1229,16 +1231,21 @@ int madera_init_outputs(struct snd_soc_component *component, int n_mono_routes)
n_mono_routes = MADERA_MAX_OUTPUT;
}
+ if (!routes)
+ routes = madera_mono_routes;
+
for (i = 0; i < n_mono_routes; i++) {
/* Default is 0 so noop with defaults */
if (pdata->out_mono[i]) {
val = MADERA_OUT1_MONO;
- snd_soc_dapm_add_routes(dapm,
- &madera_mono_routes[i], 1);
+ snd_soc_dapm_add_routes(dapm, &routes[i], 1);
} else {
val = 0;
}
+ if (i >= n_real)
+ continue;
+
regmap_update_bits(madera->regmap,
MADERA_OUTPUT_PATH_CONFIG_1L + (i * 8),
MADERA_OUT1_MONO, val);
diff --git a/sound/soc/codecs/madera.h b/sound/soc/codecs/madera.h
index 49a8f68ec43d..e0c0be59e2ef 100644
--- a/sound/soc/codecs/madera.h
+++ b/sound/soc/codecs/madera.h
@@ -423,7 +423,9 @@ int madera_core_free(struct madera_priv *priv);
int madera_init_overheat(struct madera_priv *priv);
int madera_free_overheat(struct madera_priv *priv);
int madera_init_inputs(struct snd_soc_component *component);
-int madera_init_outputs(struct snd_soc_component *component, int n_mono_routes);
+int madera_init_outputs(struct snd_soc_component *component,
+ const struct snd_soc_dapm_route *routes,
+ int n_mono_routes, int n_real);
int madera_init_bus_error_irq(struct madera_priv *priv, int dsp_num,
irq_handler_t handler);
void madera_free_bus_error_irq(struct madera_priv *priv, int dsp_num);
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
index 16313b973eaa..74f20114297c 100644
--- a/sound/soc/codecs/max98357a.c
+++ b/sound/soc/codecs/max98357a.c
@@ -5,6 +5,7 @@
*/
#include <linux/acpi.h>
+#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio.h>
@@ -24,26 +25,24 @@ struct max98357a_priv {
unsigned int sdmode_delay;
};
-static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
- int cmd, struct snd_soc_dai *dai)
+static int max98357a_sdmode_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
{
- struct max98357a_priv *max98357a = snd_soc_dai_get_drvdata(dai);
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct max98357a_priv *max98357a =
+ snd_soc_component_get_drvdata(component);
if (!max98357a->sdmode)
return 0;
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- mdelay(max98357a->sdmode_delay);
+ if (event & SND_SOC_DAPM_POST_PMU) {
+ msleep(max98357a->sdmode_delay);
gpiod_set_value(max98357a->sdmode, 1);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ dev_dbg(component->dev, "set sdmode to 1");
+ } else if (event & SND_SOC_DAPM_PRE_PMD) {
gpiod_set_value(max98357a->sdmode, 0);
- break;
+ dev_dbg(component->dev, "set sdmode to 0");
}
return 0;
@@ -51,10 +50,14 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("Speaker"),
+ SND_SOC_DAPM_OUT_DRV_E("SD_MODE", SND_SOC_NOPM, 0, 0, NULL, 0,
+ max98357a_sdmode_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
};
static const struct snd_soc_dapm_route max98357a_dapm_routes[] = {
- {"Speaker", NULL, "HiFi Playback"},
+ {"SD_MODE", NULL, "HiFi Playback"},
+ {"Speaker", NULL, "SD_MODE"},
};
static const struct snd_soc_component_driver max98357a_component_driver = {
@@ -68,10 +71,6 @@ static const struct snd_soc_component_driver max98357a_component_driver = {
.non_legacy_dai_naming = 1,
};
-static const struct snd_soc_dai_ops max98357a_dai_ops = {
- .trigger = max98357a_daiops_trigger,
-};
-
static struct snd_soc_dai_driver max98357a_dai_driver = {
.name = "HiFi",
.playback = {
@@ -91,7 +90,6 @@ static struct snd_soc_dai_driver max98357a_dai_driver = {
.channels_min = 1,
.channels_max = 2,
},
- .ops = &max98357a_dai_ops,
};
static int max98357a_platform_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c
index a36c416caad4..bcec82aa57fb 100644
--- a/sound/soc/codecs/mt6660.c
+++ b/sound/soc/codecs/mt6660.c
@@ -4,12 +4,10 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/pm_runtime.h>
#include <linux/delay.h>
-#include <linux/debugfs.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include <sound/pcm_params.h>
@@ -225,14 +223,87 @@ static int _mt6660_chip_power_on(struct mt6660_chip *chip, int on_off)
0x01, on_off ? 0x00 : 0x01);
}
+struct reg_table {
+ uint32_t addr;
+ uint32_t mask;
+ uint32_t val;
+};
+
+static const struct reg_table mt6660_setting_table[] = {
+ { 0x20, 0x80, 0x00 },
+ { 0x30, 0x01, 0x00 },
+ { 0x50, 0x1c, 0x04 },
+ { 0xB1, 0x0c, 0x00 },
+ { 0xD3, 0x03, 0x03 },
+ { 0xE0, 0x01, 0x00 },
+ { 0x98, 0x44, 0x04 },
+ { 0xB9, 0xff, 0x82 },
+ { 0xB7, 0x7777, 0x7273 },
+ { 0xB6, 0x07, 0x03 },
+ { 0x6B, 0xe0, 0x20 },
+ { 0x07, 0xff, 0x70 },
+ { 0xBB, 0xff, 0x20 },
+ { 0x69, 0xff, 0x40 },
+ { 0xBD, 0xffff, 0x17f8 },
+ { 0x70, 0xff, 0x15 },
+ { 0x7C, 0xff, 0x00 },
+ { 0x46, 0xff, 0x1d },
+ { 0x1A, 0xffffffff, 0x7fdb7ffe },
+ { 0x1B, 0xffffffff, 0x7fdb7ffe },
+ { 0x51, 0xff, 0x58 },
+ { 0xA2, 0xff, 0xce },
+ { 0x33, 0xffff, 0x7fff },
+ { 0x4C, 0xffff, 0x0116 },
+ { 0x16, 0x1800, 0x0800 },
+ { 0x68, 0x1f, 0x07 },
+};
+
+static int mt6660_component_setting(struct snd_soc_component *component)
+{
+ struct mt6660_chip *chip = snd_soc_component_get_drvdata(component);
+ int ret = 0;
+ size_t i = 0;
+
+ ret = _mt6660_chip_power_on(chip, 1);
+ if (ret < 0) {
+ dev_err(component->dev, "%s chip power on failed\n", __func__);
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mt6660_setting_table); i++) {
+ ret = snd_soc_component_update_bits(component,
+ mt6660_setting_table[i].addr,
+ mt6660_setting_table[i].mask,
+ mt6660_setting_table[i].val);
+ if (ret < 0) {
+ dev_err(component->dev, "%s update 0x%02x failed\n",
+ __func__, mt6660_setting_table[i].addr);
+ return ret;
+ }
+ }
+
+ ret = _mt6660_chip_power_on(chip, 0);
+ if (ret < 0) {
+ dev_err(component->dev, "%s chip power off failed\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
static int mt6660_component_probe(struct snd_soc_component *component)
{
struct mt6660_chip *chip = snd_soc_component_get_drvdata(component);
+ int ret;
dev_dbg(component->dev, "%s\n", __func__);
snd_soc_component_init_regmap(component, chip->regmap);
- return 0;
+ ret = mt6660_component_setting(component);
+ if (ret < 0)
+ dev_err(chip->dev, "mt6660 component setting failed\n");
+
+ return ret;
}
static void mt6660_component_remove(struct snd_soc_component *component)
@@ -506,4 +577,4 @@ module_i2c_driver(mt6660_i2c_driver);
MODULE_AUTHOR("Jeff Chang <jeff_chang@richtek.com>");
MODULE_DESCRIPTION("MT6660 SPKAMP Driver");
MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.7_G");
+MODULE_VERSION("1.0.8_G");
diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c
index 287c962ba00d..115706a55577 100644
--- a/sound/soc/codecs/rk3328_codec.c
+++ b/sound/soc/codecs/rk3328_codec.c
@@ -7,6 +7,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -31,7 +32,7 @@
struct rk3328_codec_priv {
struct regmap *regmap;
- struct regmap *grf;
+ struct gpio_desc *mute;
struct clk *mclk;
struct clk *pclk;
unsigned int sclk;
@@ -106,16 +107,6 @@ static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0;
}
-static void rk3328_analog_output(struct rk3328_codec_priv *rk3328, int mute)
-{
- unsigned int val = BIT(17);
-
- if (mute)
- val |= BIT(1);
-
- regmap_write(rk3328->grf, RK3328_GRF_SOC_CON10, val);
-}
-
static int rk3328_digital_mute(struct snd_soc_dai *dai, int mute)
{
struct rk3328_codec_priv *rk3328 =
@@ -205,7 +196,7 @@ static int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328)
}
msleep(rk3328->spk_depop_time);
- rk3328_analog_output(rk3328, 1);
+ gpiod_set_value(rk3328->mute, 0);
regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
HPOUTL_GAIN_MASK, OUT_VOLUME);
@@ -246,7 +237,7 @@ static int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328)
{
size_t i;
- rk3328_analog_output(rk3328, 0);
+ gpiod_set_value(rk3328->mute, 1);
regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
HPOUTL_GAIN_MASK, 0);
@@ -446,7 +437,6 @@ static int rk3328_platform_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "missing 'rockchip,grf'\n");
return PTR_ERR(grf);
}
- rk3328->grf = grf;
/* enable i2s_acodec_en */
regmap_write(grf, RK3328_GRF_SOC_CON2,
(BIT(14) << 16 | BIT(14)));
@@ -458,7 +448,18 @@ static int rk3328_platform_probe(struct platform_device *pdev)
rk3328->spk_depop_time = 200;
}
- rk3328_analog_output(rk3328, 0);
+ rk3328->mute = gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH);
+ if (IS_ERR(rk3328->mute))
+ return PTR_ERR(rk3328->mute);
+ /*
+ * Rock64 is the only supported platform to have widely relied on
+ * this; if we do happen to come across an old DTB, just leave the
+ * external mute forced off.
+ */
+ if (!rk3328->mute && of_machine_is_compatible("pine64,rock64")) {
+ dev_warn(&pdev->dev, "assuming implicit control of GPIO_MUTE; update devicetree if possible\n");
+ regmap_write(grf, RK3328_GRF_SOC_CON10, BIT(17) | BIT(1));
+ }
rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");
if (IS_ERR(rk3328->mclk))
diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c
index a887d5ccb10d..d181c217d835 100644
--- a/sound/soc/codecs/rl6231.c
+++ b/sound/soc/codecs/rl6231.c
@@ -102,6 +102,7 @@ struct pll_calc_map {
static const struct pll_calc_map pll_preset_table[] = {
{19200000, 4096000, 23, 14, 1, false},
{19200000, 24576000, 3, 30, 3, false},
+ {3840000, 24576000, 3, 30, 0, true},
};
static unsigned int find_best_div(unsigned int in,
diff --git a/sound/soc/codecs/rl6231.h b/sound/soc/codecs/rl6231.h
index 31a9643b0afd..6d8ed0377296 100644
--- a/sound/soc/codecs/rl6231.h
+++ b/sound/soc/codecs/rl6231.h
@@ -10,7 +10,7 @@
#ifndef __RL6231_H__
#define __RL6231_H__
-#define RL6231_PLL_INP_MAX 40000000
+#define RL6231_PLL_INP_MAX 50000000
#define RL6231_PLL_INP_MIN 256000
#define RL6231_PLL_N_MAX 0x1ff
#define RL6231_PLL_K_MAX 0x1f
diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c
index 66eb55b4ffd4..bb310bc7febd 100644
--- a/sound/soc/codecs/rt1015.c
+++ b/sound/soc/codecs/rt1015.c
@@ -444,7 +444,7 @@ static int rt1015_boost_mode_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static int rt5518_bypass_boost_get(struct snd_kcontrol *kcontrol,
+static int rt1015_bypass_boost_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
@@ -457,7 +457,7 @@ static int rt5518_bypass_boost_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int rt5518_bypass_boost_put(struct snd_kcontrol *kcontrol,
+static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
@@ -497,7 +497,7 @@ static const struct snd_kcontrol_new rt1015_snd_controls[] = {
rt1015_boost_mode_get, rt1015_boost_mode_put),
SOC_ENUM("Mono LR Select", rt1015_mono_lr_sel),
SOC_SINGLE_EXT("Bypass Boost", SND_SOC_NOPM, 0, 1, 0,
- rt5518_bypass_boost_get, rt5518_bypass_boost_put),
+ rt1015_bypass_boost_get, rt1015_bypass_boost_put),
};
static int rt1015_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
@@ -841,12 +841,12 @@ static void rt1015_remove(struct snd_soc_component *component)
#define RT1015_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
-struct snd_soc_dai_ops rt1015_aif_dai_ops = {
+static struct snd_soc_dai_ops rt1015_aif_dai_ops = {
.hw_params = rt1015_hw_params,
.set_fmt = rt1015_set_dai_fmt,
};
-struct snd_soc_dai_driver rt1015_dai[] = {
+static struct snd_soc_dai_driver rt1015_dai[] = {
{
.name = "rt1015-aif",
.id = 0,
diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c
index e66d08398f74..89e0f58512fa 100644
--- a/sound/soc/codecs/rt5659.c
+++ b/sound/soc/codecs/rt5659.c
@@ -1604,7 +1604,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct rt5659_priv *rt5659 = snd_soc_component_get_drvdata(component);
- int pd, idx = -EINVAL;
+ int pd, idx;
pd = rl6231_get_pre_div(rt5659->regmap,
RT5659_ADDA_CLK_1, RT5659_I2S_PD1_SFT);
diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c
new file mode 100644
index 000000000000..1d6963dd6403
--- /dev/null
+++ b/sound/soc/codecs/rt5682-sdw.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// rt5682-sdw.c -- RT5682 ALSA SoC audio component driver
+//
+// Copyright 2019 Realtek Semiconductor Corp.
+// Author: Oder Chiou <oder_chiou@realtek.com>
+//
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/acpi.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mutex.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_type.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "rt5682.h"
+#include "rt5682-sdw.h"
+
+static bool rt5682_sdw_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case 0x00e0:
+ case 0x00f0:
+ case 0x3000:
+ case 0x3001:
+ case 0x3004:
+ case 0x3005:
+ case 0x3008:
+ return true;
+ default:
+ return false;
+ }
+}
+
+const struct regmap_config rt5682_sdw_regmap = {
+ .name = "sdw",
+ .reg_bits = 32,
+ .val_bits = 8,
+ .max_register = RT5682_I2C_MODE,
+ .readable_reg = rt5682_sdw_readable_register,
+ .cache_type = REGCACHE_NONE,
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
+static int rt5682_update_status(struct sdw_slave *slave,
+ enum sdw_slave_status status)
+{
+ struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
+
+ /* Update the status */
+ rt5682->status = status;
+
+ if (status == SDW_SLAVE_UNATTACHED)
+ rt5682->hw_init = false;
+
+ /*
+ * Perform initialization only if slave status is present and
+ * hw_init flag is false
+ */
+ if (rt5682->hw_init || rt5682->status != SDW_SLAVE_ATTACHED)
+ return 0;
+
+ /* perform I/O transfers required for Slave initialization */
+ return rt5682_io_init(&slave->dev, slave);
+}
+
+static int rt5682_read_prop(struct sdw_slave *slave)
+{
+ struct sdw_slave_prop *prop = &slave->prop;
+ int nval, i, num_of_ports = 1;
+ u32 bit;
+ unsigned long addr;
+ struct sdw_dpn_prop *dpn;
+
+ prop->paging_support = false;
+
+ /* first we need to allocate memory for set bits in port lists */
+ prop->source_ports = 0x4; /* BITMAP: 00000100 */
+ prop->sink_ports = 0x2; /* BITMAP: 00000010 */
+
+ nval = hweight32(prop->source_ports);
+ num_of_ports += nval;
+ prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
+ sizeof(*prop->src_dpn_prop),
+ GFP_KERNEL);
+ if (!prop->src_dpn_prop)
+ return -ENOMEM;
+
+ i = 0;
+ dpn = prop->src_dpn_prop;
+ addr = prop->source_ports;
+ for_each_set_bit(bit, &addr, 32) {
+ dpn[i].num = bit;
+ dpn[i].type = SDW_DPN_FULL;
+ dpn[i].simple_ch_prep_sm = true;
+ dpn[i].ch_prep_timeout = 10;
+ i++;
+ }
+
+ /* do this again for sink now */
+ nval = hweight32(prop->sink_ports);
+ num_of_ports += nval;
+ prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
+ sizeof(*prop->sink_dpn_prop),
+ GFP_KERNEL);
+ if (!prop->sink_dpn_prop)
+ return -ENOMEM;
+
+ i = 0;
+ dpn = prop->sink_dpn_prop;
+ addr = prop->sink_ports;
+ for_each_set_bit(bit, &addr, 32) {
+ dpn[i].num = bit;
+ dpn[i].type = SDW_DPN_FULL;
+ dpn[i].simple_ch_prep_sm = true;
+ dpn[i].ch_prep_timeout = 10;
+ i++;
+ }
+
+ /* Allocate port_ready based on num_of_ports */
+ slave->port_ready = devm_kcalloc(&slave->dev, num_of_ports,
+ sizeof(*slave->port_ready),
+ GFP_KERNEL);
+ if (!slave->port_ready)
+ return -ENOMEM;
+
+ /* Initialize completion */
+ for (i = 0; i < num_of_ports; i++)
+ init_completion(&slave->port_ready[i]);
+
+ /* set the timeout values */
+ prop->clk_stop_timeout = 20;
+
+ /* wake-up event */
+ prop->wake_capable = 1;
+
+ return 0;
+}
+
+/* Bus clock frequency */
+#define RT5682_CLK_FREQ_9600000HZ 9600000
+#define RT5682_CLK_FREQ_12000000HZ 12000000
+#define RT5682_CLK_FREQ_6000000HZ 6000000
+#define RT5682_CLK_FREQ_4800000HZ 4800000
+#define RT5682_CLK_FREQ_2400000HZ 2400000
+#define RT5682_CLK_FREQ_12288000HZ 12288000
+
+static int rt5682_clock_config(struct device *dev)
+{
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+ unsigned int clk_freq, value;
+
+ clk_freq = (rt5682->params.curr_dr_freq >> 1);
+
+ switch (clk_freq) {
+ case RT5682_CLK_FREQ_12000000HZ:
+ value = 0x0;
+ break;
+ case RT5682_CLK_FREQ_6000000HZ:
+ value = 0x1;
+ break;
+ case RT5682_CLK_FREQ_9600000HZ:
+ value = 0x2;
+ break;
+ case RT5682_CLK_FREQ_4800000HZ:
+ value = 0x3;
+ break;
+ case RT5682_CLK_FREQ_2400000HZ:
+ value = 0x4;
+ break;
+ case RT5682_CLK_FREQ_12288000HZ:
+ value = 0x5;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_write(rt5682->sdw_regmap, 0xe0, value);
+ regmap_write(rt5682->sdw_regmap, 0xf0, value);
+
+ dev_dbg(dev, "%s complete, clk_freq=%d\n", __func__, clk_freq);
+
+ return 0;
+}
+
+static int rt5682_bus_config(struct sdw_slave *slave,
+ struct sdw_bus_params *params)
+{
+ struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
+ int ret;
+
+ memcpy(&rt5682->params, params, sizeof(*params));
+
+ ret = rt5682_clock_config(&slave->dev);
+ if (ret < 0)
+ dev_err(&slave->dev, "Invalid clk config");
+
+ return ret;
+}
+
+static int rt5682_interrupt_callback(struct sdw_slave *slave,
+ struct sdw_slave_intr_status *status)
+{
+ struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
+
+ dev_dbg(&slave->dev,
+ "%s control_port_stat=%x", __func__, status->control_port);
+
+ if (status->control_port & 0x4) {
+ mod_delayed_work(system_power_efficient_wq,
+ &rt5682->jack_detect_work, msecs_to_jiffies(250));
+ }
+
+ return 0;
+}
+
+static struct sdw_slave_ops rt5682_slave_ops = {
+ .read_prop = rt5682_read_prop,
+ .interrupt_callback = rt5682_interrupt_callback,
+ .update_status = rt5682_update_status,
+ .bus_config = rt5682_bus_config,
+};
+
+static int rt5682_sdw_probe(struct sdw_slave *slave,
+ const struct sdw_device_id *id)
+{
+ struct regmap *regmap;
+
+ /* Assign ops */
+ slave->ops = &rt5682_slave_ops;
+
+ /* Regmap Initialization */
+ regmap = devm_regmap_init_sdw(slave, &rt5682_sdw_regmap);
+ if (IS_ERR(regmap))
+ return -EINVAL;
+
+ rt5682_sdw_init(&slave->dev, regmap, slave);
+
+ return 0;
+}
+
+static int rt5682_sdw_remove(struct sdw_slave *slave)
+{
+ struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
+
+ if (rt5682 && rt5682->hw_init)
+ cancel_delayed_work(&rt5682->jack_detect_work);
+
+ return 0;
+}
+
+static const struct sdw_device_id rt5682_id[] = {
+ SDW_SLAVE_ENTRY(0x025d, 0x5682, 0),
+ {},
+};
+MODULE_DEVICE_TABLE(sdw, rt5682_id);
+
+static int rt5682_dev_suspend(struct device *dev)
+{
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+
+ if (!rt5682->hw_init)
+ return 0;
+
+ regcache_cache_only(rt5682->regmap, true);
+ regcache_mark_dirty(rt5682->regmap);
+
+ return 0;
+}
+
+static int rt5682_dev_resume(struct device *dev)
+{
+ struct sdw_slave *slave = dev_to_sdw_dev(dev);
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+ unsigned long time;
+
+ if (!rt5682->hw_init)
+ return 0;
+
+ if (!slave->unattach_request)
+ goto regmap_sync;
+
+ time = wait_for_completion_timeout(&slave->initialization_complete,
+ msecs_to_jiffies(RT5682_PROBE_TIMEOUT));
+ if (!time) {
+ dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ return -ETIMEDOUT;
+ }
+
+regmap_sync:
+ slave->unattach_request = 0;
+ regcache_cache_only(rt5682->regmap, false);
+ regcache_sync(rt5682->regmap);
+
+ return 0;
+}
+
+static const struct dev_pm_ops rt5682_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(rt5682_dev_suspend, rt5682_dev_resume)
+ SET_RUNTIME_PM_OPS(rt5682_dev_suspend, rt5682_dev_resume, NULL)
+};
+
+static struct sdw_driver rt5682_sdw_driver = {
+ .driver = {
+ .name = "rt5682",
+ .owner = THIS_MODULE,
+ .pm = &rt5682_pm,
+ },
+ .probe = rt5682_sdw_probe,
+ .remove = rt5682_sdw_remove,
+ .ops = &rt5682_slave_ops,
+ .id_table = rt5682_id,
+};
+module_sdw_driver(rt5682_sdw_driver);
+
+MODULE_DESCRIPTION("ASoC RT5682 driver SDW");
+MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5682-sdw.h b/sound/soc/codecs/rt5682-sdw.h
new file mode 100644
index 000000000000..76e6f607066e
--- /dev/null
+++ b/sound/soc/codecs/rt5682-sdw.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * rt5682-sdw.h -- RT5682 SDW ALSA SoC audio driver
+ *
+ * Copyright 2019 Realtek Semiconductor Corp.
+ * Author: Oder Chiou <oder_chiou@realtek.com>
+ */
+
+#ifndef __RT5682_SDW_H__
+#define __RT5682_SDW_H__
+
+#define RT5682_SDW_ADDR_L 0x3000
+#define RT5682_SDW_ADDR_H 0x3001
+#define RT5682_SDW_DATA_L 0x3004
+#define RT5682_SDW_DATA_H 0x3005
+#define RT5682_SDW_CMD 0x3008
+
+#define RT5682_PROBE_TIMEOUT 2000
+
+#endif /* __RT5682_SDW_H__ */
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index ae6f6121bc1b..e1df2d076533 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -11,13 +11,13 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
+#include <linux/pm_runtime.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/acpi.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
-#include <linux/regulator/consumer.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -31,8 +31,7 @@
#include "rl6231.h"
#include "rt5682.h"
-
-#define RT5682_NUM_SUPPLIES 3
+#include "rt5682-sdw.h"
static const char *rt5682_supply_names[RT5682_NUM_SUPPLIES] = {
"AVDD",
@@ -45,35 +44,15 @@ static const struct rt5682_platform_data i2s_default_platform_data = {
.dmic1_clk_pin = RT5682_DMIC1_CLK_GPIO3,
.jd_src = RT5682_JD1,
.btndet_delay = 16,
-};
-
-struct rt5682_priv {
- struct snd_soc_component *component;
- struct rt5682_platform_data pdata;
- struct regmap *regmap;
- struct snd_soc_jack *hs_jack;
- struct regulator_bulk_data supplies[RT5682_NUM_SUPPLIES];
- struct delayed_work jack_detect_work;
- struct delayed_work jd_check_work;
- struct mutex calibrate_mutex;
-
- int sysclk;
- int sysclk_src;
- int lrck[RT5682_AIFS];
- int bclk[RT5682_AIFS];
- int master[RT5682_AIFS];
-
- int pll_src;
- int pll_in;
- int pll_out;
-
- int jack_type;
+ .dai_clk_names[RT5682_DAI_WCLK_IDX] = "rt5682-dai-wclk",
+ .dai_clk_names[RT5682_DAI_BCLK_IDX] = "rt5682-dai-bclk",
};
static const struct reg_sequence patch_list[] = {
{RT5682_HP_IMP_SENS_CTRL_19, 0x1000},
{RT5682_DAC_ADC_DIG_VOL1, 0xa020},
{RT5682_I2C_CTRL, 0x000f},
+ {RT5682_PLL2_INTERNAL, 0x8266},
};
static const struct reg_default rt5682_reg[] = {
@@ -221,7 +200,7 @@ static const struct reg_default rt5682_reg[] = {
{0x0148, 0x0000},
{0x0149, 0x0000},
{0x0150, 0x79a1},
- {0x0151, 0x0000},
+ {0x0156, 0xaaaa},
{0x0160, 0x4ec0},
{0x0161, 0x0080},
{0x0162, 0x0200},
@@ -805,10 +784,27 @@ static const struct snd_kcontrol_new rt5682_if1_45_adc_swap_mux =
static const struct snd_kcontrol_new rt5682_if1_67_adc_swap_mux =
SOC_DAPM_ENUM("IF1 67 ADC Swap Mux", rt5682_if1_67_adc_enum);
-static void rt5682_reset(struct regmap *regmap)
+static const char * const rt5682_dac_select[] = {
+ "IF1", "SOUND"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5682_dacl_enum,
+ RT5682_AD_DA_MIXER, RT5682_DAC1_L_SEL_SFT, rt5682_dac_select);
+
+static const struct snd_kcontrol_new rt5682_dac_l_mux =
+ SOC_DAPM_ENUM("DAC L Mux", rt5682_dacl_enum);
+
+static SOC_ENUM_SINGLE_DECL(rt5682_dacr_enum,
+ RT5682_AD_DA_MIXER, RT5682_DAC1_R_SEL_SFT, rt5682_dac_select);
+
+static const struct snd_kcontrol_new rt5682_dac_r_mux =
+ SOC_DAPM_ENUM("DAC R Mux", rt5682_dacr_enum);
+
+static void rt5682_reset(struct rt5682_priv *rt5682)
{
- regmap_write(regmap, RT5682_RESET, 0);
- regmap_write(regmap, RT5682_I2C_MODE, 1);
+ regmap_write(rt5682->regmap, RT5682_RESET, 0);
+ if (!rt5682->is_sdw)
+ regmap_write(rt5682->regmap, RT5682_I2C_MODE, 1);
}
/**
* rt5682_sel_asrc_clk_src - select ASRC clock source for a set of filters
@@ -871,6 +867,8 @@ static int rt5682_button_detect(struct snd_soc_component *component)
static void rt5682_enable_push_button_irq(struct snd_soc_component *component,
bool enable)
{
+ struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+
if (enable) {
snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
RT5682_SAR_BUTT_DET_MASK, RT5682_SAR_BUTT_DET_EN);
@@ -880,8 +878,15 @@ static void rt5682_enable_push_button_irq(struct snd_soc_component *component,
snd_soc_component_update_bits(component, RT5682_4BTN_IL_CMD_2,
RT5682_4BTN_IL_MASK | RT5682_4BTN_IL_RST_MASK,
RT5682_4BTN_IL_EN | RT5682_4BTN_IL_NOR);
- snd_soc_component_update_bits(component, RT5682_IRQ_CTRL_3,
- RT5682_IL_IRQ_MASK, RT5682_IL_IRQ_EN);
+ if (rt5682->is_sdw)
+ snd_soc_component_update_bits(component,
+ RT5682_IRQ_CTRL_3,
+ RT5682_IL_IRQ_MASK | RT5682_IL_IRQ_TYPE_MASK,
+ RT5682_IL_IRQ_EN | RT5682_IL_IRQ_PUL);
+ else
+ snd_soc_component_update_bits(component,
+ RT5682_IRQ_CTRL_3, RT5682_IL_IRQ_MASK,
+ RT5682_IL_IRQ_EN);
} else {
snd_soc_component_update_bits(component, RT5682_IRQ_CTRL_3,
RT5682_IL_IRQ_MASK, RT5682_IL_IRQ_DIS);
@@ -909,6 +914,7 @@ static int rt5682_headset_detect(struct snd_soc_component *component,
int jack_insert)
{
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ struct snd_soc_dapm_context *dapm = &component->dapm;
unsigned int val, count;
if (jack_insert) {
@@ -917,10 +923,10 @@ static int rt5682_headset_detect(struct snd_soc_component *component,
RT5682_PWR_VREF2 | RT5682_PWR_MB,
RT5682_PWR_VREF2 | RT5682_PWR_MB);
snd_soc_component_update_bits(component,
- RT5682_PWR_ANLG_1, RT5682_PWR_FV2, 0);
+ RT5682_PWR_ANLG_1, RT5682_PWR_FV2, 0);
usleep_range(15000, 20000);
snd_soc_component_update_bits(component,
- RT5682_PWR_ANLG_1, RT5682_PWR_FV2, RT5682_PWR_FV2);
+ RT5682_PWR_ANLG_1, RT5682_PWR_FV2, RT5682_PWR_FV2);
snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
RT5682_PWR_CBJ, RT5682_PWR_CBJ);
@@ -951,8 +957,13 @@ static int rt5682_headset_detect(struct snd_soc_component *component,
rt5682_enable_push_button_irq(component, false);
snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_LOW);
- snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1,
- RT5682_PWR_VREF2 | RT5682_PWR_MB, 0);
+ if (snd_soc_dapm_get_pin_status(dapm, "MICBIAS"))
+ snd_soc_component_update_bits(component,
+ RT5682_PWR_ANLG_1, RT5682_PWR_VREF2, 0);
+ else
+ snd_soc_component_update_bits(component,
+ RT5682_PWR_ANLG_1,
+ RT5682_PWR_VREF2 | RT5682_PWR_MB, 0);
snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
RT5682_PWR_CBJ, 0);
@@ -999,62 +1010,69 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
rt5682->hs_jack = hs_jack;
- if (!hs_jack) {
- regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
- RT5682_JD1_EN_MASK, RT5682_JD1_DIS);
- regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
- RT5682_POW_JDH | RT5682_POW_JDL, 0);
- cancel_delayed_work_sync(&rt5682->jack_detect_work);
- return 0;
- }
+ if (!rt5682->is_sdw) {
+ if (!hs_jack) {
+ regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
+ RT5682_JD1_EN_MASK, RT5682_JD1_DIS);
+ regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
+ RT5682_POW_JDH | RT5682_POW_JDL, 0);
+ cancel_delayed_work_sync(&rt5682->jack_detect_work);
+ return 0;
+ }
- switch (rt5682->pdata.jd_src) {
- case RT5682_JD1:
- snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_2,
- RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
- snd_soc_component_write(component, RT5682_CBJ_CTRL_1, 0xd042);
- snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_3,
- RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN);
- snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
- RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN);
- regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
- RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_IRQ);
- regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
+ switch (rt5682->pdata.jd_src) {
+ case RT5682_JD1:
+ snd_soc_component_update_bits(component,
+ RT5682_CBJ_CTRL_2, RT5682_EXT_JD_SRC,
+ RT5682_EXT_JD_SRC_MANUAL);
+ snd_soc_component_write(component, RT5682_CBJ_CTRL_1,
+ 0xd042);
+ snd_soc_component_update_bits(component,
+ RT5682_CBJ_CTRL_3, RT5682_CBJ_IN_BUF_EN,
+ RT5682_CBJ_IN_BUF_EN);
+ snd_soc_component_update_bits(component,
+ RT5682_SAR_IL_CMD_1, RT5682_SAR_POW_MASK,
+ RT5682_SAR_POW_EN);
+ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
+ RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_IRQ);
+ regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
RT5682_POW_IRQ | RT5682_POW_JDH |
RT5682_POW_ANA, RT5682_POW_IRQ |
RT5682_POW_JDH | RT5682_POW_ANA);
- regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2,
- RT5682_PWR_JDH | RT5682_PWR_JDL,
- RT5682_PWR_JDH | RT5682_PWR_JDL);
- regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
- RT5682_JD1_EN_MASK | RT5682_JD1_POL_MASK,
- RT5682_JD1_EN | RT5682_JD1_POL_NOR);
- regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_4,
- 0x7f7f, (rt5682->pdata.btndet_delay << 8 |
- rt5682->pdata.btndet_delay));
- regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_5,
- 0x7f7f, (rt5682->pdata.btndet_delay << 8 |
- rt5682->pdata.btndet_delay));
- regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_6,
- 0x7f7f, (rt5682->pdata.btndet_delay << 8 |
- rt5682->pdata.btndet_delay));
- regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_7,
- 0x7f7f, (rt5682->pdata.btndet_delay << 8 |
- rt5682->pdata.btndet_delay));
- mod_delayed_work(system_power_efficient_wq,
- &rt5682->jack_detect_work, msecs_to_jiffies(250));
- break;
+ regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2,
+ RT5682_PWR_JDH | RT5682_PWR_JDL,
+ RT5682_PWR_JDH | RT5682_PWR_JDL);
+ regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
+ RT5682_JD1_EN_MASK | RT5682_JD1_POL_MASK,
+ RT5682_JD1_EN | RT5682_JD1_POL_NOR);
+ regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_4,
+ 0x7f7f, (rt5682->pdata.btndet_delay << 8 |
+ rt5682->pdata.btndet_delay));
+ regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_5,
+ 0x7f7f, (rt5682->pdata.btndet_delay << 8 |
+ rt5682->pdata.btndet_delay));
+ regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_6,
+ 0x7f7f, (rt5682->pdata.btndet_delay << 8 |
+ rt5682->pdata.btndet_delay));
+ regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_7,
+ 0x7f7f, (rt5682->pdata.btndet_delay << 8 |
+ rt5682->pdata.btndet_delay));
+ mod_delayed_work(system_power_efficient_wq,
+ &rt5682->jack_detect_work,
+ msecs_to_jiffies(250));
+ break;
- case RT5682_JD_NULL:
- regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
- RT5682_JD1_EN_MASK, RT5682_JD1_DIS);
- regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
- RT5682_POW_JDH | RT5682_POW_JDL, 0);
- break;
+ case RT5682_JD_NULL:
+ regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
+ RT5682_JD1_EN_MASK, RT5682_JD1_DIS);
+ regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
+ RT5682_POW_JDH | RT5682_POW_JDL, 0);
+ break;
- default:
- dev_warn(component->dev, "Wrong JD source\n");
- break;
+ default:
+ dev_warn(component->dev, "Wrong JD source\n");
+ break;
+ }
}
return 0;
@@ -1134,11 +1152,13 @@ static void rt5682_jack_detect_handler(struct work_struct *work)
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3);
- if (rt5682->jack_type & (SND_JACK_BTN_0 | SND_JACK_BTN_1 |
- SND_JACK_BTN_2 | SND_JACK_BTN_3))
- schedule_delayed_work(&rt5682->jd_check_work, 0);
- else
- cancel_delayed_work_sync(&rt5682->jd_check_work);
+ if (!rt5682->is_sdw) {
+ if (rt5682->jack_type & (SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3))
+ schedule_delayed_work(&rt5682->jd_check_work, 0);
+ else
+ cancel_delayed_work_sync(&rt5682->jd_check_work);
+ }
mutex_unlock(&rt5682->calibrate_mutex);
}
@@ -1232,6 +1252,9 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w,
static const int div_f[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48};
static const int div_o[] = {1, 2, 4, 6, 8, 12, 16, 24, 32, 48};
+ if (rt5682->is_sdw)
+ return 0;
+
val = snd_soc_component_read32(component, RT5682_GPIO_CTRL_1) &
RT5682_GP4_PIN_MASK;
if (w->shift == RT5682_PWR_ADC_S1F_BIT &&
@@ -1278,6 +1301,21 @@ static int is_sys_clk_from_pll1(struct snd_soc_dapm_widget *w,
return 0;
}
+static int is_sys_clk_from_pll2(struct snd_soc_dapm_widget *w,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int val;
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+
+ val = snd_soc_component_read32(component, RT5682_GLB_CLK);
+ val &= RT5682_SCLK_SRC_MASK;
+ if (val == RT5682_SCLK_SRC_PLL2)
+ return 1;
+ else
+ return 0;
+}
+
static int is_using_asrc(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_widget *sink)
{
@@ -1516,7 +1554,7 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w,
return 0;
}
-static int rt5655_set_verf(struct snd_soc_dapm_widget *w,
+static int rt5682_set_verf(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
@@ -1592,9 +1630,12 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("PLL2B", RT5682_PWR_ANLG_3, RT5682_PWR_PLL2B_BIT,
0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PLL2F", RT5682_PWR_ANLG_3, RT5682_PWR_PLL2F_BIT,
- 0, NULL, 0),
+ 0, set_filter_clk, SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_SUPPLY("Vref1", RT5682_PWR_ANLG_1, RT5682_PWR_VREF1_BIT, 0,
- rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+ rt5682_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_SUPPLY("Vref2", RT5682_PWR_ANLG_1, RT5682_PWR_VREF2_BIT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, NULL, 0),
/* ASRC */
SND_SOC_DAPM_SUPPLY_S("DAC STO1 ASRC", 1, RT5682_PLL_TRACK_1,
@@ -1686,6 +1727,8 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SOUND DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SOUND DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
/* Digital Interface Select */
SND_SOC_DAPM_MUX("IF1 01 ADC Swap Mux", SND_SOC_NOPM, 0, 0,
@@ -1702,12 +1745,19 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
SND_SOC_DAPM_MUX("ADCDAT Mux", SND_SOC_NOPM, 0, 0,
&rt5682_adcdat_pin_ctrl),
+ SND_SOC_DAPM_MUX("DAC L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5682_dac_l_mux),
+ SND_SOC_DAPM_MUX("DAC R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5682_dac_r_mux),
+
/* Audio Interface */
SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0,
RT5682_I2S1_SDP, RT5682_SEL_ADCDAT_SFT, 1),
SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0,
RT5682_I2S2_SDP, RT5682_I2S2_PIN_CFG_SFT, 1),
SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SDWRX", "SDW Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("SDWTX", "SDW Capture", 0, SND_SOC_NOPM, 0, 0),
/* Output Side */
/* DAC mixer before sound effect */
@@ -1776,7 +1826,11 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
/*PLL*/
{"ADC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll1},
+ {"ADC Stereo1 Filter", NULL, "PLL2B", is_sys_clk_from_pll2},
+ {"ADC Stereo1 Filter", NULL, "PLL2F", is_sys_clk_from_pll2},
{"DAC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll1},
+ {"DAC Stereo1 Filter", NULL, "PLL2B", is_sys_clk_from_pll2},
+ {"DAC Stereo1 Filter", NULL, "PLL2F", is_sys_clk_from_pll2},
/*ASRC*/
{"ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc},
@@ -1860,8 +1914,8 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
{"IF1_ADC Mux", "Slot 2", "IF1 23 ADC Swap Mux"},
{"IF1_ADC Mux", "Slot 4", "IF1 45 ADC Swap Mux"},
{"IF1_ADC Mux", "Slot 6", "IF1 67 ADC Swap Mux"},
- {"IF1_ADC Mux", NULL, "I2S1"},
{"ADCDAT Mux", "ADCDAT1", "IF1_ADC Mux"},
+ {"AIF1TX", NULL, "I2S1"},
{"AIF1TX", NULL, "ADCDAT Mux"},
{"IF2 ADC Swap Mux", "L/R", "Stereo1 ADC MIX"},
{"IF2 ADC Swap Mux", "R/L", "Stereo1 ADC MIX"},
@@ -1870,6 +1924,10 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
{"ADCDAT Mux", "ADCDAT2", "IF2 ADC Swap Mux"},
{"AIF2TX", NULL, "ADCDAT Mux"},
+ {"SDWTX", NULL, "PLL2B"},
+ {"SDWTX", NULL, "PLL2F"},
+ {"SDWTX", NULL, "ADCDAT Mux"},
+
{"IF1 DAC1 L", NULL, "AIF1RX"},
{"IF1 DAC1 L", NULL, "I2S1"},
{"IF1 DAC1 L", NULL, "DAC Stereo1 Filter"},
@@ -1877,10 +1935,24 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
{"IF1 DAC1 R", NULL, "I2S1"},
{"IF1 DAC1 R", NULL, "DAC Stereo1 Filter"},
+ {"SOUND DAC L", NULL, "SDWRX"},
+ {"SOUND DAC L", NULL, "DAC Stereo1 Filter"},
+ {"SOUND DAC L", NULL, "PLL2B"},
+ {"SOUND DAC L", NULL, "PLL2F"},
+ {"SOUND DAC R", NULL, "SDWRX"},
+ {"SOUND DAC R", NULL, "DAC Stereo1 Filter"},
+ {"SOUND DAC R", NULL, "PLL2B"},
+ {"SOUND DAC R", NULL, "PLL2F"},
+
+ {"DAC L Mux", "IF1", "IF1 DAC1 L"},
+ {"DAC L Mux", "SOUND", "SOUND DAC L"},
+ {"DAC R Mux", "IF1", "IF1 DAC1 R"},
+ {"DAC R Mux", "SOUND", "SOUND DAC R"},
+
{"DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL"},
- {"DAC1 MIXL", "DAC1 Switch", "IF1 DAC1 L"},
+ {"DAC1 MIXL", "DAC1 Switch", "DAC L Mux"},
{"DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR"},
- {"DAC1 MIXR", "DAC1 Switch", "IF1 DAC1 R"},
+ {"DAC1 MIXR", "DAC1 Switch", "DAC R Mux"},
{"Stereo1 DAC MIXL", "DAC L1 Switch", "DAC1 MIXL"},
{"Stereo1 DAC MIXL", "DAC R1 Switch", "DAC1 MIXR"},
@@ -2033,8 +2105,10 @@ static int rt5682_hw_params(struct snd_pcm_substream *substream,
RT5682_I2S1_DL_MASK, len_1);
if (rt5682->master[RT5682_AIF1]) {
snd_soc_component_update_bits(component,
- RT5682_ADDA_CLK_1, RT5682_I2S_M_DIV_MASK,
- pre_div << RT5682_I2S_M_DIV_SFT);
+ RT5682_ADDA_CLK_1, RT5682_I2S_M_DIV_MASK |
+ RT5682_I2S_CLK_SRC_MASK,
+ pre_div << RT5682_I2S_M_DIV_SFT |
+ (rt5682->sysclk_src) << RT5682_I2S_CLK_SRC_SFT);
}
if (params_channels(params) == 1) /* mono mode */
snd_soc_component_update_bits(component,
@@ -2207,61 +2281,157 @@ static int rt5682_set_component_pll(struct snd_soc_component *component,
unsigned int freq_out)
{
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
- struct rl6231_pll_code pll_code;
+ struct rl6231_pll_code pll_code, pll2f_code, pll2b_code;
+ unsigned int pll2_fout1;
int ret;
- if (source == rt5682->pll_src && freq_in == rt5682->pll_in &&
- freq_out == rt5682->pll_out)
+ if (source == rt5682->pll_src[pll_id] &&
+ freq_in == rt5682->pll_in[pll_id] &&
+ freq_out == rt5682->pll_out[pll_id])
return 0;
if (!freq_in || !freq_out) {
dev_dbg(component->dev, "PLL disabled\n");
- rt5682->pll_in = 0;
- rt5682->pll_out = 0;
+ rt5682->pll_in[pll_id] = 0;
+ rt5682->pll_out[pll_id] = 0;
snd_soc_component_update_bits(component, RT5682_GLB_CLK,
RT5682_SCLK_SRC_MASK, RT5682_SCLK_SRC_MCLK);
return 0;
}
- switch (source) {
- case RT5682_PLL1_S_MCLK:
- snd_soc_component_update_bits(component, RT5682_GLB_CLK,
- RT5682_PLL1_SRC_MASK, RT5682_PLL1_SRC_MCLK);
- break;
- case RT5682_PLL1_S_BCLK1:
- snd_soc_component_update_bits(component, RT5682_GLB_CLK,
- RT5682_PLL1_SRC_MASK, RT5682_PLL1_SRC_BCLK1);
- break;
- default:
- dev_err(component->dev, "Unknown PLL Source %d\n", source);
- return -EINVAL;
- }
+ if (pll_id == RT5682_PLL2) {
+ switch (source) {
+ case RT5682_PLL2_S_MCLK:
+ snd_soc_component_update_bits(component,
+ RT5682_GLB_CLK, RT5682_PLL2_SRC_MASK,
+ RT5682_PLL2_SRC_MCLK);
+ break;
+ default:
+ dev_err(component->dev, "Unknown PLL2 Source %d\n",
+ source);
+ return -EINVAL;
+ }
- ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
- if (ret < 0) {
- dev_err(component->dev, "Unsupport input clock %d\n", freq_in);
- return ret;
+ /**
+ * PLL2 concatenates 2 PLL units.
+ * We suggest the Fout of the front PLL is 3.84MHz.
+ */
+ pll2_fout1 = 3840000;
+ ret = rl6231_pll_calc(freq_in, pll2_fout1, &pll2f_code);
+ if (ret < 0) {
+ dev_err(component->dev, "Unsupport input clock %d\n",
+ freq_in);
+ return ret;
+ }
+ dev_dbg(component->dev, "PLL2F: fin=%d fout=%d bypass=%d m=%d n=%d k=%d\n",
+ freq_in, pll2_fout1,
+ pll2f_code.m_bp,
+ (pll2f_code.m_bp ? 0 : pll2f_code.m_code),
+ pll2f_code.n_code, pll2f_code.k_code);
+
+ ret = rl6231_pll_calc(pll2_fout1, freq_out, &pll2b_code);
+ if (ret < 0) {
+ dev_err(component->dev, "Unsupport input clock %d\n",
+ pll2_fout1);
+ return ret;
+ }
+ dev_dbg(component->dev, "PLL2B: fin=%d fout=%d bypass=%d m=%d n=%d k=%d\n",
+ pll2_fout1, freq_out,
+ pll2b_code.m_bp,
+ (pll2b_code.m_bp ? 0 : pll2b_code.m_code),
+ pll2b_code.n_code, pll2b_code.k_code);
+
+ snd_soc_component_write(component, RT5682_PLL2_CTRL_1,
+ pll2f_code.k_code << RT5682_PLL2F_K_SFT |
+ pll2b_code.k_code << RT5682_PLL2B_K_SFT |
+ pll2b_code.m_code);
+ snd_soc_component_write(component, RT5682_PLL2_CTRL_2,
+ pll2f_code.m_code << RT5682_PLL2F_M_SFT |
+ pll2b_code.n_code);
+ snd_soc_component_write(component, RT5682_PLL2_CTRL_3,
+ pll2f_code.n_code << RT5682_PLL2F_N_SFT);
+ snd_soc_component_update_bits(component, RT5682_PLL2_CTRL_4,
+ RT5682_PLL2B_M_BP_MASK | RT5682_PLL2F_M_BP_MASK | 0xf,
+ (pll2b_code.m_bp ? 1 : 0) << RT5682_PLL2B_M_BP_SFT |
+ (pll2f_code.m_bp ? 1 : 0) << RT5682_PLL2F_M_BP_SFT |
+ 0xf);
+ } else {
+ switch (source) {
+ case RT5682_PLL1_S_MCLK:
+ snd_soc_component_update_bits(component,
+ RT5682_GLB_CLK, RT5682_PLL1_SRC_MASK,
+ RT5682_PLL1_SRC_MCLK);
+ break;
+ case RT5682_PLL1_S_BCLK1:
+ snd_soc_component_update_bits(component,
+ RT5682_GLB_CLK, RT5682_PLL1_SRC_MASK,
+ RT5682_PLL1_SRC_BCLK1);
+ break;
+ default:
+ dev_err(component->dev, "Unknown PLL1 Source %d\n",
+ source);
+ return -EINVAL;
+ }
+
+ ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
+ if (ret < 0) {
+ dev_err(component->dev, "Unsupport input clock %d\n",
+ freq_in);
+ return ret;
+ }
+
+ dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n",
+ pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
+ pll_code.n_code, pll_code.k_code);
+
+ snd_soc_component_write(component, RT5682_PLL_CTRL_1,
+ pll_code.n_code << RT5682_PLL_N_SFT | pll_code.k_code);
+ snd_soc_component_write(component, RT5682_PLL_CTRL_2,
+ (pll_code.m_bp ? 0 : pll_code.m_code) << RT5682_PLL_M_SFT |
+ pll_code.m_bp << RT5682_PLL_M_BP_SFT | RT5682_PLL_RST);
}
- dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n",
- pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
- pll_code.n_code, pll_code.k_code);
+ rt5682->pll_in[pll_id] = freq_in;
+ rt5682->pll_out[pll_id] = freq_out;
+ rt5682->pll_src[pll_id] = source;
+
+ return 0;
+}
- snd_soc_component_write(component, RT5682_PLL_CTRL_1,
- pll_code.n_code << RT5682_PLL_N_SFT | pll_code.k_code);
- snd_soc_component_write(component, RT5682_PLL_CTRL_2,
- (pll_code.m_bp ? 0 : pll_code.m_code) << RT5682_PLL_M_SFT |
- pll_code.m_bp << RT5682_PLL_M_BP_SFT | RT5682_PLL_RST);
+static int rt5682_set_bclk1_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
- rt5682->pll_in = freq_in;
- rt5682->pll_out = freq_out;
- rt5682->pll_src = source;
+ rt5682->bclk[dai->id] = ratio;
+
+ switch (ratio) {
+ case 256:
+ snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL,
+ RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_256);
+ break;
+ case 128:
+ snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL,
+ RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_128);
+ break;
+ case 64:
+ snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL,
+ RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_64);
+ break;
+ case 32:
+ snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL,
+ RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_32);
+ break;
+ default:
+ dev_err(dai->dev, "Invalid bclk1 ratio %d\n", ratio);
+ return -EINVAL;
+ }
return 0;
}
-static int rt5682_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+static int rt5682_set_bclk2_ratio(struct snd_soc_dai *dai, unsigned int ratio)
{
struct snd_soc_component *component = dai->component;
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
@@ -2280,7 +2450,7 @@ static int rt5682_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
RT5682_I2S2_BCLK_MS2_32);
break;
default:
- dev_err(dai->dev, "Invalid bclk ratio %d\n", ratio);
+ dev_err(dai->dev, "Invalid bclk2 ratio %d\n", ratio);
return -EINVAL;
}
@@ -2319,12 +2489,393 @@ static int rt5682_set_bias_level(struct snd_soc_component *component,
return 0;
}
+#ifdef CONFIG_COMMON_CLK
+#define CLK_PLL2_FIN 48000000
+#define CLK_PLL2_FOUT 24576000
+#define CLK_48 48000
+
+static bool rt5682_clk_check(struct rt5682_priv *rt5682)
+{
+ if (!rt5682->master[RT5682_AIF1]) {
+ dev_err(rt5682->component->dev, "sysclk/dai not set correctly\n");
+ return false;
+ }
+ return true;
+}
+
+static int rt5682_wclk_prepare(struct clk_hw *hw)
+{
+ struct rt5682_priv *rt5682 =
+ container_of(hw, struct rt5682_priv,
+ dai_clks_hw[RT5682_DAI_WCLK_IDX]);
+ struct snd_soc_component *component = rt5682->component;
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_component_get_dapm(component);
+
+ if (!rt5682_clk_check(rt5682))
+ return -EINVAL;
+
+ snd_soc_dapm_mutex_lock(dapm);
+
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS");
+ snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1,
+ RT5682_PWR_MB, RT5682_PWR_MB);
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "I2S1");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2F");
+ snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2B");
+ snd_soc_dapm_sync_unlocked(dapm);
+
+ snd_soc_dapm_mutex_unlock(dapm);
+
+ return 0;
+}
+
+static void rt5682_wclk_unprepare(struct clk_hw *hw)
+{
+ struct rt5682_priv *rt5682 =
+ container_of(hw, struct rt5682_priv,
+ dai_clks_hw[RT5682_DAI_WCLK_IDX]);
+ struct snd_soc_component *component = rt5682->component;
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_component_get_dapm(component);
+
+ if (!rt5682_clk_check(rt5682))
+ return;
+
+ snd_soc_dapm_mutex_lock(dapm);
+
+ snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS");
+ if (!rt5682->jack_type)
+ snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1,
+ RT5682_PWR_MB, 0);
+ snd_soc_dapm_disable_pin_unlocked(dapm, "I2S1");
+ snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2F");
+ snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2B");
+ snd_soc_dapm_sync_unlocked(dapm);
+
+ snd_soc_dapm_mutex_unlock(dapm);
+}
+
+static unsigned long rt5682_wclk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct rt5682_priv *rt5682 =
+ container_of(hw, struct rt5682_priv,
+ dai_clks_hw[RT5682_DAI_WCLK_IDX]);
+
+ if (!rt5682_clk_check(rt5682))
+ return 0;
+ /*
+ * Only accept to set wclk rate to 48kHz temporarily.
+ */
+ return CLK_48;
+}
+
+static long rt5682_wclk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct rt5682_priv *rt5682 =
+ container_of(hw, struct rt5682_priv,
+ dai_clks_hw[RT5682_DAI_WCLK_IDX]);
+
+ if (!rt5682_clk_check(rt5682))
+ return -EINVAL;
+ /*
+ * Only accept to set wclk rate to 48kHz temporarily.
+ */
+ return CLK_48;
+}
+
+static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct rt5682_priv *rt5682 =
+ container_of(hw, struct rt5682_priv,
+ dai_clks_hw[RT5682_DAI_WCLK_IDX]);
+ struct snd_soc_component *component = rt5682->component;
+ struct clk *parent_clk;
+ const char * const clk_name = __clk_get_name(hw->clk);
+ int pre_div;
+
+ if (!rt5682_clk_check(rt5682))
+ return -EINVAL;
+
+ /*
+ * Whether the wclk's parent clk (mclk) exists or not, please ensure
+ * it is fixed or set to 48MHz before setting wclk rate. It's a
+ * temporary limitation. Only accept 48MHz clk as the clk provider.
+ *
+ * It will set the codec anyway by assuming mclk is 48MHz.
+ */
+ parent_clk = clk_get_parent(hw->clk);
+ if (!parent_clk)
+ dev_warn(component->dev,
+ "Parent mclk of wclk not acquired in driver. Please ensure mclk was provided as %d Hz.\n",
+ CLK_PLL2_FIN);
+
+ if (parent_rate != CLK_PLL2_FIN)
+ dev_warn(component->dev, "clk %s only support %d Hz input\n",
+ clk_name, CLK_PLL2_FIN);
+
+ /*
+ * It's a temporary limitation. Only accept to set wclk rate to 48kHz.
+ * It will force wclk to 48kHz even it's not.
+ */
+ if (rate != CLK_48) {
+ dev_warn(component->dev, "clk %s only support %d Hz output\n",
+ clk_name, CLK_48);
+ rate = CLK_48;
+ }
+
+ /*
+ * To achieve the rate conversion from 48MHz to 48kHz, PLL2 is needed.
+ */
+ rt5682_set_component_pll(component, RT5682_PLL2, RT5682_PLL2_S_MCLK,
+ CLK_PLL2_FIN, CLK_PLL2_FOUT);
+
+ rt5682_set_component_sysclk(component, RT5682_SCLK_S_PLL2, 0,
+ CLK_PLL2_FOUT, SND_SOC_CLOCK_IN);
+
+ pre_div = rl6231_get_clk_info(rt5682->sysclk, rate);
+
+ snd_soc_component_update_bits(component, RT5682_ADDA_CLK_1,
+ RT5682_I2S_M_DIV_MASK | RT5682_I2S_CLK_SRC_MASK,
+ pre_div << RT5682_I2S_M_DIV_SFT |
+ (rt5682->sysclk_src) << RT5682_I2S_CLK_SRC_SFT);
+
+ return 0;
+}
+
+static unsigned long rt5682_bclk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct rt5682_priv *rt5682 =
+ container_of(hw, struct rt5682_priv,
+ dai_clks_hw[RT5682_DAI_BCLK_IDX]);
+ struct snd_soc_component *component = rt5682->component;
+ unsigned int bclks_per_wclk;
+
+ snd_soc_component_read(component, RT5682_TDM_TCON_CTRL,
+ &bclks_per_wclk);
+
+ switch (bclks_per_wclk & RT5682_TDM_BCLK_MS1_MASK) {
+ case RT5682_TDM_BCLK_MS1_256:
+ return parent_rate * 256;
+ case RT5682_TDM_BCLK_MS1_128:
+ return parent_rate * 128;
+ case RT5682_TDM_BCLK_MS1_64:
+ return parent_rate * 64;
+ case RT5682_TDM_BCLK_MS1_32:
+ return parent_rate * 32;
+ default:
+ return 0;
+ }
+}
+
+static unsigned long rt5682_bclk_get_factor(unsigned long rate,
+ unsigned long parent_rate)
+{
+ unsigned long factor;
+
+ factor = rate / parent_rate;
+ if (factor < 64)
+ return 32;
+ else if (factor < 128)
+ return 64;
+ else if (factor < 256)
+ return 128;
+ else
+ return 256;
+}
+
+static long rt5682_bclk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct rt5682_priv *rt5682 =
+ container_of(hw, struct rt5682_priv,
+ dai_clks_hw[RT5682_DAI_BCLK_IDX]);
+ unsigned long factor;
+
+ if (!*parent_rate || !rt5682_clk_check(rt5682))
+ return -EINVAL;
+
+ /*
+ * BCLK rates are set as a multiplier of WCLK in HW.
+ * We don't allow changing the parent WCLK. We just do
+ * some rounding down based on the parent WCLK rate
+ * and find the appropriate multiplier of BCLK to
+ * get the rounded down BCLK value.
+ */
+ factor = rt5682_bclk_get_factor(rate, *parent_rate);
+
+ return *parent_rate * factor;
+}
+
+static int rt5682_bclk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct rt5682_priv *rt5682 =
+ container_of(hw, struct rt5682_priv,
+ dai_clks_hw[RT5682_DAI_BCLK_IDX]);
+ struct snd_soc_component *component = rt5682->component;
+ struct snd_soc_dai *dai = NULL;
+ unsigned long factor;
+
+ if (!rt5682_clk_check(rt5682))
+ return -EINVAL;
+
+ factor = rt5682_bclk_get_factor(rate, parent_rate);
+
+ for_each_component_dais(component, dai)
+ if (dai->id == RT5682_AIF1)
+ break;
+ if (!dai) {
+ dev_err(component->dev, "dai %d not found in component\n",
+ RT5682_AIF1);
+ return -ENODEV;
+ }
+
+ return rt5682_set_bclk1_ratio(dai, factor);
+}
+
+static const struct clk_ops rt5682_dai_clk_ops[RT5682_DAI_NUM_CLKS] = {
+ [RT5682_DAI_WCLK_IDX] = {
+ .prepare = rt5682_wclk_prepare,
+ .unprepare = rt5682_wclk_unprepare,
+ .recalc_rate = rt5682_wclk_recalc_rate,
+ .round_rate = rt5682_wclk_round_rate,
+ .set_rate = rt5682_wclk_set_rate,
+ },
+ [RT5682_DAI_BCLK_IDX] = {
+ .recalc_rate = rt5682_bclk_recalc_rate,
+ .round_rate = rt5682_bclk_round_rate,
+ .set_rate = rt5682_bclk_set_rate,
+ },
+};
+
+static int rt5682_register_dai_clks(struct snd_soc_component *component)
+{
+ struct device *dev = component->dev;
+ struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ struct rt5682_platform_data *pdata = &rt5682->pdata;
+ struct clk_init_data init;
+ struct clk *dai_clk;
+ struct clk_lookup *dai_clk_lookup;
+ struct clk_hw *dai_clk_hw;
+ const char *parent_name;
+ int i, ret;
+
+ for (i = 0; i < RT5682_DAI_NUM_CLKS; ++i) {
+ dai_clk_hw = &rt5682->dai_clks_hw[i];
+
+ switch (i) {
+ case RT5682_DAI_WCLK_IDX:
+ /* Make MCLK the parent of WCLK */
+ if (rt5682->mclk) {
+ parent_name = __clk_get_name(rt5682->mclk);
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ } else {
+ init.parent_names = NULL;
+ init.num_parents = 0;
+ }
+ break;
+ case RT5682_DAI_BCLK_IDX:
+ /* Make WCLK the parent of BCLK */
+ parent_name = __clk_get_name(
+ rt5682->dai_clks[RT5682_DAI_WCLK_IDX]);
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ break;
+ default:
+ dev_err(dev, "Invalid clock index\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ init.name = pdata->dai_clk_names[i];
+ init.ops = &rt5682_dai_clk_ops[i];
+ init.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE;
+ dai_clk_hw->init = &init;
+
+ dai_clk = devm_clk_register(dev, dai_clk_hw);
+ if (IS_ERR(dai_clk)) {
+ dev_warn(dev, "Failed to register %s: %ld\n",
+ init.name, PTR_ERR(dai_clk));
+ ret = PTR_ERR(dai_clk);
+ goto err;
+ }
+ rt5682->dai_clks[i] = dai_clk;
+
+ if (dev->of_node) {
+ devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+ dai_clk_hw);
+ } else {
+ dai_clk_lookup = clkdev_create(dai_clk, init.name,
+ "%s", dev_name(dev));
+ if (!dai_clk_lookup) {
+ ret = -ENOMEM;
+ goto err;
+ } else {
+ rt5682->dai_clks_lookup[i] = dai_clk_lookup;
+ }
+ }
+ }
+
+ return 0;
+
+err:
+ do {
+ if (rt5682->dai_clks_lookup[i])
+ clkdev_drop(rt5682->dai_clks_lookup[i]);
+ } while (i-- > 0);
+
+ return ret;
+}
+#endif /* CONFIG_COMMON_CLK */
+
static int rt5682_probe(struct snd_soc_component *component)
{
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ struct sdw_slave *slave;
+ unsigned long time;
+#ifdef CONFIG_COMMON_CLK
+ int ret;
+#endif
rt5682->component = component;
+#ifdef CONFIG_COMMON_CLK
+ /* Check if MCLK provided */
+ rt5682->mclk = devm_clk_get(component->dev, "mclk");
+ if (IS_ERR(rt5682->mclk)) {
+ if (PTR_ERR(rt5682->mclk) != -ENOENT) {
+ ret = PTR_ERR(rt5682->mclk);
+ return ret;
+ }
+ rt5682->mclk = NULL;
+ }
+
+ /* Register CCF DAI clock control */
+ ret = rt5682_register_dai_clks(component);
+ if (ret)
+ return ret;
+
+ /* Initial setup for CCF */
+ rt5682->lrck[RT5682_AIF1] = CLK_48;
+#endif
+
+ if (rt5682->is_sdw) {
+ slave = rt5682->slave;
+ time = wait_for_completion_timeout(
+ &slave->initialization_complete,
+ msecs_to_jiffies(RT5682_PROBE_TIMEOUT));
+ if (!time) {
+ dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ return -ETIMEDOUT;
+ }
+ }
+
return 0;
}
@@ -2332,7 +2883,16 @@ static void rt5682_remove(struct snd_soc_component *component)
{
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
- rt5682_reset(rt5682->regmap);
+#ifdef CONFIG_COMMON_CLK
+ int i;
+
+ for (i = RT5682_DAI_NUM_CLKS - 1; i >= 0; --i) {
+ if (rt5682->dai_clks_lookup[i])
+ clkdev_drop(rt5682->dai_clks_lookup[i]);
+ }
+#endif
+
+ rt5682_reset(rt5682);
}
#ifdef CONFIG_PM
@@ -2369,14 +2929,203 @@ static const struct snd_soc_dai_ops rt5682_aif1_dai_ops = {
.hw_params = rt5682_hw_params,
.set_fmt = rt5682_set_dai_fmt,
.set_tdm_slot = rt5682_set_tdm_slot,
+ .set_bclk_ratio = rt5682_set_bclk1_ratio,
};
static const struct snd_soc_dai_ops rt5682_aif2_dai_ops = {
.hw_params = rt5682_hw_params,
.set_fmt = rt5682_set_dai_fmt,
- .set_bclk_ratio = rt5682_set_bclk_ratio,
+ .set_bclk_ratio = rt5682_set_bclk2_ratio,
};
+#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW)
+struct sdw_stream_data {
+ struct sdw_stream_runtime *sdw_stream;
+};
+
+static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
+ int direction)
+{
+ struct sdw_stream_data *stream;
+
+ stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+ if (!stream)
+ return -ENOMEM;
+
+ stream->sdw_stream = (struct sdw_stream_runtime *)sdw_stream;
+
+ /* Use tx_mask or rx_mask to configure stream tag and set dma_data */
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+ dai->playback_dma_data = stream;
+ else
+ dai->capture_dma_data = stream;
+
+ return 0;
+}
+
+static void rt5682_sdw_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct sdw_stream_data *stream;
+
+ stream = snd_soc_dai_get_dma_data(dai, substream);
+ snd_soc_dai_set_dma_data(dai, substream, NULL);
+ kfree(stream);
+}
+
+static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_config stream_config;
+ struct sdw_port_config port_config;
+ enum sdw_data_direction direction;
+ struct sdw_stream_data *stream;
+ int retval, port, num_channels;
+ unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0;
+
+ dev_dbg(dai->dev, "%s %s", __func__, dai->name);
+ stream = snd_soc_dai_get_dma_data(dai, substream);
+
+ if (!stream)
+ return -ENOMEM;
+
+ if (!rt5682->slave)
+ return -EINVAL;
+
+ /* SoundWire specific configuration */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ direction = SDW_DATA_DIR_RX;
+ port = 1;
+ } else {
+ direction = SDW_DATA_DIR_TX;
+ port = 2;
+ }
+
+ stream_config.frame_rate = params_rate(params);
+ stream_config.ch_count = params_channels(params);
+ stream_config.bps = snd_pcm_format_width(params_format(params));
+ stream_config.direction = direction;
+
+ num_channels = params_channels(params);
+ port_config.ch_mask = (1 << (num_channels)) - 1;
+ port_config.num = port;
+
+ retval = sdw_stream_add_slave(rt5682->slave, &stream_config,
+ &port_config, 1, stream->sdw_stream);
+ if (retval) {
+ dev_err(dai->dev, "Unable to configure port\n");
+ return retval;
+ }
+
+ switch (params_rate(params)) {
+ case 48000:
+ val_p = RT5682_SDW_REF_1_48K;
+ val_c = RT5682_SDW_REF_2_48K;
+ break;
+ case 96000:
+ val_p = RT5682_SDW_REF_1_96K;
+ val_c = RT5682_SDW_REF_2_96K;
+ break;
+ case 192000:
+ val_p = RT5682_SDW_REF_1_192K;
+ val_c = RT5682_SDW_REF_2_192K;
+ break;
+ case 32000:
+ val_p = RT5682_SDW_REF_1_32K;
+ val_c = RT5682_SDW_REF_2_32K;
+ break;
+ case 24000:
+ val_p = RT5682_SDW_REF_1_24K;
+ val_c = RT5682_SDW_REF_2_24K;
+ break;
+ case 16000:
+ val_p = RT5682_SDW_REF_1_16K;
+ val_c = RT5682_SDW_REF_2_16K;
+ break;
+ case 12000:
+ val_p = RT5682_SDW_REF_1_12K;
+ val_c = RT5682_SDW_REF_2_12K;
+ break;
+ case 8000:
+ val_p = RT5682_SDW_REF_1_8K;
+ val_c = RT5682_SDW_REF_2_8K;
+ break;
+ case 44100:
+ val_p = RT5682_SDW_REF_1_44K;
+ val_c = RT5682_SDW_REF_2_44K;
+ break;
+ case 88200:
+ val_p = RT5682_SDW_REF_1_88K;
+ val_c = RT5682_SDW_REF_2_88K;
+ break;
+ case 176400:
+ val_p = RT5682_SDW_REF_1_176K;
+ val_c = RT5682_SDW_REF_2_176K;
+ break;
+ case 22050:
+ val_p = RT5682_SDW_REF_1_22K;
+ val_c = RT5682_SDW_REF_2_22K;
+ break;
+ case 11025:
+ val_p = RT5682_SDW_REF_1_11K;
+ val_c = RT5682_SDW_REF_2_11K;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (params_rate(params) <= 48000) {
+ osr_p = RT5682_DAC_OSR_D_8;
+ osr_c = RT5682_ADC_OSR_D_8;
+ } else if (params_rate(params) <= 96000) {
+ osr_p = RT5682_DAC_OSR_D_4;
+ osr_c = RT5682_ADC_OSR_D_4;
+ } else {
+ osr_p = RT5682_DAC_OSR_D_2;
+ osr_c = RT5682_ADC_OSR_D_2;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
+ RT5682_SDW_REF_1_MASK, val_p);
+ regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
+ RT5682_DAC_OSR_MASK, osr_p);
+ } else {
+ regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
+ RT5682_SDW_REF_2_MASK, val_c);
+ regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
+ RT5682_ADC_OSR_MASK, osr_c);
+ }
+
+ return retval;
+}
+
+static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_data *stream =
+ snd_soc_dai_get_dma_data(dai, substream);
+
+ if (!rt5682->slave)
+ return -EINVAL;
+
+ sdw_stream_remove_slave(rt5682->slave, stream->sdw_stream);
+ return 0;
+}
+
+static struct snd_soc_dai_ops rt5682_sdw_ops = {
+ .hw_params = rt5682_sdw_hw_params,
+ .hw_free = rt5682_sdw_hw_free,
+ .set_sdw_stream = rt5682_set_sdw_stream,
+ .shutdown = rt5682_sdw_shutdown,
+};
+#endif
+
static struct snd_soc_dai_driver rt5682_dai[] = {
{
.name = "rt5682-aif1",
@@ -2409,6 +3158,27 @@ static struct snd_soc_dai_driver rt5682_dai[] = {
},
.ops = &rt5682_aif2_dai_ops,
},
+#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW)
+ {
+ .name = "rt5682-sdw",
+ .id = RT5682_SDW,
+ .playback = {
+ .stream_name = "SDW Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .capture = {
+ .stream_name = "SDW Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .ops = &rt5682_sdw_ops,
+ },
+#endif
};
static const struct snd_soc_component_driver soc_component_dev_rt5682 = {
@@ -2465,6 +3235,13 @@ static int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev)
rt5682->pdata.ldo1_en = of_get_named_gpio(dev->of_node,
"realtek,ldo1-en-gpios", 0);
+ if (device_property_read_string_array(dev, "clock-output-names",
+ rt5682->pdata.dai_clk_names,
+ RT5682_DAI_NUM_CLKS) < 0)
+ dev_warn(dev, "Using default DAI clk names: %s, %s\n",
+ rt5682->pdata.dai_clk_names[RT5682_DAI_WCLK_IDX],
+ rt5682->pdata.dai_clk_names[RT5682_DAI_BCLK_IDX]);
+
return 0;
}
@@ -2474,7 +3251,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682)
mutex_lock(&rt5682->calibrate_mutex);
- rt5682_reset(rt5682->regmap);
+ rt5682_reset(rt5682);
regmap_write(rt5682->regmap, RT5682_I2C_CTRL, 0x000f);
regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xa2af);
usleep_range(15000, 20000);
@@ -2520,6 +3297,219 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682)
}
+#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW)
+static int rt5682_sdw_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct device *dev = context;
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+ unsigned int data_l, data_h;
+
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 0);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
+ regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_H, &data_h);
+ regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_L, &data_l);
+
+ *val = (data_h << 8) | data_l;
+
+ dev_vdbg(dev, "[%s] %04x => %04x\n", __func__, reg, *val);
+
+ return 0;
+}
+
+static int rt5682_sdw_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct device *dev = context;
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 1);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_H, (val >> 8) & 0xff);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_L, (val & 0xff));
+
+ dev_vdbg(dev, "[%s] %04x <= %04x\n", __func__, reg, val);
+
+ return 0;
+}
+
+static const struct regmap_config rt5682_sdw_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+ .max_register = RT5682_I2C_MODE,
+ .volatile_reg = rt5682_volatile_register,
+ .readable_reg = rt5682_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt5682_reg,
+ .num_reg_defaults = ARRAY_SIZE(rt5682_reg),
+ .use_single_read = true,
+ .use_single_write = true,
+ .reg_read = rt5682_sdw_read,
+ .reg_write = rt5682_sdw_write,
+};
+
+int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
+ struct sdw_slave *slave)
+{
+ struct rt5682_priv *rt5682;
+ int ret;
+
+ rt5682 = devm_kzalloc(dev, sizeof(*rt5682), GFP_KERNEL);
+ if (!rt5682)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, rt5682);
+ rt5682->slave = slave;
+ rt5682->sdw_regmap = regmap;
+ rt5682->is_sdw = true;
+
+ rt5682->regmap = devm_regmap_init(dev, NULL, dev, &rt5682_sdw_regmap);
+ if (IS_ERR(rt5682->regmap)) {
+ ret = PTR_ERR(rt5682->regmap);
+ dev_err(dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ /*
+ * Mark hw_init to false
+ * HW init will be performed when device reports present
+ */
+ rt5682->hw_init = false;
+ rt5682->first_hw_init = false;
+
+ mutex_init(&rt5682->calibrate_mutex);
+ INIT_DELAYED_WORK(&rt5682->jack_detect_work,
+ rt5682_jack_detect_handler);
+
+ ret = devm_snd_soc_register_component(dev, &soc_component_dev_rt5682,
+ rt5682_dai, ARRAY_SIZE(rt5682_dai));
+
+ dev_dbg(&slave->dev, "%s\n", __func__);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rt5682_sdw_init);
+
+int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
+{
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+ int ret = 0;
+ unsigned int val;
+
+ if (rt5682->hw_init)
+ return 0;
+
+ regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
+ if (val != DEVICE_ID) {
+ pr_err("Device with ID register %x is not rt5682\n", val);
+ return -ENODEV;
+ }
+
+ /*
+ * PM runtime is only enabled when a Slave reports as Attached
+ */
+ if (!rt5682->first_hw_init) {
+ /* set autosuspend parameters */
+ pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
+ pm_runtime_use_autosuspend(&slave->dev);
+
+ /* update count of parent 'active' children */
+ pm_runtime_set_active(&slave->dev);
+
+ /* make sure the device does not suspend immediately */
+ pm_runtime_mark_last_busy(&slave->dev);
+
+ pm_runtime_enable(&slave->dev);
+ }
+
+ pm_runtime_get_noresume(&slave->dev);
+
+ rt5682_reset(rt5682);
+
+ if (rt5682->first_hw_init) {
+ regcache_cache_only(rt5682->regmap, false);
+ regcache_cache_bypass(rt5682->regmap, true);
+ }
+
+ rt5682_calibrate(rt5682);
+
+ if (rt5682->first_hw_init) {
+ regcache_cache_bypass(rt5682->regmap, false);
+ regcache_mark_dirty(rt5682->regmap);
+ regcache_sync(rt5682->regmap);
+
+ /* volatile registers */
+ regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
+ RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
+
+ goto reinit;
+ }
+
+ ret = regmap_multi_reg_write(rt5682->regmap, patch_list,
+ ARRAY_SIZE(patch_list));
+ if (ret != 0)
+ dev_warn(dev, "Failed to apply regmap patch: %d\n", ret);
+
+ regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000);
+
+ regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
+ RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK,
+ RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X);
+ regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380);
+ regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000);
+ regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8,
+ RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA);
+ regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1,
+ RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ);
+
+ /* Soundwire */
+ regmap_write(rt5682->regmap, RT5682_PLL2_INTERNAL, 0xa266);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_1, 0x1700);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_2, 0x0006);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_3, 0x2600);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_4, 0x0c8f);
+ regmap_write(rt5682->regmap, RT5682_PLL_TRACK_2, 0x3000);
+ regmap_write(rt5682->regmap, RT5682_PLL_TRACK_3, 0x4000);
+ regmap_update_bits(rt5682->regmap, RT5682_GLB_CLK,
+ RT5682_SCLK_SRC_MASK | RT5682_PLL2_SRC_MASK,
+ RT5682_SCLK_SRC_PLL2 | RT5682_PLL2_SRC_SDW);
+
+ regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
+ RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
+ regmap_write(rt5682->regmap, RT5682_CBJ_CTRL_1, 0xd042);
+ regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_3,
+ RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN);
+ regmap_update_bits(rt5682->regmap, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN);
+ regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
+ RT5682_POW_IRQ | RT5682_POW_JDH |
+ RT5682_POW_ANA, RT5682_POW_IRQ |
+ RT5682_POW_JDH | RT5682_POW_ANA);
+ regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2,
+ RT5682_PWR_JDH, RT5682_PWR_JDH);
+ regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
+ RT5682_JD1_EN_MASK | RT5682_JD1_IRQ_MASK,
+ RT5682_JD1_EN | RT5682_JD1_IRQ_PUL);
+
+reinit:
+ mod_delayed_work(system_power_efficient_wq,
+ &rt5682->jack_detect_work, msecs_to_jiffies(250));
+
+ /* Mark Slave initialization complete */
+ rt5682->hw_init = true;
+ rt5682->first_hw_init = true;
+
+ pm_runtime_mark_last_busy(&slave->dev);
+ pm_runtime_put_autosuspend(&slave->dev);
+
+ dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rt5682_io_init);
+#endif
+
static int rt5682_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -2586,7 +3576,7 @@ static int rt5682_i2c_probe(struct i2c_client *i2c,
return -ENODEV;
}
- rt5682_reset(rt5682->regmap);
+ rt5682_reset(rt5682);
mutex_init(&rt5682->calibrate_mutex);
rt5682_calibrate(rt5682);
@@ -2676,7 +3666,7 @@ static void rt5682_i2c_shutdown(struct i2c_client *client)
{
struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
- rt5682_reset(rt5682->regmap);
+ rt5682_reset(rt5682);
}
#ifdef CONFIG_OF
diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h
index 18faaa2a49a0..43de6e802309 100644
--- a/sound/soc/codecs/rt5682.h
+++ b/sound/soc/codecs/rt5682.h
@@ -10,6 +10,12 @@
#define __RT5682_H__
#include <sound/rt5682.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_type.h>
#define DEVICE_ID 0x6530
@@ -177,7 +183,7 @@
#define RT5682_TEST_MODE_CTRL_4 0x0148
#define RT5682_TEST_MODE_CTRL_5 0x0149
#define RT5682_PLL1_INTERNAL 0x0150
-#define RT5682_PLL2_INTERNAL 0x0151
+#define RT5682_PLL2_INTERNAL 0x0156
#define RT5682_STO_NG2_CTRL_1 0x0160
#define RT5682_STO_NG2_CTRL_2 0x0161
#define RT5682_STO_NG2_CTRL_3 0x0162
@@ -738,7 +744,7 @@
#define RT5682_ADC_OSR_D_24 (0x7 << 12)
#define RT5682_ADC_OSR_D_32 (0x8 << 12)
#define RT5682_ADC_OSR_D_48 (0x9 << 12)
-#define RT5682_I2S_M_DIV_MASK (0xf << 12)
+#define RT5682_I2S_M_DIV_MASK (0xf << 8)
#define RT5682_I2S_M_DIV_SFT 8
#define RT5682_I2S_M_D_1 (0x0 << 8)
#define RT5682_I2S_M_D_2 (0x1 << 8)
@@ -820,6 +826,12 @@
#define RT5682_TDM_DF_PCM_B (0x3 << 11)
#define RT5682_TDM_DF_PCM_A_N (0x6 << 11)
#define RT5682_TDM_DF_PCM_B_N (0x7 << 11)
+#define RT5682_TDM_BCLK_MS1_MASK (0x3 << 9)
+#define RT5682_TDM_BCLK_MS1_SFT 9
+#define RT5682_TDM_BCLK_MS1_32 (0x0 << 9)
+#define RT5682_TDM_BCLK_MS1_64 (0x1 << 9)
+#define RT5682_TDM_BCLK_MS1_128 (0x2 << 9)
+#define RT5682_TDM_BCLK_MS1_256 (0x3 << 9)
#define RT5682_TDM_CL_MASK (0x3 << 4)
#define RT5682_TDM_CL_16 (0x0 << 4)
#define RT5682_TDM_CL_20 (0x1 << 4)
@@ -835,8 +847,8 @@
#define RT5682_TDM_M_LP_INV (0x1 << 1)
#define RT5682_TDM_MS_MASK (0x1 << 0)
#define RT5682_TDM_MS_SFT 0
-#define RT5682_TDM_MS_M (0x0 << 0)
-#define RT5682_TDM_MS_S (0x1 << 0)
+#define RT5682_TDM_MS_S (0x0 << 0)
+#define RT5682_TDM_MS_M (0x1 << 0)
/* Global Clock Control (0x0080) */
#define RT5682_SCLK_SRC_MASK (0x7 << 13)
@@ -1049,6 +1061,28 @@
#define RT5682_PWR_CLK1M_PD (0x0 << 8)
#define RT5682_PWR_CLK1M_PU (0x1 << 8)
+/* PLL2 M/N/K Code Control 1 (0x009b) */
+#define RT5682_PLL2F_K_MASK (0x1f << 8)
+#define RT5682_PLL2F_K_SFT 8
+#define RT5682_PLL2B_K_MASK (0xf << 4)
+#define RT5682_PLL2B_K_SFT 4
+#define RT5682_PLL2B_M_MASK (0xf << 0)
+
+/* PLL2 M/N/K Code Control 2 (0x009c) */
+#define RT5682_PLL2F_M_MASK (0x3f << 8)
+#define RT5682_PLL2F_M_SFT 8
+#define RT5682_PLL2B_N_MASK (0x3f << 0)
+
+/* PLL2 M/N/K Code Control 2 (0x009d) */
+#define RT5682_PLL2F_N_MASK (0x7f << 8)
+#define RT5682_PLL2F_N_SFT 8
+
+/* PLL2 M/N/K Code Control 2 (0x009e) */
+#define RT5682_PLL2B_M_BP_MASK (0x1 << 11)
+#define RT5682_PLL2B_M_BP_SFT 11
+#define RT5682_PLL2F_M_BP_MASK (0x1 << 7)
+#define RT5682_PLL2F_M_BP_SFT 7
+
/* RC Clock Control (0x009f) */
#define RT5682_POW_IRQ (0x1 << 15)
#define RT5682_POW_JDH (0x1 << 14)
@@ -1091,11 +1125,17 @@
#define RT5682_JD1_POL_MASK (0x1 << 13)
#define RT5682_JD1_POL_NOR (0x0 << 13)
#define RT5682_JD1_POL_INV (0x1 << 13)
+#define RT5682_JD1_IRQ_MASK (0x1 << 10)
+#define RT5682_JD1_IRQ_LEV (0x0 << 10)
+#define RT5682_JD1_IRQ_PUL (0x1 << 10)
/* IRQ Control 3 (0x00b8) */
#define RT5682_IL_IRQ_MASK (0x1 << 7)
#define RT5682_IL_IRQ_DIS (0x0 << 7)
#define RT5682_IL_IRQ_EN (0x1 << 7)
+#define RT5682_IL_IRQ_TYPE_MASK (0x1 << 4)
+#define RT5682_IL_IRQ_LEV (0x0 << 4)
+#define RT5682_IL_IRQ_PUL (0x1 << 4)
/* GPIO Control 1 (0x00c0) */
#define RT5682_GP1_PIN_MASK (0x3 << 14)
@@ -1309,11 +1349,19 @@ enum {
RT5682_PLL1_S_MCLK,
RT5682_PLL1_S_BCLK1,
RT5682_PLL1_S_RCCLK,
+ RT5682_PLL2_S_MCLK,
+};
+
+enum {
+ RT5682_PLL1,
+ RT5682_PLL2,
+ RT5682_PLLS,
};
enum {
RT5682_AIF1,
RT5682_AIF2,
+ RT5682_SDW,
RT5682_AIFS
};
@@ -1329,7 +1377,49 @@ enum {
RT5682_CLK_SEL_I2S2_ASRC,
};
+#define RT5682_NUM_SUPPLIES 3
+
+struct rt5682_priv {
+ struct snd_soc_component *component;
+ struct rt5682_platform_data pdata;
+ struct regmap *regmap;
+ struct regmap *sdw_regmap;
+ struct snd_soc_jack *hs_jack;
+ struct regulator_bulk_data supplies[RT5682_NUM_SUPPLIES];
+ struct delayed_work jack_detect_work;
+ struct delayed_work jd_check_work;
+ struct mutex calibrate_mutex;
+ struct sdw_slave *slave;
+ enum sdw_slave_status status;
+ struct sdw_bus_params params;
+ bool hw_init;
+ bool first_hw_init;
+ bool is_sdw;
+
+#ifdef CONFIG_COMMON_CLK
+ struct clk_hw dai_clks_hw[RT5682_DAI_NUM_CLKS];
+ struct clk_lookup *dai_clks_lookup[RT5682_DAI_NUM_CLKS];
+ struct clk *dai_clks[RT5682_DAI_NUM_CLKS];
+ struct clk *mclk;
+#endif
+
+ int sysclk;
+ int sysclk_src;
+ int lrck[RT5682_AIFS];
+ int bclk[RT5682_AIFS];
+ int master[RT5682_AIFS];
+
+ int pll_src[RT5682_PLLS];
+ int pll_in[RT5682_PLLS];
+ int pll_out[RT5682_PLLS];
+
+ int jack_type;
+};
+
int rt5682_sel_asrc_clk_src(struct snd_soc_component *component,
unsigned int filter_mask, unsigned int clk_src);
+int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
+ struct sdw_slave *slave);
+int rt5682_io_init(struct device *dev, struct sdw_slave *slave);
#endif /* __RT5682_H__ */
diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c
index be52886a5edb..6b7f7a18da36 100644
--- a/sound/soc/codecs/tas2562.c
+++ b/sound/soc/codecs/tas2562.c
@@ -26,6 +26,24 @@
#define TAS2562_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FORMAT_S32_LE)
+/* DVC equation involves floating point math
+ * round(10^(volume in dB/20)*2^30)
+ * so create a lookup table for 2dB step
+ */
+static const unsigned int float_vol_db_lookup[] = {
+0x00000d43, 0x000010b2, 0x00001505, 0x00001a67, 0x00002151,
+0x000029f1, 0x000034cd, 0x00004279, 0x000053af, 0x0000695b,
+0x0000695b, 0x0000a6fa, 0x0000d236, 0x000108a4, 0x00014d2a,
+0x0001a36e, 0x00021008, 0x000298c0, 0x000344df, 0x00041d8f,
+0x00052e5a, 0x000685c8, 0x00083621, 0x000a566d, 0x000d03a7,
+0x0010624d, 0x0014a050, 0x0019f786, 0x0020b0bc, 0x0029279d,
+0x0033cf8d, 0x004139d3, 0x00521d50, 0x00676044, 0x0082248a,
+0x00a3d70a, 0x00ce4328, 0x0103ab3d, 0x0146e75d, 0x019b8c27,
+0x02061b89, 0x028c423f, 0x03352529, 0x0409c2b0, 0x05156d68,
+0x080e9f96, 0x0a24b062, 0x0cc509ab, 0x10137987, 0x143d1362,
+0x197a967f, 0x2013739e, 0x28619ae9, 0x32d64617, 0x40000000
+};
+
struct tas2562_data {
struct snd_soc_component *component;
struct gpio_desc *sdz_gpio;
@@ -34,6 +52,12 @@ struct tas2562_data {
struct i2c_client *client;
int v_sense_slot;
int i_sense_slot;
+ int volume_lvl;
+};
+
+enum tas256x_model {
+ TAS2562,
+ TAS2563,
};
static int tas2562_set_bias_level(struct snd_soc_component *component,
@@ -383,21 +407,81 @@ static int tas2562_dac_event(struct snd_soc_dapm_widget *w,
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
+ int ret;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
- dev_info(tas2562->dev, "SND_SOC_DAPM_POST_PMU\n");
+ ret = snd_soc_component_update_bits(component,
+ TAS2562_PWR_CTRL,
+ TAS2562_MODE_MASK,
+ TAS2562_MUTE);
+ if (ret)
+ goto end;
break;
case SND_SOC_DAPM_PRE_PMD:
- dev_info(tas2562->dev, "SND_SOC_DAPM_PRE_PMD\n");
+ ret = snd_soc_component_update_bits(component,
+ TAS2562_PWR_CTRL,
+ TAS2562_MODE_MASK,
+ TAS2562_SHUTDOWN);
+ if (ret)
+ goto end;
break;
default:
- break;
+ dev_err(tas2562->dev, "Not supported evevt\n");
+ return -EINVAL;
}
+end:
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int tas2562_volume_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = tas2562->volume_lvl;
return 0;
}
+static int tas2562_volume_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
+ int ret;
+ u32 reg_val;
+
+ reg_val = float_vol_db_lookup[ucontrol->value.integer.value[0]/2];
+ ret = snd_soc_component_write(component, TAS2562_DVC_CFG4,
+ (reg_val & 0xff));
+ if (ret)
+ return ret;
+ ret = snd_soc_component_write(component, TAS2562_DVC_CFG3,
+ ((reg_val >> 8) & 0xff));
+ if (ret)
+ return ret;
+ ret = snd_soc_component_write(component, TAS2562_DVC_CFG2,
+ ((reg_val >> 16) & 0xff));
+ if (ret)
+ return ret;
+ ret = snd_soc_component_write(component, TAS2562_DVC_CFG1,
+ ((reg_val >> 24) & 0xff));
+ if (ret)
+ return ret;
+
+ tas2562->volume_lvl = ucontrol->value.integer.value[0];
+
+ return ret;
+}
+
+/* Digital Volume Control. From 0 dB to -110 dB in 1 dB steps */
+static const DECLARE_TLV_DB_SCALE(dvc_tlv, -11000, 100, 0);
+
static DECLARE_TLV_DB_SCALE(tas2562_dac_tlv, 850, 50, 0);
static const struct snd_kcontrol_new isense_switch =
@@ -411,12 +495,22 @@ static const struct snd_kcontrol_new vsense_switch =
static const struct snd_kcontrol_new tas2562_snd_controls[] = {
SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 0, 0x1c, 0,
tas2562_dac_tlv),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Digital Volume Control",
+ .index = 0,
+ .tlv.p = dvc_tlv,
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_soc_info_volsw,
+ .get = tas2562_volume_control_get,
+ .put = tas2562_volume_control_put,
+ .private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0) ,
+ },
};
static const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux),
- SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_SWITCH("ISENSE", TAS2562_PWR_CTRL, 3, 1, &isense_switch),
@@ -431,7 +525,7 @@ static const struct snd_soc_dapm_route tas2562_audio_map[] = {
{"ASI1 Sel", "Left", "ASI1"},
{"ASI1 Sel", "Right", "ASI1"},
{"ASI1 Sel", "LeftRightDiv2", "ASI1"},
- { "DAC", NULL, "DAC IN" },
+ { "DAC", NULL, "ASI1 Sel" },
{ "OUT", NULL, "DAC" },
{"ISENSE", "Switch", "IMON"},
{"VSENSE", "Switch", "VMON"},
@@ -472,6 +566,13 @@ static struct snd_soc_dai_driver tas2562_dai[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = TAS2562_FORMATS,
},
+ .capture = {
+ .stream_name = "ASI1 Capture",
+ .channels_min = 0,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = TAS2562_FORMATS,
+ },
.ops = &tas2562_speaker_dai_ops,
},
};
@@ -495,6 +596,10 @@ static const struct reg_default tas2562_reg_defaults[] = {
{ TAS2562_PB_CFG1, 0x20 },
{ TAS2562_TDM_CFG0, 0x09 },
{ TAS2562_TDM_CFG1, 0x02 },
+ { TAS2562_DVC_CFG1, 0x40 },
+ { TAS2562_DVC_CFG2, 0x40 },
+ { TAS2562_DVC_CFG3, 0x00 },
+ { TAS2562_DVC_CFG4, 0x00 },
};
static const struct regmap_config tas2562_regmap_config = {
@@ -564,13 +669,15 @@ static int tas2562_probe(struct i2c_client *client,
}
static const struct i2c_device_id tas2562_id[] = {
- { "tas2562", 0 },
+ { "tas2562", TAS2562 },
+ { "tas2563", TAS2563 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas2562_id);
static const struct of_device_id tas2562_of_match[] = {
{ .compatible = "ti,tas2562", },
+ { .compatible = "ti,tas2563", },
{ },
};
MODULE_DEVICE_TABLE(of, tas2562_of_match);
diff --git a/sound/soc/codecs/tas2562.h b/sound/soc/codecs/tas2562.h
index 62e659ab786d..28e75fc431d0 100644
--- a/sound/soc/codecs/tas2562.h
+++ b/sound/soc/codecs/tas2562.h
@@ -35,12 +35,14 @@
#define TAS2562_REV_ID TAS2562_REG(0, 0x7d)
/* Page 2 */
-#define TAS2562_DVC_CFG1 TAS2562_REG(2, 0x01)
-#define TAS2562_DVC_CFG2 TAS2562_REG(2, 0x02)
+#define TAS2562_DVC_CFG1 TAS2562_REG(2, 0x0c)
+#define TAS2562_DVC_CFG2 TAS2562_REG(2, 0x0d)
+#define TAS2562_DVC_CFG3 TAS2562_REG(2, 0x0e)
+#define TAS2562_DVC_CFG4 TAS2562_REG(2, 0x0f)
#define TAS2562_RESET BIT(0)
-#define TAS2562_MODE_MASK 0x3
+#define TAS2562_MODE_MASK GENMASK(1,0)
#define TAS2562_ACTIVE 0x0
#define TAS2562_MUTE 0x1
#define TAS2562_SHUTDOWN 0x2
@@ -73,8 +75,8 @@
#define TAS2562_TDM_CFG2_RXWLEN_24B BIT(3)
#define TAS2562_TDM_CFG2_RXWLEN_32B (BIT(2) | BIT(3))
-#define TAS2562_VSENSE_POWER_EN BIT(2)
-#define TAS2562_ISENSE_POWER_EN BIT(3)
+#define TAS2562_VSENSE_POWER_EN 2
+#define TAS2562_ISENSE_POWER_EN 3
#define TAS2562_TDM_CFG5_VSNS_EN BIT(6)
#define TAS2562_TDM_CFG5_VSNS_SLOT_MASK GENMASK(5, 0)
diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c
new file mode 100644
index 000000000000..93a0cb8e662c
--- /dev/null
+++ b/sound/soc/codecs/tlv320adcx140.c
@@ -0,0 +1,922 @@
+// SPDX-License-Identifier: GPL-2.0
+// TLV320ADCX140 Sound driver
+// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/acpi.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "tlv320adcx140.h"
+
+struct adcx140_priv {
+ struct snd_soc_component *component;
+ struct regulator *supply_areg;
+ struct gpio_desc *gpio_reset;
+ struct regmap *regmap;
+ struct device *dev;
+
+ int micbias_vg;
+
+ unsigned int dai_fmt;
+ unsigned int tdm_delay;
+ unsigned int slot_width;
+};
+
+static const struct reg_default adcx140_reg_defaults[] = {
+ { ADCX140_PAGE_SELECT, 0x00 },
+ { ADCX140_SW_RESET, 0x00 },
+ { ADCX140_SLEEP_CFG, 0x00 },
+ { ADCX140_SHDN_CFG, 0x05 },
+ { ADCX140_ASI_CFG0, 0x30 },
+ { ADCX140_ASI_CFG1, 0x00 },
+ { ADCX140_ASI_CFG2, 0x00 },
+ { ADCX140_ASI_CH1, 0x00 },
+ { ADCX140_ASI_CH2, 0x01 },
+ { ADCX140_ASI_CH3, 0x02 },
+ { ADCX140_ASI_CH4, 0x03 },
+ { ADCX140_ASI_CH5, 0x04 },
+ { ADCX140_ASI_CH6, 0x05 },
+ { ADCX140_ASI_CH7, 0x06 },
+ { ADCX140_ASI_CH8, 0x07 },
+ { ADCX140_MST_CFG0, 0x02 },
+ { ADCX140_MST_CFG1, 0x48 },
+ { ADCX140_ASI_STS, 0xff },
+ { ADCX140_CLK_SRC, 0x10 },
+ { ADCX140_PDMCLK_CFG, 0x40 },
+ { ADCX140_PDM_CFG, 0x00 },
+ { ADCX140_GPIO_CFG0, 0x22 },
+ { ADCX140_GPO_CFG1, 0x00 },
+ { ADCX140_GPO_CFG2, 0x00 },
+ { ADCX140_GPO_CFG3, 0x00 },
+ { ADCX140_GPO_CFG4, 0x00 },
+ { ADCX140_GPO_VAL, 0x00 },
+ { ADCX140_GPIO_MON, 0x00 },
+ { ADCX140_GPI_CFG0, 0x00 },
+ { ADCX140_GPI_CFG1, 0x00 },
+ { ADCX140_GPI_MON, 0x00 },
+ { ADCX140_INT_CFG, 0x00 },
+ { ADCX140_INT_MASK0, 0xff },
+ { ADCX140_INT_LTCH0, 0x00 },
+ { ADCX140_BIAS_CFG, 0x00 },
+ { ADCX140_CH1_CFG0, 0x00 },
+ { ADCX140_CH1_CFG1, 0x00 },
+ { ADCX140_CH1_CFG2, 0xc9 },
+ { ADCX140_CH1_CFG3, 0x80 },
+ { ADCX140_CH1_CFG4, 0x00 },
+ { ADCX140_CH2_CFG0, 0x00 },
+ { ADCX140_CH2_CFG1, 0x00 },
+ { ADCX140_CH2_CFG2, 0xc9 },
+ { ADCX140_CH2_CFG3, 0x80 },
+ { ADCX140_CH2_CFG4, 0x00 },
+ { ADCX140_CH3_CFG0, 0x00 },
+ { ADCX140_CH3_CFG1, 0x00 },
+ { ADCX140_CH3_CFG2, 0xc9 },
+ { ADCX140_CH3_CFG3, 0x80 },
+ { ADCX140_CH3_CFG4, 0x00 },
+ { ADCX140_CH4_CFG0, 0x00 },
+ { ADCX140_CH4_CFG1, 0x00 },
+ { ADCX140_CH4_CFG2, 0xc9 },
+ { ADCX140_CH4_CFG3, 0x80 },
+ { ADCX140_CH4_CFG4, 0x00 },
+ { ADCX140_CH5_CFG2, 0xc9 },
+ { ADCX140_CH5_CFG3, 0x80 },
+ { ADCX140_CH5_CFG4, 0x00 },
+ { ADCX140_CH6_CFG2, 0xc9 },
+ { ADCX140_CH6_CFG3, 0x80 },
+ { ADCX140_CH6_CFG4, 0x00 },
+ { ADCX140_CH7_CFG2, 0xc9 },
+ { ADCX140_CH7_CFG3, 0x80 },
+ { ADCX140_CH7_CFG4, 0x00 },
+ { ADCX140_CH8_CFG2, 0xc9 },
+ { ADCX140_CH8_CFG3, 0x80 },
+ { ADCX140_CH8_CFG4, 0x00 },
+ { ADCX140_DSP_CFG0, 0x01 },
+ { ADCX140_DSP_CFG1, 0x40 },
+ { ADCX140_DRE_CFG0, 0x7b },
+ { ADCX140_AGC_CFG0, 0xe7 },
+ { ADCX140_IN_CH_EN, 0xf0 },
+ { ADCX140_ASI_OUT_CH_EN, 0x00 },
+ { ADCX140_PWR_CFG, 0x00 },
+ { ADCX140_DEV_STS0, 0x00 },
+ { ADCX140_DEV_STS1, 0x80 },
+};
+
+static const struct regmap_range_cfg adcx140_ranges[] = {
+ {
+ .range_min = 0,
+ .range_max = 12 * 128,
+ .selector_reg = ADCX140_PAGE_SELECT,
+ .selector_mask = 0xff,
+ .selector_shift = 0,
+ .window_start = 0,
+ .window_len = 128,
+ },
+};
+
+static bool adcx140_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ADCX140_SW_RESET:
+ case ADCX140_DEV_STS0:
+ case ADCX140_DEV_STS1:
+ case ADCX140_ASI_STS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config adcx140_i2c_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .reg_defaults = adcx140_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(adcx140_reg_defaults),
+ .cache_type = REGCACHE_FLAT,
+ .ranges = adcx140_ranges,
+ .num_ranges = ARRAY_SIZE(adcx140_ranges),
+ .max_register = 12 * 128,
+ .volatile_reg = adcx140_volatile,
+};
+
+/* Digital Volume control. From -100 to 27 dB in 0.5 dB steps */
+static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10000, 50, 0);
+
+/* ADC gain. From 0 to 42 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
+
+/* DRE Level. From -12 dB to -66 dB in 1 dB steps */
+static DECLARE_TLV_DB_SCALE(dre_thresh_tlv, -6600, 100, 0);
+/* DRE Max Gain. From 2 dB to 26 dB in 2 dB steps */
+static DECLARE_TLV_DB_SCALE(dre_gain_tlv, 200, 200, 0);
+
+/* AGC Level. From -6 dB to -36 dB in 2 dB steps */
+static DECLARE_TLV_DB_SCALE(agc_thresh_tlv, -3600, 200, 0);
+/* AGC Max Gain. From 3 dB to 42 dB in 3 dB steps */
+static DECLARE_TLV_DB_SCALE(agc_gain_tlv, 300, 300, 0);
+
+static const char * const decimation_filter_text[] = {
+ "Linear Phase", "Low Latency", "Ultra-low Latency"
+};
+
+static SOC_ENUM_SINGLE_DECL(decimation_filter_enum, ADCX140_DSP_CFG0, 4,
+ decimation_filter_text);
+
+static const struct snd_kcontrol_new decimation_filter_controls[] = {
+ SOC_DAPM_ENUM("Decimation Filter", decimation_filter_enum),
+};
+
+static const char * const resistor_text[] = {
+ "2.5 kOhm", "10 kOhm", "20 kOhm"
+};
+
+static SOC_ENUM_SINGLE_DECL(in1_resistor_enum, ADCX140_CH1_CFG0, 2,
+ resistor_text);
+static SOC_ENUM_SINGLE_DECL(in2_resistor_enum, ADCX140_CH2_CFG0, 2,
+ resistor_text);
+static SOC_ENUM_SINGLE_DECL(in3_resistor_enum, ADCX140_CH3_CFG0, 2,
+ resistor_text);
+static SOC_ENUM_SINGLE_DECL(in4_resistor_enum, ADCX140_CH4_CFG0, 2,
+ resistor_text);
+
+static const struct snd_kcontrol_new in1_resistor_controls[] = {
+ SOC_DAPM_ENUM("CH1 Resistor Select", in1_resistor_enum),
+};
+static const struct snd_kcontrol_new in2_resistor_controls[] = {
+ SOC_DAPM_ENUM("CH2 Resistor Select", in2_resistor_enum),
+};
+static const struct snd_kcontrol_new in3_resistor_controls[] = {
+ SOC_DAPM_ENUM("CH3 Resistor Select", in3_resistor_enum),
+};
+static const struct snd_kcontrol_new in4_resistor_controls[] = {
+ SOC_DAPM_ENUM("CH4 Resistor Select", in4_resistor_enum),
+};
+
+/* Analog/Digital Selection */
+static const char *adcx140_mic_sel_text[] = {"Analog", "Line In", "Digital"};
+static const char *adcx140_analog_sel_text[] = {"Analog", "Line In"};
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic1p_enum,
+ ADCX140_CH1_CFG0, 5,
+ adcx140_mic_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic1p_control =
+SOC_DAPM_ENUM("MIC1P MUX", adcx140_mic1p_enum);
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic1_analog_enum,
+ ADCX140_CH1_CFG0, 7,
+ adcx140_analog_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic1_analog_control =
+SOC_DAPM_ENUM("MIC1 Analog MUX", adcx140_mic1_analog_enum);
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic1m_enum,
+ ADCX140_CH1_CFG0, 5,
+ adcx140_mic_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic1m_control =
+SOC_DAPM_ENUM("MIC1M MUX", adcx140_mic1m_enum);
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic2p_enum,
+ ADCX140_CH2_CFG0, 5,
+ adcx140_mic_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic2p_control =
+SOC_DAPM_ENUM("MIC2P MUX", adcx140_mic2p_enum);
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic2_analog_enum,
+ ADCX140_CH2_CFG0, 7,
+ adcx140_analog_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic2_analog_control =
+SOC_DAPM_ENUM("MIC2 Analog MUX", adcx140_mic2_analog_enum);
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic2m_enum,
+ ADCX140_CH2_CFG0, 5,
+ adcx140_mic_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic2m_control =
+SOC_DAPM_ENUM("MIC2M MUX", adcx140_mic2m_enum);
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic3p_enum,
+ ADCX140_CH3_CFG0, 5,
+ adcx140_mic_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic3p_control =
+SOC_DAPM_ENUM("MIC3P MUX", adcx140_mic3p_enum);
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic3_analog_enum,
+ ADCX140_CH3_CFG0, 7,
+ adcx140_analog_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic3_analog_control =
+SOC_DAPM_ENUM("MIC3 Analog MUX", adcx140_mic3_analog_enum);
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic3m_enum,
+ ADCX140_CH3_CFG0, 5,
+ adcx140_mic_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic3m_control =
+SOC_DAPM_ENUM("MIC3M MUX", adcx140_mic3m_enum);
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic4p_enum,
+ ADCX140_CH4_CFG0, 5,
+ adcx140_mic_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic4p_control =
+SOC_DAPM_ENUM("MIC4P MUX", adcx140_mic4p_enum);
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic4_analog_enum,
+ ADCX140_CH4_CFG0, 7,
+ adcx140_analog_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic4_analog_control =
+SOC_DAPM_ENUM("MIC4 Analog MUX", adcx140_mic4_analog_enum);
+
+static SOC_ENUM_SINGLE_DECL(adcx140_mic4m_enum,
+ ADCX140_CH4_CFG0, 5,
+ adcx140_mic_sel_text);
+
+static const struct snd_kcontrol_new adcx140_dapm_mic4m_control =
+SOC_DAPM_ENUM("MIC4M MUX", adcx140_mic4m_enum);
+
+static const struct snd_kcontrol_new adcx140_dapm_ch1_en_switch =
+ SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 7, 1, 0);
+static const struct snd_kcontrol_new adcx140_dapm_ch2_en_switch =
+ SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 6, 1, 0);
+static const struct snd_kcontrol_new adcx140_dapm_ch3_en_switch =
+ SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 5, 1, 0);
+static const struct snd_kcontrol_new adcx140_dapm_ch4_en_switch =
+ SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 4, 1, 0);
+
+static const struct snd_kcontrol_new adcx140_dapm_ch1_dre_en_switch =
+ SOC_DAPM_SINGLE("Switch", ADCX140_CH1_CFG0, 0, 1, 0);
+static const struct snd_kcontrol_new adcx140_dapm_ch2_dre_en_switch =
+ SOC_DAPM_SINGLE("Switch", ADCX140_CH2_CFG0, 0, 1, 0);
+static const struct snd_kcontrol_new adcx140_dapm_ch3_dre_en_switch =
+ SOC_DAPM_SINGLE("Switch", ADCX140_CH3_CFG0, 0, 1, 0);
+static const struct snd_kcontrol_new adcx140_dapm_ch4_dre_en_switch =
+ SOC_DAPM_SINGLE("Switch", ADCX140_CH4_CFG0, 0, 1, 0);
+
+static const struct snd_kcontrol_new adcx140_dapm_dre_en_switch =
+ SOC_DAPM_SINGLE("Switch", ADCX140_DSP_CFG1, 3, 1, 0);
+
+/* Output Mixer */
+static const struct snd_kcontrol_new adcx140_output_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Digital CH1 Switch", 0, 0, 0, 0),
+ SOC_DAPM_SINGLE("Digital CH2 Switch", 0, 0, 0, 0),
+ SOC_DAPM_SINGLE("Digital CH3 Switch", 0, 0, 0, 0),
+ SOC_DAPM_SINGLE("Digital CH4 Switch", 0, 0, 0, 0),
+};
+
+static const struct snd_soc_dapm_widget adcx140_dapm_widgets[] = {
+ /* Analog Differential Inputs */
+ SND_SOC_DAPM_INPUT("MIC1P"),
+ SND_SOC_DAPM_INPUT("MIC1M"),
+ SND_SOC_DAPM_INPUT("MIC2P"),
+ SND_SOC_DAPM_INPUT("MIC2M"),
+ SND_SOC_DAPM_INPUT("MIC3P"),
+ SND_SOC_DAPM_INPUT("MIC3M"),
+ SND_SOC_DAPM_INPUT("MIC4P"),
+ SND_SOC_DAPM_INPUT("MIC4M"),
+
+ SND_SOC_DAPM_OUTPUT("CH1_OUT"),
+ SND_SOC_DAPM_OUTPUT("CH2_OUT"),
+ SND_SOC_DAPM_OUTPUT("CH3_OUT"),
+ SND_SOC_DAPM_OUTPUT("CH4_OUT"),
+ SND_SOC_DAPM_OUTPUT("CH5_OUT"),
+ SND_SOC_DAPM_OUTPUT("CH6_OUT"),
+ SND_SOC_DAPM_OUTPUT("CH7_OUT"),
+ SND_SOC_DAPM_OUTPUT("CH8_OUT"),
+
+ SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0,
+ &adcx140_output_mixer_controls[0],
+ ARRAY_SIZE(adcx140_output_mixer_controls)),
+
+ /* Input Selection to MIC_PGA */
+ SND_SOC_DAPM_MUX("MIC1P Input Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic1p_control),
+ SND_SOC_DAPM_MUX("MIC2P Input Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic2p_control),
+ SND_SOC_DAPM_MUX("MIC3P Input Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic3p_control),
+ SND_SOC_DAPM_MUX("MIC4P Input Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic4p_control),
+
+ /* Input Selection to MIC_PGA */
+ SND_SOC_DAPM_MUX("MIC1 Analog Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic1_analog_control),
+ SND_SOC_DAPM_MUX("MIC2 Analog Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic2_analog_control),
+ SND_SOC_DAPM_MUX("MIC3 Analog Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic3_analog_control),
+ SND_SOC_DAPM_MUX("MIC4 Analog Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic4_analog_control),
+
+ SND_SOC_DAPM_MUX("MIC1M Input Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic1m_control),
+ SND_SOC_DAPM_MUX("MIC2M Input Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic2m_control),
+ SND_SOC_DAPM_MUX("MIC3M Input Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic3m_control),
+ SND_SOC_DAPM_MUX("MIC4M Input Mux", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_mic4m_control),
+
+ SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH4", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_ADC("CH1_ADC", "CH1 Capture", ADCX140_IN_CH_EN, 7, 0),
+ SND_SOC_DAPM_ADC("CH2_ADC", "CH2 Capture", ADCX140_IN_CH_EN, 6, 0),
+ SND_SOC_DAPM_ADC("CH3_ADC", "CH3 Capture", ADCX140_IN_CH_EN, 5, 0),
+ SND_SOC_DAPM_ADC("CH4_ADC", "CH4 Capture", ADCX140_IN_CH_EN, 4, 0),
+
+ SND_SOC_DAPM_SWITCH("CH1_ASI_EN", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_ch1_en_switch),
+ SND_SOC_DAPM_SWITCH("CH2_ASI_EN", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_ch2_en_switch),
+ SND_SOC_DAPM_SWITCH("CH3_ASI_EN", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_ch3_en_switch),
+ SND_SOC_DAPM_SWITCH("CH4_ASI_EN", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_ch4_en_switch),
+
+ SND_SOC_DAPM_SWITCH("DRE_ENABLE", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_dre_en_switch),
+
+ SND_SOC_DAPM_SWITCH("CH1_DRE_EN", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_ch1_dre_en_switch),
+ SND_SOC_DAPM_SWITCH("CH2_DRE_EN", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_ch2_dre_en_switch),
+ SND_SOC_DAPM_SWITCH("CH3_DRE_EN", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_ch3_dre_en_switch),
+ SND_SOC_DAPM_SWITCH("CH4_DRE_EN", SND_SOC_NOPM, 0, 0,
+ &adcx140_dapm_ch4_dre_en_switch),
+
+ SND_SOC_DAPM_MUX("IN1 Analog Mic Resistor", SND_SOC_NOPM, 0, 0,
+ in1_resistor_controls),
+ SND_SOC_DAPM_MUX("IN2 Analog Mic Resistor", SND_SOC_NOPM, 0, 0,
+ in2_resistor_controls),
+ SND_SOC_DAPM_MUX("IN3 Analog Mic Resistor", SND_SOC_NOPM, 0, 0,
+ in3_resistor_controls),
+ SND_SOC_DAPM_MUX("IN4 Analog Mic Resistor", SND_SOC_NOPM, 0, 0,
+ in4_resistor_controls),
+
+ SND_SOC_DAPM_MUX("Decimation Filter", SND_SOC_NOPM, 0, 0,
+ decimation_filter_controls),
+};
+
+static const struct snd_soc_dapm_route adcx140_audio_map[] = {
+ /* Outputs */
+ {"CH1_OUT", NULL, "Output Mixer"},
+ {"CH2_OUT", NULL, "Output Mixer"},
+ {"CH3_OUT", NULL, "Output Mixer"},
+ {"CH4_OUT", NULL, "Output Mixer"},
+
+ {"CH1_ASI_EN", "Switch", "CH1_ADC"},
+ {"CH2_ASI_EN", "Switch", "CH2_ADC"},
+ {"CH3_ASI_EN", "Switch", "CH3_ADC"},
+ {"CH4_ASI_EN", "Switch", "CH4_ADC"},
+
+ {"Decimation Filter", "Linear Phase", "DRE_ENABLE"},
+ {"Decimation Filter", "Low Latency", "DRE_ENABLE"},
+ {"Decimation Filter", "Ultra-low Latency", "DRE_ENABLE"},
+
+ {"DRE_ENABLE", "Switch", "CH1_DRE_EN"},
+ {"DRE_ENABLE", "Switch", "CH2_DRE_EN"},
+ {"DRE_ENABLE", "Switch", "CH3_DRE_EN"},
+ {"DRE_ENABLE", "Switch", "CH4_DRE_EN"},
+
+ {"CH1_DRE_EN", "Switch", "CH1_ADC"},
+ {"CH2_DRE_EN", "Switch", "CH2_ADC"},
+ {"CH3_DRE_EN", "Switch", "CH3_ADC"},
+ {"CH4_DRE_EN", "Switch", "CH4_ADC"},
+
+ /* Mic input */
+ {"CH1_ADC", NULL, "MIC_GAIN_CTL_CH1"},
+ {"CH2_ADC", NULL, "MIC_GAIN_CTL_CH2"},
+ {"CH3_ADC", NULL, "MIC_GAIN_CTL_CH3"},
+ {"CH4_ADC", NULL, "MIC_GAIN_CTL_CH4"},
+
+ {"MIC_GAIN_CTL_CH1", NULL, "IN1 Analog Mic Resistor"},
+ {"MIC_GAIN_CTL_CH1", NULL, "IN1 Analog Mic Resistor"},
+ {"MIC_GAIN_CTL_CH2", NULL, "IN2 Analog Mic Resistor"},
+ {"MIC_GAIN_CTL_CH2", NULL, "IN2 Analog Mic Resistor"},
+ {"MIC_GAIN_CTL_CH3", NULL, "IN3 Analog Mic Resistor"},
+ {"MIC_GAIN_CTL_CH3", NULL, "IN3 Analog Mic Resistor"},
+ {"MIC_GAIN_CTL_CH4", NULL, "IN4 Analog Mic Resistor"},
+ {"MIC_GAIN_CTL_CH4", NULL, "IN4 Analog Mic Resistor"},
+
+ {"IN1 Analog Mic Resistor", "2.5 kOhm", "MIC1P Input Mux"},
+ {"IN1 Analog Mic Resistor", "10 kOhm", "MIC1P Input Mux"},
+ {"IN1 Analog Mic Resistor", "20 kOhm", "MIC1P Input Mux"},
+
+ {"IN1 Analog Mic Resistor", "2.5 kOhm", "MIC1M Input Mux"},
+ {"IN1 Analog Mic Resistor", "10 kOhm", "MIC1M Input Mux"},
+ {"IN1 Analog Mic Resistor", "20 kOhm", "MIC1M Input Mux"},
+
+ {"IN2 Analog Mic Resistor", "2.5 kOhm", "MIC2P Input Mux"},
+ {"IN2 Analog Mic Resistor", "10 kOhm", "MIC2P Input Mux"},
+ {"IN2 Analog Mic Resistor", "20 kOhm", "MIC2P Input Mux"},
+
+ {"IN2 Analog Mic Resistor", "2.5 kOhm", "MIC2M Input Mux"},
+ {"IN2 Analog Mic Resistor", "10 kOhm", "MIC2M Input Mux"},
+ {"IN2 Analog Mic Resistor", "20 kOhm", "MIC2M Input Mux"},
+
+ {"IN3 Analog Mic Resistor", "2.5 kOhm", "MIC3P Input Mux"},
+ {"IN3 Analog Mic Resistor", "10 kOhm", "MIC3P Input Mux"},
+ {"IN3 Analog Mic Resistor", "20 kOhm", "MIC3P Input Mux"},
+
+ {"IN3 Analog Mic Resistor", "2.5 kOhm", "MIC3M Input Mux"},
+ {"IN3 Analog Mic Resistor", "10 kOhm", "MIC3M Input Mux"},
+ {"IN3 Analog Mic Resistor", "20 kOhm", "MIC3M Input Mux"},
+
+ {"IN4 Analog Mic Resistor", "2.5 kOhm", "MIC4P Input Mux"},
+ {"IN4 Analog Mic Resistor", "10 kOhm", "MIC4P Input Mux"},
+ {"IN4 Analog Mic Resistor", "20 kOhm", "MIC4P Input Mux"},
+
+ {"IN4 Analog Mic Resistor", "2.5 kOhm", "MIC4M Input Mux"},
+ {"IN4 Analog Mic Resistor", "10 kOhm", "MIC4M Input Mux"},
+ {"IN4 Analog Mic Resistor", "20 kOhm", "MIC4M Input Mux"},
+
+ {"MIC1 Analog Mux", "Line In", "MIC1P"},
+ {"MIC2 Analog Mux", "Line In", "MIC2P"},
+ {"MIC3 Analog Mux", "Line In", "MIC3P"},
+ {"MIC4 Analog Mux", "Line In", "MIC4P"},
+
+ {"MIC1P Input Mux", "Analog", "MIC1P"},
+ {"MIC1M Input Mux", "Analog", "MIC1M"},
+ {"MIC2P Input Mux", "Analog", "MIC2P"},
+ {"MIC2M Input Mux", "Analog", "MIC2M"},
+ {"MIC3P Input Mux", "Analog", "MIC3P"},
+ {"MIC3M Input Mux", "Analog", "MIC3M"},
+ {"MIC4P Input Mux", "Analog", "MIC4P"},
+ {"MIC4M Input Mux", "Analog", "MIC4M"},
+};
+
+static const struct snd_kcontrol_new adcx140_snd_controls[] = {
+ SOC_SINGLE_TLV("Analog CH1 Mic Gain Volume", ADCX140_CH1_CFG1, 2, 42, 0,
+ adc_tlv),
+ SOC_SINGLE_TLV("Analog CH2 Mic Gain Volume", ADCX140_CH1_CFG2, 2, 42, 0,
+ adc_tlv),
+ SOC_SINGLE_TLV("Analog CH3 Mic Gain Volume", ADCX140_CH1_CFG3, 2, 42, 0,
+ adc_tlv),
+ SOC_SINGLE_TLV("Analog CH4 Mic Gain Volume", ADCX140_CH1_CFG4, 2, 42, 0,
+ adc_tlv),
+
+ SOC_SINGLE_TLV("DRE Threshold", ADCX140_DRE_CFG0, 4, 9, 0,
+ dre_thresh_tlv),
+ SOC_SINGLE_TLV("DRE Max Gain", ADCX140_DRE_CFG0, 0, 12, 0,
+ dre_gain_tlv),
+
+ SOC_SINGLE_TLV("AGC Threshold", ADCX140_AGC_CFG0, 4, 15, 0,
+ agc_thresh_tlv),
+ SOC_SINGLE_TLV("AGC Max Gain", ADCX140_AGC_CFG0, 0, 13, 0,
+ agc_gain_tlv),
+
+ SOC_SINGLE_TLV("Digital CH1 Out Volume", ADCX140_CH1_CFG2,
+ 0, 0xff, 0, dig_vol_tlv),
+ SOC_SINGLE_TLV("Digital CH2 Out Volume", ADCX140_CH2_CFG2,
+ 0, 0xff, 0, dig_vol_tlv),
+ SOC_SINGLE_TLV("Digital CH3 Out Volume", ADCX140_CH3_CFG2,
+ 0, 0xff, 0, dig_vol_tlv),
+ SOC_SINGLE_TLV("Digital CH4 Out Volume", ADCX140_CH4_CFG2,
+ 0, 0xff, 0, dig_vol_tlv),
+ SOC_SINGLE_TLV("Digital CH5 Out Volume", ADCX140_CH5_CFG2,
+ 0, 0xff, 0, dig_vol_tlv),
+ SOC_SINGLE_TLV("Digital CH6 Out Volume", ADCX140_CH6_CFG2,
+ 0, 0xff, 0, dig_vol_tlv),
+ SOC_SINGLE_TLV("Digital CH7 Out Volume", ADCX140_CH7_CFG2,
+ 0, 0xff, 0, dig_vol_tlv),
+ SOC_SINGLE_TLV("Digital CH8 Out Volume", ADCX140_CH8_CFG2,
+ 0, 0xff, 0, dig_vol_tlv),
+};
+
+static int adcx140_reset(struct adcx140_priv *adcx140)
+{
+ int ret = 0;
+
+ if (adcx140->gpio_reset) {
+ gpiod_direction_output(adcx140->gpio_reset, 0);
+ /* 8.4.1: wait for hw shutdown (25ms) + >= 1ms */
+ usleep_range(30000, 100000);
+ gpiod_direction_output(adcx140->gpio_reset, 1);
+ } else {
+ ret = regmap_write(adcx140->regmap, ADCX140_SW_RESET,
+ ADCX140_RESET);
+ }
+
+ /* 8.4.2: wait >= 10 ms after entering sleep mode. */
+ usleep_range(10000, 100000);
+
+ return 0;
+}
+
+static int adcx140_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ u8 data = 0;
+
+ switch (params_width(params)) {
+ case 16:
+ data = ADCX140_16_BIT_WORD;
+ break;
+ case 20:
+ data = ADCX140_20_BIT_WORD;
+ break;
+ case 24:
+ data = ADCX140_24_BIT_WORD;
+ break;
+ case 32:
+ data = ADCX140_32_BIT_WORD;
+ break;
+ default:
+ dev_err(component->dev, "%s: Unsupported width %d\n",
+ __func__, params_width(params));
+ return -EINVAL;
+ }
+
+ snd_soc_component_update_bits(component, ADCX140_ASI_CFG0,
+ ADCX140_WORD_LEN_MSK, data);
+
+ return 0;
+}
+
+static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_component *component = codec_dai->component;
+ struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component);
+ u8 iface_reg1 = 0;
+ u8 iface_reg2 = 0;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ iface_reg2 |= ADCX140_BCLK_FSYNC_MASTER;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ case SND_SOC_DAIFMT_CBM_CFS:
+ default:
+ dev_err(component->dev, "Invalid DAI master/slave interface\n");
+ return -EINVAL;
+ }
+
+ /* signal polarity */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_IF:
+ iface_reg1 |= ADCX140_FSYNCINV_BIT;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ iface_reg1 |= ADCX140_BCLKINV_BIT | ADCX140_FSYNCINV_BIT;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface_reg1 |= ADCX140_BCLKINV_BIT;
+ break;
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ default:
+ dev_err(component->dev, "Invalid DAI clock signal polarity\n");
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ iface_reg1 |= ADCX140_I2S_MODE_BIT;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface_reg1 |= ADCX140_LEFT_JUST_BIT;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ break;
+ default:
+ dev_err(component->dev, "Invalid DAI interface format\n");
+ return -EINVAL;
+ }
+
+ adcx140->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+
+ snd_soc_component_update_bits(component, ADCX140_ASI_CFG0,
+ ADCX140_FSYNCINV_BIT |
+ ADCX140_BCLKINV_BIT |
+ ADCX140_ASI_FORMAT_MSK,
+ iface_reg1);
+ snd_soc_component_update_bits(component, ADCX140_MST_CFG0,
+ ADCX140_BCLK_FSYNC_MASTER, iface_reg2);
+
+ return 0;
+}
+
+static int adcx140_set_dai_tdm_slot(struct snd_soc_dai *codec_dai,
+ unsigned int tx_mask, unsigned int rx_mask,
+ int slots, int slot_width)
+{
+ struct snd_soc_component *component = codec_dai->component;
+ struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component);
+ unsigned int lsb;
+
+ if (tx_mask != rx_mask) {
+ dev_err(component->dev, "tx and rx masks must be symmetric\n");
+ return -EINVAL;
+ }
+
+ /* TDM based on DSP mode requires slots to be adjacent */
+ lsb = __ffs(tx_mask);
+ if ((lsb + 1) != __fls(tx_mask)) {
+ dev_err(component->dev, "Invalid mask, slots must be adjacent\n");
+ return -EINVAL;
+ }
+
+ switch (slot_width) {
+ case 16:
+ case 20:
+ case 24:
+ case 32:
+ break;
+ default:
+ dev_err(component->dev, "Unsupported slot width %d\n", slot_width);
+ return -EINVAL;
+ }
+
+ adcx140->tdm_delay = lsb;
+ adcx140->slot_width = slot_width;
+
+ return 0;
+}
+
+static int adcx140_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component);
+ int offset = 0;
+ int width = adcx140->slot_width;
+
+ if (!width)
+ width = substream->runtime->sample_bits;
+
+ /* TDM slot selection only valid in DSP_A/_B mode */
+ if (adcx140->dai_fmt == SND_SOC_DAIFMT_DSP_A)
+ offset += (adcx140->tdm_delay * width + 1);
+ else if (adcx140->dai_fmt == SND_SOC_DAIFMT_DSP_B)
+ offset += adcx140->tdm_delay * width;
+
+ /* Configure data offset */
+ snd_soc_component_update_bits(component, ADCX140_ASI_CFG1,
+ ADCX140_TX_OFFSET_MASK, offset);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops adcx140_dai_ops = {
+ .hw_params = adcx140_hw_params,
+ .set_fmt = adcx140_set_dai_fmt,
+ .prepare = adcx140_prepare,
+ .set_tdm_slot = adcx140_set_dai_tdm_slot,
+};
+
+static int adcx140_codec_probe(struct snd_soc_component *component)
+{
+ struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component);
+ int sleep_cfg_val = ADCX140_WAKE_DEV;
+ u8 bias_source;
+ u8 vref_source;
+ int ret;
+
+ ret = device_property_read_u8(adcx140->dev, "ti,mic-bias-source",
+ &bias_source);
+ if (ret)
+ bias_source = ADCX140_MIC_BIAS_VAL_VREF;
+
+ if (bias_source != ADCX140_MIC_BIAS_VAL_VREF &&
+ bias_source != ADCX140_MIC_BIAS_VAL_VREF_1096 &&
+ bias_source != ADCX140_MIC_BIAS_VAL_AVDD) {
+ dev_err(adcx140->dev, "Mic Bias source value is invalid\n");
+ return -EINVAL;
+ }
+
+ ret = device_property_read_u8(adcx140->dev, "ti,vref-source",
+ &vref_source);
+ if (ret)
+ vref_source = ADCX140_MIC_BIAS_VREF_275V;
+
+ if (vref_source != ADCX140_MIC_BIAS_VREF_275V &&
+ vref_source != ADCX140_MIC_BIAS_VREF_25V &&
+ vref_source != ADCX140_MIC_BIAS_VREF_1375V) {
+ dev_err(adcx140->dev, "Mic Bias source value is invalid\n");
+ return -EINVAL;
+ }
+
+ bias_source |= vref_source;
+
+ ret = adcx140_reset(adcx140);
+ if (ret)
+ goto out;
+
+ if(adcx140->supply_areg == NULL)
+ sleep_cfg_val |= ADCX140_AREG_INTERNAL;
+
+ ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val);
+ if (ret) {
+ dev_err(adcx140->dev, "setting sleep config failed %d\n", ret);
+ goto out;
+ }
+
+ /* 8.4.3: Wait >= 1ms after entering active mode. */
+ usleep_range(1000, 100000);
+
+ ret = regmap_update_bits(adcx140->regmap, ADCX140_BIAS_CFG,
+ ADCX140_MIC_BIAS_VAL_MSK |
+ ADCX140_MIC_BIAS_VREF_MSK, bias_source);
+ if (ret)
+ dev_err(adcx140->dev, "setting MIC bias failed %d\n", ret);
+out:
+ return ret;
+}
+
+static int adcx140_set_bias_level(struct snd_soc_component *component,
+ enum snd_soc_bias_level level)
+{
+ struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component);
+ int pwr_cfg = 0;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ case SND_SOC_BIAS_PREPARE:
+ case SND_SOC_BIAS_STANDBY:
+ pwr_cfg = ADCX140_PWR_CFG_BIAS_PDZ | ADCX140_PWR_CFG_PLL_PDZ |
+ ADCX140_PWR_CFG_ADC_PDZ;
+ break;
+ case SND_SOC_BIAS_OFF:
+ pwr_cfg = 0x0;
+ break;
+ }
+
+ return regmap_write(adcx140->regmap, ADCX140_PWR_CFG, pwr_cfg);
+}
+
+static const struct snd_soc_component_driver soc_codec_driver_adcx140 = {
+ .probe = adcx140_codec_probe,
+ .set_bias_level = adcx140_set_bias_level,
+ .controls = adcx140_snd_controls,
+ .num_controls = ARRAY_SIZE(adcx140_snd_controls),
+ .dapm_widgets = adcx140_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(adcx140_dapm_widgets),
+ .dapm_routes = adcx140_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(adcx140_audio_map),
+ .suspend_bias_off = 1,
+ .idle_bias_on = 0,
+ .use_pmdown_time = 1,
+ .endianness = 1,
+ .non_legacy_dai_naming = 1,
+};
+
+static struct snd_soc_dai_driver adcx140_dai_driver[] = {
+ {
+ .name = "tlv320adcx140-codec",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = ADCX140_MAX_CHANNELS,
+ .rates = ADCX140_RATES,
+ .formats = ADCX140_FORMATS,
+ },
+ .ops = &adcx140_dai_ops,
+ .symmetric_rates = 1,
+ }
+};
+
+static const struct of_device_id tlv320adcx140_of_match[] = {
+ { .compatible = "ti,tlv320adc3140" },
+ { .compatible = "ti,tlv320adc5140" },
+ { .compatible = "ti,tlv320adc6140" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tlv320adcx140_of_match);
+
+static int adcx140_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct adcx140_priv *adcx140;
+ int ret;
+
+ adcx140 = devm_kzalloc(&i2c->dev, sizeof(*adcx140), GFP_KERNEL);
+ if (!adcx140)
+ return -ENOMEM;
+
+ adcx140->gpio_reset = devm_gpiod_get_optional(adcx140->dev,
+ "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(adcx140->gpio_reset))
+ dev_info(&i2c->dev, "Reset GPIO not defined\n");
+
+ adcx140->supply_areg = devm_regulator_get_optional(adcx140->dev,
+ "areg");
+ if (IS_ERR(adcx140->supply_areg)) {
+ if (PTR_ERR(adcx140->supply_areg) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ else
+ adcx140->supply_areg = NULL;
+ } else {
+ ret = regulator_enable(adcx140->supply_areg);
+ if (ret) {
+ dev_err(adcx140->dev, "Failed to enable areg\n");
+ return ret;
+ }
+ }
+
+ adcx140->regmap = devm_regmap_init_i2c(i2c, &adcx140_i2c_regmap);
+ if (IS_ERR(adcx140->regmap)) {
+ ret = PTR_ERR(adcx140->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+ adcx140->dev = &i2c->dev;
+ i2c_set_clientdata(i2c, adcx140);
+
+ return devm_snd_soc_register_component(&i2c->dev,
+ &soc_codec_driver_adcx140,
+ adcx140_dai_driver, 1);
+}
+
+static const struct i2c_device_id adcx140_i2c_id[] = {
+ { "tlv320adc3140", 0 },
+ { "tlv320adc5140", 1 },
+ { "tlv320adc6140", 2 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, adcx140_i2c_id);
+
+static struct i2c_driver adcx140_i2c_driver = {
+ .driver = {
+ .name = "tlv320adcx140-codec",
+ .of_match_table = of_match_ptr(tlv320adcx140_of_match),
+ },
+ .probe = adcx140_i2c_probe,
+ .id_table = adcx140_i2c_id,
+};
+module_i2c_driver(adcx140_i2c_driver);
+
+MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
+MODULE_DESCRIPTION("ASoC TLV320ADCX140 CODEC Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/tlv320adcx140.h b/sound/soc/codecs/tlv320adcx140.h
new file mode 100644
index 000000000000..6d055e55909e
--- /dev/null
+++ b/sound/soc/codecs/tlv320adcx140.h
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0
+// TLV320ADCX104 Sound driver
+// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+
+#ifndef _TLV320ADCX140_H
+#define _TLV320ADCX140_H
+
+#define ADCX140_RATES (SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000)
+
+#define ADCX140_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+#define ADCX140_PAGE_SELECT 0x00
+#define ADCX140_SW_RESET 0x01
+#define ADCX140_SLEEP_CFG 0x02
+#define ADCX140_SHDN_CFG 0x05
+#define ADCX140_ASI_CFG0 0x07
+#define ADCX140_ASI_CFG1 0x08
+#define ADCX140_ASI_CFG2 0x09
+#define ADCX140_ASI_CH1 0x0b
+#define ADCX140_ASI_CH2 0x0c
+#define ADCX140_ASI_CH3 0x0d
+#define ADCX140_ASI_CH4 0x0e
+#define ADCX140_ASI_CH5 0x0f
+#define ADCX140_ASI_CH6 0x10
+#define ADCX140_ASI_CH7 0x11
+#define ADCX140_ASI_CH8 0x12
+#define ADCX140_MST_CFG0 0x13
+#define ADCX140_MST_CFG1 0x14
+#define ADCX140_ASI_STS 0x15
+#define ADCX140_CLK_SRC 0x16
+#define ADCX140_PDMCLK_CFG 0x1f
+#define ADCX140_PDM_CFG 0x20
+#define ADCX140_GPIO_CFG0 0x21
+#define ADCX140_GPO_CFG1 0x22
+#define ADCX140_GPO_CFG2 0x23
+#define ADCX140_GPO_CFG3 0x24
+#define ADCX140_GPO_CFG4 0x25
+#define ADCX140_GPO_VAL 0x29
+#define ADCX140_GPIO_MON 0x2a
+#define ADCX140_GPI_CFG0 0x2b
+#define ADCX140_GPI_CFG1 0x2c
+#define ADCX140_GPI_MON 0x2f
+#define ADCX140_INT_CFG 0x32
+#define ADCX140_INT_MASK0 0x33
+#define ADCX140_INT_LTCH0 0x36
+#define ADCX140_BIAS_CFG 0x3b
+#define ADCX140_CH1_CFG0 0x3c
+#define ADCX140_CH1_CFG1 0x3d
+#define ADCX140_CH1_CFG2 0x3e
+#define ADCX140_CH1_CFG3 0x3f
+#define ADCX140_CH1_CFG4 0x40
+#define ADCX140_CH2_CFG0 0x41
+#define ADCX140_CH2_CFG1 0x42
+#define ADCX140_CH2_CFG2 0x43
+#define ADCX140_CH2_CFG3 0x44
+#define ADCX140_CH2_CFG4 0x45
+#define ADCX140_CH3_CFG0 0x46
+#define ADCX140_CH3_CFG1 0x47
+#define ADCX140_CH3_CFG2 0x48
+#define ADCX140_CH3_CFG3 0x49
+#define ADCX140_CH3_CFG4 0x4a
+#define ADCX140_CH4_CFG0 0x4b
+#define ADCX140_CH4_CFG1 0x4c
+#define ADCX140_CH4_CFG2 0x4d
+#define ADCX140_CH4_CFG3 0x4e
+#define ADCX140_CH4_CFG4 0x4f
+#define ADCX140_CH5_CFG2 0x52
+#define ADCX140_CH5_CFG3 0x53
+#define ADCX140_CH5_CFG4 0x54
+#define ADCX140_CH6_CFG2 0x57
+#define ADCX140_CH6_CFG3 0x58
+#define ADCX140_CH6_CFG4 0x59
+#define ADCX140_CH7_CFG2 0x5c
+#define ADCX140_CH7_CFG3 0x5d
+#define ADCX140_CH7_CFG4 0x5e
+#define ADCX140_CH8_CFG2 0x61
+#define ADCX140_CH8_CFG3 0x62
+#define ADCX140_CH8_CFG4 0x63
+#define ADCX140_DSP_CFG0 0x6b
+#define ADCX140_DSP_CFG1 0x6c
+#define ADCX140_DRE_CFG0 0x6d
+#define ADCX140_AGC_CFG0 0x70
+#define ADCX140_IN_CH_EN 0x73
+#define ADCX140_ASI_OUT_CH_EN 0x74
+#define ADCX140_PWR_CFG 0x75
+#define ADCX140_DEV_STS0 0x76
+#define ADCX140_DEV_STS1 0x77
+
+#define ADCX140_RESET BIT(0)
+
+#define ADCX140_WAKE_DEV BIT(0)
+#define ADCX140_AREG_INTERNAL BIT(7)
+
+#define ADCX140_BCLKINV_BIT BIT(2)
+#define ADCX140_FSYNCINV_BIT BIT(3)
+#define ADCX140_INV_MSK (ADCX140_BCLKINV_BIT | ADCX140_FSYNCINV_BIT)
+#define ADCX140_BCLK_FSYNC_MASTER BIT(7)
+#define ADCX140_I2S_MODE_BIT BIT(6)
+#define ADCX140_LEFT_JUST_BIT BIT(7)
+#define ADCX140_ASI_FORMAT_MSK (ADCX140_I2S_MODE_BIT | ADCX140_LEFT_JUST_BIT)
+
+#define ADCX140_16_BIT_WORD 0x0
+#define ADCX140_20_BIT_WORD BIT(4)
+#define ADCX140_24_BIT_WORD BIT(5)
+#define ADCX140_32_BIT_WORD (BIT(4) | BIT(5))
+#define ADCX140_WORD_LEN_MSK 0x30
+
+#define ADCX140_MAX_CHANNELS 8
+
+#define ADCX140_MIC_BIAS_VAL_VREF 0
+#define ADCX140_MIC_BIAS_VAL_VREF_1096 1
+#define ADCX140_MIC_BIAS_VAL_AVDD 6
+#define ADCX140_MIC_BIAS_VAL_MSK GENMASK(6, 4)
+
+#define ADCX140_MIC_BIAS_VREF_275V 0
+#define ADCX140_MIC_BIAS_VREF_25V 1
+#define ADCX140_MIC_BIAS_VREF_1375V 2
+#define ADCX140_MIC_BIAS_VREF_MSK GENMASK(1, 0)
+
+#define ADCX140_PWR_CFG_BIAS_PDZ BIT(7)
+#define ADCX140_PWR_CFG_ADC_PDZ BIT(6)
+#define ADCX140_PWR_CFG_PLL_PDZ BIT(5)
+
+#define ADCX140_TX_OFFSET_MASK GENMASK(4, 0)
+
+#endif /* _TLV320ADCX140_ */
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index b4e9a6c73f90..d087f3b20b1d 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -1098,11 +1098,9 @@ static int aic32x4_setup_regulators(struct device *dev,
return PTR_ERR(aic32x4->supply_av);
}
} else {
- if (IS_ERR(aic32x4->supply_dv) &&
- PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER)
+ if (PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER)
return -EPROBE_DEFER;
- if (IS_ERR(aic32x4->supply_av) &&
- PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER)
+ if (PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER)
return -EPROBE_DEFER;
}
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index 158e878abd6c..aefaadfba8a1 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -1883,20 +1883,16 @@ static int wcd934x_set_channel_map(struct snd_soc_dai *dai,
return -EINVAL;
}
- if (wcd->rx_chs) {
- wcd->num_rx_port = rx_num;
- for (i = 0; i < rx_num; i++) {
- wcd->rx_chs[i].ch_num = rx_slot[i];
- INIT_LIST_HEAD(&wcd->rx_chs[i].list);
- }
+ wcd->num_rx_port = rx_num;
+ for (i = 0; i < rx_num; i++) {
+ wcd->rx_chs[i].ch_num = rx_slot[i];
+ INIT_LIST_HEAD(&wcd->rx_chs[i].list);
}
- if (wcd->tx_chs) {
- wcd->num_tx_port = tx_num;
- for (i = 0; i < tx_num; i++) {
- wcd->tx_chs[i].ch_num = tx_slot[i];
- INIT_LIST_HEAD(&wcd->tx_chs[i].list);
- }
+ wcd->num_tx_port = tx_num;
+ for (i = 0; i < tx_num; i++) {
+ wcd->tx_chs[i].ch_num = tx_slot[i];
+ INIT_LIST_HEAD(&wcd->tx_chs[i].list);
}
return 0;
@@ -3392,18 +3388,15 @@ static void wcd934x_codec_hphdelay_lutbypass(struct snd_soc_component *comp,
{
u8 hph_dly_mask;
u16 hph_lut_bypass_reg = 0;
- u16 hph_comp_ctrl7 = 0;
switch (interp_idx) {
case INTERP_HPHL:
hph_dly_mask = 1;
hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHL_COMP_LUT;
- hph_comp_ctrl7 = WCD934X_CDC_COMPANDER1_CTL7;
break;
case INTERP_HPHR:
hph_dly_mask = 2;
hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHR_COMP_LUT;
- hph_comp_ctrl7 = WCD934X_CDC_COMPANDER2_CTL7;
break;
default:
return;
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
index 727d6703c905..fbcee21736e8 100644
--- a/sound/soc/codecs/wm0010.c
+++ b/sound/soc/codecs/wm0010.c
@@ -43,7 +43,7 @@ struct dfw_binrec {
u8 command;
u32 length:24;
u32 address;
- uint8_t data[0];
+ uint8_t data[];
} __packed;
struct dfw_inforec {
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 2a9b610f6d43..d3d32b501aca 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1030,8 +1030,8 @@ static int wm_coeff_write_acked_control(struct wm_coeff_ctl *ctl,
return -ETIMEDOUT;
}
-static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
- const void *buf, size_t len)
+static int wm_coeff_write_ctrl_raw(struct wm_coeff_ctl *ctl,
+ const void *buf, size_t len)
{
struct wm_adsp *dsp = ctl->dsp;
void *scratch;
@@ -1061,6 +1061,23 @@ static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
return 0;
}
+static int wm_coeff_write_ctrl(struct wm_coeff_ctl *ctl,
+ const void *buf, size_t len)
+{
+ int ret = 0;
+
+ if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
+ ret = -EPERM;
+ else if (buf != ctl->cache)
+ memcpy(ctl->cache, buf, len);
+
+ ctl->set = 1;
+ if (ctl->enabled && ctl->dsp->running)
+ ret = wm_coeff_write_ctrl_raw(ctl, buf, len);
+
+ return ret;
+}
+
static int wm_coeff_put(struct snd_kcontrol *kctl,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1071,16 +1088,7 @@ static int wm_coeff_put(struct snd_kcontrol *kctl,
int ret = 0;
mutex_lock(&ctl->dsp->pwr_lock);
-
- if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
- ret = -EPERM;
- else
- memcpy(ctl->cache, p, ctl->len);
-
- ctl->set = 1;
- if (ctl->enabled && ctl->dsp->running)
- ret = wm_coeff_write_control(ctl, p, ctl->len);
-
+ ret = wm_coeff_write_ctrl(ctl, p, ctl->len);
mutex_unlock(&ctl->dsp->pwr_lock);
return ret;
@@ -1096,15 +1104,10 @@ static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
mutex_lock(&ctl->dsp->pwr_lock);
- if (copy_from_user(ctl->cache, bytes, size)) {
+ if (copy_from_user(ctl->cache, bytes, size))
ret = -EFAULT;
- } else {
- ctl->set = 1;
- if (ctl->enabled && ctl->dsp->running)
- ret = wm_coeff_write_control(ctl, ctl->cache, size);
- else if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
- ret = -EPERM;
- }
+ else
+ ret = wm_coeff_write_ctrl(ctl, ctl->cache, size);
mutex_unlock(&ctl->dsp->pwr_lock);
@@ -1135,8 +1138,8 @@ static int wm_coeff_put_acked(struct snd_kcontrol *kctl,
return ret;
}
-static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
- void *buf, size_t len)
+static int wm_coeff_read_ctrl_raw(struct wm_coeff_ctl *ctl,
+ void *buf, size_t len)
{
struct wm_adsp *dsp = ctl->dsp;
void *scratch;
@@ -1166,29 +1169,37 @@ static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
return 0;
}
-static int wm_coeff_get(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_value *ucontrol)
+static int wm_coeff_read_ctrl(struct wm_coeff_ctl *ctl, void *buf, size_t len)
{
- struct soc_bytes_ext *bytes_ext =
- (struct soc_bytes_ext *)kctl->private_value;
- struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
- char *p = ucontrol->value.bytes.data;
int ret = 0;
- mutex_lock(&ctl->dsp->pwr_lock);
-
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
if (ctl->enabled && ctl->dsp->running)
- ret = wm_coeff_read_control(ctl, p, ctl->len);
+ return wm_coeff_read_ctrl_raw(ctl, buf, len);
else
- ret = -EPERM;
+ return -EPERM;
} else {
if (!ctl->flags && ctl->enabled && ctl->dsp->running)
- ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
+ ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
- memcpy(p, ctl->cache, ctl->len);
+ if (buf != ctl->cache)
+ memcpy(buf, ctl->cache, len);
}
+ return ret;
+}
+
+static int wm_coeff_get(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *)kctl->private_value;
+ struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
+ char *p = ucontrol->value.bytes.data;
+ int ret;
+
+ mutex_lock(&ctl->dsp->pwr_lock);
+ ret = wm_coeff_read_ctrl(ctl, p, ctl->len);
mutex_unlock(&ctl->dsp->pwr_lock);
return ret;
@@ -1204,15 +1215,7 @@ static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
mutex_lock(&ctl->dsp->pwr_lock);
- if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
- if (ctl->enabled && ctl->dsp->running)
- ret = wm_coeff_read_control(ctl, ctl->cache, size);
- else
- ret = -EPERM;
- } else {
- if (!ctl->flags && ctl->enabled && ctl->dsp->running)
- ret = wm_coeff_read_control(ctl, ctl->cache, size);
- }
+ ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, size);
if (!ret && copy_to_user(bytes, ctl->cache, size))
ret = -EFAULT;
@@ -1340,7 +1343,7 @@ static int wm_coeff_init_control_caches(struct wm_adsp *dsp)
* created so we don't need to do anything.
*/
if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) {
- ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
+ ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
if (ret < 0)
return ret;
}
@@ -1358,7 +1361,8 @@ static int wm_coeff_sync_controls(struct wm_adsp *dsp)
if (!ctl->enabled)
continue;
if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
- ret = wm_coeff_write_control(ctl, ctl->cache, ctl->len);
+ ret = wm_coeff_write_ctrl_raw(ctl, ctl->cache,
+ ctl->len);
if (ret < 0)
return ret;
}
@@ -2048,7 +2052,7 @@ int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
if (len > ctl->len)
return -EINVAL;
- ret = wm_coeff_write_control(ctl, buf, len);
+ ret = wm_coeff_write_ctrl(ctl, buf, len);
kcontrol = snd_soc_card_get_kcontrol(dsp->component->card, ctl->name);
snd_ctl_notify(dsp->component->card->snd_card,
@@ -2070,7 +2074,7 @@ int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type,
if (len > ctl->len)
return -EINVAL;
- return wm_coeff_read_control(ctl, buf, len);
+ return wm_coeff_read_ctrl(ctl, buf, len);
}
EXPORT_SYMBOL_GPL(wm_adsp_read_ctl);