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/cros_ec_codec.c25
-rw-r--r--sound/soc/codecs/cs4271.c4
-rw-r--r--sound/soc/codecs/cs47l15.c4
-rw-r--r--sound/soc/codecs/cs47l24.c6
-rw-r--r--sound/soc/codecs/cs47l35.c6
-rw-r--r--sound/soc/codecs/cs47l85.c6
-rw-r--r--sound/soc/codecs/cs47l90.c6
-rw-r--r--sound/soc/codecs/cs47l92.c4
-rw-r--r--sound/soc/codecs/hdac_hdmi.c6
-rw-r--r--sound/soc/codecs/max98357a.c37
-rw-r--r--sound/soc/codecs/mt6660.c81
-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/rt1308-sdw.c38
-rw-r--r--sound/soc/codecs/rt1308-sdw.h2
-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.c1298
-rw-r--r--sound/soc/codecs/rt5682.h100
-rw-r--r--sound/soc/codecs/tas2562.c121
-rw-r--r--sound/soc/codecs/tas2562.h12
-rw-r--r--sound/soc/codecs/tlv320adcx140.c920
-rw-r--r--sound/soc/codecs/tlv320adcx140.h131
-rw-r--r--sound/soc/codecs/wcd9335.c18
-rw-r--r--sound/soc/codecs/wcd9335.h7
-rw-r--r--sound/soc/codecs/wcd934x.c37
-rw-r--r--sound/soc/codecs/wm0010.c2
-rw-r--r--sound/soc/codecs/wm5110.c6
-rw-r--r--sound/soc/codecs/wm8974.c8
-rw-r--r--sound/soc/codecs/wm_adsp.c14
-rw-r--r--sound/soc/codecs/wsa881x.c46
36 files changed, 3378 insertions, 597 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index ea912439e446..e6a0c5d05fa5 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 || SOUNDWIRE
+
+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/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/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 e8840dc142ef..8d1869bf7f9c 100644
--- a/sound/soc/codecs/cs47l15.c
+++ b/sound/soc/codecs/cs47l15.c
@@ -1239,12 +1239,12 @@ static int cs47l15_open(struct snd_compr_stream *stream)
struct madera *madera = priv->madera;
int n_adsp;
- if (strcmp(rtd->codec_dai->name, "cs47l15-dsp-trace") == 0) {
+ if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "cs47l15-dsp-trace") == 0) {
n_adsp = 0;
} else {
dev_err(madera->dev,
"No suitable compressed stream for DAI '%s'\n",
- rtd->codec_dai->name);
+ asoc_rtd_to_codec(rtd, 0)->name);
return -EINVAL;
}
diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c
index 25bffc2968f0..6b0570f59630 100644
--- a/sound/soc/codecs/cs47l24.c
+++ b/sound/soc/codecs/cs47l24.c
@@ -1076,14 +1076,14 @@ static int cs47l24_open(struct snd_compr_stream *stream)
struct arizona *arizona = priv->core.arizona;
int n_adsp;
- if (strcmp(rtd->codec_dai->name, "cs47l24-dsp-voicectrl") == 0) {
+ if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "cs47l24-dsp-voicectrl") == 0) {
n_adsp = 2;
- } else if (strcmp(rtd->codec_dai->name, "cs47l24-dsp-trace") == 0) {
+ } else if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "cs47l24-dsp-trace") == 0) {
n_adsp = 1;
} else {
dev_err(arizona->dev,
"No suitable compressed stream for DAI '%s'\n",
- rtd->codec_dai->name);
+ asoc_rtd_to_codec(rtd, 0)->name);
return -EINVAL;
}
diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c
index 3d48a0d9ecc5..18839807c9d1 100644
--- a/sound/soc/codecs/cs47l35.c
+++ b/sound/soc/codecs/cs47l35.c
@@ -1514,14 +1514,14 @@ static int cs47l35_open(struct snd_compr_stream *stream)
struct madera *madera = priv->madera;
int n_adsp;
- if (strcmp(rtd->codec_dai->name, "cs47l35-dsp-voicectrl") == 0) {
+ if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "cs47l35-dsp-voicectrl") == 0) {
n_adsp = 2;
- } else if (strcmp(rtd->codec_dai->name, "cs47l35-dsp-trace") == 0) {
+ } else if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "cs47l35-dsp-trace") == 0) {
n_adsp = 0;
} else {
dev_err(madera->dev,
"No suitable compressed stream for DAI '%s'\n",
- rtd->codec_dai->name);
+ asoc_rtd_to_codec(rtd, 0)->name);
return -EINVAL;
}
diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c
index bef3471f482d..a575113207f0 100644
--- a/sound/soc/codecs/cs47l85.c
+++ b/sound/soc/codecs/cs47l85.c
@@ -2457,14 +2457,14 @@ static int cs47l85_open(struct snd_compr_stream *stream)
struct madera *madera = priv->madera;
int n_adsp;
- if (strcmp(rtd->codec_dai->name, "cs47l85-dsp-voicectrl") == 0) {
+ if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "cs47l85-dsp-voicectrl") == 0) {
n_adsp = 5;
- } else if (strcmp(rtd->codec_dai->name, "cs47l85-dsp-trace") == 0) {
+ } else if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "cs47l85-dsp-trace") == 0) {
n_adsp = 0;
} else {
dev_err(madera->dev,
"No suitable compressed stream for DAI '%s'\n",
- rtd->codec_dai->name);
+ asoc_rtd_to_codec(rtd, 0)->name);
return -EINVAL;
}
diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c
index 266eade82764..81a1311b14e6 100644
--- a/sound/soc/codecs/cs47l90.c
+++ b/sound/soc/codecs/cs47l90.c
@@ -2368,14 +2368,14 @@ static int cs47l90_open(struct snd_compr_stream *stream)
struct madera *madera = priv->madera;
int n_adsp;
- if (strcmp(rtd->codec_dai->name, "cs47l90-dsp-voicectrl") == 0) {
+ if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "cs47l90-dsp-voicectrl") == 0) {
n_adsp = 5;
- } else if (strcmp(rtd->codec_dai->name, "cs47l90-dsp-trace") == 0) {
+ } else if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "cs47l90-dsp-trace") == 0) {
n_adsp = 0;
} else {
dev_err(madera->dev,
"No suitable compressed stream for DAI '%s'\n",
- rtd->codec_dai->name);
+ asoc_rtd_to_codec(rtd, 0)->name);
return -EINVAL;
}
diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c
index 942040fd354f..15fc213d178d 100644
--- a/sound/soc/codecs/cs47l92.c
+++ b/sound/soc/codecs/cs47l92.c
@@ -1840,12 +1840,12 @@ static int cs47l92_open(struct snd_compr_stream *stream)
struct madera *madera = priv->madera;
int n_adsp;
- if (strcmp(rtd->codec_dai->name, "cs47l92-dsp-trace") == 0) {
+ if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "cs47l92-dsp-trace") == 0) {
n_adsp = 0;
} else {
dev_err(madera->dev,
"No suitable compressed stream for DAI '%s'\n",
- rtd->codec_dai->name);
+ asoc_rtd_to_codec(rtd, 0)->name);
return -EINVAL;
}
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index e6558475e006..fba9b749839d 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -1998,11 +1998,11 @@ static struct hdac_hdmi_drv_data intel_drv_data = {
static int hdac_hdmi_dev_probe(struct hdac_device *hdev)
{
- struct hdac_hdmi_priv *hdmi_priv = NULL;
+ struct hdac_hdmi_priv *hdmi_priv;
struct snd_soc_dai_driver *hdmi_dais = NULL;
- struct hdac_ext_link *hlink = NULL;
+ struct hdac_ext_link *hlink;
int num_dais = 0;
- int ret = 0;
+ int ret;
struct hdac_driver *hdrv = drv_to_hdac_driver(hdev->dev.driver);
const struct hda_device_id *hdac_id = hdac_get_device_id(hdev, hdrv);
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
index 16313b973eaa..a8bd793a7867 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)
@@ -135,6 +133,7 @@ MODULE_DEVICE_TABLE(of, max98357a_device_id);
#ifdef CONFIG_ACPI
static const struct acpi_device_id max98357a_acpi_match[] = {
{ "MX98357A", 0 },
+ { "MX98360A", 0 },
{},
};
MODULE_DEVICE_TABLE(acpi, max98357a_acpi_match);
diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c
index a36c416caad4..d1797003c83d 100644
--- a/sound/soc/codecs/mt6660.c
+++ b/sound/soc/codecs/mt6660.c
@@ -1,15 +1,13 @@
-// SPDX-License-Identifier: GPL-2.0 //
+// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 MediaTek Inc.
#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/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c
index d930f60cb797..a5a7e46de246 100644
--- a/sound/soc/codecs/rt1308-sdw.c
+++ b/sound/soc/codecs/rt1308-sdw.c
@@ -507,6 +507,28 @@ static void rt1308_sdw_shutdown(struct snd_pcm_substream *substream,
kfree(stream);
}
+static int rt1308_sdw_set_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask,
+ unsigned int rx_mask,
+ int slots, int slot_width)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rt1308_sdw_priv *rt1308 =
+ snd_soc_component_get_drvdata(component);
+
+ if (tx_mask)
+ return -EINVAL;
+
+ if (slots > 2)
+ return -EINVAL;
+
+ rt1308->rx_mask = rx_mask;
+ rt1308->slots = slots;
+ /* slot_width is not used since it's irrelevant for SoundWire */
+
+ return 0;
+}
+
static int rt1308_sdw_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
@@ -517,7 +539,7 @@ static int rt1308_sdw_hw_params(struct snd_pcm_substream *substream,
struct sdw_port_config port_config;
enum sdw_data_direction direction;
struct sdw_stream_data *stream;
- int retval, port, num_channels;
+ int retval, port, num_channels, ch_mask;
dev_dbg(dai->dev, "%s %s", __func__, dai->name);
stream = snd_soc_dai_get_dma_data(dai, substream);
@@ -537,13 +559,20 @@ static int rt1308_sdw_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
+ if (rt1308->slots) {
+ num_channels = rt1308->slots;
+ ch_mask = rt1308->rx_mask;
+ } else {
+ num_channels = params_channels(params);
+ ch_mask = (1 << num_channels) - 1;
+ }
+
stream_config.frame_rate = params_rate(params);
- stream_config.ch_count = params_channels(params);
+ stream_config.ch_count = num_channels;
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.ch_mask = ch_mask;
port_config.num = port;
retval = sdw_stream_add_slave(rt1308->sdw_slave, &stream_config,
@@ -597,6 +626,7 @@ static const struct snd_soc_dai_ops rt1308_aif_dai_ops = {
.hw_free = rt1308_sdw_pcm_hw_free,
.set_sdw_stream = rt1308_set_sdw_stream,
.shutdown = rt1308_sdw_shutdown,
+ .set_tdm_slot = rt1308_sdw_set_tdm_slot,
};
#define RT1308_STEREO_RATES SNDRV_PCM_RATE_48000
diff --git a/sound/soc/codecs/rt1308-sdw.h b/sound/soc/codecs/rt1308-sdw.h
index c9341e70d6cf..c5ce75666dcc 100644
--- a/sound/soc/codecs/rt1308-sdw.h
+++ b/sound/soc/codecs/rt1308-sdw.h
@@ -160,6 +160,8 @@ struct rt1308_sdw_priv {
struct sdw_bus_params params;
bool hw_init;
bool first_hw_init;
+ int rx_mask;
+ int slots;
};
struct sdw_stream_data {
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..a2d1d3ae1e31
--- /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 __maybe_unused 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 __maybe_unused 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..c9268a230daa 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);
}
@@ -1146,7 +1166,7 @@ static void rt5682_jack_detect_handler(struct work_struct *work)
static const struct snd_kcontrol_new rt5682_snd_controls[] = {
/* DAC Digital Volume */
SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5682_DAC1_DIG_VOL,
- RT5682_L_VOL_SFT + 1, RT5682_R_VOL_SFT + 1, 86, 0, dac_vol_tlv),
+ RT5682_L_VOL_SFT + 1, RT5682_R_VOL_SFT + 1, 87, 0, dac_vol_tlv),
/* IN Boost Volume */
SOC_SINGLE_TLV("CBJ Boost Volume", RT5682_CBJ_BST_CTRL,
@@ -1177,11 +1197,11 @@ static int rt5682_div_sel(struct rt5682_priv *rt5682,
}
for (i = 0; i < size - 1; i++) {
- pr_info("div[%d]=%d\n", i, div[i]);
+ dev_dbg(rt5682->component->dev, "div[%d]=%d\n", i, div[i]);
if (target * div[i] == rt5682->sysclk)
return i;
if (target * div[i + 1] > rt5682->sysclk) {
- pr_err("can't find div for sysclk %d\n",
+ dev_dbg(rt5682->component->dev, "can't find div for sysclk %d\n",
rt5682->sysclk);
return i;
}
@@ -1211,10 +1231,13 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
- int idx = -EINVAL;
+ int idx = -EINVAL, dmic_clk_rate = 3072000;
static const int div[] = {2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128};
- idx = rt5682_div_sel(rt5682, 1500000, div, ARRAY_SIZE(div));
+ if (rt5682->pdata.dmic_clk_rate)
+ dmic_clk_rate = rt5682->pdata.dmic_clk_rate;
+
+ idx = rt5682_div_sel(rt5682, dmic_clk_rate, div, ARRAY_SIZE(div));
snd_soc_component_update_bits(component, RT5682_DMIC_CTRL_1,
RT5682_DMIC_CLK_MASK, idx << RT5682_DMIC_CLK_SFT);
@@ -1232,6 +1255,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 +1304,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)
{
@@ -1503,10 +1544,18 @@ static int rt5682_hp_event(struct snd_soc_dapm_widget *w,
static int set_dmic_power(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ unsigned int delay = 50;
+
+ if (rt5682->pdata.dmic_delay)
+ delay = rt5682->pdata.dmic_delay;
+
switch (event) {
case SND_SOC_DAPM_POST_PMU:
/*Add delay to avoid pop noise*/
- msleep(150);
+ msleep(delay);
break;
default:
@@ -1516,7 +1565,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 +1641,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 +1738,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 +1756,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 +1837,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 +1925,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 +1935,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 +1946,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 +2116,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 +2292,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;
- 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);
+ return 0;
+}
- rt5682->pll_in = freq_in;
- rt5682->pll_out = freq_out;
- rt5682->pll_src = source;
+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->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 +2461,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 +2500,392 @@ 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;
+ 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;
+ }
+ } else {
+#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;
+ } else {
+ /* 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
+ }
+
return 0;
}
@@ -2332,7 +2893,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 +2939,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 +3168,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 = {
@@ -2461,10 +3241,21 @@ static int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev)
&rt5682->pdata.jd_src);
device_property_read_u32(dev, "realtek,btndet-delay",
&rt5682->pdata.btndet_delay);
+ device_property_read_u32(dev, "realtek,dmic-clk-rate-hz",
+ &rt5682->pdata.dmic_clk_rate);
+ device_property_read_u32(dev, "realtek,dmic-delay-ms",
+ &rt5682->pdata.dmic_delay);
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 +3265,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 +3311,221 @@ 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);
+ regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1,
+ RT5682_PM_HP_MASK, RT5682_PM_HP_HV);
+
+ /* 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 +3592,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);
@@ -2651,6 +3657,8 @@ static int rt5682_i2c_probe(struct i2c_client *i2c,
RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ);
regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1,
RT5682_PM_HP_MASK, RT5682_PM_HP_HV);
+ regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
+ RT5682_FIFO_CLK_DIV_MASK, RT5682_FIFO_CLK_DIV_2);
INIT_DELAYED_WORK(&rt5682->jack_detect_work,
rt5682_jack_detect_handler);
@@ -2676,7 +3684,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..0baeece84ec4 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
@@ -651,6 +657,8 @@
#define RT5682_DMIC_1_EN_SFT 15
#define RT5682_DMIC_1_DIS (0x0 << 15)
#define RT5682_DMIC_1_EN (0x1 << 15)
+#define RT5682_FIFO_CLK_DIV_MASK (0x7 << 12)
+#define RT5682_FIFO_CLK_DIV_2 (0x1 << 12)
#define RT5682_DMIC_1_DP_MASK (0x3 << 4)
#define RT5682_DMIC_1_DP_SFT 4
#define RT5682_DMIC_1_DP_GPIO2 (0x0 << 4)
@@ -738,7 +746,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 +828,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 +849,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 +1063,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 +1127,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 +1351,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 +1379,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..7fae88655a0f 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 =
@@ -409,14 +493,24 @@ static const struct snd_kcontrol_new vsense_switch =
1, 1);
static const struct snd_kcontrol_new tas2562_snd_controls[] = {
- SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 0, 0x1c, 0,
+ SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 1, 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..38897568ee96
--- /dev/null
+++ b/sound/soc/codecs/tlv320adcx140.c
@@ -0,0 +1,920 @@
+// 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_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_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/wcd9335.c b/sound/soc/codecs/wcd9335.c
index f11ffa28683b..700cc1212770 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -4926,11 +4926,11 @@ static const struct regmap_range_cfg wcd9335_ranges[] = {
.name = "WCD9335",
.range_min = 0x0,
.range_max = WCD9335_MAX_REGISTER,
- .selector_reg = WCD9335_REG(0x0, 0),
+ .selector_reg = WCD9335_SEL_REGISTER,
.selector_mask = 0xff,
.selector_shift = 0,
- .window_start = 0x0,
- .window_len = 0x1000,
+ .window_start = 0x800,
+ .window_len = 0x100,
},
};
@@ -4968,12 +4968,12 @@ static const struct regmap_range_cfg wcd9335_ifc_ranges[] = {
{
.name = "WCD9335-IFC-DEV",
.range_min = 0x0,
- .range_max = WCD9335_REG(0, 0x7ff),
- .selector_reg = WCD9335_REG(0, 0x0),
- .selector_mask = 0xff,
+ .range_max = WCD9335_MAX_REGISTER,
+ .selector_reg = WCD9335_SEL_REGISTER,
+ .selector_mask = 0xfff,
.selector_shift = 0,
- .window_start = 0x0,
- .window_len = 0x1000,
+ .window_start = 0x800,
+ .window_len = 0x400,
},
};
@@ -4981,7 +4981,7 @@ static struct regmap_config wcd9335_ifc_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.can_multi_write = true,
- .max_register = WCD9335_REG(0, 0x7FF),
+ .max_register = WCD9335_MAX_REGISTER,
.ranges = wcd9335_ifc_ranges,
.num_ranges = ARRAY_SIZE(wcd9335_ifc_ranges),
};
diff --git a/sound/soc/codecs/wcd9335.h b/sound/soc/codecs/wcd9335.h
index 4d9be2496c30..72060824c743 100644
--- a/sound/soc/codecs/wcd9335.h
+++ b/sound/soc/codecs/wcd9335.h
@@ -8,9 +8,9 @@
* in slimbus mode the reg base starts from 0x800
* in i2s/i2c mode the reg base is 0x0
*/
-#define WCD9335_REG(pg, r) ((pg << 12) | (r) | 0x800)
+#define WCD9335_REG(pg, r) ((pg << 8) | (r))
#define WCD9335_REG_OFFSET(r) (r & 0xFF)
-#define WCD9335_PAGE_OFFSET(r) ((r >> 12) & 0xFF)
+#define WCD9335_PAGE_OFFSET(r) ((r >> 8) & 0xFF)
/* Page-0 Registers */
#define WCD9335_PAGE0_PAGE_REGISTER WCD9335_REG(0x00, 0x000)
@@ -600,7 +600,8 @@
#define WCD9335_CDC_CLK_RST_CTRL_FS_CNT_ENABLE BIT(0)
#define WCD9335_CDC_CLK_RST_CTRL_FS_CNT_DISABLE 0
#define WCD9335_CDC_TOP_TOP_CFG1 WCD9335_REG(0x0d, 0x082)
-#define WCD9335_MAX_REGISTER WCD9335_REG(0x80, 0x0FF)
+#define WCD9335_MAX_REGISTER 0xffff
+#define WCD9335_SEL_REGISTER 0x800
/* SLIMBUS Slave Registers */
#define WCD9335_SLIM_PGD_PORT_INT_EN0 WCD9335_REG(0, 0x30)
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index 158e878abd6c..5269857e2746 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -3,7 +3,6 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
-#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/wcd934x/registers.h>
@@ -11,10 +10,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_clk.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <linux/of.h>
-#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -1202,11 +1198,6 @@ static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd, int sido_src)
regmap_update_bits(wcd->regmap, WCD934X_ANA_RCO,
WCD934X_ANA_RCO_BG_EN_MASK, 0);
usleep_range(100, 110);
- } else if (sido_src == SIDO_SOURCE_RCO_BG) {
- regmap_update_bits(wcd->regmap, WCD934X_ANA_RCO,
- WCD934X_ANA_RCO_BG_EN_MASK,
- WCD934X_ANA_RCO_BG_ENABLE);
- usleep_range(100, 110);
regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL,
WCD934X_ANA_BUCK_PRE_EN1_MASK,
WCD934X_ANA_BUCK_PRE_EN1_ENABLE);
@@ -1219,6 +1210,11 @@ static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd, int sido_src)
WCD934X_ANA_BUCK_HI_ACCU_EN_MASK,
WCD934X_ANA_BUCK_HI_ACCU_ENABLE);
usleep_range(100, 110);
+ } else if (sido_src == SIDO_SOURCE_RCO_BG) {
+ regmap_update_bits(wcd->regmap, WCD934X_ANA_RCO,
+ WCD934X_ANA_RCO_BG_EN_MASK,
+ WCD934X_ANA_RCO_BG_ENABLE);
+ usleep_range(100, 110);
}
wcd->sido_input_src = sido_src;
@@ -1883,20 +1879,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 +3384,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/wm5110.c b/sound/soc/codecs/wm5110.c
index 9dc215b5c504..499e87d1dfcc 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -2245,14 +2245,14 @@ static int wm5110_open(struct snd_compr_stream *stream)
struct arizona *arizona = priv->core.arizona;
int n_adsp;
- if (strcmp(rtd->codec_dai->name, "wm5110-dsp-voicectrl") == 0) {
+ if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "wm5110-dsp-voicectrl") == 0) {
n_adsp = 2;
- } else if (strcmp(rtd->codec_dai->name, "wm5110-dsp-trace") == 0) {
+ } else if (strcmp(asoc_rtd_to_codec(rtd, 0)->name, "wm5110-dsp-trace") == 0) {
n_adsp = 0;
} else {
dev_err(arizona->dev,
"No suitable compressed stream for DAI '%s'\n",
- rtd->codec_dai->name);
+ asoc_rtd_to_codec(rtd, 0)->name);
return -EINVAL;
}
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index dc4fe4f5239d..06ba36595ddd 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -196,14 +196,6 @@ SOC_DAPM_SINGLE("MicN Switch", WM8974_INPUT, 1, 1, 0),
SOC_DAPM_SINGLE("MicP Switch", WM8974_INPUT, 0, 1, 0),
};
-/* AUX Input boost vol */
-static const struct snd_kcontrol_new wm8974_aux_boost_controls =
-SOC_DAPM_SINGLE("Aux Volume", WM8974_ADCBOOST, 0, 7, 0);
-
-/* Mic Input boost vol */
-static const struct snd_kcontrol_new wm8974_mic_boost_controls =
-SOC_DAPM_SINGLE("Mic Volume", WM8974_ADCBOOST, 4, 7, 0);
-
static const struct snd_soc_dapm_widget wm8974_dapm_widgets[] = {
SND_SOC_DAPM_MIXER("Speaker Mixer", WM8974_POWER3, 2, 0,
&wm8974_speaker_mixer_controls[0],
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index d3d32b501aca..1ef69409ccd1 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1436,12 +1436,12 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
subname = NULL; /* don't append subname */
break;
case 2:
- ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
+ ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
"%s%c %.12s %x", dsp->name, *region_name,
wm_adsp_fw_text[dsp->fw], alg_region->alg);
break;
default:
- ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
+ ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
"%s %.12s %x", dsp->name,
wm_adsp_fw_text[dsp->fw], alg_region->alg);
break;
@@ -3467,22 +3467,22 @@ int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
if (wm_adsp_fw[dsp->fw].num_caps == 0) {
adsp_err(dsp, "%s: Firmware does not support compressed API\n",
- rtd->codec_dai->name);
+ asoc_rtd_to_codec(rtd, 0)->name);
ret = -ENXIO;
goto out;
}
if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) {
adsp_err(dsp, "%s: Firmware does not support stream direction\n",
- rtd->codec_dai->name);
+ asoc_rtd_to_codec(rtd, 0)->name);
ret = -EINVAL;
goto out;
}
list_for_each_entry(tmp, &dsp->compr_list, list) {
- if (!strcmp(tmp->name, rtd->codec_dai->name)) {
+ if (!strcmp(tmp->name, asoc_rtd_to_codec(rtd, 0)->name)) {
adsp_err(dsp, "%s: Only a single stream supported per dai\n",
- rtd->codec_dai->name);
+ asoc_rtd_to_codec(rtd, 0)->name);
ret = -EBUSY;
goto out;
}
@@ -3496,7 +3496,7 @@ int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
compr->dsp = dsp;
compr->stream = stream;
- compr->name = rtd->codec_dai->name;
+ compr->name = asoc_rtd_to_codec(rtd, 0)->name;
list_add_tail(&compr->list, &dsp->compr_list);
diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c
index b59f1d0e7f84..f2d6f2f81f14 100644
--- a/sound/soc/codecs/wsa881x.c
+++ b/sound/soc/codecs/wsa881x.c
@@ -676,7 +676,6 @@ struct wsa881x_priv {
int active_ports;
bool port_prepared[WSA881X_MAX_SWR_PORTS];
bool port_enable[WSA881X_MAX_SWR_PORTS];
- bool stream_prepared;
};
static void wsa881x_init(struct wsa881x_priv *wsa881x)
@@ -954,41 +953,6 @@ static const struct snd_soc_dapm_widget wsa881x_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("SPKR"),
};
-static int wsa881x_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct wsa881x_priv *wsa881x = dev_get_drvdata(dai->dev);
- int ret;
-
- if (wsa881x->stream_prepared) {
- sdw_disable_stream(wsa881x->sruntime);
- sdw_deprepare_stream(wsa881x->sruntime);
- wsa881x->stream_prepared = false;
- }
-
-
- ret = sdw_prepare_stream(wsa881x->sruntime);
- if (ret)
- return ret;
-
- /**
- * NOTE: there is a strict hw requirement about the ordering of port
- * enables and actual PA enable. PA enable should only happen after
- * soundwire ports are enabled if not DC on the line is accumulated
- * resulting in Click/Pop Noise
- * PA enable/mute are handled as part of DAPM and digital mute.
- */
-
- ret = sdw_enable_stream(wsa881x->sruntime);
- if (ret) {
- sdw_deprepare_stream(wsa881x->sruntime);
- return ret;
- }
- wsa881x->stream_prepared = true;
-
- return ret;
-}
-
static int wsa881x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -1016,12 +980,7 @@ static int wsa881x_hw_free(struct snd_pcm_substream *substream,
{
struct wsa881x_priv *wsa881x = dev_get_drvdata(dai->dev);
- if (wsa881x->stream_prepared) {
- sdw_disable_stream(wsa881x->sruntime);
- sdw_deprepare_stream(wsa881x->sruntime);
- sdw_stream_remove_slave(wsa881x->slave, wsa881x->sruntime);
- wsa881x->stream_prepared = false;
- }
+ sdw_stream_remove_slave(wsa881x->slave, wsa881x->sruntime);
return 0;
}
@@ -1052,7 +1011,6 @@ static int wsa881x_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
static struct snd_soc_dai_ops wsa881x_dai_ops = {
.hw_params = wsa881x_hw_params,
- .prepare = wsa881x_prepare,
.hw_free = wsa881x_hw_free,
.mute_stream = wsa881x_digital_mute,
.set_sdw_stream = wsa881x_set_sdw_stream,
@@ -1150,7 +1108,7 @@ static int wsa881x_probe(struct sdw_slave *pdev,
wsa881x->sconfig.type = SDW_STREAM_PDM;
pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0);
pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop;
- gpiod_set_value(wsa881x->sd_n, 1);
+ gpiod_direction_output(wsa881x->sd_n, 1);
wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config);
if (IS_ERR(wsa881x->regmap)) {