summaryrefslogtreecommitdiff
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/88pm860x-codec.c32
-rw-r--r--sound/soc/codecs/Kconfig25
-rw-r--r--sound/soc/codecs/Makefile10
-rw-r--r--sound/soc/codecs/ab8500-codec.c7
-rw-r--r--sound/soc/codecs/ad1980.c36
-rw-r--r--sound/soc/codecs/adau1373.c22
-rw-r--r--sound/soc/codecs/adau1701.c1
-rw-r--r--sound/soc/codecs/adau1761-i2c.c1
-rw-r--r--sound/soc/codecs/adau1781-i2c.c1
-rw-r--r--sound/soc/codecs/adau1977-i2c.c1
-rw-r--r--sound/soc/codecs/adav803.c1
-rw-r--r--sound/soc/codecs/adav80x.c2
-rw-r--r--sound/soc/codecs/ak4535.c1
-rw-r--r--sound/soc/codecs/ak4641.c1
-rw-r--r--sound/soc/codecs/ak4642.c34
-rw-r--r--sound/soc/codecs/ak4671.c1
-rw-r--r--sound/soc/codecs/alc5623.c8
-rw-r--r--sound/soc/codecs/alc5632.c10
-rw-r--r--sound/soc/codecs/arizona.c80
-rw-r--r--sound/soc/codecs/arizona.h19
-rw-r--r--sound/soc/codecs/cs35l32.c60
-rw-r--r--sound/soc/codecs/cs35l32.h2
-rw-r--r--sound/soc/codecs/cs4265.c19
-rw-r--r--sound/soc/codecs/cs4270.c1
-rw-r--r--sound/soc/codecs/cs4271-i2c.c1
-rw-r--r--sound/soc/codecs/cs42l51-i2c.c1
-rw-r--r--sound/soc/codecs/cs42l52.c65
-rw-r--r--sound/soc/codecs/cs42l56.c71
-rw-r--r--sound/soc/codecs/cs42l73.c115
-rw-r--r--sound/soc/codecs/cs42xx8-i2c.c4
-rw-r--r--sound/soc/codecs/cs42xx8.c19
-rw-r--r--sound/soc/codecs/cs42xx8.h1
-rw-r--r--sound/soc/codecs/cs4349.c392
-rw-r--r--sound/soc/codecs/cs4349.h136
-rw-r--r--sound/soc/codecs/da7210.c29
-rw-r--r--sound/soc/codecs/da7213.c18
-rw-r--r--sound/soc/codecs/da732x.c15
-rw-r--r--sound/soc/codecs/da9055.c19
-rw-r--r--sound/soc/codecs/gtm601.c95
-rw-r--r--sound/soc/codecs/ics43432.c76
-rw-r--r--sound/soc/codecs/isabelle.c11
-rw-r--r--sound/soc/codecs/jz4740.c7
-rw-r--r--sound/soc/codecs/lm4857.c1
-rw-r--r--sound/soc/codecs/lm49453.c19
-rw-r--r--sound/soc/codecs/max9768.c71
-rw-r--r--sound/soc/codecs/max98088.c329
-rw-r--r--sound/soc/codecs/max98088.h2
-rw-r--r--sound/soc/codecs/max98090.c171
-rw-r--r--sound/soc/codecs/max98090.h1
-rw-r--r--sound/soc/codecs/max98095.c354
-rw-r--r--sound/soc/codecs/max98357a.c25
-rw-r--r--sound/soc/codecs/max9850.c8
-rw-r--r--sound/soc/codecs/max9877.c33
-rw-r--r--sound/soc/codecs/max98925.c6
-rw-r--r--sound/soc/codecs/mc13783.c6
-rw-r--r--sound/soc/codecs/ml26124.c3
-rw-r--r--sound/soc/codecs/pcm1681.c14
-rw-r--r--sound/soc/codecs/pcm512x-i2c.c1
-rw-r--r--sound/soc/codecs/pcm512x.c4
-rw-r--r--sound/soc/codecs/rl6231.c104
-rw-r--r--sound/soc/codecs/rl6231.h1
-rw-r--r--sound/soc/codecs/rt286.c11
-rw-r--r--sound/soc/codecs/rt298.c1271
-rw-r--r--sound/soc/codecs/rt298.h206
-rw-r--r--sound/soc/codecs/rt5631.c8
-rw-r--r--sound/soc/codecs/rt5640.c19
-rw-r--r--sound/soc/codecs/rt5645.c456
-rw-r--r--sound/soc/codecs/rt5645.h43
-rw-r--r--sound/soc/codecs/rt5651.c19
-rw-r--r--sound/soc/codecs/rt5670.c21
-rw-r--r--sound/soc/codecs/rt5677-spi.c233
-rw-r--r--sound/soc/codecs/rt5677-spi.h8
-rw-r--r--sound/soc/codecs/rt5677.c159
-rw-r--r--sound/soc/codecs/rt5677.h5
-rw-r--r--sound/soc/codecs/sgtl5000.c10
-rw-r--r--sound/soc/codecs/si476x.c2
-rw-r--r--sound/soc/codecs/sirf-audio-codec.c4
-rw-r--r--sound/soc/codecs/ssm2518.c10
-rw-r--r--sound/soc/codecs/ssm2602-i2c.c1
-rw-r--r--sound/soc/codecs/ssm2602.c7
-rw-r--r--sound/soc/codecs/ssm4567.c34
-rw-r--r--sound/soc/codecs/sta32x.c1
-rw-r--r--sound/soc/codecs/sta350.c1
-rw-r--r--sound/soc/codecs/sta529.c4
-rw-r--r--sound/soc/codecs/stac9766.c57
-rw-r--r--sound/soc/codecs/sti-sas.c628
-rw-r--r--sound/soc/codecs/tas2552.c20
-rw-r--r--sound/soc/codecs/tas2552.h2
-rw-r--r--sound/soc/codecs/tas5086.c11
-rw-r--r--sound/soc/codecs/tas571x.c2
-rw-r--r--sound/soc/codecs/tfa9879.c3
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c3
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c1
-rw-r--r--sound/soc/codecs/tlv320aic3x.c22
-rw-r--r--sound/soc/codecs/tlv320dac33.c1
-rw-r--r--sound/soc/codecs/tpa6130a2.c15
-rw-r--r--sound/soc/codecs/ts3a227e.c48
-rw-r--r--sound/soc/codecs/twl4030.c7
-rw-r--r--sound/soc/codecs/uda134x.c180
-rw-r--r--sound/soc/codecs/uda134x.h2
-rw-r--r--sound/soc/codecs/uda1380.c15
-rw-r--r--sound/soc/codecs/wm0010.c26
-rw-r--r--sound/soc/codecs/wm1250-ev1.c1
-rw-r--r--sound/soc/codecs/wm2000.c1
-rw-r--r--sound/soc/codecs/wm2200.c9
-rw-r--r--sound/soc/codecs/wm5100.c13
-rw-r--r--sound/soc/codecs/wm5102.c27
-rw-r--r--sound/soc/codecs/wm5110.c315
-rw-r--r--sound/soc/codecs/wm8350.c7
-rw-r--r--sound/soc/codecs/wm8400.c5
-rw-r--r--sound/soc/codecs/wm8510.c2
-rw-r--r--sound/soc/codecs/wm8523.c2
-rw-r--r--sound/soc/codecs/wm8580.c2
-rw-r--r--sound/soc/codecs/wm8711.c1
-rw-r--r--sound/soc/codecs/wm8728.c1
-rw-r--r--sound/soc/codecs/wm8731.c88
-rw-r--r--sound/soc/codecs/wm8737.c8
-rw-r--r--sound/soc/codecs/wm8741.c63
-rw-r--r--sound/soc/codecs/wm8750.c1
-rw-r--r--sound/soc/codecs/wm8753.c14
-rw-r--r--sound/soc/codecs/wm8776.c5
-rw-r--r--sound/soc/codecs/wm8804-i2c.c1
-rw-r--r--sound/soc/codecs/wm8804.c2
-rw-r--r--sound/soc/codecs/wm8900.c1
-rw-r--r--sound/soc/codecs/wm8903.c1
-rw-r--r--sound/soc/codecs/wm8904.c5
-rw-r--r--sound/soc/codecs/wm8940.c1
-rw-r--r--sound/soc/codecs/wm8955.c1
-rw-r--r--sound/soc/codecs/wm8960.c247
-rw-r--r--sound/soc/codecs/wm8960.h1
-rw-r--r--sound/soc/codecs/wm8961.c8
-rw-r--r--sound/soc/codecs/wm8962.c31
-rw-r--r--sound/soc/codecs/wm8971.c1
-rw-r--r--sound/soc/codecs/wm8974.c1
-rw-r--r--sound/soc/codecs/wm8978.c1
-rw-r--r--sound/soc/codecs/wm8983.c81
-rw-r--r--sound/soc/codecs/wm8985.c1
-rw-r--r--sound/soc/codecs/wm8988.c1
-rw-r--r--sound/soc/codecs/wm8990.c6
-rw-r--r--sound/soc/codecs/wm8991.c53
-rw-r--r--sound/soc/codecs/wm8993.c12
-rw-r--r--sound/soc/codecs/wm8994.c18
-rw-r--r--sound/soc/codecs/wm8995.c1
-rw-r--r--sound/soc/codecs/wm8996.c11
-rw-r--r--sound/soc/codecs/wm8997.c20
-rw-r--r--sound/soc/codecs/wm9081.c10
-rw-r--r--sound/soc/codecs/wm9090.c22
-rw-r--r--sound/soc/codecs/wm9705.c40
-rw-r--r--sound/soc/codecs/wm9712.c45
-rw-r--r--sound/soc/codecs/wm9713.c55
-rw-r--r--sound/soc/codecs/wm9713.h2
-rw-r--r--sound/soc/codecs/wm_hubs.c7
152 files changed, 4862 insertions, 2569 deletions
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 38b3dad9d..e8bed6b0c 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -156,33 +156,29 @@ static const DECLARE_TLV_DB_SCALE(dpga_tlv, -9450, 150, 1);
static const DECLARE_TLV_DB_SCALE(adc_tlv, -900, 300, 0);
/* {-23, -17, -13.5, -11, -9, -6, -3, 0}dB */
-static const unsigned int mic_tlv[] = {
- TLV_DB_RANGE_HEAD(5),
+static const DECLARE_TLV_DB_RANGE(mic_tlv,
0, 0, TLV_DB_SCALE_ITEM(-2300, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(-1700, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(-1350, 0, 0),
3, 3, TLV_DB_SCALE_ITEM(-1100, 0, 0),
- 4, 7, TLV_DB_SCALE_ITEM(-900, 300, 0),
-};
+ 4, 7, TLV_DB_SCALE_ITEM(-900, 300, 0)
+);
/* {0, 0, 0, -6, 0, 6, 12, 18}dB */
-static const unsigned int aux_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(aux_tlv,
0, 2, TLV_DB_SCALE_ITEM(0, 0, 0),
- 3, 7, TLV_DB_SCALE_ITEM(-600, 600, 0),
-};
+ 3, 7, TLV_DB_SCALE_ITEM(-600, 600, 0)
+);
/* {-16, -13, -10, -7, -5.2, -3,3, -2.2, 0}dB, mute instead of -16dB */
-static const unsigned int out_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+static const DECLARE_TLV_DB_RANGE(out_tlv,
0, 3, TLV_DB_SCALE_ITEM(-1600, 300, 1),
4, 4, TLV_DB_SCALE_ITEM(-520, 0, 0),
5, 5, TLV_DB_SCALE_ITEM(-330, 0, 0),
- 6, 7, TLV_DB_SCALE_ITEM(-220, 220, 0),
-};
+ 6, 7, TLV_DB_SCALE_ITEM(-220, 220, 0)
+);
-static const unsigned int st_tlv[] = {
- TLV_DB_RANGE_HEAD(8),
+static const DECLARE_TLV_DB_RANGE(st_tlv,
0, 1, TLV_DB_SCALE_ITEM(-12041, 602, 0),
2, 3, TLV_DB_SCALE_ITEM(-11087, 250, 0),
4, 5, TLV_DB_SCALE_ITEM(-10643, 158, 0),
@@ -190,8 +186,8 @@ static const unsigned int st_tlv[] = {
8, 9, TLV_DB_SCALE_ITEM(-10133, 92, 0),
10, 13, TLV_DB_SCALE_ITEM(-9958, 70, 0),
14, 17, TLV_DB_SCALE_ITEM(-9689, 53, 0),
- 18, 271, TLV_DB_SCALE_ITEM(-9484, 37, 0),
-};
+ 18, 271, TLV_DB_SCALE_ITEM(-9484, 37, 0)
+);
/* Sidetone Gain = M * 2^(-5-N) */
struct st_gain {
@@ -1028,10 +1024,8 @@ static int pm860x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
if (dir == PM860X_CLK_DIR_OUT)
pm860x->dir = PM860X_CLK_DIR_OUT;
- else {
- pm860x->dir = PM860X_CLK_DIR_IN;
+ else /* Slave mode is not supported */
return -EINVAL;
- }
return 0;
}
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index efaafce8b..0c9733ecd 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -53,6 +53,7 @@ config SND_SOC_ALL_CODECS
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_CS4349 if I2C
select SND_SOC_CX20442 if TTY
select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI
select SND_SOC_DA7213 if I2C
@@ -62,6 +63,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_BT_SCO
select SND_SOC_ES8328_SPI if SPI_MASTER
select SND_SOC_ES8328_I2C if I2C
+ select SND_SOC_GTM601
+ select SND_SOC_ICS43432
select SND_SOC_ISABELLE if I2C
select SND_SOC_JZ4740_CODEC
select SND_SOC_LM4857 if I2C
@@ -83,6 +86,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_PCM512x_I2C if I2C
select SND_SOC_PCM512x_SPI if SPI_MASTER
select SND_SOC_RT286 if I2C
+ select SND_SOC_RT298 if I2C
select SND_SOC_RT5631 if I2C
select SND_SOC_RT5640 if I2C
select SND_SOC_RT5645 if I2C
@@ -102,6 +106,7 @@ config SND_SOC_ALL_CODECS
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_TAS5086 if I2C
select SND_SOC_TAS571X if I2C
@@ -403,6 +408,11 @@ config SND_SOC_CS42XX8_I2C
select SND_SOC_CS42XX8
select REGMAP_I2C
+# Cirrus Logic CS4349 HiFi DAC
+config SND_SOC_CS4349
+ tristate "Cirrus Logic CS4349 CODEC"
+ depends on I2C
+
config SND_SOC_CX20442
tristate
depends on TTY
@@ -446,6 +456,12 @@ config SND_SOC_ES8328_SPI
tristate
select SND_SOC_ES8328
+config SND_SOC_GTM601
+ tristate 'GTM601 UMTS modem audio codec'
+
+config SND_SOC_ICS43432
+ tristate
+
config SND_SOC_ISABELLE
tristate
@@ -512,12 +528,18 @@ config SND_SOC_RL6231
config SND_SOC_RL6347A
tristate
default y if SND_SOC_RT286=y
+ default y if SND_SOC_RT298=y
default m if SND_SOC_RT286=m
+ default m if SND_SOC_RT298=m
config SND_SOC_RT286
tristate
depends on I2C
+config SND_SOC_RT298
+ tristate
+ depends on I2C
+
config SND_SOC_RT5631
tristate "Realtek ALC5631/RT5631 CODEC"
depends on I2C
@@ -610,6 +632,9 @@ config SND_SOC_STA529
config SND_SOC_STAC9766
tristate
+config SND_SOC_STI_SAS
+ tristate "codec Audio support for STI SAS codec"
+
config SND_SOC_TAS2552
tristate "Texas Instruments TAS2552 Mono Audio amplifier"
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index cf160d972..4a3207795 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -45,6 +45,7 @@ snd-soc-cs4271-i2c-objs := cs4271-i2c.o
snd-soc-cs4271-spi-objs := cs4271-spi.o
snd-soc-cs42xx8-objs := cs42xx8.o
snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o
+snd-soc-cs4349-objs := cs4349.o
snd-soc-cx20442-objs := cx20442.o
snd-soc-da7210-objs := da7210.o
snd-soc-da7213-objs := da7213.o
@@ -55,6 +56,8 @@ snd-soc-dmic-objs := dmic.o
snd-soc-es8328-objs := es8328.o
snd-soc-es8328-i2c-objs := es8328-i2c.o
snd-soc-es8328-spi-objs := es8328-spi.o
+snd-soc-gtm601-objs := gtm601.o
+snd-soc-ics43432-objs := ics43432.o
snd-soc-isabelle-objs := isabelle.o
snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-l3-objs := l3.o
@@ -79,6 +82,7 @@ snd-soc-pcm512x-spi-objs := pcm512x-spi.o
snd-soc-rl6231-objs := rl6231.o
snd-soc-rl6347a-objs := rl6347a.o
snd-soc-rt286-objs := rt286.o
+snd-soc-rt298-objs := rt298.o
snd-soc-rt5631-objs := rt5631.o
snd-soc-rt5640-objs := rt5640.o
snd-soc-rt5645-objs := rt5645.o
@@ -106,6 +110,7 @@ snd-soc-sta32x-objs := sta32x.o
snd-soc-sta350-objs := sta350.o
snd-soc-sta529-objs := sta529.o
snd-soc-stac9766-objs := stac9766.o
+snd-soc-sti-sas-objs := sti-sas.o
snd-soc-tas5086-objs := tas5086.o
snd-soc-tas571x-objs := tas571x.o
snd-soc-tfa9879-objs := tfa9879.o
@@ -232,6 +237,7 @@ obj-$(CONFIG_SND_SOC_CS4271_I2C) += snd-soc-cs4271-i2c.o
obj-$(CONFIG_SND_SOC_CS4271_SPI) += snd-soc-cs4271-spi.o
obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o
obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o
+obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o
@@ -242,6 +248,8 @@ obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
+obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o
+obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
@@ -266,6 +274,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o
obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o
+obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o
@@ -289,6 +298,7 @@ obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o
obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
+obj-$(CONFIG_SND_SOC_STI_SAS) += snd-soc-sti-sas.o
obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index c7d243db0..affb19223 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -1335,11 +1335,10 @@ static DECLARE_TLV_DB_SCALE(dax_dig_gain_tlv, -6300, 100, 1);
static DECLARE_TLV_DB_SCALE(hs_ear_dig_gain_tlv, -100, 100, 1);
/* -1dB = Mute */
-static const unsigned int hs_gain_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(hs_gain_tlv,
0, 3, TLV_DB_SCALE_ITEM(-3200, 400, 0),
- 4, 15, TLV_DB_SCALE_ITEM(-1800, 200, 0),
-};
+ 4, 15, TLV_DB_SCALE_ITEM(-1800, 200, 0)
+);
static DECLARE_TLV_DB_SCALE(mic_gain_tlv, 0, 100, 0);
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 3cc69a626..9ef20dbcc 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -202,19 +202,21 @@ static struct snd_soc_dai_driver ad1980_dai = {
.formats = SND_SOC_STD_AC97_FMTS, },
};
+#define AD1980_VENDOR_ID 0x41445300
+#define AD1980_VENDOR_MASK 0xffffff00
+
static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
{
struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
unsigned int retry_cnt = 0;
+ int ret;
do {
- if (try_warm && soc_ac97_ops->warm_reset) {
- soc_ac97_ops->warm_reset(ac97);
- if (snd_soc_read(codec, AC97_RESET) == 0x0090)
- return 1;
- }
+ ret = snd_ac97_reset(ac97, true, AD1980_VENDOR_ID,
+ AD1980_VENDOR_MASK);
+ if (ret >= 0)
+ return 0;
- soc_ac97_ops->reset(ac97);
/*
* Set bit 16slot in register 74h, then every slot will has only
* 16 bits. This command is sent out in 20bit mode, in which
@@ -223,8 +225,6 @@ static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
*/
snd_soc_write(codec, AC97_AD_SERIAL_CFG, 0x9900);
- if (snd_soc_read(codec, AC97_RESET) == 0x0090)
- return 0;
} while (retry_cnt++ < 10);
dev_err(codec->dev, "Failed to reset: AC97 link error\n");
@@ -240,7 +240,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
u16 vendor_id2;
u16 ext_status;
- ac97 = snd_soc_new_ac97_codec(codec);
+ ac97 = snd_soc_new_ac97_codec(codec, 0, 0);
if (IS_ERR(ac97)) {
ret = PTR_ERR(ac97);
dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret);
@@ -260,22 +260,10 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
if (ret < 0)
goto reset_err;
- /* Read out vendor ID to make sure it is ad1980 */
- if (snd_soc_read(codec, AC97_VENDOR_ID1) != 0x4144) {
- ret = -ENODEV;
- goto reset_err;
- }
-
vendor_id2 = snd_soc_read(codec, AC97_VENDOR_ID2);
-
- if (vendor_id2 != 0x5370) {
- if (vendor_id2 != 0x5374) {
- ret = -ENODEV;
- goto reset_err;
- } else {
- dev_warn(codec->dev,
- "Found AD1981 - only 2/2 IN/OUT Channels supported\n");
- }
+ if (vendor_id2 == 0x5374) {
+ dev_warn(codec->dev,
+ "Found AD1981 - only 2/2 IN/OUT Channels supported\n");
}
/* unmute captures and playbacks volume */
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index a43160254..fe1353a79 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -320,13 +320,12 @@ static const struct reg_default adau1373_reg_defaults[] = {
{ ADAU1373_DIGEN, 0x00 },
};
-static const unsigned int adau1373_out_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+static const DECLARE_TLV_DB_RANGE(adau1373_out_tlv,
0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1),
8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0),
16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0),
- 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0),
-};
+ 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0)
+);
static const DECLARE_TLV_DB_MINMAX(adau1373_digital_tlv, -9563, 0);
static const DECLARE_TLV_DB_SCALE(adau1373_in_pga_tlv, -1300, 100, 1);
@@ -381,12 +380,11 @@ static const char *adau1373_bass_hpf_cutoff_text[] = {
"158Hz", "232Hz", "347Hz", "520Hz",
};
-static const unsigned int adau1373_bass_tlv[] = {
- TLV_DB_RANGE_HEAD(3),
+static const DECLARE_TLV_DB_RANGE(adau1373_bass_tlv,
0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1),
3, 4, TLV_DB_SCALE_ITEM(950, 250, 0),
- 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0),
-};
+ 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0)
+);
static SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum,
ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text);
@@ -414,11 +412,10 @@ static SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum,
static SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum,
ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text);
-static const unsigned int adau1373_3d_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(adau1373_3d_tlv,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
- 1, 7, TLV_DB_LINEAR_ITEM(-1800, -120),
-};
+ 1, 7, TLV_DB_LINEAR_ITEM(-1800, -120)
+);
static const char *adau1373_lr_mux_text[] = {
"Mute",
@@ -1534,7 +1531,6 @@ MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id);
static struct i2c_driver adau1373_i2c_driver = {
.driver = {
.name = "adau1373",
- .owner = THIS_MODULE,
},
.probe = adau1373_i2c_probe,
.remove = adau1373_i2c_remove,
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 0c8df9c6d..b84944037 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -915,7 +915,6 @@ MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id);
static struct i2c_driver adau1701_i2c_driver = {
.driver = {
.name = "adau1701",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(adau1701_dt_ids),
},
.probe = adau1701_i2c_probe,
diff --git a/sound/soc/codecs/adau1761-i2c.c b/sound/soc/codecs/adau1761-i2c.c
index 862796dec..348ccb17d 100644
--- a/sound/soc/codecs/adau1761-i2c.c
+++ b/sound/soc/codecs/adau1761-i2c.c
@@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(i2c, adau1761_i2c_ids);
static struct i2c_driver adau1761_i2c_driver = {
.driver = {
.name = "adau1761",
- .owner = THIS_MODULE,
},
.probe = adau1761_i2c_probe,
.remove = adau1761_i2c_remove,
diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c
index 2ce4362cc..0e32bba92 100644
--- a/sound/soc/codecs/adau1781-i2c.c
+++ b/sound/soc/codecs/adau1781-i2c.c
@@ -45,7 +45,6 @@ MODULE_DEVICE_TABLE(i2c, adau1781_i2c_ids);
static struct i2c_driver adau1781_i2c_driver = {
.driver = {
.name = "adau1781",
- .owner = THIS_MODULE,
},
.probe = adau1781_i2c_probe,
.remove = adau1781_i2c_remove,
diff --git a/sound/soc/codecs/adau1977-i2c.c b/sound/soc/codecs/adau1977-i2c.c
index 9700e8c83..21e7394a9 100644
--- a/sound/soc/codecs/adau1977-i2c.c
+++ b/sound/soc/codecs/adau1977-i2c.c
@@ -46,7 +46,6 @@ MODULE_DEVICE_TABLE(i2c, adau1977_i2c_ids);
static struct i2c_driver adau1977_i2c_driver = {
.driver = {
.name = "adau1977",
- .owner = THIS_MODULE,
},
.probe = adau1977_i2c_probe,
.remove = adau1977_i2c_remove,
diff --git a/sound/soc/codecs/adav803.c b/sound/soc/codecs/adav803.c
index 66d9fce34..52881faed 100644
--- a/sound/soc/codecs/adav803.c
+++ b/sound/soc/codecs/adav803.c
@@ -36,7 +36,6 @@ static int adav803_remove(struct i2c_client *client)
static struct i2c_driver adav803_driver = {
.driver = {
.name = "adav803",
- .owner = THIS_MODULE,
},
.probe = adav803_probe,
.remove = adav803_remove,
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index 69c63b92e..198c92455 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -113,7 +113,7 @@
#define ADAV80X_PLL_OUTE_SYSCLKPD(x) BIT(2 - (x))
-static struct reg_default adav80x_reg_defaults[] = {
+static const struct reg_default adav80x_reg_defaults[] = {
{ ADAV80X_PLAYBACK_CTRL, 0x01 },
{ ADAV80X_AUX_IN_CTRL, 0x01 },
{ ADAV80X_REC_CTRL, 0x02 },
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 8670861e5..54428c643 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -444,7 +444,6 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
static struct i2c_driver ak4535_i2c_driver = {
.driver = {
.name = "ak4535",
- .owner = THIS_MODULE,
},
.probe = ak4535_i2c_probe,
.remove = ak4535_i2c_remove,
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index 2d0ff4595..b14176f8d 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -609,7 +609,6 @@ MODULE_DEVICE_TABLE(i2c, ak4641_i2c_id);
static struct i2c_driver ak4641_i2c_driver = {
.driver = {
.name = "ak4641",
- .owner = THIS_MODULE,
},
.probe = ak4641_i2c_probe,
.remove = ak4641_i2c_remove,
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 7c0f6552c..4a90143d0 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -64,12 +64,15 @@
#define FIL1_0 0x1c
#define FIL1_1 0x1d
#define FIL1_2 0x1e
-#define FIL1_3 0x1f
+#define FIL1_3 0x1f /* The maximum valid register for ak4642 */
#define PW_MGMT4 0x20
#define MD_CTL5 0x21
#define LO_MS 0x22
#define HP_MS 0x23
-#define SPK_MS 0x24
+#define SPK_MS 0x24 /* The maximum valid register for ak4643 */
+#define EQ_FBEQAB 0x25
+#define EQ_FBEQCD 0x26
+#define EQ_FBEQE 0x27 /* The maximum valid register for ak4648 */
/* PW_MGMT1*/
#define PMVCM (1 << 6) /* VCOM Power Management */
@@ -241,7 +244,7 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = {
/*
* ak4642 register cache
*/
-static const struct reg_default ak4642_reg[] = {
+static const struct reg_default ak4643_reg[] = {
{ 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 },
{ 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 },
{ 8, 0xe1 }, { 9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 },
@@ -254,6 +257,14 @@ static const struct reg_default ak4642_reg[] = {
{ 36, 0x00 },
};
+/* The default settings for 0x0 ~ 0x1f registers are the same for ak4642
+ and ak4643. So we reuse the ak4643 reg_default for ak4642.
+ The valid registers for ak4642 are 0x0 ~ 0x1f which is a subset of ak4643,
+ so define NUM_AK4642_REG_DEFAULTS for ak4642.
+*/
+#define ak4642_reg ak4643_reg
+#define NUM_AK4642_REG_DEFAULTS (FIL1_3 + 1)
+
static const struct reg_default ak4648_reg[] = {
{ 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 },
{ 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 },
@@ -535,15 +546,23 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
static const struct regmap_config ak4642_regmap = {
.reg_bits = 8,
.val_bits = 8,
- .max_register = ARRAY_SIZE(ak4642_reg) + 1,
+ .max_register = FIL1_3,
.reg_defaults = ak4642_reg,
- .num_reg_defaults = ARRAY_SIZE(ak4642_reg),
+ .num_reg_defaults = NUM_AK4642_REG_DEFAULTS,
+};
+
+static const struct regmap_config ak4643_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = SPK_MS,
+ .reg_defaults = ak4643_reg,
+ .num_reg_defaults = ARRAY_SIZE(ak4643_reg),
};
static const struct regmap_config ak4648_regmap = {
.reg_bits = 8,
.val_bits = 8,
- .max_register = ARRAY_SIZE(ak4648_reg) + 1,
+ .max_register = EQ_FBEQE,
.reg_defaults = ak4648_reg,
.num_reg_defaults = ARRAY_SIZE(ak4648_reg),
};
@@ -553,7 +572,7 @@ static const struct ak4642_drvdata ak4642_drvdata = {
};
static const struct ak4642_drvdata ak4643_drvdata = {
- .regmap_config = &ak4642_regmap,
+ .regmap_config = &ak4643_regmap,
};
static const struct ak4642_drvdata ak4648_drvdata = {
@@ -626,7 +645,6 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
static struct i2c_driver ak4642_i2c_driver = {
.driver = {
.name = "ak4642-codec",
- .owner = THIS_MODULE,
.of_match_table = ak4642_of_match,
},
.probe = ak4642_i2c_probe,
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index 0e59063ae..c73a9f691 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -663,7 +663,6 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);
static struct i2c_driver ak4671_i2c_driver = {
.driver = {
.name = "ak4671-codec",
- .owner = THIS_MODULE,
},
.probe = ak4671_i2c_probe,
.remove = ak4671_i2c_remove,
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index 0fc24e0d5..d2e3a3ef7 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -82,12 +82,11 @@ static int amp_mixer_event(struct snd_soc_dapm_widget *w,
static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0);
static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);
static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);
-static const unsigned int boost_tlv[] = {
- TLV_DB_RANGE_HEAD(3),
+static const DECLARE_TLV_DB_RANGE(boost_tlv,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
- 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
-};
+ 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0)
+);
static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
static const struct snd_kcontrol_new alc5621_vol_snd_controls[] = {
@@ -1085,7 +1084,6 @@ MODULE_DEVICE_TABLE(of, alc5623_of_match);
static struct i2c_driver alc5623_i2c_driver = {
.driver = {
.name = "alc562x-codec",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(alc5623_of_match),
},
.probe = alc5623_i2c_probe,
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index 607a63b97..4d3ba33eb 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -35,7 +35,7 @@
/*
* ALC5632 register cache
*/
-static struct reg_default alc5632_reg_defaults[] = {
+static const struct reg_default alc5632_reg_defaults[] = {
{ 2, 0x8080 }, /* R2 - Speaker Output Volume */
{ 4, 0x8080 }, /* R4 - Headphone Output Volume */
{ 6, 0x8080 }, /* R6 - AUXOUT Volume */
@@ -146,11 +146,10 @@ static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0);
static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);
/* -16.5db min scale, 1.5db steps, no mute */
static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);
-static const unsigned int boost_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(boost_tlv,
0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
- 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
-};
+ 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0)
+);
/* 0db min scale, 6 db steps, no mute */
static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
/* 0db min scalem 0.75db steps, no mute */
@@ -1183,7 +1182,6 @@ MODULE_DEVICE_TABLE(of, alc5632_of_match);
static struct i2c_driver alc5632_i2c_driver = {
.driver = {
.name = "alc5632",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(alc5632_of_match),
},
.probe = alc5632_i2c_probe,
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 4180827a8..8a2221ab3 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -1366,7 +1366,7 @@ static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
- struct reg_default dac_comp[] = {
+ struct reg_sequence dac_comp[] = {
{ 0x80, 0x3 },
{ ARIZONA_DAC_COMP_1, 0 },
{ ARIZONA_DAC_COMP_2, 0 },
@@ -1504,7 +1504,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
else
rates = &arizona_48k_bclk_rates[0];
- wl = snd_pcm_format_width(params_format(params));
+ wl = params_width(params);
if (tdm_slots) {
arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
@@ -2304,6 +2304,82 @@ const struct snd_kcontrol_new arizona_adsp2_rate_controls[] = {
};
EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls);
+static bool arizona_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
+{
+ s16 a = be16_to_cpu(_a);
+ s16 b = be16_to_cpu(_b);
+
+ if (!mode) {
+ return abs(a) >= 4096;
+ } else {
+ if (abs(b) >= 4096)
+ return true;
+
+ return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
+ }
+}
+
+int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+ struct soc_bytes *params = (void *)kcontrol->private_value;
+ unsigned int val;
+ __be16 *data;
+ int len;
+ int ret;
+
+ len = params->num_regs * regmap_get_val_bytes(arizona->regmap);
+
+ data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
+ if (!data)
+ return -ENOMEM;
+
+ data[0] &= cpu_to_be16(ARIZONA_EQ1_B1_MODE);
+
+ if (arizona_eq_filter_unstable(!!data[0], data[1], data[2]) ||
+ arizona_eq_filter_unstable(true, data[4], data[5]) ||
+ arizona_eq_filter_unstable(true, data[8], data[9]) ||
+ arizona_eq_filter_unstable(true, data[12], data[13]) ||
+ arizona_eq_filter_unstable(false, data[16], data[17])) {
+ dev_err(arizona->dev, "Rejecting unstable EQ coefficients\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = regmap_read(arizona->regmap, params->base, &val);
+ if (ret != 0)
+ goto out;
+
+ val &= ~ARIZONA_EQ1_B1_MODE;
+ data[0] |= cpu_to_be16(val);
+
+ ret = regmap_raw_write(arizona->regmap, params->base, data, len);
+
+out:
+ kfree(data);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(arizona_eq_coeff_put);
+
+int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+ __be16 *data = (__be16 *)ucontrol->value.bytes.data;
+ s16 val = be16_to_cpu(*data);
+
+ if (abs(val) >= 4096) {
+ dev_err(arizona->dev, "Rejecting unstable LHPF coefficients\n");
+ return -EINVAL;
+ }
+
+ return snd_soc_bytes_put(kcontrol, ucontrol);
+}
+EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
+
MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 36867d05e..ada0a418f 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -194,6 +194,20 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
ARIZONA_MIXER_ROUTES(name " Preloader", name "L"), \
ARIZONA_MIXER_ROUTES(name " Preloader", name "R")
+#define ARIZONA_EQ_CONTROL(xname, xbase) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
+ .put = arizona_eq_coeff_put, .private_value = \
+ ((unsigned long)&(struct soc_bytes) { .base = xbase, \
+ .num_regs = 20, .mask = ~ARIZONA_EQ1_B1_MODE }) }
+
+#define ARIZONA_LHPF_CONTROL(xname, xbase) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
+ .put = arizona_lhpf_coeff_put, .private_value = \
+ ((unsigned long)&(struct soc_bytes) { .base = xbase, \
+ .num_regs = 1 }) }
+
#define ARIZONA_RATE_ENUM_SIZE 4
extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE];
extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE];
@@ -229,6 +243,11 @@ extern int arizona_hp_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
+extern int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+extern int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir);
diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c
index 8f40025b7..44c30fe3e 100644
--- a/sound/soc/codecs/cs35l32.c
+++ b/sound/soc/codecs/cs35l32.c
@@ -74,33 +74,8 @@ static const struct reg_default cs35l32_reg_defaults[] = {
static bool cs35l32_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
- case CS35L32_DEVID_AB:
- case CS35L32_DEVID_CD:
- case CS35L32_DEVID_E:
- case CS35L32_FAB_ID:
- case CS35L32_REV_ID:
- case CS35L32_PWRCTL1:
- case CS35L32_PWRCTL2:
- case CS35L32_CLK_CTL:
- case CS35L32_BATT_THRESHOLD:
- case CS35L32_VMON:
- case CS35L32_BST_CPCP_CTL:
- case CS35L32_IMON_SCALING:
- case CS35L32_AUDIO_LED_MNGR:
- case CS35L32_ADSP_CTL:
- case CS35L32_CLASSD_CTL:
- case CS35L32_PROTECT_CTL:
- case CS35L32_INT_MASK_1:
- case CS35L32_INT_MASK_2:
- case CS35L32_INT_MASK_3:
- case CS35L32_INT_STATUS_1:
- case CS35L32_INT_STATUS_2:
- case CS35L32_INT_STATUS_3:
- case CS35L32_LED_STATUS:
- case CS35L32_FLASH_MODE:
- case CS35L32_MOVIE_MODE:
- case CS35L32_FLASH_TIMER:
- case CS35L32_FLASH_INHIBIT:
+ case CS35L32_DEVID_AB ... CS35L32_AUDIO_LED_MNGR:
+ case CS35L32_ADSP_CTL ... CS35L32_FLASH_INHIBIT:
return true;
default:
return false;
@@ -110,15 +85,8 @@ static bool cs35l32_readable_register(struct device *dev, unsigned int reg)
static bool cs35l32_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
- case CS35L32_DEVID_AB:
- case CS35L32_DEVID_CD:
- case CS35L32_DEVID_E:
- case CS35L32_FAB_ID:
- case CS35L32_REV_ID:
- case CS35L32_INT_STATUS_1:
- case CS35L32_INT_STATUS_2:
- case CS35L32_INT_STATUS_3:
- case CS35L32_LED_STATUS:
+ case CS35L32_DEVID_AB ... CS35L32_REV_ID:
+ case CS35L32_INT_STATUS_1 ... CS35L32_LED_STATUS:
return true;
default:
return false;
@@ -128,10 +96,7 @@ static bool cs35l32_volatile_register(struct device *dev, unsigned int reg)
static bool cs35l32_precious_register(struct device *dev, unsigned int reg)
{
switch (reg) {
- case CS35L32_INT_STATUS_1:
- case CS35L32_INT_STATUS_2:
- case CS35L32_INT_STATUS_3:
- case CS35L32_LED_STATUS:
+ case CS35L32_INT_STATUS_1 ... CS35L32_LED_STATUS:
return true;
default:
return false;
@@ -276,7 +241,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs35l32 = {
};
/* Current and threshold powerup sequence Pg37 in datasheet */
-static const struct reg_default cs35l32_monitor_patch[] = {
+static const struct reg_sequence cs35l32_monitor_patch[] = {
{ 0x00, 0x99 },
{ 0x48, 0x17 },
@@ -441,8 +406,7 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client,
if (IS_ERR(cs35l32->reset_gpio))
return PTR_ERR(cs35l32->reset_gpio);
- if (cs35l32->reset_gpio)
- gpiod_set_value_cansleep(cs35l32->reset_gpio, 1);
+ gpiod_set_value_cansleep(cs35l32->reset_gpio, 1);
/* initialize codec */
ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_AB, &reg);
@@ -536,8 +500,7 @@ static int cs35l32_i2c_remove(struct i2c_client *i2c_client)
snd_soc_unregister_codec(&i2c_client->dev);
/* Hold down reset */
- if (cs35l32->reset_gpio)
- gpiod_set_value_cansleep(cs35l32->reset_gpio, 0);
+ gpiod_set_value_cansleep(cs35l32->reset_gpio, 0);
return 0;
}
@@ -551,8 +514,7 @@ static int cs35l32_runtime_suspend(struct device *dev)
regcache_mark_dirty(cs35l32->regmap);
/* Hold down reset */
- if (cs35l32->reset_gpio)
- gpiod_set_value_cansleep(cs35l32->reset_gpio, 0);
+ gpiod_set_value_cansleep(cs35l32->reset_gpio, 0);
/* remove power */
regulator_bulk_disable(ARRAY_SIZE(cs35l32->supplies),
@@ -575,8 +537,7 @@ static int cs35l32_runtime_resume(struct device *dev)
return ret;
}
- if (cs35l32->reset_gpio)
- gpiod_set_value_cansleep(cs35l32->reset_gpio, 1);
+ gpiod_set_value_cansleep(cs35l32->reset_gpio, 1);
regcache_cache_only(cs35l32->regmap, false);
regcache_sync(cs35l32->regmap);
@@ -607,7 +568,6 @@ MODULE_DEVICE_TABLE(i2c, cs35l32_id);
static struct i2c_driver cs35l32_i2c_driver = {
.driver = {
.name = "cs35l32",
- .owner = THIS_MODULE,
.pm = &cs35l32_runtime_pm,
.of_match_table = cs35l32_of_match,
},
diff --git a/sound/soc/codecs/cs35l32.h b/sound/soc/codecs/cs35l32.h
index 31ab804a2..1d6c2508c 100644
--- a/sound/soc/codecs/cs35l32.h
+++ b/sound/soc/codecs/cs35l32.h
@@ -80,7 +80,7 @@ struct cs35l32_platform_data {
#define CS35L32_GAIN_MGR_MASK 0x08
#define CS35L32_ADSP_SHARE_MASK 0x08
#define CS35L32_ADSP_DATACFG_MASK 0x30
-#define CS35L32_SDOUT_3ST 0x80
+#define CS35L32_SDOUT_3ST 0x08
#define CS35L32_BATT_REC_MASK 0x0E
#define CS35L32_BATT_THRESH_MASK 0x30
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c
index 8e3619847..55db19ddc 100644
--- a/sound/soc/codecs/cs4265.c
+++ b/sound/soc/codecs/cs4265.c
@@ -60,23 +60,7 @@ static const struct reg_default cs4265_reg_defaults[] = {
static bool cs4265_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
- case CS4265_PWRCTL:
- case CS4265_DAC_CTL:
- case CS4265_ADC_CTL:
- case CS4265_MCLK_FREQ:
- case CS4265_SIG_SEL:
- case CS4265_CHB_PGA_CTL:
- case CS4265_CHA_PGA_CTL:
- case CS4265_ADC_CTL2:
- case CS4265_DAC_CHA_VOL:
- case CS4265_DAC_CHB_VOL:
- case CS4265_DAC_CTL2:
- case CS4265_SPDIF_CTL1:
- case CS4265_SPDIF_CTL2:
- case CS4265_INT_MASK:
- case CS4265_STATUS_MODE_MSB:
- case CS4265_STATUS_MODE_LSB:
- case CS4265_CHIP_ID:
+ case CS4265_CHIP_ID ... CS4265_SPDIF_CTL2:
return true;
default:
return false;
@@ -658,7 +642,6 @@ MODULE_DEVICE_TABLE(i2c, cs4265_id);
static struct i2c_driver cs4265_i2c_driver = {
.driver = {
.name = "cs4265",
- .owner = THIS_MODULE,
.of_match_table = cs4265_of_match,
},
.id_table = cs4265_id,
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index e6d4ff9fd..e07807d96 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -751,7 +751,6 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
static struct i2c_driver cs4270_i2c_driver = {
.driver = {
.name = "cs4270",
- .owner = THIS_MODULE,
.of_match_table = cs4270_of_match,
},
.id_table = cs4270_id,
diff --git a/sound/soc/codecs/cs4271-i2c.c b/sound/soc/codecs/cs4271-i2c.c
index b264da030..dcb3223d7 100644
--- a/sound/soc/codecs/cs4271-i2c.c
+++ b/sound/soc/codecs/cs4271-i2c.c
@@ -48,7 +48,6 @@ MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id);
static struct i2c_driver cs4271_i2c_driver = {
.driver = {
.name = "cs4271",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(cs4271_dt_ids),
},
.probe = cs4271_i2c_probe,
diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c
index c40428f25..9bad47847 100644
--- a/sound/soc/codecs/cs42l51-i2c.c
+++ b/sound/soc/codecs/cs42l51-i2c.c
@@ -45,7 +45,6 @@ static int cs42l51_i2c_remove(struct i2c_client *i2c)
static struct i2c_driver cs42l51_i2c_driver = {
.driver = {
.name = "cs42l51",
- .owner = THIS_MODULE,
.of_match_table = cs42l51_of_match,
},
.probe = cs42l51_i2c_probe,
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 4de52c995..47b97fcef 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -110,58 +110,7 @@ static const struct reg_default cs42l52_reg_defaults[] = {
static bool cs42l52_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
- case CS42L52_CHIP:
- case CS42L52_PWRCTL1:
- case CS42L52_PWRCTL2:
- case CS42L52_PWRCTL3:
- case CS42L52_CLK_CTL:
- case CS42L52_IFACE_CTL1:
- case CS42L52_IFACE_CTL2:
- case CS42L52_ADC_PGA_A:
- case CS42L52_ADC_PGA_B:
- case CS42L52_ANALOG_HPF_CTL:
- case CS42L52_ADC_HPF_FREQ:
- case CS42L52_ADC_MISC_CTL:
- case CS42L52_PB_CTL1:
- case CS42L52_MISC_CTL:
- case CS42L52_PB_CTL2:
- case CS42L52_MICA_CTL:
- case CS42L52_MICB_CTL:
- case CS42L52_PGAA_CTL:
- case CS42L52_PGAB_CTL:
- case CS42L52_PASSTHRUA_VOL:
- case CS42L52_PASSTHRUB_VOL:
- case CS42L52_ADCA_VOL:
- case CS42L52_ADCB_VOL:
- case CS42L52_ADCA_MIXER_VOL:
- case CS42L52_ADCB_MIXER_VOL:
- case CS42L52_PCMA_MIXER_VOL:
- case CS42L52_PCMB_MIXER_VOL:
- case CS42L52_BEEP_FREQ:
- case CS42L52_BEEP_VOL:
- case CS42L52_BEEP_TONE_CTL:
- case CS42L52_TONE_CTL:
- case CS42L52_MASTERA_VOL:
- case CS42L52_MASTERB_VOL:
- case CS42L52_HPA_VOL:
- case CS42L52_HPB_VOL:
- case CS42L52_SPKA_VOL:
- case CS42L52_SPKB_VOL:
- case CS42L52_ADC_PCM_MIXER:
- case CS42L52_LIMITER_CTL1:
- case CS42L52_LIMITER_CTL2:
- case CS42L52_LIMITER_AT_RATE:
- case CS42L52_ALC_CTL:
- case CS42L52_ALC_RATE:
- case CS42L52_ALC_THRESHOLD:
- case CS42L52_NOISE_GATE_CTL:
- case CS42L52_CLK_STATUS:
- case CS42L52_BATT_COMPEN:
- case CS42L52_BATT_LEVEL:
- case CS42L52_SPK_STATUS:
- case CS42L52_TEM_CTL:
- case CS42L52_THE_FOLDBACK:
- case CS42L52_CHARGE_PUMP:
+ case CS42L52_CHIP ... CS42L52_CHARGE_PUMP:
return true;
default:
return false;
@@ -196,11 +145,10 @@ static DECLARE_TLV_DB_SCALE(mix_tlv, -50, 50, 0);
static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0);
-static const unsigned int limiter_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(limiter_tlv,
0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
- 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0),
-};
+ 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0)
+);
static const char * const cs42l52_adca_text[] = {
"Input1A", "Input2A", "Input3A", "Input4A", "PGA Input Left"};
@@ -919,7 +867,7 @@ static int cs42l52_set_bias_level(struct snd_soc_codec *codec,
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE)
-static struct snd_soc_dai_ops cs42l52_ops = {
+static const struct snd_soc_dai_ops cs42l52_ops = {
.hw_params = cs42l52_pcm_hw_params,
.digital_mute = cs42l52_digital_mute,
.set_fmt = cs42l52_set_fmt,
@@ -1118,7 +1066,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs42l52 = {
};
/* Current and threshold powerup sequence Pg37 */
-static const struct reg_default cs42l52_threshold_patch[] = {
+static const struct reg_sequence cs42l52_threshold_patch[] = {
{ 0x00, 0x99 },
{ 0x3E, 0xBA },
@@ -1285,7 +1233,6 @@ MODULE_DEVICE_TABLE(i2c, cs42l52_id);
static struct i2c_driver cs42l52_i2c_driver = {
.driver = {
.name = "cs42l52",
- .owner = THIS_MODULE,
.of_match_table = cs42l52_of_match,
},
.id_table = cs42l52_id,
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
index 1e11ba45a..7cd5f769b 100644
--- a/sound/soc/codecs/cs42l56.c
+++ b/sound/soc/codecs/cs42l56.c
@@ -115,52 +115,7 @@ static const struct reg_default cs42l56_reg_defaults[] = {
static bool cs42l56_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
- case CS42L56_CHIP_ID_1:
- case CS42L56_CHIP_ID_2:
- case CS42L56_PWRCTL_1:
- case CS42L56_PWRCTL_2:
- case CS42L56_CLKCTL_1:
- case CS42L56_CLKCTL_2:
- case CS42L56_SERIAL_FMT:
- case CS42L56_CLASSH_CTL:
- case CS42L56_MISC_CTL:
- case CS42L56_INT_STATUS:
- case CS42L56_PLAYBACK_CTL:
- case CS42L56_DSP_MUTE_CTL:
- case CS42L56_ADCA_MIX_VOLUME:
- case CS42L56_ADCB_MIX_VOLUME:
- case CS42L56_PCMA_MIX_VOLUME:
- case CS42L56_PCMB_MIX_VOLUME:
- case CS42L56_ANAINPUT_ADV_VOLUME:
- case CS42L56_DIGINPUT_ADV_VOLUME:
- case CS42L56_MASTER_A_VOLUME:
- case CS42L56_MASTER_B_VOLUME:
- case CS42L56_BEEP_FREQ_ONTIME:
- case CS42L56_BEEP_FREQ_OFFTIME:
- case CS42L56_BEEP_TONE_CFG:
- case CS42L56_TONE_CTL:
- case CS42L56_CHAN_MIX_SWAP:
- case CS42L56_AIN_REFCFG_ADC_MUX:
- case CS42L56_HPF_CTL:
- case CS42L56_MISC_ADC_CTL:
- case CS42L56_GAIN_BIAS_CTL:
- case CS42L56_PGAA_MUX_VOLUME:
- case CS42L56_PGAB_MUX_VOLUME:
- case CS42L56_ADCA_ATTENUATOR:
- case CS42L56_ADCB_ATTENUATOR:
- case CS42L56_ALC_EN_ATTACK_RATE:
- case CS42L56_ALC_RELEASE_RATE:
- case CS42L56_ALC_THRESHOLD:
- case CS42L56_NOISE_GATE_CTL:
- case CS42L56_ALC_LIM_SFT_ZC:
- case CS42L56_AMUTE_HPLO_MUX:
- case CS42L56_HPA_VOLUME:
- case CS42L56_HPB_VOLUME:
- case CS42L56_LOA_VOLUME:
- case CS42L56_LOB_VOLUME:
- case CS42L56_LIM_THRESHOLD_CTL:
- case CS42L56_LIM_CTL_RELEASE_RATE:
- case CS42L56_LIM_ATTACK_RATE:
+ case CS42L56_CHIP_ID_1 ... CS42L56_LIM_ATTACK_RATE:
return true;
default:
return false;
@@ -185,21 +140,18 @@ static DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0);
static DECLARE_TLV_DB_SCALE(preamp_tlv, 0, 1000, 0);
static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);
-static const unsigned int ngnb_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(ngnb_tlv,
0, 1, TLV_DB_SCALE_ITEM(-8200, 600, 0),
- 2, 5, TLV_DB_SCALE_ITEM(-7600, 300, 0),
-};
-static const unsigned int ngb_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+ 2, 5, TLV_DB_SCALE_ITEM(-7600, 300, 0)
+);
+static const DECLARE_TLV_DB_RANGE(ngb_tlv,
0, 2, TLV_DB_SCALE_ITEM(-6400, 600, 0),
- 3, 7, TLV_DB_SCALE_ITEM(-4600, 300, 0),
-};
-static const unsigned int alc_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+ 3, 7, TLV_DB_SCALE_ITEM(-4600, 300, 0)
+);
+static const DECLARE_TLV_DB_RANGE(alc_tlv,
0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
- 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0),
-};
+ 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0)
+);
static const char * const beep_config_text[] = {
"Off", "Single", "Multiple", "Continuous"
@@ -989,7 +941,7 @@ static int cs42l56_set_bias_level(struct snd_soc_codec *codec,
SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops cs42l56_ops = {
+static const struct snd_soc_dai_ops cs42l56_ops = {
.hw_params = cs42l56_pcm_hw_params,
.digital_mute = cs42l56_digital_mute,
.set_fmt = cs42l56_set_dai_fmt,
@@ -1408,7 +1360,6 @@ MODULE_DEVICE_TABLE(i2c, cs42l56_id);
static struct i2c_driver cs42l56_i2c_driver = {
.driver = {
.name = "cs42l56",
- .owner = THIS_MODULE,
.of_match_table = cs42l56_of_match,
},
.id_table = cs42l56_id,
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index b7853b9d3..42a8fd4e1 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -153,111 +153,18 @@ static bool cs42l73_volatile_register(struct device *dev, unsigned int reg)
static bool cs42l73_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
- case CS42L73_DEVID_AB:
- case CS42L73_DEVID_CD:
- case CS42L73_DEVID_E:
- case CS42L73_REVID:
- case CS42L73_PWRCTL1:
- case CS42L73_PWRCTL2:
- case CS42L73_PWRCTL3:
- case CS42L73_CPFCHC:
- case CS42L73_OLMBMSDC:
- case CS42L73_DMMCC:
- case CS42L73_XSPC:
- case CS42L73_XSPMMCC:
- case CS42L73_ASPC:
- case CS42L73_ASPMMCC:
- case CS42L73_VSPC:
- case CS42L73_VSPMMCC:
- case CS42L73_VXSPFS:
- case CS42L73_MIOPC:
- case CS42L73_ADCIPC:
- case CS42L73_MICAPREPGAAVOL:
- case CS42L73_MICBPREPGABVOL:
- case CS42L73_IPADVOL:
- case CS42L73_IPBDVOL:
- case CS42L73_PBDC:
- case CS42L73_HLADVOL:
- case CS42L73_HLBDVOL:
- case CS42L73_SPKDVOL:
- case CS42L73_ESLDVOL:
- case CS42L73_HPAAVOL:
- case CS42L73_HPBAVOL:
- case CS42L73_LOAAVOL:
- case CS42L73_LOBAVOL:
- case CS42L73_STRINV:
- case CS42L73_XSPINV:
- case CS42L73_ASPINV:
- case CS42L73_VSPINV:
- case CS42L73_LIMARATEHL:
- case CS42L73_LIMRRATEHL:
- case CS42L73_LMAXHL:
- case CS42L73_LIMARATESPK:
- case CS42L73_LIMRRATESPK:
- case CS42L73_LMAXSPK:
- case CS42L73_LIMARATEESL:
- case CS42L73_LIMRRATEESL:
- case CS42L73_LMAXESL:
- case CS42L73_ALCARATE:
- case CS42L73_ALCRRATE:
- case CS42L73_ALCMINMAX:
- case CS42L73_NGCAB:
- case CS42L73_ALCNGMC:
- case CS42L73_MIXERCTL:
- case CS42L73_HLAIPAA:
- case CS42L73_HLBIPBA:
- case CS42L73_HLAXSPAA:
- case CS42L73_HLBXSPBA:
- case CS42L73_HLAASPAA:
- case CS42L73_HLBASPBA:
- case CS42L73_HLAVSPMA:
- case CS42L73_HLBVSPMA:
- case CS42L73_XSPAIPAA:
- case CS42L73_XSPBIPBA:
- case CS42L73_XSPAXSPAA:
- case CS42L73_XSPBXSPBA:
- case CS42L73_XSPAASPAA:
- case CS42L73_XSPAASPBA:
- case CS42L73_XSPAVSPMA:
- case CS42L73_XSPBVSPMA:
- case CS42L73_ASPAIPAA:
- case CS42L73_ASPBIPBA:
- case CS42L73_ASPAXSPAA:
- case CS42L73_ASPBXSPBA:
- case CS42L73_ASPAASPAA:
- case CS42L73_ASPBASPBA:
- case CS42L73_ASPAVSPMA:
- case CS42L73_ASPBVSPMA:
- case CS42L73_VSPAIPAA:
- case CS42L73_VSPBIPBA:
- case CS42L73_VSPAXSPAA:
- case CS42L73_VSPBXSPBA:
- case CS42L73_VSPAASPAA:
- case CS42L73_VSPBASPBA:
- case CS42L73_VSPAVSPMA:
- case CS42L73_VSPBVSPMA:
- case CS42L73_MMIXCTL:
- case CS42L73_SPKMIPMA:
- case CS42L73_SPKMXSPA:
- case CS42L73_SPKMASPA:
- case CS42L73_SPKMVSPMA:
- case CS42L73_ESLMIPMA:
- case CS42L73_ESLMXSPA:
- case CS42L73_ESLMASPA:
- case CS42L73_ESLMVSPMA:
- case CS42L73_IM1:
- case CS42L73_IM2:
+ case CS42L73_DEVID_AB ... CS42L73_DEVID_E:
+ case CS42L73_REVID ... CS42L73_IM2:
return true;
default:
return false;
}
}
-static const unsigned int hpaloa_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(hpaloa_tlv,
0, 13, TLV_DB_SCALE_ITEM(-7600, 200, 0),
- 14, 75, TLV_DB_SCALE_ITEM(-4900, 100, 0),
-};
+ 14, 75, TLV_DB_SCALE_ITEM(-4900, 100, 0)
+);
static DECLARE_TLV_DB_SCALE(adc_boost_tlv, 0, 2500, 0);
@@ -267,11 +174,10 @@ static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0);
static DECLARE_TLV_DB_SCALE(micpga_tlv, -600, 50, 0);
-static const unsigned int limiter_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(limiter_tlv,
0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
- 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0),
-};
+ 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0)
+);
static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1);
@@ -1236,8 +1142,8 @@ static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate)
struct snd_soc_codec *codec = dai->codec;
int id = dai->id;
- return snd_soc_update_bits(codec, CS42L73_SPC(id),
- 0x7F, tristate << 7);
+ return snd_soc_update_bits(codec, CS42L73_SPC(id), CS42L73_SP_3ST,
+ tristate << 7);
}
static const struct snd_pcm_hw_constraint_list constraints_12_24 = {
@@ -1491,7 +1397,6 @@ MODULE_DEVICE_TABLE(i2c, cs42l73_id);
static struct i2c_driver cs42l73_i2c_driver = {
.driver = {
.name = "cs42l73",
- .owner = THIS_MODULE,
.of_match_table = cs42l73_of_match,
},
.id_table = cs42l73_id,
diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c
index 657dce27e..800c1d549 100644
--- a/sound/soc/codecs/cs42xx8-i2c.c
+++ b/sound/soc/codecs/cs42xx8-i2c.c
@@ -20,7 +20,7 @@
static int cs42xx8_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
- u32 ret = cs42xx8_probe(&i2c->dev,
+ int ret = cs42xx8_probe(&i2c->dev,
devm_regmap_init_i2c(i2c, &cs42xx8_regmap_config));
if (ret)
return ret;
@@ -49,8 +49,8 @@ MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id);
static struct i2c_driver cs42xx8_i2c_driver = {
.driver = {
.name = "cs42xx8",
- .owner = THIS_MODULE,
.pm = &cs42xx8_pm,
+ .of_match_table = cs42xx8_of_match,
},
.probe = cs42xx8_i2c_probe,
.remove = cs42xx8_i2c_remove,
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c
index e1d46862e..d562e1b9a 100644
--- a/sound/soc/codecs/cs42xx8.c
+++ b/sound/soc/codecs/cs42xx8.c
@@ -425,7 +425,7 @@ const struct cs42xx8_driver_data cs42888_data = {
};
EXPORT_SYMBOL_GPL(cs42888_data);
-static const struct of_device_id cs42xx8_of_match[] = {
+const struct of_device_id cs42xx8_of_match[] = {
{ .compatible = "cirrus,cs42448", .data = &cs42448_data, },
{ .compatible = "cirrus,cs42888", .data = &cs42888_data, },
{ /* sentinel */ }
@@ -435,16 +435,24 @@ EXPORT_SYMBOL_GPL(cs42xx8_of_match);
int cs42xx8_probe(struct device *dev, struct regmap *regmap)
{
- const struct of_device_id *of_id = of_match_device(cs42xx8_of_match, dev);
+ const struct of_device_id *of_id;
struct cs42xx8_priv *cs42xx8;
int ret, val, i;
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(dev, "failed to allocate regmap: %d\n", ret);
+ return ret;
+ }
+
cs42xx8 = devm_kzalloc(dev, sizeof(*cs42xx8), GFP_KERNEL);
if (cs42xx8 == NULL)
return -ENOMEM;
+ cs42xx8->regmap = regmap;
dev_set_drvdata(dev, cs42xx8);
+ of_id = of_match_device(cs42xx8_of_match, dev);
if (of_id)
cs42xx8->drvdata = of_id->data;
@@ -482,13 +490,6 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap)
/* Make sure hardware reset done */
msleep(5);
- cs42xx8->regmap = regmap;
- if (IS_ERR(cs42xx8->regmap)) {
- ret = PTR_ERR(cs42xx8->regmap);
- dev_err(dev, "failed to allocate regmap: %d\n", ret);
- goto err_enable;
- }
-
/*
* We haven't marked the chip revision as volatile due to
* sharing a register with the right input volume; explicitly
diff --git a/sound/soc/codecs/cs42xx8.h b/sound/soc/codecs/cs42xx8.h
index b2c10e537..d36c61b6d 100644
--- a/sound/soc/codecs/cs42xx8.h
+++ b/sound/soc/codecs/cs42xx8.h
@@ -22,6 +22,7 @@ extern const struct dev_pm_ops cs42xx8_pm;
extern const struct cs42xx8_driver_data cs42448_data;
extern const struct cs42xx8_driver_data cs42888_data;
extern const struct regmap_config cs42xx8_regmap_config;
+extern const struct of_device_id cs42xx8_of_match[];
int cs42xx8_probe(struct device *dev, struct regmap *regmap);
/* CS42888 register map */
diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c
new file mode 100644
index 000000000..0ac8fc5ed
--- /dev/null
+++ b/sound/soc/codecs/cs4349.c
@@ -0,0 +1,392 @@
+/*
+ * cs4349.c -- CS4349 ALSA Soc Audio driver
+ *
+ * Copyright 2015 Cirrus Logic, Inc.
+ *
+ * Authors: Tim Howe <Tim.Howe@cirrus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include "cs4349.h"
+
+
+static const struct reg_default cs4349_reg_defaults[] = {
+ { 2, 0x00 }, /* r02 - Mode Control */
+ { 3, 0x09 }, /* r03 - Volume, Mixing and Inversion Control */
+ { 4, 0x81 }, /* r04 - Mute Control */
+ { 5, 0x00 }, /* r05 - Channel A Volume Control */
+ { 6, 0x00 }, /* r06 - Channel B Volume Control */
+ { 7, 0xB1 }, /* r07 - Ramp and Filter Control */
+ { 8, 0x1C }, /* r08 - Misc. Control */
+};
+
+/* Private data for the CS4349 */
+struct cs4349_private {
+ struct regmap *regmap;
+ struct gpio_desc *reset_gpio;
+ unsigned int mode;
+ int rate;
+};
+
+static bool cs4349_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS4349_CHIPID ... CS4349_MISC:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs4349_writeable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS4349_MODE ... CS4349_MISC:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static int cs4349_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int format)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct cs4349_private *cs4349 = snd_soc_codec_get_drvdata(codec);
+ unsigned int fmt;
+
+ fmt = format & SND_SOC_DAIFMT_FORMAT_MASK;
+
+ switch (fmt) {
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_LEFT_J:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ cs4349->mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cs4349_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct cs4349_private *cs4349 = snd_soc_codec_get_drvdata(codec);
+ int fmt, ret;
+
+ cs4349->rate = params_rate(params);
+
+ switch (cs4349->mode) {
+ case SND_SOC_DAIFMT_I2S:
+ fmt = DIF_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ fmt = DIF_LEFT_JST;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ switch (params_width(params)) {
+ case 16:
+ fmt = DIF_RGHT_JST16;
+ break;
+ case 24:
+ fmt = DIF_RGHT_JST24;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = snd_soc_update_bits(codec, CS4349_MODE, DIF_MASK,
+ MODE_FORMAT(fmt));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int cs4349_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int reg;
+
+ reg = 0;
+ if (mute)
+ reg = MUTE_AB_MASK;
+
+ return snd_soc_update_bits(codec, CS4349_MUTE, MUTE_AB_MASK, reg);
+}
+
+static DECLARE_TLV_DB_SCALE(dig_tlv, -12750, 50, 0);
+
+static const char * const chan_mix_texts[] = {
+ "Mute", "MuteA", "MuteA SwapB", "MuteA MonoB", "SwapA MuteB",
+ "BothR", "Swap", "SwapA MonoB", "MuteB", "Normal", "BothL",
+ "MonoB", "MonoA MuteB", "MonoA", "MonoA SwapB", "Mono",
+ /*Normal == Channel A = Left, Channel B = Right*/
+};
+
+static const char * const fm_texts[] = {
+ "Auto", "Single", "Double", "Quad",
+};
+
+static const char * const deemph_texts[] = {
+ "None", "44.1k", "48k", "32k",
+};
+
+static const char * const softr_zeroc_texts[] = {
+ "Immediate", "Zero Cross", "Soft Ramp", "SR on ZC",
+};
+
+static int deemph_values[] = {
+ 0, 4, 8, 12,
+};
+
+static int softr_zeroc_values[] = {
+ 0, 64, 128, 192,
+};
+
+static const struct soc_enum chan_mix_enum =
+ SOC_ENUM_SINGLE(CS4349_VMI, 0,
+ ARRAY_SIZE(chan_mix_texts),
+ chan_mix_texts);
+
+static const struct soc_enum fm_mode_enum =
+ SOC_ENUM_SINGLE(CS4349_MODE, 0,
+ ARRAY_SIZE(fm_texts),
+ fm_texts);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(deemph_enum, CS4349_MODE, 0, DEM_MASK,
+ deemph_texts, deemph_values);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(softr_zeroc_enum, CS4349_RMPFLT, 0,
+ SR_ZC_MASK, softr_zeroc_texts,
+ softr_zeroc_values);
+
+static const struct snd_kcontrol_new cs4349_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("Master Playback Volume",
+ CS4349_VOLA, CS4349_VOLB, 0, 0xFF, 1, dig_tlv),
+ SOC_ENUM("Functional Mode", fm_mode_enum),
+ SOC_ENUM("De-Emphasis Control", deemph_enum),
+ SOC_ENUM("Soft Ramp Zero Cross Control", softr_zeroc_enum),
+ SOC_ENUM("Channel Mixer", chan_mix_enum),
+ SOC_SINGLE("VolA = VolB Switch", CS4349_VMI, 7, 1, 0),
+ SOC_SINGLE("InvertA Switch", CS4349_VMI, 6, 1, 0),
+ SOC_SINGLE("InvertB Switch", CS4349_VMI, 5, 1, 0),
+ SOC_SINGLE("Auto-Mute Switch", CS4349_MUTE, 7, 1, 0),
+ SOC_SINGLE("MUTEC A = B Switch", CS4349_MUTE, 5, 1, 0),
+ SOC_SINGLE("Soft Ramp Up Switch", CS4349_RMPFLT, 5, 1, 0),
+ SOC_SINGLE("Soft Ramp Down Switch", CS4349_RMPFLT, 4, 1, 0),
+ SOC_SINGLE("Slow Roll Off Filter Switch", CS4349_RMPFLT, 2, 1, 0),
+ SOC_SINGLE("Freeze Switch", CS4349_MISC, 5, 1, 0),
+ SOC_SINGLE("Popguard Switch", CS4349_MISC, 4, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget cs4349_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("HiFi DAC", NULL, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_OUTPUT("OutputA"),
+ SND_SOC_DAPM_OUTPUT("OutputB"),
+};
+
+static const struct snd_soc_dapm_route cs4349_routes[] = {
+ {"DAC Playback", NULL, "OutputA"},
+ {"DAC Playback", NULL, "OutputB"},
+
+ {"OutputA", NULL, "HiFi DAC"},
+ {"OutputB", NULL, "HiFi DAC"},
+};
+
+#define CS4349_PCM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
+ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
+ SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+#define CS4349_PCM_RATES SNDRV_PCM_RATE_8000_192000
+
+static const struct snd_soc_dai_ops cs4349_dai_ops = {
+ .hw_params = cs4349_pcm_hw_params,
+ .set_fmt = cs4349_set_dai_fmt,
+ .digital_mute = cs4349_digital_mute,
+};
+
+static struct snd_soc_dai_driver cs4349_dai = {
+ .name = "cs4349_hifi",
+ .playback = {
+ .stream_name = "DAC Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CS4349_PCM_RATES,
+ .formats = CS4349_PCM_FORMATS,
+ },
+ .ops = &cs4349_dai_ops,
+ .symmetric_rates = 1,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_cs4349 = {
+ .controls = cs4349_snd_controls,
+ .num_controls = ARRAY_SIZE(cs4349_snd_controls),
+
+ .dapm_widgets = cs4349_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(cs4349_dapm_widgets),
+ .dapm_routes = cs4349_routes,
+ .num_dapm_routes = ARRAY_SIZE(cs4349_routes),
+};
+
+static const struct regmap_config cs4349_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = CS4349_MISC,
+ .reg_defaults = cs4349_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(cs4349_reg_defaults),
+ .readable_reg = cs4349_readable_register,
+ .writeable_reg = cs4349_writeable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int cs4349_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct cs4349_private *cs4349;
+ int ret;
+
+ cs4349 = devm_kzalloc(&client->dev, sizeof(*cs4349), GFP_KERNEL);
+ if (!cs4349)
+ return -ENOMEM;
+
+ cs4349->regmap = devm_regmap_init_i2c(client, &cs4349_regmap);
+ if (IS_ERR(cs4349->regmap)) {
+ ret = PTR_ERR(cs4349->regmap);
+ dev_err(&client->dev, "regmap_init() failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Reset the Device */
+ cs4349->reset_gpio = devm_gpiod_get_optional(&client->dev,
+ "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(cs4349->reset_gpio))
+ return PTR_ERR(cs4349->reset_gpio);
+
+ gpiod_set_value_cansleep(cs4349->reset_gpio, 1);
+
+ i2c_set_clientdata(client, cs4349);
+
+ return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4349,
+ &cs4349_dai, 1);
+}
+
+static int cs4349_i2c_remove(struct i2c_client *client)
+{
+ struct cs4349_private *cs4349 = i2c_get_clientdata(client);
+
+ snd_soc_unregister_codec(&client->dev);
+
+ /* Hold down reset */
+ gpiod_set_value_cansleep(cs4349->reset_gpio, 0);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int cs4349_runtime_suspend(struct device *dev)
+{
+ struct cs4349_private *cs4349 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regmap_update_bits(cs4349->regmap, CS4349_MISC, PWR_DWN, PWR_DWN);
+ if (ret < 0)
+ return ret;
+
+ regcache_cache_only(cs4349->regmap, true);
+
+ /* Hold down reset */
+ gpiod_set_value_cansleep(cs4349->reset_gpio, 0);
+
+ return 0;
+}
+
+static int cs4349_runtime_resume(struct device *dev)
+{
+ struct cs4349_private *cs4349 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regmap_update_bits(cs4349->regmap, CS4349_MISC, PWR_DWN, 0);
+ if (ret < 0)
+ return ret;
+
+ gpiod_set_value_cansleep(cs4349->reset_gpio, 1);
+
+ regcache_cache_only(cs4349->regmap, false);
+ regcache_sync(cs4349->regmap);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops cs4349_runtime_pm = {
+ SET_RUNTIME_PM_OPS(cs4349_runtime_suspend, cs4349_runtime_resume,
+ NULL)
+};
+
+static const struct of_device_id cs4349_of_match[] = {
+ { .compatible = "cirrus,cs4349", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, cs4349_of_match);
+
+static const struct i2c_device_id cs4349_i2c_id[] = {
+ {"cs4349", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, cs4349_i2c_id);
+
+static struct i2c_driver cs4349_i2c_driver = {
+ .driver = {
+ .name = "cs4349",
+ .of_match_table = cs4349_of_match,
+ },
+ .id_table = cs4349_i2c_id,
+ .probe = cs4349_i2c_probe,
+ .remove = cs4349_i2c_remove,
+};
+
+module_i2c_driver(cs4349_i2c_driver);
+
+MODULE_AUTHOR("Tim Howe <tim.howe@cirrus.com>");
+MODULE_DESCRIPTION("Cirrus Logic CS4349 ALSA SoC Codec Driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs4349.h b/sound/soc/codecs/cs4349.h
new file mode 100644
index 000000000..d58c06a25
--- /dev/null
+++ b/sound/soc/codecs/cs4349.h
@@ -0,0 +1,136 @@
+/*
+ * ALSA SoC CS4349 codec driver
+ *
+ * Copyright 2015 Cirrus Logic, Inc.
+ *
+ * Author: Tim Howe <Tim.Howe@cirrus.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#ifndef __CS4349_H__
+#define __CS4349_H__
+
+/* CS4349 registers addresses */
+#define CS4349_CHIPID 0x01 /* Device and Rev ID, Read Only */
+#define CS4349_MODE 0x02 /* Mode Control */
+#define CS4349_VMI 0x03 /* Volume, Mixing, Inversion Control */
+#define CS4349_MUTE 0x04 /* Mute Control */
+#define CS4349_VOLA 0x05 /* DAC Channel A Volume Control */
+#define CS4349_VOLB 0x06 /* DAC Channel B Volume Control */
+#define CS4349_RMPFLT 0x07 /* Ramp and Filter Control */
+#define CS4349_MISC 0x08 /* Power Down,Freeze Control,Pop Stop*/
+
+#define CS4349_I2C_INCR 0x80
+
+
+/* Device and Revision ID */
+#define CS4349_REVA 0xF0 /* Rev A */
+#define CS4349_REVB 0xF1 /* Rev B */
+#define CS4349_REVC2 0xFF /* Rev C2 */
+
+
+/* PDN_DONE Poll Maximum
+ * If soft ramp is set it will take much longer to power down
+ * the system.
+ */
+#define PDN_POLL_MAX 900
+
+
+/* Bitfield Definitions */
+
+/* CS4349_MODE */
+/* (Digital Interface Format, De-Emphasis Control, Functional Mode */
+#define DIF2 (1 << 6)
+#define DIF1 (1 << 5)
+#define DIF0 (1 << 4)
+#define DEM1 (1 << 3)
+#define DEM0 (1 << 2)
+#define FM1 (1 << 1)
+#define DIF_LEFT_JST 0x00
+#define DIF_I2S 0x01
+#define DIF_RGHT_JST16 0x02
+#define DIF_RGHT_JST24 0x03
+#define DIF_TDM0 0x04
+#define DIF_TDM1 0x05
+#define DIF_TDM2 0x06
+#define DIF_TDM3 0x07
+#define DIF_MASK 0x70
+#define MODE_FORMAT(x) (((x)&7)<<4)
+#define DEM_MASK 0x0C
+#define NO_DEM 0x00
+#define DEM_441 0x04
+#define DEM_48K 0x08
+#define DEM_32K 0x0C
+#define FM_AUTO 0x00
+#define FM_SNGL 0x01
+#define FM_DBL 0x02
+#define FM_QUAD 0x03
+#define FM_SNGL_MIN 30000
+#define FM_SNGL_MAX 54000
+#define FM_DBL_MAX 108000
+#define FM_QUAD_MAX 216000
+#define FM_MASK 0x03
+
+/* CS4349_VMI (VMI = Volume, Mixing and Inversion Controls) */
+#define VOLBISA (1 << 7)
+#define VOLAISB (1 << 7)
+/* INVERT_A only available for Left Jstfd, Right Jstfd16 and Right Jstfd24 */
+#define INVERT_A (1 << 6)
+/* INVERT_B only available for Left Jstfd, Right Jstfd16 and Right Jstfd24 */
+#define INVERT_B (1 << 5)
+#define ATAPI3 (1 << 3)
+#define ATAPI2 (1 << 2)
+#define ATAPI1 (1 << 1)
+#define ATAPI0 (1 << 0)
+#define MUTEAB 0x00
+#define MUTEA_RIGHTB 0x01
+#define MUTEA_LEFTB 0x02
+#define MUTEA_SUMLRDIV2B 0x03
+#define RIGHTA_MUTEB 0x04
+#define RIGHTA_RIGHTB 0x05
+#define RIGHTA_LEFTB 0x06
+#define RIGHTA_SUMLRDIV2B 0x07
+#define LEFTA_MUTEB 0x08
+#define LEFTA_RIGHTB 0x09 /* Default */
+#define LEFTA_LEFTB 0x0A
+#define LEFTA_SUMLRDIV2B 0x0B
+#define SUMLRDIV2A_MUTEB 0x0C
+#define SUMLRDIV2A_RIGHTB 0x0D
+#define SUMLRDIV2A_LEFTB 0x0E
+#define SUMLRDIV2_AB 0x0F
+#define CHMIX_MASK 0x0F
+
+/* CS4349_MUTE */
+#define AUTOMUTE (1 << 7)
+#define MUTEC_AB (1 << 5)
+#define MUTE_A (1 << 4)
+#define MUTE_B (1 << 3)
+#define MUTE_AB_MASK 0x18
+
+/* CS4349_RMPFLT (Ramp and Filter Control) */
+#define SCZ1 (1 << 7)
+#define SCZ0 (1 << 6)
+#define RMP_UP (1 << 5)
+#define RMP_DN (1 << 4)
+#define FILT_SEL (1 << 2)
+#define IMMDT_CHNG 0x31
+#define ZEROCRSS 0x71
+#define SOFT_RMP 0xB1
+#define SFTRMP_ZEROCRSS 0xF1
+#define SR_ZC_MASK 0xC0
+
+/* CS4349_MISC */
+#define PWR_DWN (1 << 7)
+#define FREEZE (1 << 5)
+#define POPG_EN (1 << 4)
+
+#endif /* __CS4349_H__ */
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 21810e5f3..7dc52fe67 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -267,33 +267,29 @@ enum clk_src {
*
* Reserved area are considered as "mute".
*/
-static const unsigned int hp_out_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(hp_out_tlv,
0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
/* -54 dB to +15 dB */
- 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0),
-};
+ 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0)
+);
-static const unsigned int lineout_vol_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(lineout_vol_tlv,
0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
/* -54dB to 15dB */
0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0)
-};
+);
-static const unsigned int mono_vol_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(mono_vol_tlv,
0x0, 0x2, TLV_DB_SCALE_ITEM(-1800, 0, 1),
/* -18dB to 6dB */
0x3, 0x7, TLV_DB_SCALE_ITEM(-1800, 600, 0)
-};
+);
-static const unsigned int aux1_vol_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(aux1_vol_tlv,
0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
/* -48dB to 21dB */
0x11, 0x3f, TLV_DB_SCALE_ITEM(-4800, 150, 0)
-};
+);
static const DECLARE_TLV_DB_SCALE(eq_gain_tlv, -1050, 150, 0);
static const DECLARE_TLV_DB_SCALE(adc_eq_master_gain_tlv, -1800, 600, 1);
@@ -680,7 +676,7 @@ struct da7210_priv {
int master;
};
-static struct reg_default da7210_reg_defaults[] = {
+static const struct reg_default da7210_reg_defaults[] = {
{ 0x00, 0x00 },
{ 0x01, 0x11 },
{ 0x03, 0x00 },
@@ -1182,7 +1178,7 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
#if IS_ENABLED(CONFIG_I2C)
-static struct reg_default da7210_regmap_i2c_patch[] = {
+static const struct reg_sequence da7210_regmap_i2c_patch[] = {
/* System controller master disable */
{ DA7210_STARTUP1, 0x00 },
@@ -1259,7 +1255,6 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id);
static struct i2c_driver da7210_i2c_driver = {
.driver = {
.name = "da7210",
- .owner = THIS_MODULE,
},
.probe = da7210_i2c_probe,
.remove = da7210_i2c_remove,
@@ -1269,7 +1264,7 @@ static struct i2c_driver da7210_i2c_driver = {
#if defined(CONFIG_SPI_MASTER)
-static struct reg_default da7210_regmap_spi_patch[] = {
+static const struct reg_sequence da7210_regmap_spi_patch[] = {
/* Dummy read to give two pulses over nCS for SPI */
{ DA7210_AUX2, 0x00 },
{ DA7210_AUX2, 0x00 },
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c
index 238e48a3a..a9c86efb3 100644
--- a/sound/soc/codecs/da7213.c
+++ b/sound/soc/codecs/da7213.c
@@ -28,27 +28,24 @@
/* Gain and Volume */
-static const unsigned int aux_vol_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(aux_vol_tlv,
/* -54dB */
0x0, 0x11, TLV_DB_SCALE_ITEM(-5400, 0, 0),
/* -52.5dB to 15dB */
0x12, 0x3f, TLV_DB_SCALE_ITEM(-5250, 150, 0)
-};
+);
-static const unsigned int digital_gain_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(digital_gain_tlv,
0x0, 0x07, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
/* -78dB to 12dB */
0x08, 0x7f, TLV_DB_SCALE_ITEM(-7800, 75, 0)
-};
+);
-static const unsigned int alc_analog_gain_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(alc_analog_gain_tlv,
0x0, 0x0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
/* 0dB to 36dB */
0x01, 0x07, TLV_DB_SCALE_ITEM(0, 600, 0)
-};
+);
static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -600, 600, 0);
static const DECLARE_TLV_DB_SCALE(mixin_gain_tlv, -450, 150, 0);
@@ -954,7 +951,7 @@ static const struct snd_soc_dapm_route da7213_audio_map[] = {
{"LINE", NULL, "Lineout PGA"},
};
-static struct reg_default da7213_reg_defaults[] = {
+static const struct reg_default da7213_reg_defaults[] = {
{ DA7213_DIG_ROUTING_DAI, 0x10 },
{ DA7213_SR, 0x0A },
{ DA7213_REFERENCES, 0x80 },
@@ -1585,7 +1582,6 @@ MODULE_DEVICE_TABLE(i2c, da7213_i2c_id);
static struct i2c_driver da7213_i2c_driver = {
.driver = {
.name = "da7213",
- .owner = THIS_MODULE,
},
.probe = da7213_i2c_probe,
.remove = da7213_remove,
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
index 207523686..1d5a89c51 100644
--- a/sound/soc/codecs/da732x.c
+++ b/sound/soc/codecs/da732x.c
@@ -43,7 +43,7 @@ struct da732x_priv {
/*
* da732x register cache - default settings
*/
-static struct reg_default da732x_reg_cache[] = {
+static const struct reg_default da732x_reg_cache[] = {
{ DA732X_REG_REF1 , 0x02 },
{ DA732X_REG_BIAS_EN , 0x80 },
{ DA732X_REG_BIAS1 , 0x00 },
@@ -1196,13 +1196,7 @@ static int da732x_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
#define DA732X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops da732x_dai1_ops = {
- .hw_params = da732x_hw_params,
- .set_fmt = da732x_set_dai_fmt,
- .set_sysclk = da732x_set_dai_sysclk,
-};
-
-static struct snd_soc_dai_ops da732x_dai2_ops = {
+static const struct snd_soc_dai_ops da732x_dai_ops = {
.hw_params = da732x_hw_params,
.set_fmt = da732x_set_dai_fmt,
.set_sysclk = da732x_set_dai_sysclk,
@@ -1227,7 +1221,7 @@ static struct snd_soc_dai_driver da732x_dai[] = {
.rates = DA732X_RATES,
.formats = DA732X_FORMATS,
},
- .ops = &da732x_dai1_ops,
+ .ops = &da732x_dai_ops,
},
{
.name = "DA732X_AIFB",
@@ -1247,7 +1241,7 @@ static struct snd_soc_dai_driver da732x_dai[] = {
.rates = DA732X_RATES,
.formats = DA732X_FORMATS,
},
- .ops = &da732x_dai2_ops,
+ .ops = &da732x_dai_ops,
},
};
@@ -1572,7 +1566,6 @@ MODULE_DEVICE_TABLE(i2c, da732x_i2c_id);
static struct i2c_driver da732x_i2c_driver = {
.driver = {
.name = "da7320",
- .owner = THIS_MODULE,
},
.probe = da732x_i2c_probe,
.remove = da732x_i2c_remove,
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c
index 66bb44647..0b2ede8db 100644
--- a/sound/soc/codecs/da9055.c
+++ b/sound/soc/codecs/da9055.c
@@ -289,26 +289,23 @@ enum clk_src {
/* Gain and Volume */
-static const unsigned int aux_vol_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(aux_vol_tlv,
0x0, 0x10, TLV_DB_SCALE_ITEM(-5400, 0, 0),
/* -54dB to 15dB */
0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0)
-};
+);
-static const unsigned int digital_gain_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(digital_gain_tlv,
0x0, 0x07, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
/* -78dB to 12dB */
0x08, 0x7f, TLV_DB_SCALE_ITEM(-7800, 75, 0)
-};
+);
-static const unsigned int alc_analog_gain_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(alc_analog_gain_tlv,
0x0, 0x0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
/* 0dB to 36dB */
0x01, 0x07, TLV_DB_SCALE_ITEM(0, 600, 0)
-};
+);
static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -600, 600, 0);
static const DECLARE_TLV_DB_SCALE(mixin_gain_tlv, -450, 150, 0);
@@ -948,7 +945,7 @@ struct da9055_priv {
struct da9055_platform_data *pdata;
};
-static struct reg_default da9055_reg_defaults[] = {
+static const struct reg_default da9055_reg_defaults[] = {
{ 0x21, 0x10 },
{ 0x22, 0x0A },
{ 0x23, 0x00 },
@@ -1533,12 +1530,12 @@ static const struct of_device_id da9055_of_match[] = {
{ .compatible = "dlg,da9055-codec", },
{ }
};
+MODULE_DEVICE_TABLE(of, da9055_of_match);
/* I2C codec control layer */
static struct i2c_driver da9055_i2c_driver = {
.driver = {
.name = "da9055-codec",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(da9055_of_match),
},
.probe = da9055_i2c_probe,
diff --git a/sound/soc/codecs/gtm601.c b/sound/soc/codecs/gtm601.c
new file mode 100644
index 000000000..0b8005299
--- /dev/null
+++ b/sound/soc/codecs/gtm601.c
@@ -0,0 +1,95 @@
+/*
+ * This is a simple driver for the GTM601 Voice PCM interface
+ *
+ * Copyright (C) 2015 Goldelico GmbH
+ *
+ * Author: Marek Belisko <marek@goldelico.com>
+ *
+ * Based on wm8727.c driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+static const struct snd_soc_dapm_widget gtm601_dapm_widgets[] = {
+ SND_SOC_DAPM_OUTPUT("AOUT"),
+ SND_SOC_DAPM_INPUT("AIN"),
+};
+
+static const struct snd_soc_dapm_route gtm601_dapm_routes[] = {
+ { "AOUT", NULL, "Playback" },
+ { "Capture", NULL, "AIN" },
+};
+
+static struct snd_soc_dai_driver gtm601_dai = {
+ .name = "gtm601",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+};
+
+static const struct snd_soc_codec_driver soc_codec_dev_gtm601 = {
+ .dapm_widgets = gtm601_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(gtm601_dapm_widgets),
+ .dapm_routes = gtm601_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(gtm601_dapm_routes),
+};
+
+static int gtm601_platform_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_gtm601, &gtm601_dai, 1);
+}
+
+static int gtm601_platform_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id gtm601_codec_of_match[] = {
+ { .compatible = "option,gtm601", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, gtm601_codec_of_match);
+#endif
+
+static struct platform_driver gtm601_codec_driver = {
+ .driver = {
+ .name = "gtm601",
+ .of_match_table = of_match_ptr(gtm601_codec_of_match),
+ },
+ .probe = gtm601_platform_probe,
+ .remove = gtm601_platform_remove,
+};
+
+module_platform_driver(gtm601_codec_driver);
+
+MODULE_DESCRIPTION("ASoC gtm601 driver");
+MODULE_AUTHOR("Marek Belisko <marek@goldelico.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gtm601");
diff --git a/sound/soc/codecs/ics43432.c b/sound/soc/codecs/ics43432.c
new file mode 100644
index 000000000..dd850b939
--- /dev/null
+++ b/sound/soc/codecs/ics43432.c
@@ -0,0 +1,76 @@
+/*
+ * I2S MEMS microphone driver for InvenSense ICS-43432
+ *
+ * - Non configurable.
+ * - I2S interface, 64 BCLs per frame, 32 bits per channel, 24 bit data
+ *
+ * Copyright (c) 2015 Axis Communications AB
+ *
+ * Licensed under GPL v2.
+ */
+
+#include <linux/module.h>
+#include <linux/init.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>
+
+#define ICS43432_RATE_MIN 7190 /* Hz, from data sheet */
+#define ICS43432_RATE_MAX 52800 /* Hz, from data sheet */
+
+#define ICS43432_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32)
+
+static struct snd_soc_dai_driver ics43432_dai = {
+ .name = "ics43432-hifi",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = ICS43432_RATE_MIN,
+ .rate_max = ICS43432_RATE_MAX,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .formats = ICS43432_FORMATS,
+ },
+};
+
+static struct snd_soc_codec_driver ics43432_codec_driver = {
+};
+
+static int ics43432_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev, &ics43432_codec_driver,
+ &ics43432_dai, 1);
+}
+
+static int ics43432_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ics43432_ids[] = {
+ { .compatible = "invensense,ics43432", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ics43432_ids);
+#endif
+
+static struct platform_driver ics43432_driver = {
+ .driver = {
+ .name = "ics43432",
+ .of_match_table = of_match_ptr(ics43432_ids),
+ },
+ .probe = ics43432_probe,
+ .remove = ics43432_remove,
+};
+
+module_platform_driver(ics43432_driver);
+
+MODULE_DESCRIPTION("ASoC ICS43432 driver");
+MODULE_AUTHOR("Ricard Wanderlof <ricardw@axis.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c
index ebd90283c..be448373d 100644
--- a/sound/soc/codecs/isabelle.c
+++ b/sound/soc/codecs/isabelle.c
@@ -33,7 +33,7 @@
/* Register default values for ISABELLE driver. */
-static struct reg_default isabelle_reg_defs[] = {
+static const struct reg_default isabelle_reg_defs[] = {
{ 0, 0x00 },
{ 1, 0x00 },
{ 2, 0x00 },
@@ -1016,25 +1016,25 @@ static int isabelle_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
#define ISABELLE_FORMATS (SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops isabelle_hs_dai_ops = {
+static const struct snd_soc_dai_ops isabelle_hs_dai_ops = {
.hw_params = isabelle_hw_params,
.set_fmt = isabelle_set_dai_fmt,
.digital_mute = isabelle_hs_mute,
};
-static struct snd_soc_dai_ops isabelle_hf_dai_ops = {
+static const struct snd_soc_dai_ops isabelle_hf_dai_ops = {
.hw_params = isabelle_hw_params,
.set_fmt = isabelle_set_dai_fmt,
.digital_mute = isabelle_hf_mute,
};
-static struct snd_soc_dai_ops isabelle_line_dai_ops = {
+static const struct snd_soc_dai_ops isabelle_line_dai_ops = {
.hw_params = isabelle_hw_params,
.set_fmt = isabelle_set_dai_fmt,
.digital_mute = isabelle_line_mute,
};
-static struct snd_soc_dai_ops isabelle_ul_dai_ops = {
+static const struct snd_soc_dai_ops isabelle_ul_dai_ops = {
.hw_params = isabelle_hw_params,
.set_fmt = isabelle_set_dai_fmt,
};
@@ -1149,7 +1149,6 @@ MODULE_DEVICE_TABLE(i2c, isabelle_i2c_id);
static struct i2c_driver isabelle_i2c_driver = {
.driver = {
.name = "isabelle",
- .owner = THIS_MODULE,
},
.probe = isabelle_i2c_probe,
.remove = isabelle_i2c_remove,
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 9363fdbca..1f5ab9995 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -78,11 +78,10 @@ struct jz4740_codec {
struct regmap *regmap;
};
-static const unsigned int jz4740_mic_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(jz4740_mic_tlv,
0, 2, TLV_DB_SCALE_ITEM(0, 600, 0),
- 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0),
-};
+ 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0)
+);
static const DECLARE_TLV_DB_SCALE(jz4740_out_tlv, 0, 200, 0);
static const DECLARE_TLV_DB_SCALE(jz4740_in_tlv, -3450, 150, 0);
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 99ffc49aa..558de1053 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -142,7 +142,6 @@ MODULE_DEVICE_TABLE(i2c, lm4857_i2c_id);
static struct i2c_driver lm4857_i2c_driver = {
.driver = {
.name = "lm4857",
- .owner = THIS_MODULE,
},
.probe = lm4857_i2c_probe,
.id_table = lm4857_i2c_id,
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
index 6600aa0a3..9af5640e3 100644
--- a/sound/soc/codecs/lm49453.c
+++ b/sound/soc/codecs/lm49453.c
@@ -30,7 +30,7 @@
#include <asm/div64.h>
#include "lm49453.h"
-static struct reg_default lm49453_reg_defs[] = {
+static const struct reg_default lm49453_reg_defs[] = {
{ 0, 0x00 },
{ 1, 0x00 },
{ 2, 0x00 },
@@ -188,7 +188,6 @@ static struct reg_default lm49453_reg_defs[] = {
/* codec private data */
struct lm49453_priv {
struct regmap *regmap;
- int fs_rate;
};
/* capture path controls */
@@ -1112,13 +1111,10 @@ static int lm49453_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
- struct lm49453_priv *lm49453 = snd_soc_codec_get_drvdata(codec);
u16 clk_div = 0;
- lm49453->fs_rate = params_rate(params);
-
/* Setting DAC clock dividers based on substream sample rate. */
- switch (lm49453->fs_rate) {
+ switch (params_rate(params)) {
case 8000:
case 16000:
case 32000:
@@ -1291,35 +1287,35 @@ static int lm49453_set_bias_level(struct snd_soc_codec *codec,
#define LM49453_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops lm49453_headset_dai_ops = {
+static const struct snd_soc_dai_ops lm49453_headset_dai_ops = {
.hw_params = lm49453_hw_params,
.set_sysclk = lm49453_set_dai_sysclk,
.set_fmt = lm49453_set_dai_fmt,
.digital_mute = lm49453_hp_mute,
};
-static struct snd_soc_dai_ops lm49453_speaker_dai_ops = {
+static const struct snd_soc_dai_ops lm49453_speaker_dai_ops = {
.hw_params = lm49453_hw_params,
.set_sysclk = lm49453_set_dai_sysclk,
.set_fmt = lm49453_set_dai_fmt,
.digital_mute = lm49453_ls_mute,
};
-static struct snd_soc_dai_ops lm49453_haptic_dai_ops = {
+static const struct snd_soc_dai_ops lm49453_haptic_dai_ops = {
.hw_params = lm49453_hw_params,
.set_sysclk = lm49453_set_dai_sysclk,
.set_fmt = lm49453_set_dai_fmt,
.digital_mute = lm49453_ha_mute,
};
-static struct snd_soc_dai_ops lm49453_ep_dai_ops = {
+static const struct snd_soc_dai_ops lm49453_ep_dai_ops = {
.hw_params = lm49453_hw_params,
.set_sysclk = lm49453_set_dai_sysclk,
.set_fmt = lm49453_set_dai_fmt,
.digital_mute = lm49453_ep_mute,
};
-static struct snd_soc_dai_ops lm49453_lineout_dai_ops = {
+static const struct snd_soc_dai_ops lm49453_lineout_dai_ops = {
.hw_params = lm49453_hw_params,
.set_sysclk = lm49453_set_dai_sysclk,
.set_fmt = lm49453_set_dai_fmt,
@@ -1460,7 +1456,6 @@ MODULE_DEVICE_TABLE(i2c, lm49453_i2c_id);
static struct i2c_driver lm49453_i2c_driver = {
.driver = {
.name = "lm49453",
- .owner = THIS_MODULE,
},
.probe = lm49453_i2c_probe,
.remove = lm49453_i2c_remove,
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
index e1c196a41..5b82e26cd 100644
--- a/sound/soc/codecs/max9768.c
+++ b/sound/soc/codecs/max9768.c
@@ -35,7 +35,7 @@ struct max9768 {
u32 flags;
};
-static struct reg_default max9768_default_regs[] = {
+static const struct reg_default max9768_default_regs[] = {
{ 0, 0 },
{ 3, MAX9768_CTRL_FILTERLESS},
};
@@ -43,8 +43,8 @@ static struct reg_default max9768_default_regs[] = {
static int max9768_get_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
- struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
+ struct max9768 *max9768 = snd_soc_component_get_drvdata(c);
int val = gpio_get_value_cansleep(max9768->mute_gpio);
ucontrol->value.integer.value[0] = !val;
@@ -55,16 +55,15 @@ static int max9768_get_gpio(struct snd_kcontrol *kcontrol,
static int max9768_set_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
- struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
+ struct max9768 *max9768 = snd_soc_component_get_drvdata(c);
gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]);
return 0;
}
-static const unsigned int volume_tlv[] = {
- TLV_DB_RANGE_HEAD(43),
+static const DECLARE_TLV_DB_RANGE(volume_tlv,
0, 0, TLV_DB_SCALE_ITEM(-16150, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(-9280, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(-9030, 0, 0),
@@ -107,8 +106,8 @@ static const unsigned int volume_tlv[] = {
51, 57, TLV_DB_SCALE_ITEM(290, 50, 0),
58, 58, TLV_DB_SCALE_ITEM(650, 0, 0),
59, 62, TLV_DB_SCALE_ITEM(700, 60, 0),
- 63, 63, TLV_DB_SCALE_ITEM(950, 0, 0),
-};
+ 63, 63, TLV_DB_SCALE_ITEM(950, 0, 0)
+);
static const struct snd_kcontrol_new max9768_volume[] = {
SOC_SINGLE_TLV("Playback Volume", MAX9768_VOL, 0, 63, 0, volume_tlv),
@@ -130,19 +129,20 @@ static const struct snd_soc_dapm_route max9768_dapm_routes[] = {
{ "OUT-", NULL, "IN" },
};
-static int max9768_probe(struct snd_soc_codec *codec)
+static int max9768_probe(struct snd_soc_component *component)
{
- struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+ struct max9768 *max9768 = snd_soc_component_get_drvdata(component);
int ret;
if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) {
- ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM);
+ ret = regmap_write(max9768->regmap, MAX9768_CTRL,
+ MAX9768_CTRL_PWM);
if (ret)
return ret;
}
if (gpio_is_valid(max9768->mute_gpio)) {
- ret = snd_soc_add_codec_controls(codec, max9768_mute,
+ ret = snd_soc_add_component_controls(component, max9768_mute,
ARRAY_SIZE(max9768_mute));
if (ret)
return ret;
@@ -151,7 +151,7 @@ static int max9768_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_codec_driver max9768_codec_driver = {
+static struct snd_soc_component_driver max9768_component_driver = {
.probe = max9768_probe,
.controls = max9768_volume,
.num_controls = ARRAY_SIZE(max9768_volume),
@@ -183,11 +183,13 @@ static int max9768_i2c_probe(struct i2c_client *client,
if (pdata) {
/* Mute on powerup to avoid clicks */
- err = gpio_request_one(pdata->mute_gpio, GPIOF_INIT_HIGH, "MAX9768 Mute");
+ err = devm_gpio_request_one(&client->dev, pdata->mute_gpio,
+ GPIOF_INIT_HIGH, "MAX9768 Mute");
max9768->mute_gpio = err ?: pdata->mute_gpio;
/* Activate chip by releasing shutdown, enables I2C */
- err = gpio_request_one(pdata->shdn_gpio, GPIOF_INIT_HIGH, "MAX9768 Shutdown");
+ err = devm_gpio_request_one(&client->dev, pdata->shdn_gpio,
+ GPIOF_INIT_HIGH, "MAX9768 Shutdown");
max9768->shdn_gpio = err ?: pdata->shdn_gpio;
max9768->flags = pdata->flags;
@@ -199,38 +201,11 @@ static int max9768_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, max9768);
max9768->regmap = devm_regmap_init_i2c(client, &max9768_i2c_regmap_config);
- if (IS_ERR(max9768->regmap)) {
- err = PTR_ERR(max9768->regmap);
- goto err_gpio_free;
- }
+ if (IS_ERR(max9768->regmap))
+ return PTR_ERR(max9768->regmap);
- err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0);
- if (err)
- goto err_gpio_free;
-
- return 0;
-
- err_gpio_free:
- if (gpio_is_valid(max9768->shdn_gpio))
- gpio_free(max9768->shdn_gpio);
- if (gpio_is_valid(max9768->mute_gpio))
- gpio_free(max9768->mute_gpio);
-
- return err;
-}
-
-static int max9768_i2c_remove(struct i2c_client *client)
-{
- struct max9768 *max9768 = i2c_get_clientdata(client);
-
- snd_soc_unregister_codec(&client->dev);
-
- if (gpio_is_valid(max9768->shdn_gpio))
- gpio_free(max9768->shdn_gpio);
- if (gpio_is_valid(max9768->mute_gpio))
- gpio_free(max9768->mute_gpio);
-
- return 0;
+ return devm_snd_soc_register_component(&client->dev,
+ &max9768_component_driver, NULL, 0);
}
static const struct i2c_device_id max9768_i2c_id[] = {
@@ -242,10 +217,8 @@ MODULE_DEVICE_TABLE(i2c, max9768_i2c_id);
static struct i2c_driver max9768_i2c_driver = {
.driver = {
.name = "max9768",
- .owner = THIS_MODULE,
},
.probe = max9768_i2c_probe,
- .remove = max9768_i2c_remove,
.id_table = max9768_i2c_id,
};
module_i2c_driver(max9768_i2c_driver);
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index d0f45348b..20dcc496d 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -258,292 +258,36 @@ static const struct reg_default max98088_reg[] = {
{ 0xc9, 0x00 }, /* C9 DAI2 biquad */
};
-static struct {
- int readable;
- int writable;
- int vol;
-} max98088_access[M98088_REG_CNT] = {
- { 0xFF, 0xFF, 1 }, /* 00 IRQ status */
- { 0xFF, 0x00, 1 }, /* 01 MIC status */
- { 0xFF, 0x00, 1 }, /* 02 jack status */
- { 0x1F, 0x1F, 1 }, /* 03 battery voltage */
- { 0xFF, 0xFF, 0 }, /* 04 */
- { 0xFF, 0xFF, 0 }, /* 05 */
- { 0xFF, 0xFF, 0 }, /* 06 */
- { 0xFF, 0xFF, 0 }, /* 07 */
- { 0xFF, 0xFF, 0 }, /* 08 */
- { 0xFF, 0xFF, 0 }, /* 09 */
- { 0xFF, 0xFF, 0 }, /* 0A */
- { 0xFF, 0xFF, 0 }, /* 0B */
- { 0xFF, 0xFF, 0 }, /* 0C */
- { 0xFF, 0xFF, 0 }, /* 0D */
- { 0xFF, 0xFF, 0 }, /* 0E */
- { 0xFF, 0xFF, 0 }, /* 0F interrupt enable */
-
- { 0xFF, 0xFF, 0 }, /* 10 master clock */
- { 0xFF, 0xFF, 0 }, /* 11 DAI1 clock mode */
- { 0xFF, 0xFF, 0 }, /* 12 DAI1 clock control */
- { 0xFF, 0xFF, 0 }, /* 13 DAI1 clock control */
- { 0xFF, 0xFF, 0 }, /* 14 DAI1 format */
- { 0xFF, 0xFF, 0 }, /* 15 DAI1 clock */
- { 0xFF, 0xFF, 0 }, /* 16 DAI1 config */
- { 0xFF, 0xFF, 0 }, /* 17 DAI1 TDM */
- { 0xFF, 0xFF, 0 }, /* 18 DAI1 filters */
- { 0xFF, 0xFF, 0 }, /* 19 DAI2 clock mode */
- { 0xFF, 0xFF, 0 }, /* 1A DAI2 clock control */
- { 0xFF, 0xFF, 0 }, /* 1B DAI2 clock control */
- { 0xFF, 0xFF, 0 }, /* 1C DAI2 format */
- { 0xFF, 0xFF, 0 }, /* 1D DAI2 clock */
- { 0xFF, 0xFF, 0 }, /* 1E DAI2 config */
- { 0xFF, 0xFF, 0 }, /* 1F DAI2 TDM */
-
- { 0xFF, 0xFF, 0 }, /* 20 DAI2 filters */
- { 0xFF, 0xFF, 0 }, /* 21 data config */
- { 0xFF, 0xFF, 0 }, /* 22 DAC mixer */
- { 0xFF, 0xFF, 0 }, /* 23 left ADC mixer */
- { 0xFF, 0xFF, 0 }, /* 24 right ADC mixer */
- { 0xFF, 0xFF, 0 }, /* 25 left HP mixer */
- { 0xFF, 0xFF, 0 }, /* 26 right HP mixer */
- { 0xFF, 0xFF, 0 }, /* 27 HP control */
- { 0xFF, 0xFF, 0 }, /* 28 left REC mixer */
- { 0xFF, 0xFF, 0 }, /* 29 right REC mixer */
- { 0xFF, 0xFF, 0 }, /* 2A REC control */
- { 0xFF, 0xFF, 0 }, /* 2B left SPK mixer */
- { 0xFF, 0xFF, 0 }, /* 2C right SPK mixer */
- { 0xFF, 0xFF, 0 }, /* 2D SPK control */
- { 0xFF, 0xFF, 0 }, /* 2E sidetone */
- { 0xFF, 0xFF, 0 }, /* 2F DAI1 playback level */
-
- { 0xFF, 0xFF, 0 }, /* 30 DAI1 playback level */
- { 0xFF, 0xFF, 0 }, /* 31 DAI2 playback level */
- { 0xFF, 0xFF, 0 }, /* 32 DAI2 playbakc level */
- { 0xFF, 0xFF, 0 }, /* 33 left ADC level */
- { 0xFF, 0xFF, 0 }, /* 34 right ADC level */
- { 0xFF, 0xFF, 0 }, /* 35 MIC1 level */
- { 0xFF, 0xFF, 0 }, /* 36 MIC2 level */
- { 0xFF, 0xFF, 0 }, /* 37 INA level */
- { 0xFF, 0xFF, 0 }, /* 38 INB level */
- { 0xFF, 0xFF, 0 }, /* 39 left HP volume */
- { 0xFF, 0xFF, 0 }, /* 3A right HP volume */
- { 0xFF, 0xFF, 0 }, /* 3B left REC volume */
- { 0xFF, 0xFF, 0 }, /* 3C right REC volume */
- { 0xFF, 0xFF, 0 }, /* 3D left SPK volume */
- { 0xFF, 0xFF, 0 }, /* 3E right SPK volume */
- { 0xFF, 0xFF, 0 }, /* 3F MIC config */
-
- { 0xFF, 0xFF, 0 }, /* 40 MIC threshold */
- { 0xFF, 0xFF, 0 }, /* 41 excursion limiter filter */
- { 0xFF, 0xFF, 0 }, /* 42 excursion limiter threshold */
- { 0xFF, 0xFF, 0 }, /* 43 ALC */
- { 0xFF, 0xFF, 0 }, /* 44 power limiter threshold */
- { 0xFF, 0xFF, 0 }, /* 45 power limiter config */
- { 0xFF, 0xFF, 0 }, /* 46 distortion limiter config */
- { 0xFF, 0xFF, 0 }, /* 47 audio input */
- { 0xFF, 0xFF, 0 }, /* 48 microphone */
- { 0xFF, 0xFF, 0 }, /* 49 level control */
- { 0xFF, 0xFF, 0 }, /* 4A bypass switches */
- { 0xFF, 0xFF, 0 }, /* 4B jack detect */
- { 0xFF, 0xFF, 0 }, /* 4C input enable */
- { 0xFF, 0xFF, 0 }, /* 4D output enable */
- { 0xFF, 0xFF, 0 }, /* 4E bias control */
- { 0xFF, 0xFF, 0 }, /* 4F DAC power */
-
- { 0xFF, 0xFF, 0 }, /* 50 DAC power */
- { 0xFF, 0xFF, 0 }, /* 51 system */
- { 0xFF, 0xFF, 0 }, /* 52 DAI1 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 53 DAI1 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 54 DAI1 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 55 DAI1 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 56 DAI1 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 57 DAI1 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 58 DAI1 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 59 DAI1 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 5A DAI1 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 5B DAI1 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 5C DAI1 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 5D DAI1 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 5E DAI1 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 5F DAI1 EQ2 */
-
- { 0xFF, 0xFF, 0 }, /* 60 DAI1 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 61 DAI1 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 62 DAI1 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 63 DAI1 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 64 DAI1 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 65 DAI1 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 66 DAI1 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 67 DAI1 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 68 DAI1 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 69 DAI1 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 6A DAI1 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 6B DAI1 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 6C DAI1 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 6D DAI1 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 6E DAI1 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 6F DAI1 EQ3 */
-
- { 0xFF, 0xFF, 0 }, /* 70 DAI1 EQ4 */
- { 0xFF, 0xFF, 0 }, /* 71 DAI1 EQ4 */
- { 0xFF, 0xFF, 0 }, /* 72 DAI1 EQ4 */
- { 0xFF, 0xFF, 0 }, /* 73 DAI1 EQ4 */
- { 0xFF, 0xFF, 0 }, /* 74 DAI1 EQ4 */
- { 0xFF, 0xFF, 0 }, /* 75 DAI1 EQ4 */
- { 0xFF, 0xFF, 0 }, /* 76 DAI1 EQ4 */
- { 0xFF, 0xFF, 0 }, /* 77 DAI1 EQ4 */
- { 0xFF, 0xFF, 0 }, /* 78 DAI1 EQ4 */
- { 0xFF, 0xFF, 0 }, /* 79 DAI1 EQ4 */
- { 0xFF, 0xFF, 0 }, /* 7A DAI1 EQ5 */
- { 0xFF, 0xFF, 0 }, /* 7B DAI1 EQ5 */
- { 0xFF, 0xFF, 0 }, /* 7C DAI1 EQ5 */
- { 0xFF, 0xFF, 0 }, /* 7D DAI1 EQ5 */
- { 0xFF, 0xFF, 0 }, /* 7E DAI1 EQ5 */
- { 0xFF, 0xFF, 0 }, /* 7F DAI1 EQ5 */
-
- { 0xFF, 0xFF, 0 }, /* 80 DAI1 EQ5 */
- { 0xFF, 0xFF, 0 }, /* 81 DAI1 EQ5 */
- { 0xFF, 0xFF, 0 }, /* 82 DAI1 EQ5 */
- { 0xFF, 0xFF, 0 }, /* 83 DAI1 EQ5 */
- { 0xFF, 0xFF, 0 }, /* 84 DAI2 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 85 DAI2 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 86 DAI2 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 87 DAI2 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 88 DAI2 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 89 DAI2 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 8A DAI2 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 8B DAI2 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 8C DAI2 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 8D DAI2 EQ1 */
- { 0xFF, 0xFF, 0 }, /* 8E DAI2 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 8F DAI2 EQ2 */
-
- { 0xFF, 0xFF, 0 }, /* 90 DAI2 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 91 DAI2 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 92 DAI2 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 93 DAI2 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 94 DAI2 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 95 DAI2 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 96 DAI2 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 97 DAI2 EQ2 */
- { 0xFF, 0xFF, 0 }, /* 98 DAI2 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 99 DAI2 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 9A DAI2 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 9B DAI2 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 9C DAI2 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 9D DAI2 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 9E DAI2 EQ3 */
- { 0xFF, 0xFF, 0 }, /* 9F DAI2 EQ3 */
-
- { 0xFF, 0xFF, 0 }, /* A0 DAI2 EQ3 */
- { 0xFF, 0xFF, 0 }, /* A1 DAI2 EQ3 */
- { 0xFF, 0xFF, 0 }, /* A2 DAI2 EQ4 */
- { 0xFF, 0xFF, 0 }, /* A3 DAI2 EQ4 */
- { 0xFF, 0xFF, 0 }, /* A4 DAI2 EQ4 */
- { 0xFF, 0xFF, 0 }, /* A5 DAI2 EQ4 */
- { 0xFF, 0xFF, 0 }, /* A6 DAI2 EQ4 */
- { 0xFF, 0xFF, 0 }, /* A7 DAI2 EQ4 */
- { 0xFF, 0xFF, 0 }, /* A8 DAI2 EQ4 */
- { 0xFF, 0xFF, 0 }, /* A9 DAI2 EQ4 */
- { 0xFF, 0xFF, 0 }, /* AA DAI2 EQ4 */
- { 0xFF, 0xFF, 0 }, /* AB DAI2 EQ4 */
- { 0xFF, 0xFF, 0 }, /* AC DAI2 EQ5 */
- { 0xFF, 0xFF, 0 }, /* AD DAI2 EQ5 */
- { 0xFF, 0xFF, 0 }, /* AE DAI2 EQ5 */
- { 0xFF, 0xFF, 0 }, /* AF DAI2 EQ5 */
-
- { 0xFF, 0xFF, 0 }, /* B0 DAI2 EQ5 */
- { 0xFF, 0xFF, 0 }, /* B1 DAI2 EQ5 */
- { 0xFF, 0xFF, 0 }, /* B2 DAI2 EQ5 */
- { 0xFF, 0xFF, 0 }, /* B3 DAI2 EQ5 */
- { 0xFF, 0xFF, 0 }, /* B4 DAI2 EQ5 */
- { 0xFF, 0xFF, 0 }, /* B5 DAI2 EQ5 */
- { 0xFF, 0xFF, 0 }, /* B6 DAI1 biquad */
- { 0xFF, 0xFF, 0 }, /* B7 DAI1 biquad */
- { 0xFF, 0xFF, 0 }, /* B8 DAI1 biquad */
- { 0xFF, 0xFF, 0 }, /* B9 DAI1 biquad */
- { 0xFF, 0xFF, 0 }, /* BA DAI1 biquad */
- { 0xFF, 0xFF, 0 }, /* BB DAI1 biquad */
- { 0xFF, 0xFF, 0 }, /* BC DAI1 biquad */
- { 0xFF, 0xFF, 0 }, /* BD DAI1 biquad */
- { 0xFF, 0xFF, 0 }, /* BE DAI1 biquad */
- { 0xFF, 0xFF, 0 }, /* BF DAI1 biquad */
-
- { 0xFF, 0xFF, 0 }, /* C0 DAI2 biquad */
- { 0xFF, 0xFF, 0 }, /* C1 DAI2 biquad */
- { 0xFF, 0xFF, 0 }, /* C2 DAI2 biquad */
- { 0xFF, 0xFF, 0 }, /* C3 DAI2 biquad */
- { 0xFF, 0xFF, 0 }, /* C4 DAI2 biquad */
- { 0xFF, 0xFF, 0 }, /* C5 DAI2 biquad */
- { 0xFF, 0xFF, 0 }, /* C6 DAI2 biquad */
- { 0xFF, 0xFF, 0 }, /* C7 DAI2 biquad */
- { 0xFF, 0xFF, 0 }, /* C8 DAI2 biquad */
- { 0xFF, 0xFF, 0 }, /* C9 DAI2 biquad */
- { 0x00, 0x00, 0 }, /* CA */
- { 0x00, 0x00, 0 }, /* CB */
- { 0x00, 0x00, 0 }, /* CC */
- { 0x00, 0x00, 0 }, /* CD */
- { 0x00, 0x00, 0 }, /* CE */
- { 0x00, 0x00, 0 }, /* CF */
-
- { 0x00, 0x00, 0 }, /* D0 */
- { 0x00, 0x00, 0 }, /* D1 */
- { 0x00, 0x00, 0 }, /* D2 */
- { 0x00, 0x00, 0 }, /* D3 */
- { 0x00, 0x00, 0 }, /* D4 */
- { 0x00, 0x00, 0 }, /* D5 */
- { 0x00, 0x00, 0 }, /* D6 */
- { 0x00, 0x00, 0 }, /* D7 */
- { 0x00, 0x00, 0 }, /* D8 */
- { 0x00, 0x00, 0 }, /* D9 */
- { 0x00, 0x00, 0 }, /* DA */
- { 0x00, 0x00, 0 }, /* DB */
- { 0x00, 0x00, 0 }, /* DC */
- { 0x00, 0x00, 0 }, /* DD */
- { 0x00, 0x00, 0 }, /* DE */
- { 0x00, 0x00, 0 }, /* DF */
-
- { 0x00, 0x00, 0 }, /* E0 */
- { 0x00, 0x00, 0 }, /* E1 */
- { 0x00, 0x00, 0 }, /* E2 */
- { 0x00, 0x00, 0 }, /* E3 */
- { 0x00, 0x00, 0 }, /* E4 */
- { 0x00, 0x00, 0 }, /* E5 */
- { 0x00, 0x00, 0 }, /* E6 */
- { 0x00, 0x00, 0 }, /* E7 */
- { 0x00, 0x00, 0 }, /* E8 */
- { 0x00, 0x00, 0 }, /* E9 */
- { 0x00, 0x00, 0 }, /* EA */
- { 0x00, 0x00, 0 }, /* EB */
- { 0x00, 0x00, 0 }, /* EC */
- { 0x00, 0x00, 0 }, /* ED */
- { 0x00, 0x00, 0 }, /* EE */
- { 0x00, 0x00, 0 }, /* EF */
-
- { 0x00, 0x00, 0 }, /* F0 */
- { 0x00, 0x00, 0 }, /* F1 */
- { 0x00, 0x00, 0 }, /* F2 */
- { 0x00, 0x00, 0 }, /* F3 */
- { 0x00, 0x00, 0 }, /* F4 */
- { 0x00, 0x00, 0 }, /* F5 */
- { 0x00, 0x00, 0 }, /* F6 */
- { 0x00, 0x00, 0 }, /* F7 */
- { 0x00, 0x00, 0 }, /* F8 */
- { 0x00, 0x00, 0 }, /* F9 */
- { 0x00, 0x00, 0 }, /* FA */
- { 0x00, 0x00, 0 }, /* FB */
- { 0x00, 0x00, 0 }, /* FC */
- { 0x00, 0x00, 0 }, /* FD */
- { 0x00, 0x00, 0 }, /* FE */
- { 0xFF, 0x00, 1 }, /* FF */
-};
-
static bool max98088_readable_register(struct device *dev, unsigned int reg)
{
- return max98088_access[reg].readable;
+ switch (reg) {
+ case M98088_REG_00_IRQ_STATUS ... 0xC9:
+ case M98088_REG_FF_REV_ID:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool max98088_writeable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case M98088_REG_03_BATTERY_VOLTAGE ... 0xC9:
+ return true;
+ default:
+ return false;
+ }
}
static bool max98088_volatile_register(struct device *dev, unsigned int reg)
{
- return max98088_access[reg].vol;
+ switch (reg) {
+ case M98088_REG_00_IRQ_STATUS ... M98088_REG_03_BATTERY_VOLTAGE:
+ case M98088_REG_FF_REV_ID:
+ return true;
+ default:
+ return false;
+ }
}
static const struct regmap_config max98088_regmap = {
@@ -551,6 +295,7 @@ static const struct regmap_config max98088_regmap = {
.val_bits = 8,
.readable_reg = max98088_readable_register,
+ .writeable_reg = max98088_writeable_register,
.volatile_reg = max98088_volatile_register,
.max_register = 0xff,
@@ -680,29 +425,26 @@ static int max98088_mic2pre_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static const unsigned int max98088_micboost_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
- 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
- 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
-};
+static const DECLARE_TLV_DB_RANGE(max98088_micboost_tlv,
+ 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0)
+);
-static const unsigned int max98088_hp_tlv[] = {
- TLV_DB_RANGE_HEAD(5),
+static const DECLARE_TLV_DB_RANGE(max98088_hp_tlv,
0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0),
7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0),
15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0),
22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0),
- 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0),
-};
+ 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0)
+);
-static const unsigned int max98088_spk_tlv[] = {
- TLV_DB_RANGE_HEAD(5),
+static const DECLARE_TLV_DB_RANGE(max98088_spk_tlv,
0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0),
7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0),
15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0),
22, 27, TLV_DB_SCALE_ITEM(100, 100, 0),
- 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0),
-};
+ 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0)
+);
static const struct snd_kcontrol_new max98088_snd_controls[] = {
@@ -2011,7 +1753,6 @@ MODULE_DEVICE_TABLE(i2c, max98088_i2c_id);
static struct i2c_driver max98088_i2c_driver = {
.driver = {
.name = "max98088",
- .owner = THIS_MODULE,
},
.probe = max98088_i2c_probe,
.remove = max98088_i2c_remove,
diff --git a/sound/soc/codecs/max98088.h b/sound/soc/codecs/max98088.h
index be89a4f4a..efa39bf46 100644
--- a/sound/soc/codecs/max98088.h
+++ b/sound/soc/codecs/max98088.h
@@ -16,7 +16,7 @@
*/
#define M98088_REG_00_IRQ_STATUS 0x00
#define M98088_REG_01_MIC_STATUS 0x01
-#define M98088_REG_02_JACK_STAUS 0x02
+#define M98088_REG_02_JACK_STATUS 0x02
#define M98088_REG_03_BATTERY_VOLTAGE 0x03
#define M98088_REG_0F_IRQ_ENABLE 0x0F
#define M98088_REG_10_SYS_CLK 0x10
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index 78268f051..584aab83e 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -267,75 +267,8 @@ static bool max98090_volatile_register(struct device *dev, unsigned int reg)
static bool max98090_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
- case M98090_REG_DEVICE_STATUS:
- case M98090_REG_JACK_STATUS:
- case M98090_REG_INTERRUPT_S:
- case M98090_REG_RESERVED:
- case M98090_REG_LINE_INPUT_CONFIG:
- case M98090_REG_LINE_INPUT_LEVEL:
- case M98090_REG_INPUT_MODE:
- case M98090_REG_MIC1_INPUT_LEVEL:
- case M98090_REG_MIC2_INPUT_LEVEL:
- case M98090_REG_MIC_BIAS_VOLTAGE:
- case M98090_REG_DIGITAL_MIC_ENABLE:
- case M98090_REG_DIGITAL_MIC_CONFIG:
- case M98090_REG_LEFT_ADC_MIXER:
- case M98090_REG_RIGHT_ADC_MIXER:
- case M98090_REG_LEFT_ADC_LEVEL:
- case M98090_REG_RIGHT_ADC_LEVEL:
- case M98090_REG_ADC_BIQUAD_LEVEL:
- case M98090_REG_ADC_SIDETONE:
- case M98090_REG_SYSTEM_CLOCK:
- case M98090_REG_CLOCK_MODE:
- case M98090_REG_CLOCK_RATIO_NI_MSB:
- case M98090_REG_CLOCK_RATIO_NI_LSB:
- case M98090_REG_CLOCK_RATIO_MI_MSB:
- case M98090_REG_CLOCK_RATIO_MI_LSB:
- case M98090_REG_MASTER_MODE:
- case M98090_REG_INTERFACE_FORMAT:
- case M98090_REG_TDM_CONTROL:
- case M98090_REG_TDM_FORMAT:
- case M98090_REG_IO_CONFIGURATION:
- case M98090_REG_FILTER_CONFIG:
- case M98090_REG_DAI_PLAYBACK_LEVEL:
- case M98090_REG_DAI_PLAYBACK_LEVEL_EQ:
- case M98090_REG_LEFT_HP_MIXER:
- case M98090_REG_RIGHT_HP_MIXER:
- case M98090_REG_HP_CONTROL:
- case M98090_REG_LEFT_HP_VOLUME:
- case M98090_REG_RIGHT_HP_VOLUME:
- case M98090_REG_LEFT_SPK_MIXER:
- case M98090_REG_RIGHT_SPK_MIXER:
- case M98090_REG_SPK_CONTROL:
- case M98090_REG_LEFT_SPK_VOLUME:
- case M98090_REG_RIGHT_SPK_VOLUME:
- case M98090_REG_DRC_TIMING:
- case M98090_REG_DRC_COMPRESSOR:
- case M98090_REG_DRC_EXPANDER:
- case M98090_REG_DRC_GAIN:
- case M98090_REG_RCV_LOUTL_MIXER:
- case M98090_REG_RCV_LOUTL_CONTROL:
- case M98090_REG_RCV_LOUTL_VOLUME:
- case M98090_REG_LOUTR_MIXER:
- case M98090_REG_LOUTR_CONTROL:
- case M98090_REG_LOUTR_VOLUME:
- case M98090_REG_JACK_DETECT:
- case M98090_REG_INPUT_ENABLE:
- case M98090_REG_OUTPUT_ENABLE:
- case M98090_REG_LEVEL_CONTROL:
- case M98090_REG_DSP_FILTER_ENABLE:
- case M98090_REG_BIAS_CONTROL:
- case M98090_REG_DAC_CONTROL:
- case M98090_REG_ADC_CONTROL:
- case M98090_REG_DEVICE_SHUTDOWN:
- case M98090_REG_EQUALIZER_BASE ... M98090_REG_EQUALIZER_BASE + 0x68:
- case M98090_REG_RECORD_BIQUAD_BASE ... M98090_REG_RECORD_BIQUAD_BASE + 0x0E:
- case M98090_REG_DMIC3_VOLUME:
- case M98090_REG_DMIC4_VOLUME:
- case M98090_REG_DMIC34_BQ_PREATTEN:
- case M98090_REG_RECORD_TDM_SLOT:
- case M98090_REG_SAMPLE_RATE:
- case M98090_REG_DMIC34_BIQUAD_BASE ... M98090_REG_DMIC34_BIQUAD_BASE + 0x0E:
+ case M98090_REG_DEVICE_STATUS ... M98090_REG_INTERRUPT_S:
+ case M98090_REG_LINE_INPUT_CONFIG ... 0xD1:
case M98090_REG_REVISION_ID:
return true;
default:
@@ -360,22 +293,20 @@ static int max98090_reset(struct max98090_priv *max98090)
return ret;
}
-static const unsigned int max98090_micboost_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(max98090_micboost_tlv,
0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
- 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
-};
+ 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0)
+);
static const DECLARE_TLV_DB_SCALE(max98090_mic_tlv, 0, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_line_single_ended_tlv,
-600, 600, 0);
-static const unsigned int max98090_line_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(max98090_line_tlv,
0, 3, TLV_DB_SCALE_ITEM(-600, 300, 0),
- 4, 5, TLV_DB_SCALE_ITEM(1400, 600, 0),
-};
+ 4, 5, TLV_DB_SCALE_ITEM(1400, 600, 0)
+);
static const DECLARE_TLV_DB_SCALE(max98090_avg_tlv, 0, 600, 0);
static const DECLARE_TLV_DB_SCALE(max98090_av_tlv, -1200, 100, 0);
@@ -391,38 +322,34 @@ static const DECLARE_TLV_DB_SCALE(max98090_alccomp_tlv, -3100, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_drcexp_tlv, -6600, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_sdg_tlv, 50, 200, 0);
-static const unsigned int max98090_mixout_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(max98090_mixout_tlv,
0, 1, TLV_DB_SCALE_ITEM(-1200, 250, 0),
- 2, 3, TLV_DB_SCALE_ITEM(-600, 600, 0),
-};
+ 2, 3, TLV_DB_SCALE_ITEM(-600, 600, 0)
+);
-static const unsigned int max98090_hp_tlv[] = {
- TLV_DB_RANGE_HEAD(5),
+static const DECLARE_TLV_DB_RANGE(max98090_hp_tlv,
0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0),
7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0),
15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0),
22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0),
- 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0),
-};
+ 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0)
+);
-static const unsigned int max98090_spk_tlv[] = {
- TLV_DB_RANGE_HEAD(5),
+static const DECLARE_TLV_DB_RANGE(max98090_spk_tlv,
0, 4, TLV_DB_SCALE_ITEM(-4800, 400, 0),
5, 10, TLV_DB_SCALE_ITEM(-2900, 300, 0),
11, 14, TLV_DB_SCALE_ITEM(-1200, 200, 0),
15, 29, TLV_DB_SCALE_ITEM(-500, 100, 0),
- 30, 39, TLV_DB_SCALE_ITEM(950, 50, 0),
-};
+ 30, 39, TLV_DB_SCALE_ITEM(950, 50, 0)
+);
-static const unsigned int max98090_rcv_lout_tlv[] = {
- TLV_DB_RANGE_HEAD(5),
+static const DECLARE_TLV_DB_RANGE(max98090_rcv_lout_tlv,
0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0),
7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0),
15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0),
22, 27, TLV_DB_SCALE_ITEM(100, 100, 0),
- 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0),
-};
+ 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0)
+);
static int max98090_get_enab_tlv(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -850,6 +777,19 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static int max98090_shdn_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
+
+ if (event & SND_SOC_DAPM_POST_PMU)
+ max98090->shdn_pending = true;
+
+ return 0;
+
+}
+
static const char *mic1_mux_text[] = { "IN12", "IN56" };
static SOC_ENUM_SINGLE_DECL(mic1_mux_enum,
@@ -1158,9 +1098,11 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("SDOEN", M98090_REG_IO_CONFIGURATION,
M98090_SDOEN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DMICL_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
- M98090_DIGMICL_SHIFT, 0, NULL, 0),
+ M98090_DIGMICL_SHIFT, 0, max98090_shdn_event,
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("DMICR_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
- M98090_DIGMICR_SHIFT, 0, NULL, 0),
+ M98090_DIGMICR_SHIFT, 0, max98090_shdn_event,
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("AHPF", M98090_REG_FILTER_CONFIG,
M98090_AHPF_SHIFT, 0, NULL, 0),
@@ -1205,10 +1147,12 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
&max98090_right_adc_mixer_controls[0],
ARRAY_SIZE(max98090_right_adc_mixer_controls)),
- SND_SOC_DAPM_ADC("ADCL", NULL, M98090_REG_INPUT_ENABLE,
- M98090_ADLEN_SHIFT, 0),
- SND_SOC_DAPM_ADC("ADCR", NULL, M98090_REG_INPUT_ENABLE,
- M98090_ADREN_SHIFT, 0),
+ SND_SOC_DAPM_ADC_E("ADCL", NULL, M98090_REG_INPUT_ENABLE,
+ M98090_ADLEN_SHIFT, 0, max98090_shdn_event,
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_ADC_E("ADCR", NULL, M98090_REG_INPUT_ENABLE,
+ M98090_ADREN_SHIFT, 0, max98090_shdn_event,
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_AIF_OUT("AIFOUTL", "HiFi Capture", 0,
SND_SOC_NOPM, 0, 0),
@@ -1801,10 +1745,13 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec,
if (IS_ERR(max98090->mclk))
break;
- if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON)
+ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) {
clk_disable_unprepare(max98090->mclk);
- else
- clk_prepare_enable(max98090->mclk);
+ } else {
+ ret = clk_prepare_enable(max98090->mclk);
+ if (ret)
+ return ret;
+ }
break;
case SND_SOC_BIAS_STANDBY:
@@ -2383,7 +2330,7 @@ EXPORT_SYMBOL_GPL(max98090_mic_detect);
#define MAX98090_RATES SNDRV_PCM_RATE_8000_96000
#define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops max98090_dai_ops = {
+static const struct snd_soc_dai_ops max98090_dai_ops = {
.set_sysclk = max98090_dai_set_sysclk,
.set_fmt = max98090_dai_set_fmt,
.set_tdm_slot = max98090_set_tdm_slot,
@@ -2536,9 +2483,26 @@ static int max98090_remove(struct snd_soc_codec *codec)
return 0;
}
+static void max98090_seq_notifier(struct snd_soc_dapm_context *dapm,
+ enum snd_soc_dapm_type event, int subseq)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
+ struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
+
+ if (max98090->shdn_pending) {
+ snd_soc_update_bits(codec, M98090_REG_DEVICE_SHUTDOWN,
+ M98090_SHDNN_MASK, 0);
+ msleep(40);
+ snd_soc_update_bits(codec, M98090_REG_DEVICE_SHUTDOWN,
+ M98090_SHDNN_MASK, M98090_SHDNN_MASK);
+ max98090->shdn_pending = false;
+ }
+}
+
static struct snd_soc_codec_driver soc_codec_dev_max98090 = {
.probe = max98090_probe,
.remove = max98090_remove,
+ .seq_notifier = max98090_seq_notifier,
.set_bias_level = max98090_set_bias_level,
};
@@ -2714,7 +2678,6 @@ MODULE_DEVICE_TABLE(acpi, max98090_acpi_match);
static struct i2c_driver max98090_i2c_driver = {
.driver = {
.name = "max98090",
- .owner = THIS_MODULE,
.pm = &max98090_pm,
.of_match_table = of_match_ptr(max98090_of_match),
.acpi_match_table = ACPI_PTR(max98090_acpi_match),
diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h
index 21ff743f5..bc610d9a9 100644
--- a/sound/soc/codecs/max98090.h
+++ b/sound/soc/codecs/max98090.h
@@ -1543,6 +1543,7 @@ struct max98090_priv {
unsigned int pa2en;
unsigned int sidetone;
bool master;
+ bool shdn_pending;
};
int max98090_mic_detect(struct snd_soc_codec *codec,
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 9a46d3dcf..1fedac503 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -202,300 +202,36 @@ static const struct reg_default max98095_reg_def[] = {
{ 0xff, 0x00 }, /* FF */
};
-static struct {
- int readable;
- int writable;
-} max98095_access[M98095_REG_CNT] = {
- { 0x00, 0x00 }, /* 00 */
- { 0xFF, 0x00 }, /* 01 */
- { 0xFF, 0x00 }, /* 02 */
- { 0xFF, 0x00 }, /* 03 */
- { 0xFF, 0x00 }, /* 04 */
- { 0xFF, 0x00 }, /* 05 */
- { 0xFF, 0x00 }, /* 06 */
- { 0xFF, 0x00 }, /* 07 */
- { 0xFF, 0x00 }, /* 08 */
- { 0xFF, 0x00 }, /* 09 */
- { 0xFF, 0x00 }, /* 0A */
- { 0xFF, 0x00 }, /* 0B */
- { 0xFF, 0x00 }, /* 0C */
- { 0xFF, 0x00 }, /* 0D */
- { 0xFF, 0x00 }, /* 0E */
- { 0xFF, 0x9F }, /* 0F */
- { 0xFF, 0xFF }, /* 10 */
- { 0xFF, 0xFF }, /* 11 */
- { 0xFF, 0xFF }, /* 12 */
- { 0xFF, 0xFF }, /* 13 */
- { 0xFF, 0xFF }, /* 14 */
- { 0xFF, 0xFF }, /* 15 */
- { 0xFF, 0xFF }, /* 16 */
- { 0xFF, 0xFF }, /* 17 */
- { 0xFF, 0xFF }, /* 18 */
- { 0xFF, 0xFF }, /* 19 */
- { 0xFF, 0xFF }, /* 1A */
- { 0xFF, 0xFF }, /* 1B */
- { 0xFF, 0xFF }, /* 1C */
- { 0xFF, 0xFF }, /* 1D */
- { 0xFF, 0x77 }, /* 1E */
- { 0xFF, 0x77 }, /* 1F */
- { 0xFF, 0x77 }, /* 20 */
- { 0xFF, 0x77 }, /* 21 */
- { 0xFF, 0x77 }, /* 22 */
- { 0xFF, 0x77 }, /* 23 */
- { 0xFF, 0xFF }, /* 24 */
- { 0xFF, 0x7F }, /* 25 */
- { 0xFF, 0x31 }, /* 26 */
- { 0xFF, 0xFF }, /* 27 */
- { 0xFF, 0xFF }, /* 28 */
- { 0xFF, 0xFF }, /* 29 */
- { 0xFF, 0xF7 }, /* 2A */
- { 0xFF, 0x2F }, /* 2B */
- { 0xFF, 0xEF }, /* 2C */
- { 0xFF, 0xFF }, /* 2D */
- { 0xFF, 0xFF }, /* 2E */
- { 0xFF, 0xFF }, /* 2F */
- { 0xFF, 0xFF }, /* 30 */
- { 0xFF, 0xFF }, /* 31 */
- { 0xFF, 0xFF }, /* 32 */
- { 0xFF, 0xFF }, /* 33 */
- { 0xFF, 0xF7 }, /* 34 */
- { 0xFF, 0x2F }, /* 35 */
- { 0xFF, 0xCF }, /* 36 */
- { 0xFF, 0xFF }, /* 37 */
- { 0xFF, 0xFF }, /* 38 */
- { 0xFF, 0xFF }, /* 39 */
- { 0xFF, 0xFF }, /* 3A */
- { 0xFF, 0xFF }, /* 3B */
- { 0xFF, 0xFF }, /* 3C */
- { 0xFF, 0xFF }, /* 3D */
- { 0xFF, 0xF7 }, /* 3E */
- { 0xFF, 0x2F }, /* 3F */
- { 0xFF, 0xCF }, /* 40 */
- { 0xFF, 0xFF }, /* 41 */
- { 0xFF, 0x77 }, /* 42 */
- { 0xFF, 0xFF }, /* 43 */
- { 0xFF, 0xFF }, /* 44 */
- { 0xFF, 0xFF }, /* 45 */
- { 0xFF, 0xFF }, /* 46 */
- { 0xFF, 0xFF }, /* 47 */
- { 0xFF, 0xFF }, /* 48 */
- { 0xFF, 0x0F }, /* 49 */
- { 0xFF, 0xFF }, /* 4A */
- { 0xFF, 0xFF }, /* 4B */
- { 0xFF, 0x3F }, /* 4C */
- { 0xFF, 0x3F }, /* 4D */
- { 0xFF, 0x3F }, /* 4E */
- { 0xFF, 0xFF }, /* 4F */
- { 0xFF, 0x7F }, /* 50 */
- { 0xFF, 0x7F }, /* 51 */
- { 0xFF, 0x0F }, /* 52 */
- { 0xFF, 0x3F }, /* 53 */
- { 0xFF, 0x3F }, /* 54 */
- { 0xFF, 0x3F }, /* 55 */
- { 0xFF, 0xFF }, /* 56 */
- { 0xFF, 0xFF }, /* 57 */
- { 0xFF, 0xBF }, /* 58 */
- { 0xFF, 0x1F }, /* 59 */
- { 0xFF, 0xBF }, /* 5A */
- { 0xFF, 0x1F }, /* 5B */
- { 0xFF, 0xBF }, /* 5C */
- { 0xFF, 0x3F }, /* 5D */
- { 0xFF, 0x3F }, /* 5E */
- { 0xFF, 0x7F }, /* 5F */
- { 0xFF, 0x7F }, /* 60 */
- { 0xFF, 0x47 }, /* 61 */
- { 0xFF, 0x9F }, /* 62 */
- { 0xFF, 0x9F }, /* 63 */
- { 0xFF, 0x9F }, /* 64 */
- { 0xFF, 0x9F }, /* 65 */
- { 0xFF, 0x9F }, /* 66 */
- { 0xFF, 0xBF }, /* 67 */
- { 0xFF, 0xBF }, /* 68 */
- { 0xFF, 0xFF }, /* 69 */
- { 0xFF, 0xFF }, /* 6A */
- { 0xFF, 0x7F }, /* 6B */
- { 0xFF, 0xF7 }, /* 6C */
- { 0xFF, 0xFF }, /* 6D */
- { 0xFF, 0xFF }, /* 6E */
- { 0xFF, 0x1F }, /* 6F */
- { 0xFF, 0xF7 }, /* 70 */
- { 0xFF, 0xFF }, /* 71 */
- { 0xFF, 0xFF }, /* 72 */
- { 0xFF, 0x1F }, /* 73 */
- { 0xFF, 0xF7 }, /* 74 */
- { 0xFF, 0xFF }, /* 75 */
- { 0xFF, 0xFF }, /* 76 */
- { 0xFF, 0x1F }, /* 77 */
- { 0xFF, 0xF7 }, /* 78 */
- { 0xFF, 0xFF }, /* 79 */
- { 0xFF, 0xFF }, /* 7A */
- { 0xFF, 0x1F }, /* 7B */
- { 0xFF, 0xF7 }, /* 7C */
- { 0xFF, 0xFF }, /* 7D */
- { 0xFF, 0xFF }, /* 7E */
- { 0xFF, 0x1F }, /* 7F */
- { 0xFF, 0xF7 }, /* 80 */
- { 0xFF, 0xFF }, /* 81 */
- { 0xFF, 0xFF }, /* 82 */
- { 0xFF, 0x1F }, /* 83 */
- { 0xFF, 0x7F }, /* 84 */
- { 0xFF, 0x0F }, /* 85 */
- { 0xFF, 0xD8 }, /* 86 */
- { 0xFF, 0xFF }, /* 87 */
- { 0xFF, 0xEF }, /* 88 */
- { 0xFF, 0xFE }, /* 89 */
- { 0xFF, 0xFE }, /* 8A */
- { 0xFF, 0xFF }, /* 8B */
- { 0xFF, 0xFF }, /* 8C */
- { 0xFF, 0x3F }, /* 8D */
- { 0xFF, 0xFF }, /* 8E */
- { 0xFF, 0x3F }, /* 8F */
- { 0xFF, 0x8F }, /* 90 */
- { 0xFF, 0xFF }, /* 91 */
- { 0xFF, 0x3F }, /* 92 */
- { 0xFF, 0xFF }, /* 93 */
- { 0xFF, 0xFF }, /* 94 */
- { 0xFF, 0x0F }, /* 95 */
- { 0xFF, 0x3F }, /* 96 */
- { 0xFF, 0x8C }, /* 97 */
- { 0x00, 0x00 }, /* 98 */
- { 0x00, 0x00 }, /* 99 */
- { 0x00, 0x00 }, /* 9A */
- { 0x00, 0x00 }, /* 9B */
- { 0x00, 0x00 }, /* 9C */
- { 0x00, 0x00 }, /* 9D */
- { 0x00, 0x00 }, /* 9E */
- { 0x00, 0x00 }, /* 9F */
- { 0x00, 0x00 }, /* A0 */
- { 0x00, 0x00 }, /* A1 */
- { 0x00, 0x00 }, /* A2 */
- { 0x00, 0x00 }, /* A3 */
- { 0x00, 0x00 }, /* A4 */
- { 0x00, 0x00 }, /* A5 */
- { 0x00, 0x00 }, /* A6 */
- { 0x00, 0x00 }, /* A7 */
- { 0x00, 0x00 }, /* A8 */
- { 0x00, 0x00 }, /* A9 */
- { 0x00, 0x00 }, /* AA */
- { 0x00, 0x00 }, /* AB */
- { 0x00, 0x00 }, /* AC */
- { 0x00, 0x00 }, /* AD */
- { 0x00, 0x00 }, /* AE */
- { 0x00, 0x00 }, /* AF */
- { 0x00, 0x00 }, /* B0 */
- { 0x00, 0x00 }, /* B1 */
- { 0x00, 0x00 }, /* B2 */
- { 0x00, 0x00 }, /* B3 */
- { 0x00, 0x00 }, /* B4 */
- { 0x00, 0x00 }, /* B5 */
- { 0x00, 0x00 }, /* B6 */
- { 0x00, 0x00 }, /* B7 */
- { 0x00, 0x00 }, /* B8 */
- { 0x00, 0x00 }, /* B9 */
- { 0x00, 0x00 }, /* BA */
- { 0x00, 0x00 }, /* BB */
- { 0x00, 0x00 }, /* BC */
- { 0x00, 0x00 }, /* BD */
- { 0x00, 0x00 }, /* BE */
- { 0x00, 0x00 }, /* BF */
- { 0x00, 0x00 }, /* C0 */
- { 0x00, 0x00 }, /* C1 */
- { 0x00, 0x00 }, /* C2 */
- { 0x00, 0x00 }, /* C3 */
- { 0x00, 0x00 }, /* C4 */
- { 0x00, 0x00 }, /* C5 */
- { 0x00, 0x00 }, /* C6 */
- { 0x00, 0x00 }, /* C7 */
- { 0x00, 0x00 }, /* C8 */
- { 0x00, 0x00 }, /* C9 */
- { 0x00, 0x00 }, /* CA */
- { 0x00, 0x00 }, /* CB */
- { 0x00, 0x00 }, /* CC */
- { 0x00, 0x00 }, /* CD */
- { 0x00, 0x00 }, /* CE */
- { 0x00, 0x00 }, /* CF */
- { 0x00, 0x00 }, /* D0 */
- { 0x00, 0x00 }, /* D1 */
- { 0x00, 0x00 }, /* D2 */
- { 0x00, 0x00 }, /* D3 */
- { 0x00, 0x00 }, /* D4 */
- { 0x00, 0x00 }, /* D5 */
- { 0x00, 0x00 }, /* D6 */
- { 0x00, 0x00 }, /* D7 */
- { 0x00, 0x00 }, /* D8 */
- { 0x00, 0x00 }, /* D9 */
- { 0x00, 0x00 }, /* DA */
- { 0x00, 0x00 }, /* DB */
- { 0x00, 0x00 }, /* DC */
- { 0x00, 0x00 }, /* DD */
- { 0x00, 0x00 }, /* DE */
- { 0x00, 0x00 }, /* DF */
- { 0x00, 0x00 }, /* E0 */
- { 0x00, 0x00 }, /* E1 */
- { 0x00, 0x00 }, /* E2 */
- { 0x00, 0x00 }, /* E3 */
- { 0x00, 0x00 }, /* E4 */
- { 0x00, 0x00 }, /* E5 */
- { 0x00, 0x00 }, /* E6 */
- { 0x00, 0x00 }, /* E7 */
- { 0x00, 0x00 }, /* E8 */
- { 0x00, 0x00 }, /* E9 */
- { 0x00, 0x00 }, /* EA */
- { 0x00, 0x00 }, /* EB */
- { 0x00, 0x00 }, /* EC */
- { 0x00, 0x00 }, /* ED */
- { 0x00, 0x00 }, /* EE */
- { 0x00, 0x00 }, /* EF */
- { 0x00, 0x00 }, /* F0 */
- { 0x00, 0x00 }, /* F1 */
- { 0x00, 0x00 }, /* F2 */
- { 0x00, 0x00 }, /* F3 */
- { 0x00, 0x00 }, /* F4 */
- { 0x00, 0x00 }, /* F5 */
- { 0x00, 0x00 }, /* F6 */
- { 0x00, 0x00 }, /* F7 */
- { 0x00, 0x00 }, /* F8 */
- { 0x00, 0x00 }, /* F9 */
- { 0x00, 0x00 }, /* FA */
- { 0x00, 0x00 }, /* FB */
- { 0x00, 0x00 }, /* FC */
- { 0x00, 0x00 }, /* FD */
- { 0x00, 0x00 }, /* FE */
- { 0xFF, 0x00 }, /* FF */
-};
-
static bool max98095_readable(struct device *dev, unsigned int reg)
{
- if (reg >= M98095_REG_CNT)
- return 0;
- return max98095_access[reg].readable != 0;
+ switch (reg) {
+ case M98095_001_HOST_INT_STS ... M98095_097_PWR_SYS:
+ case M98095_0FF_REV_ID:
+ return true;
+ default:
+ return false;
+ }
}
-static bool max98095_volatile(struct device *dev, unsigned int reg)
+static bool max98095_writeable(struct device *dev, unsigned int reg)
{
- if (reg > M98095_REG_MAX_CACHED)
- return 1;
-
switch (reg) {
- case M98095_000_HOST_DATA:
- case M98095_001_HOST_INT_STS:
- case M98095_002_HOST_RSP_STS:
- case M98095_003_HOST_CMD_STS:
- case M98095_004_CODEC_STS:
- case M98095_005_DAI1_ALC_STS:
- case M98095_006_DAI2_ALC_STS:
- case M98095_007_JACK_AUTO_STS:
- case M98095_008_JACK_MANUAL_STS:
- case M98095_009_JACK_VBAT_STS:
- case M98095_00A_ACC_ADC_STS:
- case M98095_00B_MIC_NG_AGC_STS:
- case M98095_00C_SPK_L_VOLT_STS:
- case M98095_00D_SPK_R_VOLT_STS:
- case M98095_00E_TEMP_SENSOR_STS:
- return 1;
+ case M98095_00F_HOST_CFG ... M98095_097_PWR_SYS:
+ return true;
+ default:
+ return false;
}
+}
- return 0;
+static bool max98095_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case M98095_000_HOST_DATA ... M98095_00E_TEMP_SENSOR_STS:
+ case M98095_REG_MAX_CACHED + 1 ... M98095_0FF_REV_ID:
+ return true;
+ default:
+ return false;
+ }
}
static const struct regmap_config max98095_regmap = {
@@ -508,6 +244,7 @@ static const struct regmap_config max98095_regmap = {
.cache_type = REGCACHE_RBTREE,
.readable_reg = max98095_readable,
+ .writeable_reg = max98095_writeable,
.volatile_reg = max98095_volatile,
};
@@ -661,48 +398,43 @@ static int max98095_mic2pre_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static const unsigned int max98095_micboost_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(max98095_micboost_tlv,
0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
- 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
-};
+ 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0)
+);
static const DECLARE_TLV_DB_SCALE(max98095_mic_tlv, 0, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98095_adc_tlv, -1200, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98095_adcboost_tlv, 0, 600, 0);
-static const unsigned int max98095_hp_tlv[] = {
- TLV_DB_RANGE_HEAD(5),
+static const DECLARE_TLV_DB_RANGE(max98095_hp_tlv,
0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0),
7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0),
15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0),
22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0),
- 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0),
-};
+ 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0)
+);
-static const unsigned int max98095_spk_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+static const DECLARE_TLV_DB_RANGE(max98095_spk_tlv,
0, 10, TLV_DB_SCALE_ITEM(-5900, 400, 0),
11, 18, TLV_DB_SCALE_ITEM(-1700, 200, 0),
19, 27, TLV_DB_SCALE_ITEM(-200, 100, 0),
- 28, 39, TLV_DB_SCALE_ITEM(650, 50, 0),
-};
+ 28, 39, TLV_DB_SCALE_ITEM(650, 50, 0)
+);
-static const unsigned int max98095_rcv_lout_tlv[] = {
- TLV_DB_RANGE_HEAD(5),
+static const DECLARE_TLV_DB_RANGE(max98095_rcv_lout_tlv,
0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0),
7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0),
15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0),
22, 27, TLV_DB_SCALE_ITEM(100, 100, 0),
- 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0),
-};
+ 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0)
+);
-static const unsigned int max98095_lin_tlv[] = {
- TLV_DB_RANGE_HEAD(3),
+static const DECLARE_TLV_DB_RANGE(max98095_lin_tlv,
0, 2, TLV_DB_SCALE_ITEM(-600, 300, 0),
3, 3, TLV_DB_SCALE_ITEM(300, 1100, 0),
- 4, 5, TLV_DB_SCALE_ITEM(1400, 600, 0),
-};
+ 4, 5, TLV_DB_SCALE_ITEM(1400, 600, 0)
+);
static const struct snd_kcontrol_new max98095_snd_controls[] = {
@@ -1653,10 +1385,13 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec,
if (IS_ERR(max98095->mclk))
break;
- if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON)
+ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) {
clk_disable_unprepare(max98095->mclk);
- else
- clk_prepare_enable(max98095->mclk);
+ } else {
+ ret = clk_prepare_enable(max98095->mclk);
+ if (ret)
+ return ret;
+ }
break;
case SND_SOC_BIAS_STANDBY:
@@ -2431,7 +2166,6 @@ MODULE_DEVICE_TABLE(of, max98095_of_match);
static struct i2c_driver max98095_i2c_driver = {
.driver = {
.name = "max98095",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(max98095_of_match),
},
.probe = max98095_i2c_probe,
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
index 3a2fda08a..f5e3dce26 100644
--- a/sound/soc/codecs/max98357a.c
+++ b/sound/soc/codecs/max98357a.c
@@ -31,6 +31,9 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
{
struct gpio_desc *sdmode = snd_soc_dai_get_drvdata(dai);
+ if (!sdmode)
+ return 0;
+
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
@@ -48,24 +51,21 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
}
static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = {
- SND_SOC_DAPM_DAC("SDMode", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_OUTPUT("Speaker"),
};
static const struct snd_soc_dapm_route max98357a_dapm_routes[] = {
- {"Speaker", NULL, "SDMode"},
+ {"Speaker", NULL, "HiFi Playback"},
};
static int max98357a_codec_probe(struct snd_soc_codec *codec)
{
struct gpio_desc *sdmode;
- sdmode = devm_gpiod_get(codec->dev, "sdmode", GPIOD_OUT_LOW);
- if (IS_ERR(sdmode)) {
- dev_err(codec->dev, "%s() unable to get sdmode GPIO: %ld\n",
- __func__, PTR_ERR(sdmode));
+ sdmode = devm_gpiod_get_optional(codec->dev, "sdmode", GPIOD_OUT_LOW);
+ if (IS_ERR(sdmode))
return PTR_ERR(sdmode);
- }
+
snd_soc_codec_set_drvdata(codec, sdmode);
return 0;
@@ -79,7 +79,7 @@ static struct snd_soc_codec_driver max98357a_codec_driver = {
.num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes),
};
-static struct snd_soc_dai_ops max98357a_dai_ops = {
+static const struct snd_soc_dai_ops max98357a_dai_ops = {
.trigger = max98357a_daiops_trigger,
};
@@ -104,15 +104,8 @@ static struct snd_soc_dai_driver max98357a_dai_driver = {
static int max98357a_platform_probe(struct platform_device *pdev)
{
- int ret;
-
- ret = snd_soc_register_codec(&pdev->dev, &max98357a_codec_driver,
+ return snd_soc_register_codec(&pdev->dev, &max98357a_codec_driver,
&max98357a_dai_driver, 1);
- if (ret)
- dev_err(&pdev->dev, "%s() error registering codec driver: %d\n",
- __func__, ret);
-
- return ret;
}
static int max98357a_platform_remove(struct platform_device *pdev)
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
index 481d58f1c..c14a79d02 100644
--- a/sound/soc/codecs/max9850.c
+++ b/sound/soc/codecs/max9850.c
@@ -67,13 +67,12 @@ static const struct regmap_config max9850_regmap = {
.cache_type = REGCACHE_RBTREE,
};
-static const unsigned int max9850_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+static const DECLARE_TLV_DB_RANGE(max9850_tlv,
0x18, 0x1f, TLV_DB_SCALE_ITEM(-7450, 400, 0),
0x20, 0x33, TLV_DB_SCALE_ITEM(-4150, 200, 0),
0x34, 0x37, TLV_DB_SCALE_ITEM(-150, 100, 0),
- 0x38, 0x3f, TLV_DB_SCALE_ITEM(250, 50, 0),
-};
+ 0x38, 0x3f, TLV_DB_SCALE_ITEM(250, 50, 0)
+);
static const struct snd_kcontrol_new max9850_controls[] = {
SOC_SINGLE_TLV("Headphone Volume", MAX9850_VOLUME, 0, 0x3f, 1, max9850_tlv),
@@ -352,7 +351,6 @@ MODULE_DEVICE_TABLE(i2c, max9850_i2c_id);
static struct i2c_driver max9850_i2c_driver = {
.driver = {
.name = "max9850",
- .owner = THIS_MODULE,
},
.probe = max9850_i2c_probe,
.remove = max9850_i2c_remove,
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
index 29549cdbf..61cc18e35 100644
--- a/sound/soc/codecs/max9877.c
+++ b/sound/soc/codecs/max9877.c
@@ -20,9 +20,7 @@
#include "max9877.h"
-static struct regmap *regmap;
-
-static struct reg_default max9877_regs[] = {
+static const struct reg_default max9877_regs[] = {
{ 0, 0x40 },
{ 1, 0x00 },
{ 2, 0x00 },
@@ -30,19 +28,17 @@ static struct reg_default max9877_regs[] = {
{ 4, 0x49 },
};
-static const unsigned int max9877_pgain_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(max9877_pgain_tlv,
0, 1, TLV_DB_SCALE_ITEM(0, 900, 0),
- 2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0),
-};
+ 2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0)
+);
-static const unsigned int max9877_output_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+static const DECLARE_TLV_DB_RANGE(max9877_output_tlv,
0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1),
8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0),
16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0),
- 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0),
-};
+ 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0)
+);
static const char *max9877_out_mode[] = {
"INA -> SPK",
@@ -123,7 +119,7 @@ static const struct snd_soc_dapm_route max9877_dapm_routes[] = {
{ "HPR", NULL, "SHDN" },
};
-static const struct snd_soc_codec_driver max9877_codec = {
+static const struct snd_soc_component_driver max9877_component_driver = {
.controls = max9877_controls,
.num_controls = ARRAY_SIZE(max9877_controls),
@@ -145,6 +141,7 @@ static const struct regmap_config max9877_regmap = {
static int max9877_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct regmap *regmap;
int i;
regmap = devm_regmap_init_i2c(client, &max9877_regmap);
@@ -155,14 +152,8 @@ static int max9877_i2c_probe(struct i2c_client *client,
for (i = 0; i < ARRAY_SIZE(max9877_regs); i++)
regmap_write(regmap, max9877_regs[i].reg, max9877_regs[i].def);
- return snd_soc_register_codec(&client->dev, &max9877_codec, NULL, 0);
-}
-
-static int max9877_i2c_remove(struct i2c_client *client)
-{
- snd_soc_unregister_codec(&client->dev);
-
- return 0;
+ return devm_snd_soc_register_component(&client->dev,
+ &max9877_component_driver, NULL, 0);
}
static const struct i2c_device_id max9877_i2c_id[] = {
@@ -174,10 +165,8 @@ MODULE_DEVICE_TABLE(i2c, max9877_i2c_id);
static struct i2c_driver max9877_i2c_driver = {
.driver = {
.name = "max9877",
- .owner = THIS_MODULE,
},
.probe = max9877_i2c_probe,
- .remove = max9877_i2c_remove,
.id_table = max9877_i2c_id,
};
diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c
index aad664225..5990de317 100644
--- a/sound/soc/codecs/max98925.c
+++ b/sound/soc/codecs/max98925.c
@@ -271,8 +271,6 @@ static inline int max98925_rate_value(struct snd_soc_codec *codec,
break;
}
}
- dev_dbg(codec->dev, "%s: sample rate is %d, returning %d\n",
- __func__, rate_table[i].rate, *value);
return ret;
}
@@ -432,7 +430,7 @@ static int max98925_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec;
struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
- switch (snd_pcm_format_width(params_format(params))) {
+ switch (params_width(params)) {
case 16:
regmap_update_bits(max98925->regmap,
MAX98925_FORMAT,
@@ -523,7 +521,6 @@ static int max98925_probe(struct snd_soc_codec *codec)
struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
max98925->codec = codec;
- codec->control_data = max98925->regmap;
regmap_write(max98925->regmap, MAX98925_GLOBAL_ENABLE, 0x00);
/* It's not the default but we need to set DAI_DLY */
regmap_write(max98925->regmap,
@@ -639,7 +636,6 @@ MODULE_DEVICE_TABLE(of, max98925_of_match);
static struct i2c_driver max98925_i2c_driver = {
.driver = {
.name = "max98925",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(max98925_of_match),
.pm = NULL,
},
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index 3d44fc50e..3e770cbe7 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -650,14 +650,14 @@ static int mc13783_remove(struct snd_soc_codec *codec)
#define MC13783_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops mc13783_ops_dac = {
+static const struct snd_soc_dai_ops mc13783_ops_dac = {
.hw_params = mc13783_pcm_hw_params_dac,
.set_fmt = mc13783_set_fmt_async,
.set_sysclk = mc13783_set_sysclk_dac,
.set_tdm_slot = mc13783_set_tdm_slot_dac,
};
-static struct snd_soc_dai_ops mc13783_ops_codec = {
+static const struct snd_soc_dai_ops mc13783_ops_codec = {
.hw_params = mc13783_pcm_hw_params_codec,
.set_fmt = mc13783_set_fmt_async,
.set_sysclk = mc13783_set_sysclk_codec,
@@ -698,7 +698,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = {
},
};
-static struct snd_soc_dai_ops mc13783_ops_sync = {
+static const struct snd_soc_dai_ops mc13783_ops_sync = {
.hw_params = mc13783_pcm_hw_params_sync,
.set_fmt = mc13783_set_fmt_sync,
.set_sysclk = mc13783_set_sysclk_sync,
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index b74118e01..f561c78b9 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -199,7 +199,7 @@ static const struct clk_coeff coeff_div[] = {
{12288000, 48000, 0xc, 0x0, 0x30, 0x0, 0x4},
};
-static struct reg_default ml26124_reg[] = {
+static const struct reg_default ml26124_reg[] = {
/* CLOCK control Register */
{0x00, 0x00 }, /* Sampling Rate */
{0x02, 0x00}, /* PLL NL */
@@ -597,7 +597,6 @@ MODULE_DEVICE_TABLE(i2c, ml26124_i2c_id);
static struct i2c_driver ml26124_i2c_driver = {
.driver = {
.name = "ml26124",
- .owner = THIS_MODULE,
},
.probe = ml26124_i2c_probe,
.remove = ml26124_i2c_remove,
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c
index e7ba55797..583252342 100644
--- a/sound/soc/codecs/pcm1681.c
+++ b/sound/soc/codecs/pcm1681.c
@@ -95,17 +95,22 @@ static int pcm1681_set_deemph(struct snd_soc_codec *codec)
struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
int i = 0, val = -1, enable = 0;
- if (priv->deemph)
- for (i = 0; i < ARRAY_SIZE(pcm1681_deemph); i++)
- if (pcm1681_deemph[i] == priv->rate)
+ if (priv->deemph) {
+ for (i = 0; i < ARRAY_SIZE(pcm1681_deemph); i++) {
+ if (pcm1681_deemph[i] == priv->rate) {
val = i;
+ break;
+ }
+ }
+ }
if (val != -1) {
regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL,
PCM1681_DEEMPH_RATE_MASK, val << 3);
enable = 1;
- } else
+ } else {
enable = 0;
+ }
/* enable/disable deemphasis functionality */
return regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL,
@@ -330,7 +335,6 @@ static int pcm1681_i2c_remove(struct i2c_client *client)
static struct i2c_driver pcm1681_i2c_driver = {
.driver = {
.name = "pcm1681",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcm1681_dt_ids),
},
.id_table = pcm1681_i2c_id,
diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c
index dcdfac0ff..dbff416e3 100644
--- a/sound/soc/codecs/pcm512x-i2c.c
+++ b/sound/soc/codecs/pcm512x-i2c.c
@@ -67,7 +67,6 @@ static struct i2c_driver pcm512x_i2c_driver = {
.id_table = pcm512x_i2c_id,
.driver = {
.name = "pcm512x",
- .owner = THIS_MODULE,
.of_match_table = pcm512x_of_match,
.pm = &pcm512x_pm_ops,
},
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index de16429f0..047c48953 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -1117,7 +1117,7 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
params_rate(params),
params_channels(params));
- switch (snd_pcm_format_width(params_format(params))) {
+ switch (params_width(params)) {
case 16:
alen = PCM512x_ALEN_16;
break;
@@ -1132,7 +1132,7 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
break;
default:
dev_err(codec->dev, "Bad frame size: %d\n",
- snd_pcm_format_width(params_format(params)));
+ params_width(params));
return -EINVAL;
}
diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c
index 56650d6c2..aca479fa7 100644
--- a/sound/soc/codecs/rl6231.c
+++ b/sound/soc/codecs/rl6231.c
@@ -11,38 +11,98 @@
*/
#include <linux/module.h>
+#include <linux/regmap.h>
#include "rl6231.h"
/**
- * rl6231_calc_dmic_clk - Calculate the parameter of dmic.
+ * rl6231_get_pre_div - Return the value of pre divider.
+ *
+ * @map: map for setting.
+ * @reg: register.
+ * @sft: shift.
+ *
+ * Return the value of pre divider from given register value.
+ * Return negative error code for unexpected register value.
+ */
+int rl6231_get_pre_div(struct regmap *map, unsigned int reg, int sft)
+{
+ int pd, val;
+
+ regmap_read(map, reg, &val);
+
+ val = (val >> sft) & 0x7;
+
+ switch (val) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ pd = val + 1;
+ break;
+ case 4:
+ pd = 6;
+ break;
+ case 5:
+ pd = 8;
+ break;
+ case 6:
+ pd = 12;
+ break;
+ case 7:
+ pd = 16;
+ break;
+ default:
+ pd = -EINVAL;
+ break;
+ }
+
+ return pd;
+}
+EXPORT_SYMBOL_GPL(rl6231_get_pre_div);
+
+/**
+ * rl6231_calc_dmic_clk - Calculate the frequency divider parameter of dmic.
*
* @rate: base clock rate.
*
- * Choose dmic clock between 1MHz and 3MHz.
- * It is better for clock to approximate 3MHz.
+ * Choose divider parameter that gives the highest possible DMIC frequency in
+ * 1MHz - 3MHz range.
*/
int rl6231_calc_dmic_clk(int rate)
{
- int div[] = {2, 3, 4, 6, 8, 12}, idx = -EINVAL;
- int i, red, bound, temp;
+ int div[] = {2, 3, 4, 6, 8, 12};
+ int i;
+
+ if (rate < 1000000 * div[0]) {
+ pr_warn("Base clock rate %d is too low\n", rate);
+ return -EINVAL;
+ }
- red = 3000000 * 12;
for (i = 0; i < ARRAY_SIZE(div); i++) {
- bound = div[i] * 3000000;
- if (rate > bound)
- continue;
- temp = bound - rate;
- if (temp < red) {
- red = temp;
- idx = i;
- }
+ /* find divider that gives DMIC frequency below 3MHz */
+ if (3000000 * div[i] >= rate)
+ return i;
}
- return idx;
+ pr_warn("Base clock rate %d is too high\n", rate);
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(rl6231_calc_dmic_clk);
+struct pll_calc_map {
+ unsigned int pll_in;
+ unsigned int pll_out;
+ int k;
+ int n;
+ int m;
+ bool m_bp;
+};
+
+static const struct pll_calc_map pll_preset_table[] = {
+ {19200000, 24576000, 3, 30, 3, false},
+};
+
/**
* rl6231_pll_calc - Calcualte PLL M/N/K code.
* @freq_in: external clock provided to codec.
@@ -57,7 +117,7 @@ int rl6231_pll_calc(const unsigned int freq_in,
const unsigned int freq_out, struct rl6231_pll_code *pll_code)
{
int max_n = RL6231_PLL_N_MAX, max_m = RL6231_PLL_M_MAX;
- int k, red, n_t, pll_out, in_t, out_t;
+ int i, k, red, n_t, pll_out, in_t, out_t;
int n = 0, m = 0, m_t = 0;
int red_t = abs(freq_out - freq_in);
bool bypass = false;
@@ -65,6 +125,18 @@ int rl6231_pll_calc(const unsigned int freq_in,
if (RL6231_PLL_INP_MAX < freq_in || RL6231_PLL_INP_MIN > freq_in)
return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(pll_preset_table); i++) {
+ if (freq_in == pll_preset_table[i].pll_in &&
+ freq_out == pll_preset_table[i].pll_out) {
+ k = pll_preset_table[i].k;
+ m = pll_preset_table[i].m;
+ n = pll_preset_table[i].n;
+ bypass = pll_preset_table[i].m_bp;
+ pr_debug("Use preset PLL parameter table\n");
+ goto code_find;
+ }
+ }
+
k = 100000000 / freq_out - 2;
if (k > RL6231_PLL_K_MAX)
k = RL6231_PLL_K_MAX;
diff --git a/sound/soc/codecs/rl6231.h b/sound/soc/codecs/rl6231.h
index 0f7b057ed..4c77b441f 100644
--- a/sound/soc/codecs/rl6231.h
+++ b/sound/soc/codecs/rl6231.h
@@ -30,5 +30,6 @@ int rl6231_calc_dmic_clk(int rate);
int rl6231_pll_calc(const unsigned int freq_in,
const unsigned int freq_out, struct rl6231_pll_code *pll_code);
int rl6231_get_clk_info(int sclk, int rate);
+int rl6231_get_pre_div(struct regmap *map, unsigned int reg, int sft);
#endif /* __RL6231_H__ */
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index 5c43e263b..bd9365885 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -38,7 +38,7 @@
#define RT288_VENDOR_ID 0x10ec0288
struct rt286_priv {
- struct reg_default *index_cache;
+ const struct reg_default *index_cache;
int index_cache_size;
struct regmap *regmap;
struct snd_soc_codec *codec;
@@ -50,7 +50,7 @@ struct rt286_priv {
int clk_id;
};
-static struct reg_default rt286_index_def[] = {
+static const struct reg_default rt286_index_def[] = {
{ 0x01, 0xaaaa },
{ 0x02, 0x8aaa },
{ 0x03, 0x0002 },
@@ -1108,7 +1108,7 @@ static const struct acpi_device_id rt286_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, rt286_acpi_match);
-static struct dmi_system_id force_combo_jack_table[] = {
+static const struct dmi_system_id force_combo_jack_table[] = {
{
.ident = "Intel Wilson Beach",
.matches = {
@@ -1118,7 +1118,7 @@ static struct dmi_system_id force_combo_jack_table[] = {
{ }
};
-static struct dmi_system_id dmi_dell_dino[] = {
+static const struct dmi_system_id dmi_dell_dino[] = {
{
.ident = "Dell Dino",
.matches = {
@@ -1157,7 +1157,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
}
if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) {
dev_err(&i2c->dev,
- "Device with ID register %x is not rt286\n", val);
+ "Device with ID register %#x is not rt286\n", val);
return -ENODEV;
}
@@ -1259,7 +1259,6 @@ static int rt286_i2c_remove(struct i2c_client *i2c)
static struct i2c_driver rt286_i2c_driver = {
.driver = {
.name = "rt286",
- .owner = THIS_MODULE,
.acpi_match_table = ACPI_PTR(rt286_acpi_match),
},
.probe = rt286_i2c_probe,
diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c
new file mode 100644
index 000000000..f823eb502
--- /dev/null
+++ b/sound/soc/codecs/rt298.c
@@ -0,0 +1,1271 @@
+/*
+ * rt298.c -- RT298 ALSA SoC audio codec driver
+ *
+ * Copyright 2015 Realtek Semiconductor Corp.
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#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/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/acpi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/jack.h>
+#include <linux/workqueue.h>
+#include <sound/rt298.h>
+#include <sound/hda_verbs.h>
+
+#include "rl6347a.h"
+#include "rt298.h"
+
+#define RT298_VENDOR_ID 0x10ec0298
+
+struct rt298_priv {
+ struct reg_default *index_cache;
+ int index_cache_size;
+ struct regmap *regmap;
+ struct snd_soc_codec *codec;
+ struct rt298_platform_data pdata;
+ struct i2c_client *i2c;
+ struct snd_soc_jack *jack;
+ struct delayed_work jack_detect_work;
+ int sys_clk;
+ int clk_id;
+ int is_hp_in;
+};
+
+static struct reg_default rt298_index_def[] = {
+ { 0x01, 0xa5a8 },
+ { 0x02, 0x8e95 },
+ { 0x03, 0x0002 },
+ { 0x04, 0xaf67 },
+ { 0x08, 0x200f },
+ { 0x09, 0xd010 },
+ { 0x0a, 0x0100 },
+ { 0x0b, 0x0000 },
+ { 0x0d, 0x2800 },
+ { 0x0f, 0x0022 },
+ { 0x19, 0x0217 },
+ { 0x20, 0x0020 },
+ { 0x33, 0x0208 },
+ { 0x46, 0x0300 },
+ { 0x49, 0x4004 },
+ { 0x4f, 0x50c9 },
+ { 0x50, 0x3000 },
+ { 0x63, 0x1b02 },
+ { 0x67, 0x1111 },
+ { 0x68, 0x1016 },
+ { 0x69, 0x273f },
+};
+#define INDEX_CACHE_SIZE ARRAY_SIZE(rt298_index_def)
+
+static const struct reg_default rt298_reg[] = {
+ { 0x00170500, 0x00000400 },
+ { 0x00220000, 0x00000031 },
+ { 0x00239000, 0x0000007f },
+ { 0x0023a000, 0x0000007f },
+ { 0x00270500, 0x00000400 },
+ { 0x00370500, 0x00000400 },
+ { 0x00870500, 0x00000400 },
+ { 0x00920000, 0x00000031 },
+ { 0x00935000, 0x000000c3 },
+ { 0x00936000, 0x000000c3 },
+ { 0x00970500, 0x00000400 },
+ { 0x00b37000, 0x00000097 },
+ { 0x00b37200, 0x00000097 },
+ { 0x00b37300, 0x00000097 },
+ { 0x00c37000, 0x00000000 },
+ { 0x00c37100, 0x00000080 },
+ { 0x01270500, 0x00000400 },
+ { 0x01370500, 0x00000400 },
+ { 0x01371f00, 0x411111f0 },
+ { 0x01439000, 0x00000080 },
+ { 0x0143a000, 0x00000080 },
+ { 0x01470700, 0x00000000 },
+ { 0x01470500, 0x00000400 },
+ { 0x01470c00, 0x00000000 },
+ { 0x01470100, 0x00000000 },
+ { 0x01837000, 0x00000000 },
+ { 0x01870500, 0x00000400 },
+ { 0x02050000, 0x00000000 },
+ { 0x02139000, 0x00000080 },
+ { 0x0213a000, 0x00000080 },
+ { 0x02170100, 0x00000000 },
+ { 0x02170500, 0x00000400 },
+ { 0x02170700, 0x00000000 },
+ { 0x02270100, 0x00000000 },
+ { 0x02370100, 0x00000000 },
+ { 0x01870700, 0x00000020 },
+ { 0x00830000, 0x000000c3 },
+ { 0x00930000, 0x000000c3 },
+ { 0x01270700, 0x00000000 },
+};
+
+static bool rt298_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case 0 ... 0xff:
+ case RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID):
+ case RT298_GET_HP_SENSE:
+ case RT298_GET_MIC1_SENSE:
+ case RT298_PROC_COEF:
+ case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_MIC1, 0):
+ case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_SPK_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_HP_OUT, 0):
+ return true;
+ default:
+ return true;
+ }
+
+
+}
+
+static bool rt298_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case 0 ... 0xff:
+ case RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID):
+ case RT298_GET_HP_SENSE:
+ case RT298_GET_MIC1_SENSE:
+ case RT298_SET_AUDIO_POWER:
+ case RT298_SET_HPO_POWER:
+ case RT298_SET_SPK_POWER:
+ case RT298_SET_DMIC1_POWER:
+ case RT298_SPK_MUX:
+ case RT298_HPO_MUX:
+ case RT298_ADC0_MUX:
+ case RT298_ADC1_MUX:
+ case RT298_SET_MIC1:
+ case RT298_SET_PIN_HPO:
+ case RT298_SET_PIN_SPK:
+ case RT298_SET_PIN_DMIC1:
+ case RT298_SPK_EAPD:
+ case RT298_SET_AMP_GAIN_HPO:
+ case RT298_SET_DMIC2_DEFAULT:
+ case RT298_DACL_GAIN:
+ case RT298_DACR_GAIN:
+ case RT298_ADCL_GAIN:
+ case RT298_ADCR_GAIN:
+ case RT298_MIC_GAIN:
+ case RT298_SPOL_GAIN:
+ case RT298_SPOR_GAIN:
+ case RT298_HPOL_GAIN:
+ case RT298_HPOR_GAIN:
+ case RT298_F_DAC_SWITCH:
+ case RT298_F_RECMIX_SWITCH:
+ case RT298_REC_MIC_SWITCH:
+ case RT298_REC_I2S_SWITCH:
+ case RT298_REC_LINE_SWITCH:
+ case RT298_REC_BEEP_SWITCH:
+ case RT298_DAC_FORMAT:
+ case RT298_ADC_FORMAT:
+ case RT298_COEF_INDEX:
+ case RT298_PROC_COEF:
+ case RT298_SET_AMP_GAIN_ADC_IN1:
+ case RT298_SET_AMP_GAIN_ADC_IN2:
+ case RT298_SET_POWER(RT298_DAC_OUT1):
+ case RT298_SET_POWER(RT298_DAC_OUT2):
+ case RT298_SET_POWER(RT298_ADC_IN1):
+ case RT298_SET_POWER(RT298_ADC_IN2):
+ case RT298_SET_POWER(RT298_DMIC2):
+ case RT298_SET_POWER(RT298_MIC1):
+ case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_MIC1, 0):
+ case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_SPK_OUT, 0):
+ case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_HP_OUT, 0):
+ return true;
+ default:
+ return false;
+ }
+}
+
+#ifdef CONFIG_PM
+static void rt298_index_sync(struct snd_soc_codec *codec)
+{
+ struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec);
+ int i;
+
+ for (i = 0; i < INDEX_CACHE_SIZE; i++) {
+ snd_soc_write(codec, rt298->index_cache[i].reg,
+ rt298->index_cache[i].def);
+ }
+}
+#endif
+
+static int rt298_support_power_controls[] = {
+ RT298_DAC_OUT1,
+ RT298_DAC_OUT2,
+ RT298_ADC_IN1,
+ RT298_ADC_IN2,
+ RT298_MIC1,
+ RT298_DMIC1,
+ RT298_DMIC2,
+ RT298_SPK_OUT,
+ RT298_HP_OUT,
+};
+#define RT298_POWER_REG_LEN ARRAY_SIZE(rt298_support_power_controls)
+
+static int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic)
+{
+ struct snd_soc_dapm_context *dapm;
+ unsigned int val, buf;
+
+ *hp = false;
+ *mic = false;
+
+ if (!rt298->codec)
+ return -EINVAL;
+
+ dapm = snd_soc_codec_get_dapm(rt298->codec);
+
+ if (rt298->pdata.cbj_en) {
+ regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf);
+ *hp = buf & 0x80000000;
+ if (*hp == rt298->is_hp_in)
+ return -1;
+ rt298->is_hp_in = *hp;
+ if (*hp) {
+ /* power on HV,VERF */
+ regmap_update_bits(rt298->regmap,
+ RT298_DC_GAIN, 0x200, 0x200);
+
+ snd_soc_dapm_force_enable_pin(dapm, "HV");
+ snd_soc_dapm_force_enable_pin(dapm, "VREF");
+ /* power LDO1 */
+ snd_soc_dapm_force_enable_pin(dapm, "LDO1");
+ snd_soc_dapm_sync(dapm);
+
+ regmap_write(rt298->regmap, RT298_SET_MIC1, 0x24);
+ msleep(50);
+
+ regmap_update_bits(rt298->regmap,
+ RT298_CBJ_CTRL1, 0xfcc0, 0xd400);
+ msleep(300);
+ regmap_read(rt298->regmap, RT298_CBJ_CTRL2, &val);
+
+ if (0x0070 == (val & 0x0070)) {
+ *mic = true;
+ } else {
+ regmap_update_bits(rt298->regmap,
+ RT298_CBJ_CTRL1, 0xfcc0, 0xe400);
+ msleep(300);
+ regmap_read(rt298->regmap,
+ RT298_CBJ_CTRL2, &val);
+ if (0x0070 == (val & 0x0070))
+ *mic = true;
+ else
+ *mic = false;
+ }
+ regmap_update_bits(rt298->regmap,
+ RT298_DC_GAIN, 0x200, 0x0);
+
+ } else {
+ *mic = false;
+ regmap_write(rt298->regmap, RT298_SET_MIC1, 0x20);
+ }
+ } else {
+ regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf);
+ *hp = buf & 0x80000000;
+ regmap_read(rt298->regmap, RT298_GET_MIC1_SENSE, &buf);
+ *mic = buf & 0x80000000;
+ }
+
+ snd_soc_dapm_disable_pin(dapm, "HV");
+ snd_soc_dapm_disable_pin(dapm, "VREF");
+ if (!*hp)
+ snd_soc_dapm_disable_pin(dapm, "LDO1");
+ snd_soc_dapm_sync(dapm);
+
+ pr_debug("*hp = %d *mic = %d\n", *hp, *mic);
+
+ return 0;
+}
+
+static void rt298_jack_detect_work(struct work_struct *work)
+{
+ struct rt298_priv *rt298 =
+ container_of(work, struct rt298_priv, jack_detect_work.work);
+ int status = 0;
+ bool hp = false;
+ bool mic = false;
+
+ if (rt298_jack_detect(rt298, &hp, &mic) < 0)
+ return;
+
+ if (hp == true)
+ status |= SND_JACK_HEADPHONE;
+
+ if (mic == true)
+ status |= SND_JACK_MICROPHONE;
+
+ snd_soc_jack_report(rt298->jack, status,
+ SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
+}
+
+int rt298_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
+{
+ struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec);
+
+ rt298->jack = jack;
+
+ /* Send an initial empty report */
+ snd_soc_jack_report(rt298->jack, 0,
+ SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt298_mic_detect);
+
+static int is_mclk_mode(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
+ struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec);
+
+ if (rt298->clk_id == RT298_SCLK_S_MCLK)
+ return 1;
+ else
+ return 0;
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0);
+static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
+
+static const struct snd_kcontrol_new rt298_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT298_DACL_GAIN,
+ RT298_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv),
+ SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT298_ADCL_GAIN,
+ RT298_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv),
+ SOC_SINGLE_TLV("AMIC Volume", RT298_MIC_GAIN,
+ 0, 0x3, 0, mic_vol_tlv),
+ SOC_DOUBLE_R("Speaker Playback Switch", RT298_SPOL_GAIN,
+ RT298_SPOR_GAIN, RT298_MUTE_SFT, 1, 1),
+};
+
+/* Digital Mixer */
+static const struct snd_kcontrol_new rt298_front_mix[] = {
+ SOC_DAPM_SINGLE("DAC Switch", RT298_F_DAC_SWITCH,
+ RT298_MUTE_SFT, 1, 1),
+ SOC_DAPM_SINGLE("RECMIX Switch", RT298_F_RECMIX_SWITCH,
+ RT298_MUTE_SFT, 1, 1),
+};
+
+/* Analog Input Mixer */
+static const struct snd_kcontrol_new rt298_rec_mix[] = {
+ SOC_DAPM_SINGLE("Mic1 Switch", RT298_REC_MIC_SWITCH,
+ RT298_MUTE_SFT, 1, 1),
+ SOC_DAPM_SINGLE("I2S Switch", RT298_REC_I2S_SWITCH,
+ RT298_MUTE_SFT, 1, 1),
+ SOC_DAPM_SINGLE("Line1 Switch", RT298_REC_LINE_SWITCH,
+ RT298_MUTE_SFT, 1, 1),
+ SOC_DAPM_SINGLE("Beep Switch", RT298_REC_BEEP_SWITCH,
+ RT298_MUTE_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new spo_enable_control =
+ SOC_DAPM_SINGLE("Switch", RT298_SET_PIN_SPK,
+ RT298_SET_PIN_SFT, 1, 0);
+
+static const struct snd_kcontrol_new hpol_enable_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT298_HPOL_GAIN,
+ RT298_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpor_enable_control =
+ SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT298_HPOR_GAIN,
+ RT298_MUTE_SFT, 1, 1);
+
+/* ADC0 source */
+static const char * const rt298_adc_src[] = {
+ "Mic", "RECMIX", "Dmic"
+};
+
+static const int rt298_adc_values[] = {
+ 0, 4, 5,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(
+ rt298_adc0_enum, RT298_ADC0_MUX, RT298_ADC_SEL_SFT,
+ RT298_ADC_SEL_MASK, rt298_adc_src, rt298_adc_values);
+
+static const struct snd_kcontrol_new rt298_adc0_mux =
+ SOC_DAPM_ENUM("ADC 0 source", rt298_adc0_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(
+ rt298_adc1_enum, RT298_ADC1_MUX, RT298_ADC_SEL_SFT,
+ RT298_ADC_SEL_MASK, rt298_adc_src, rt298_adc_values);
+
+static const struct snd_kcontrol_new rt298_adc1_mux =
+ SOC_DAPM_ENUM("ADC 1 source", rt298_adc1_enum);
+
+static const char * const rt298_dac_src[] = {
+ "Front", "Surround"
+};
+/* HP-OUT source */
+static SOC_ENUM_SINGLE_DECL(rt298_hpo_enum, RT298_HPO_MUX,
+ 0, rt298_dac_src);
+
+static const struct snd_kcontrol_new rt298_hpo_mux =
+SOC_DAPM_ENUM("HPO source", rt298_hpo_enum);
+
+/* SPK-OUT source */
+static SOC_ENUM_SINGLE_DECL(rt298_spo_enum, RT298_SPK_MUX,
+ 0, rt298_dac_src);
+
+static const struct snd_kcontrol_new rt298_spo_mux =
+SOC_DAPM_ENUM("SPO source", rt298_spo_enum);
+
+static int rt298_spk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_write(codec,
+ RT298_SPK_EAPD, RT298_SET_EAPD_HIGH);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_write(codec,
+ RT298_SPK_EAPD, RT298_SET_EAPD_LOW);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt298_set_dmic1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_write(codec, RT298_SET_PIN_DMIC1, 0x20);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_write(codec, RT298_SET_PIN_DMIC1, 0);
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt298_adc_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ unsigned int nid;
+
+ nid = (w->reg >> 20) & 0xff;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec,
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0),
+ 0x7080, 0x7000);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec,
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0),
+ 0x7080, 0x7080);
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt298_mic1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec,
+ RT298_A_BIAS_CTRL3, 0xc000, 0x8000);
+ snd_soc_update_bits(codec,
+ RT298_A_BIAS_CTRL2, 0xc000, 0x8000);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec,
+ RT298_A_BIAS_CTRL3, 0xc000, 0x0000);
+ snd_soc_update_bits(codec,
+ RT298_A_BIAS_CTRL2, 0xc000, 0x0000);
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt298_vref_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec,
+ RT298_CBJ_CTRL1, 0x0400, 0x0000);
+ mdelay(50);
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget rt298_dapm_widgets[] = {
+
+ SND_SOC_DAPM_SUPPLY_S("HV", 1, RT298_POWER_CTRL1,
+ 12, 1, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("VREF", RT298_POWER_CTRL1,
+ 0, 1, rt298_vref_event, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_SUPPLY_S("BG_MBIAS", 1, RT298_POWER_CTRL2,
+ 1, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT298_POWER_CTRL2,
+ 2, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("LDO2", 1, RT298_POWER_CTRL2,
+ 3, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("VREF1", 1, RT298_POWER_CTRL2,
+ 4, 1, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("LV", 2, RT298_POWER_CTRL1,
+ 13, 1, NULL, 0),
+
+
+ SND_SOC_DAPM_SUPPLY("MCLK MODE", RT298_PLL_CTRL1,
+ 5, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MIC1 Input Buffer", SND_SOC_NOPM,
+ 0, 0, rt298_mic1_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* Input Lines */
+ SND_SOC_DAPM_INPUT("DMIC1 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC2 Pin"),
+ SND_SOC_DAPM_INPUT("MIC1"),
+ SND_SOC_DAPM_INPUT("LINE1"),
+ SND_SOC_DAPM_INPUT("Beep"),
+
+ /* DMIC */
+ SND_SOC_DAPM_PGA_E("DMIC1", RT298_SET_POWER(RT298_DMIC1), 0, 1,
+ NULL, 0, rt298_set_dmic1_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA("DMIC2", RT298_SET_POWER(RT298_DMIC2), 0, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DMIC Receiver", SND_SOC_NOPM,
+ 0, 0, NULL, 0),
+
+ /* REC Mixer */
+ SND_SOC_DAPM_MIXER("RECMIX", SND_SOC_NOPM, 0, 0,
+ rt298_rec_mix, ARRAY_SIZE(rt298_rec_mix)),
+
+ /* ADCs */
+ SND_SOC_DAPM_ADC("ADC 0", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0),
+
+ /* ADC Mux */
+ SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT298_SET_POWER(RT298_ADC_IN1), 0, 1,
+ &rt298_adc0_mux, rt298_adc_event, SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT298_SET_POWER(RT298_ADC_IN2), 0, 1,
+ &rt298_adc1_mux, rt298_adc_event, SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMU),
+
+ /* Audio Interface */
+ SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+ /* Output Side */
+ /* DACs */
+ SND_SOC_DAPM_DAC("DAC 0", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("DAC 1", NULL, SND_SOC_NOPM, 0, 0),
+
+ /* Output Mux */
+ SND_SOC_DAPM_MUX("SPK Mux", SND_SOC_NOPM, 0, 0, &rt298_spo_mux),
+ SND_SOC_DAPM_MUX("HPO Mux", SND_SOC_NOPM, 0, 0, &rt298_hpo_mux),
+
+ SND_SOC_DAPM_SUPPLY("HP Power", RT298_SET_PIN_HPO,
+ RT298_SET_PIN_SFT, 0, NULL, 0),
+
+ /* Output Mixer */
+ SND_SOC_DAPM_MIXER("Front", RT298_SET_POWER(RT298_DAC_OUT1), 0, 1,
+ rt298_front_mix, ARRAY_SIZE(rt298_front_mix)),
+ SND_SOC_DAPM_PGA("Surround", RT298_SET_POWER(RT298_DAC_OUT2), 0, 1,
+ NULL, 0),
+
+ /* Output Pga */
+ SND_SOC_DAPM_SWITCH_E("SPO", SND_SOC_NOPM, 0, 0,
+ &spo_enable_control, rt298_spk_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_SWITCH("HPO L", SND_SOC_NOPM, 0, 0,
+ &hpol_enable_control),
+ SND_SOC_DAPM_SWITCH("HPO R", SND_SOC_NOPM, 0, 0,
+ &hpor_enable_control),
+
+ /* Output Lines */
+ SND_SOC_DAPM_OUTPUT("SPOL"),
+ SND_SOC_DAPM_OUTPUT("SPOR"),
+ SND_SOC_DAPM_OUTPUT("HPO Pin"),
+ SND_SOC_DAPM_OUTPUT("SPDIF"),
+};
+
+static const struct snd_soc_dapm_route rt298_dapm_routes[] = {
+
+ {"ADC 0", NULL, "MCLK MODE", is_mclk_mode},
+ {"ADC 1", NULL, "MCLK MODE", is_mclk_mode},
+ {"Front", NULL, "MCLK MODE", is_mclk_mode},
+ {"Surround", NULL, "MCLK MODE", is_mclk_mode},
+
+ {"HP Power", NULL, "LDO1"},
+ {"HP Power", NULL, "LDO2"},
+ {"HP Power", NULL, "LV"},
+ {"HP Power", NULL, "VREF1"},
+ {"HP Power", NULL, "BG_MBIAS"},
+
+ {"MIC1", NULL, "LDO1"},
+ {"MIC1", NULL, "LDO2"},
+ {"MIC1", NULL, "HV"},
+ {"MIC1", NULL, "LV"},
+ {"MIC1", NULL, "VREF"},
+ {"MIC1", NULL, "VREF1"},
+ {"MIC1", NULL, "BG_MBIAS"},
+ {"MIC1", NULL, "MIC1 Input Buffer"},
+
+ {"SPO", NULL, "LDO1"},
+ {"SPO", NULL, "LDO2"},
+ {"SPO", NULL, "HV"},
+ {"SPO", NULL, "LV"},
+ {"SPO", NULL, "VREF"},
+ {"SPO", NULL, "VREF1"},
+ {"SPO", NULL, "BG_MBIAS"},
+
+ {"DMIC1", NULL, "DMIC1 Pin"},
+ {"DMIC2", NULL, "DMIC2 Pin"},
+ {"DMIC1", NULL, "DMIC Receiver"},
+ {"DMIC2", NULL, "DMIC Receiver"},
+
+ {"RECMIX", "Beep Switch", "Beep"},
+ {"RECMIX", "Line1 Switch", "LINE1"},
+ {"RECMIX", "Mic1 Switch", "MIC1"},
+
+ {"ADC 0 Mux", "Dmic", "DMIC1"},
+ {"ADC 0 Mux", "RECMIX", "RECMIX"},
+ {"ADC 0 Mux", "Mic", "MIC1"},
+ {"ADC 1 Mux", "Dmic", "DMIC2"},
+ {"ADC 1 Mux", "RECMIX", "RECMIX"},
+ {"ADC 1 Mux", "Mic", "MIC1"},
+
+ {"ADC 0", NULL, "ADC 0 Mux"},
+ {"ADC 1", NULL, "ADC 1 Mux"},
+
+ {"AIF1TX", NULL, "ADC 0"},
+ {"AIF2TX", NULL, "ADC 1"},
+
+ {"DAC 0", NULL, "AIF1RX"},
+ {"DAC 1", NULL, "AIF2RX"},
+
+ {"Front", "DAC Switch", "DAC 0"},
+ {"Front", "RECMIX Switch", "RECMIX"},
+
+ {"Surround", NULL, "DAC 1"},
+
+ {"SPK Mux", "Front", "Front"},
+ {"SPK Mux", "Surround", "Surround"},
+
+ {"HPO Mux", "Front", "Front"},
+ {"HPO Mux", "Surround", "Surround"},
+
+ {"SPO", "Switch", "SPK Mux"},
+ {"HPO L", "Switch", "HPO Mux"},
+ {"HPO R", "Switch", "HPO Mux"},
+ {"HPO L", NULL, "HP Power"},
+ {"HPO R", NULL, "HP Power"},
+
+ {"SPOL", NULL, "SPO"},
+ {"SPOR", NULL, "SPO"},
+ {"HPO Pin", NULL, "HPO L"},
+ {"HPO Pin", NULL, "HPO R"},
+};
+
+static int rt298_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec);
+ unsigned int val = 0;
+ int d_len_code;
+
+ switch (params_rate(params)) {
+ /* bit 14 0:48K 1:44.1K */
+ case 44100:
+ case 48000:
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported sample rate %d\n",
+ params_rate(params));
+ return -EINVAL;
+ }
+ switch (rt298->sys_clk) {
+ case 12288000:
+ case 24576000:
+ if (params_rate(params) != 48000) {
+ dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n",
+ params_rate(params), rt298->sys_clk);
+ return -EINVAL;
+ }
+ break;
+ case 11289600:
+ case 22579200:
+ if (params_rate(params) != 44100) {
+ dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n",
+ params_rate(params), rt298->sys_clk);
+ return -EINVAL;
+ }
+ break;
+ }
+
+ if (params_channels(params) <= 16) {
+ /* bit 3:0 Number of Channel */
+ val |= (params_channels(params) - 1);
+ } else {
+ dev_err(codec->dev, "Unsupported channels %d\n",
+ params_channels(params));
+ return -EINVAL;
+ }
+
+ d_len_code = 0;
+ switch (params_width(params)) {
+ /* bit 6:4 Bits per Sample */
+ case 16:
+ d_len_code = 0;
+ val |= (0x1 << 4);
+ break;
+ case 32:
+ d_len_code = 2;
+ val |= (0x4 << 4);
+ break;
+ case 20:
+ d_len_code = 1;
+ val |= (0x2 << 4);
+ break;
+ case 24:
+ d_len_code = 2;
+ val |= (0x3 << 4);
+ break;
+ case 8:
+ d_len_code = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL1, 0x0018, d_len_code << 3);
+ dev_dbg(codec->dev, "format val = 0x%x\n", val);
+
+ snd_soc_update_bits(codec, RT298_DAC_FORMAT, 0x407f, val);
+ snd_soc_update_bits(codec, RT298_ADC_FORMAT, 0x407f, val);
+
+ return 0;
+}
+
+static int rt298_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL1, 0x800, 0x800);
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL1, 0x800, 0x0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL1, 0x300, 0x0);
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL1, 0x300, 0x1 << 8);
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL1, 0x300, 0x2 << 8);
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL1, 0x300, 0x3 << 8);
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* bit 15 Stream Type 0:PCM 1:Non-PCM */
+ snd_soc_update_bits(codec, RT298_DAC_FORMAT, 0x8000, 0);
+ snd_soc_update_bits(codec, RT298_ADC_FORMAT, 0x8000, 0);
+
+ return 0;
+}
+
+static int rt298_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "%s freq=%d\n", __func__, freq);
+
+ if (RT298_SCLK_S_MCLK == clk_id) {
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL2, 0x0100, 0x0);
+ snd_soc_update_bits(codec,
+ RT298_PLL_CTRL1, 0x20, 0x20);
+ } else {
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL2, 0x0100, 0x0100);
+ snd_soc_update_bits(codec,
+ RT298_PLL_CTRL, 0x4, 0x4);
+ snd_soc_update_bits(codec,
+ RT298_PLL_CTRL1, 0x20, 0x0);
+ }
+
+ switch (freq) {
+ case 19200000:
+ if (RT298_SCLK_S_MCLK == clk_id) {
+ dev_err(codec->dev, "Should not use MCLK\n");
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL2, 0x40, 0x40);
+ break;
+ case 24000000:
+ if (RT298_SCLK_S_MCLK == clk_id) {
+ dev_err(codec->dev, "Should not use MCLK\n");
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL2, 0x40, 0x0);
+ break;
+ case 12288000:
+ case 11289600:
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL2, 0x8, 0x0);
+ snd_soc_update_bits(codec,
+ RT298_CLK_DIV, 0xfc1e, 0x0004);
+ break;
+ case 24576000:
+ case 22579200:
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL2, 0x8, 0x8);
+ snd_soc_update_bits(codec,
+ RT298_CLK_DIV, 0xfc1e, 0x5406);
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported system clock\n");
+ return -EINVAL;
+ }
+
+ rt298->sys_clk = freq;
+ rt298->clk_id = clk_id;
+
+ return 0;
+}
+
+static int rt298_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ dev_dbg(codec->dev, "%s ratio=%d\n", __func__, ratio);
+ if (50 == ratio)
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL1, 0x1000, 0x1000);
+ else
+ snd_soc_update_bits(codec,
+ RT298_I2S_CTRL1, 0x1000, 0x0);
+
+
+ return 0;
+}
+
+static int rt298_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_PREPARE:
+ if (SND_SOC_BIAS_STANDBY ==
+ snd_soc_codec_get_bias_level(codec)) {
+ snd_soc_write(codec,
+ RT298_SET_AUDIO_POWER, AC_PWRST_D0);
+ snd_soc_update_bits(codec, 0x0d, 0x200, 0x200);
+ snd_soc_update_bits(codec, 0x52, 0x80, 0x0);
+ mdelay(20);
+ snd_soc_update_bits(codec, 0x0d, 0x200, 0x0);
+ snd_soc_update_bits(codec, 0x52, 0x80, 0x80);
+ }
+ break;
+
+ case SND_SOC_BIAS_ON:
+ mdelay(30);
+ snd_soc_update_bits(codec,
+ RT298_CBJ_CTRL1, 0x0400, 0x0400);
+
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ snd_soc_write(codec,
+ RT298_SET_AUDIO_POWER, AC_PWRST_D3);
+ snd_soc_update_bits(codec,
+ RT298_CBJ_CTRL1, 0x0400, 0x0000);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static irqreturn_t rt298_irq(int irq, void *data)
+{
+ struct rt298_priv *rt298 = data;
+ bool hp = false;
+ bool mic = false;
+ int ret, status = 0;
+
+ ret = rt298_jack_detect(rt298, &hp, &mic);
+
+ /* Clear IRQ */
+ regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x1, 0x1);
+
+ if (ret == 0) {
+ if (hp == true)
+ status |= SND_JACK_HEADPHONE;
+
+ if (mic == true)
+ status |= SND_JACK_MICROPHONE;
+
+ snd_soc_jack_report(rt298->jack, status,
+ SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
+
+ pm_wakeup_event(&rt298->i2c->dev, 300);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int rt298_probe(struct snd_soc_codec *codec)
+{
+ struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec);
+
+ rt298->codec = codec;
+
+ if (rt298->i2c->irq) {
+ regmap_update_bits(rt298->regmap,
+ RT298_IRQ_CTRL, 0x2, 0x2);
+
+ INIT_DELAYED_WORK(&rt298->jack_detect_work,
+ rt298_jack_detect_work);
+ schedule_delayed_work(&rt298->jack_detect_work,
+ msecs_to_jiffies(1250));
+ }
+
+ return 0;
+}
+
+static int rt298_remove(struct snd_soc_codec *codec)
+{
+ struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec);
+
+ cancel_delayed_work_sync(&rt298->jack_detect_work);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt298_suspend(struct snd_soc_codec *codec)
+{
+ struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec);
+
+ rt298->is_hp_in = -1;
+ regcache_cache_only(rt298->regmap, true);
+ regcache_mark_dirty(rt298->regmap);
+
+ return 0;
+}
+
+static int rt298_resume(struct snd_soc_codec *codec)
+{
+ struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt298->regmap, false);
+ rt298_index_sync(codec);
+ regcache_sync(rt298->regmap);
+
+ return 0;
+}
+#else
+#define rt298_suspend NULL
+#define rt298_resume NULL
+#endif
+
+#define RT298_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+#define RT298_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+
+static const struct snd_soc_dai_ops rt298_aif_dai_ops = {
+ .hw_params = rt298_hw_params,
+ .set_fmt = rt298_set_dai_fmt,
+ .set_sysclk = rt298_set_dai_sysclk,
+ .set_bclk_ratio = rt298_set_bclk_ratio,
+};
+
+static struct snd_soc_dai_driver rt298_dai[] = {
+ {
+ .name = "rt298-aif1",
+ .id = RT298_AIF1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT298_STEREO_RATES,
+ .formats = RT298_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT298_STEREO_RATES,
+ .formats = RT298_FORMATS,
+ },
+ .ops = &rt298_aif_dai_ops,
+ .symmetric_rates = 1,
+ },
+ {
+ .name = "rt298-aif2",
+ .id = RT298_AIF2,
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT298_STEREO_RATES,
+ .formats = RT298_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT298_STEREO_RATES,
+ .formats = RT298_FORMATS,
+ },
+ .ops = &rt298_aif_dai_ops,
+ .symmetric_rates = 1,
+ },
+
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt298 = {
+ .probe = rt298_probe,
+ .remove = rt298_remove,
+ .suspend = rt298_suspend,
+ .resume = rt298_resume,
+ .set_bias_level = rt298_set_bias_level,
+ .idle_bias_off = true,
+ .controls = rt298_snd_controls,
+ .num_controls = ARRAY_SIZE(rt298_snd_controls),
+ .dapm_widgets = rt298_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rt298_dapm_widgets),
+ .dapm_routes = rt298_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(rt298_dapm_routes),
+};
+
+static const struct regmap_config rt298_regmap = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .max_register = 0x02370100,
+ .volatile_reg = rt298_volatile_register,
+ .readable_reg = rt298_readable_register,
+ .reg_write = rl6347a_hw_write,
+ .reg_read = rl6347a_hw_read,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt298_reg,
+ .num_reg_defaults = ARRAY_SIZE(rt298_reg),
+};
+
+static const struct i2c_device_id rt298_i2c_id[] = {
+ {"rt298", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, rt298_i2c_id);
+
+static const struct acpi_device_id rt298_acpi_match[] = {
+ { "INT343A", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, rt298_acpi_match);
+
+static int rt298_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct rt298_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ struct rt298_priv *rt298;
+ struct device *dev = &i2c->dev;
+ const struct acpi_device_id *acpiid;
+ int i, ret;
+
+ rt298 = devm_kzalloc(&i2c->dev, sizeof(*rt298),
+ GFP_KERNEL);
+ if (NULL == rt298)
+ return -ENOMEM;
+
+ rt298->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt298_regmap);
+ if (IS_ERR(rt298->regmap)) {
+ ret = PTR_ERR(rt298->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ regmap_read(rt298->regmap,
+ RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret);
+ if (ret != RT298_VENDOR_ID) {
+ dev_err(&i2c->dev,
+ "Device with ID register %#x is not rt298\n", ret);
+ return -ENODEV;
+ }
+
+ rt298->index_cache = rt298_index_def;
+ rt298->index_cache_size = INDEX_CACHE_SIZE;
+ rt298->i2c = i2c;
+ i2c_set_clientdata(i2c, rt298);
+
+ /* restore codec default */
+ for (i = 0; i < INDEX_CACHE_SIZE; i++)
+ regmap_write(rt298->regmap, rt298->index_cache[i].reg,
+ rt298->index_cache[i].def);
+ for (i = 0; i < ARRAY_SIZE(rt298_reg); i++)
+ regmap_write(rt298->regmap, rt298_reg[i].reg,
+ rt298_reg[i].def);
+
+ if (pdata)
+ rt298->pdata = *pdata;
+
+ /* enable jack combo mode on supported devices */
+ acpiid = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (acpiid) {
+ rt298->pdata = *(struct rt298_platform_data *)
+ acpiid->driver_data;
+ }
+
+ /* VREF Charging */
+ regmap_update_bits(rt298->regmap, 0x04, 0x80, 0x80);
+ regmap_update_bits(rt298->regmap, 0x1b, 0x860, 0x860);
+ /* Vref2 */
+ regmap_update_bits(rt298->regmap, 0x08, 0x20, 0x20);
+
+ regmap_write(rt298->regmap, RT298_SET_AUDIO_POWER, AC_PWRST_D3);
+
+ for (i = 0; i < RT298_POWER_REG_LEN; i++)
+ regmap_write(rt298->regmap,
+ RT298_SET_POWER(rt298_support_power_controls[i]),
+ AC_PWRST_D1);
+
+ if (!rt298->pdata.cbj_en) {
+ regmap_write(rt298->regmap, RT298_CBJ_CTRL2, 0x0000);
+ regmap_write(rt298->regmap, RT298_MIC1_DET_CTRL, 0x0816);
+ regmap_update_bits(rt298->regmap,
+ RT298_CBJ_CTRL1, 0xf000, 0xb000);
+ } else {
+ regmap_update_bits(rt298->regmap,
+ RT298_CBJ_CTRL1, 0xf000, 0x5000);
+ }
+
+ mdelay(10);
+
+ if (!rt298->pdata.gpio2_en)
+ regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0x40);
+ else
+ regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0);
+
+ mdelay(10);
+
+ regmap_write(rt298->regmap, RT298_MISC_CTRL1, 0x0000);
+ regmap_update_bits(rt298->regmap,
+ RT298_WIND_FILTER_CTRL, 0x0082, 0x0082);
+ regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x2, 0x2);
+ rt298->is_hp_in = -1;
+
+ if (rt298->i2c->irq) {
+ ret = request_threaded_irq(rt298->i2c->irq, NULL, rt298_irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt298", rt298);
+ if (ret != 0) {
+ dev_err(&i2c->dev,
+ "Failed to reguest IRQ: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt298,
+ rt298_dai, ARRAY_SIZE(rt298_dai));
+
+ return ret;
+}
+
+static int rt298_i2c_remove(struct i2c_client *i2c)
+{
+ struct rt298_priv *rt298 = i2c_get_clientdata(i2c);
+
+ if (i2c->irq)
+ free_irq(i2c->irq, rt298);
+ snd_soc_unregister_codec(&i2c->dev);
+
+ return 0;
+}
+
+
+static struct i2c_driver rt298_i2c_driver = {
+ .driver = {
+ .name = "rt298",
+ .acpi_match_table = ACPI_PTR(rt298_acpi_match),
+ },
+ .probe = rt298_i2c_probe,
+ .remove = rt298_i2c_remove,
+ .id_table = rt298_i2c_id,
+};
+
+module_i2c_driver(rt298_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT298 driver");
+MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt298.h b/sound/soc/codecs/rt298.h
new file mode 100644
index 000000000..31da16265
--- /dev/null
+++ b/sound/soc/codecs/rt298.h
@@ -0,0 +1,206 @@
+/*
+ * rt298.h -- RT298 ALSA SoC audio driver
+ *
+ * Copyright 2011 Realtek Microelectronics
+ * Author: Johnny Hsu <johnnyhsu@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __RT298_H__
+#define __RT298_H__
+
+#define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D)
+
+#define RT298_AUDIO_FUNCTION_GROUP 0x01
+#define RT298_DAC_OUT1 0x02
+#define RT298_DAC_OUT2 0x03
+#define RT298_DIG_CVT 0x06
+#define RT298_ADC_IN1 0x09
+#define RT298_ADC_IN2 0x08
+#define RT298_MIXER_IN 0x0b
+#define RT298_MIXER_OUT1 0x0c
+#define RT298_MIXER_OUT2 0x0d
+#define RT298_DMIC1 0x12
+#define RT298_DMIC2 0x13
+#define RT298_SPK_OUT 0x14
+#define RT298_MIC1 0x18
+#define RT298_LINE1 0x1a
+#define RT298_BEEP 0x1d
+#define RT298_SPDIF 0x1e
+#define RT298_VENDOR_REGISTERS 0x20
+#define RT298_HP_OUT 0x21
+#define RT298_MIXER_IN1 0x22
+#define RT298_MIXER_IN2 0x23
+
+#define RT298_SET_PIN_SFT 6
+#define RT298_SET_PIN_ENABLE 0x40
+#define RT298_SET_PIN_DISABLE 0
+#define RT298_SET_EAPD_HIGH 0x2
+#define RT298_SET_EAPD_LOW 0
+
+#define RT298_MUTE_SFT 7
+
+/* Verb commands */
+#define RT298_GET_PARAM(NID, PARAM) VERB_CMD(AC_VERB_PARAMETERS, NID, PARAM)
+#define RT298_SET_POWER(NID) VERB_CMD(AC_VERB_SET_POWER_STATE, NID, 0)
+#define RT298_SET_AUDIO_POWER RT298_SET_POWER(RT298_AUDIO_FUNCTION_GROUP)
+#define RT298_SET_HPO_POWER RT298_SET_POWER(RT298_HP_OUT)
+#define RT298_SET_SPK_POWER RT298_SET_POWER(RT298_SPK_OUT)
+#define RT298_SET_DMIC1_POWER RT298_SET_POWER(RT298_DMIC1)
+#define RT298_SPK_MUX\
+ VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_SPK_OUT, 0)
+#define RT298_HPO_MUX\
+ VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_HP_OUT, 0)
+#define RT298_ADC0_MUX\
+ VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_MIXER_IN1, 0)
+#define RT298_ADC1_MUX\
+ VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_MIXER_IN2, 0)
+#define RT298_SET_MIC1\
+ VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_MIC1, 0)
+#define RT298_SET_PIN_HPO\
+ VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_HP_OUT, 0)
+#define RT298_SET_PIN_SPK\
+ VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_SPK_OUT, 0)
+#define RT298_SET_PIN_DMIC1\
+ VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_DMIC1, 0)
+#define RT298_SET_PIN_SPDIF\
+ VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_SPDIF, 0)
+#define RT298_SET_PIN_DIG_CVT\
+ VERB_CMD(AC_VERB_SET_DIGI_CONVERT_1, RT298_DIG_CVT, 0)
+#define RT298_SPK_EAPD\
+ VERB_CMD(AC_VERB_SET_EAPD_BTLENABLE, RT298_SPK_OUT, 0)
+#define RT298_SET_AMP_GAIN_HPO\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0)
+#define RT298_SET_AMP_GAIN_ADC_IN1\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0)
+#define RT298_SET_AMP_GAIN_ADC_IN2\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN2, 0)
+#define RT298_GET_HP_SENSE\
+ VERB_CMD(AC_VERB_GET_PIN_SENSE, RT298_HP_OUT, 0)
+#define RT298_GET_MIC1_SENSE\
+ VERB_CMD(AC_VERB_GET_PIN_SENSE, RT298_MIC1, 0)
+#define RT298_SET_DMIC2_DEFAULT\
+ VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT298_DMIC2, 0)
+#define RT298_SET_SPDIF_DEFAULT\
+ VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT298_SPDIF, 0)
+#define RT298_DACL_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_DAC_OUT1, 0xa000)
+#define RT298_DACR_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_DAC_OUT1, 0x9000)
+#define RT298_ADCL_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0x6000)
+#define RT298_ADCR_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0x5000)
+#define RT298_MIC_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIC1, 0x7000)
+#define RT298_SPOL_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_SPK_OUT, 0xa000)
+#define RT298_SPOR_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_SPK_OUT, 0x9000)
+#define RT298_HPOL_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0xa000)
+#define RT298_HPOR_GAIN\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0x9000)
+#define RT298_F_DAC_SWITCH\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_OUT1, 0x7000)
+#define RT298_F_RECMIX_SWITCH\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_OUT1, 0x7100)
+#define RT298_REC_MIC_SWITCH\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7000)
+#define RT298_REC_I2S_SWITCH\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7100)
+#define RT298_REC_LINE_SWITCH\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7200)
+#define RT298_REC_BEEP_SWITCH\
+ VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7300)
+#define RT298_DAC_FORMAT\
+ VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT298_DAC_OUT1, 0)
+#define RT298_ADC_FORMAT\
+ VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT298_ADC_IN1, 0)
+#define RT298_COEF_INDEX\
+ VERB_CMD(AC_VERB_SET_COEF_INDEX, RT298_VENDOR_REGISTERS, 0)
+#define RT298_PROC_COEF\
+ VERB_CMD(AC_VERB_SET_PROC_COEF, RT298_VENDOR_REGISTERS, 0)
+
+/* Index registers */
+#define RT298_A_BIAS_CTRL1 0x01
+#define RT298_A_BIAS_CTRL2 0x02
+#define RT298_POWER_CTRL1 0x03
+#define RT298_A_BIAS_CTRL3 0x04
+#define RT298_POWER_CTRL2 0x08
+#define RT298_I2S_CTRL1 0x09
+#define RT298_I2S_CTRL2 0x0a
+#define RT298_CLK_DIV 0x0b
+#define RT298_DC_GAIN 0x0d
+#define RT298_POWER_CTRL3 0x0f
+#define RT298_MIC1_DET_CTRL 0x19
+#define RT298_MISC_CTRL1 0x20
+#define RT298_IRQ_CTRL 0x33
+#define RT298_WIND_FILTER_CTRL 0x46
+#define RT298_PLL_CTRL1 0x49
+#define RT298_CBJ_CTRL1 0x4f
+#define RT298_CBJ_CTRL2 0x50
+#define RT298_PLL_CTRL 0x63
+#define RT298_DEPOP_CTRL1 0x66
+#define RT298_DEPOP_CTRL2 0x67
+#define RT298_DEPOP_CTRL3 0x68
+#define RT298_DEPOP_CTRL4 0x69
+
+/* SPDIF (0x06) */
+#define RT298_SPDIF_SEL_SFT 0
+#define RT298_SPDIF_SEL_PCM0 0
+#define RT298_SPDIF_SEL_PCM1 1
+#define RT298_SPDIF_SEL_SPOUT 2
+#define RT298_SPDIF_SEL_PP 3
+
+/* RECMIX (0x0b) */
+#define RT298_M_REC_BEEP_SFT 0
+#define RT298_M_REC_LINE1_SFT 1
+#define RT298_M_REC_MIC1_SFT 2
+#define RT298_M_REC_I2S_SFT 3
+
+/* Front (0x0c) */
+#define RT298_M_FRONT_DAC_SFT 0
+#define RT298_M_FRONT_REC_SFT 1
+
+/* SPK-OUT (0x14) */
+#define RT298_M_SPK_MUX_SFT 14
+#define RT298_SPK_SEL_MASK 0x1
+#define RT298_SPK_SEL_SFT 0
+#define RT298_SPK_SEL_F 0
+#define RT298_SPK_SEL_S 1
+
+/* HP-OUT (0x21) */
+#define RT298_M_HP_MUX_SFT 14
+#define RT298_HP_SEL_MASK 0x1
+#define RT298_HP_SEL_SFT 0
+#define RT298_HP_SEL_F 0
+#define RT298_HP_SEL_S 1
+
+/* ADC (0x22) (0x23) */
+#define RT298_ADC_SEL_MASK 0x7
+#define RT298_ADC_SEL_SFT 0
+#define RT298_ADC_SEL_SURR 0
+#define RT298_ADC_SEL_FRONT 1
+#define RT298_ADC_SEL_DMIC 2
+#define RT298_ADC_SEL_BEEP 4
+#define RT298_ADC_SEL_LINE1 5
+#define RT298_ADC_SEL_I2S 6
+#define RT298_ADC_SEL_MIC1 7
+
+#define RT298_SCLK_S_MCLK 0
+#define RT298_SCLK_S_PLL 1
+
+enum {
+ RT298_AIF1,
+ RT298_AIF2,
+ RT298_AIFS,
+};
+
+int rt298_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
+
+#endif /* __RT298_H__ */
+
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index 058167c80..1be2bab7d 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -174,16 +174,15 @@ static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0);
static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */
-static unsigned int mic_bst_tlv[] = {
- TLV_DB_RANGE_HEAD(7),
+static const DECLARE_TLV_DB_RANGE(mic_bst_tlv,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
- 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
-};
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0)
+);
static int rt5631_dmic_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1725,7 +1724,6 @@ static int rt5631_i2c_remove(struct i2c_client *client)
static struct i2c_driver rt5631_i2c_driver = {
.driver = {
.name = "rt5631",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(rt5631_i2c_dt_ids),
},
.probe = rt5631_i2c_probe,
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index ff72cd8c2..e1ceeb885 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -51,7 +51,7 @@ static const struct regmap_range_cfg rt5640_ranges[] = {
.window_len = 0x1, },
};
-static const struct reg_default init_list[] = {
+static const struct reg_sequence init_list[] = {
{RT5640_PR_BASE + 0x3d, 0x3600},
{RT5640_PR_BASE + 0x12, 0x0aa8},
{RT5640_PR_BASE + 0x14, 0x0aaa},
@@ -347,16 +347,15 @@ static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
-static unsigned int bst_tlv[] = {
- TLV_DB_RANGE_HEAD(7),
+static const DECLARE_TLV_DB_RANGE(bst_tlv,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
- 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
-};
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0)
+);
/* Interface data select */
static const char * const rt5640_data_select[] = {
@@ -459,10 +458,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
- int idx = -EINVAL;
-
- idx = rl6231_calc_dmic_clk(rt5640->sysclk);
+ int idx, rate;
+ rate = rt5640->sysclk / rl6231_get_pre_div(rt5640->regmap,
+ RT5640_ADDA_CLK1, RT5640_I2S_PD1_SFT);
+ idx = rl6231_calc_dmic_clk(rate);
if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n");
else
@@ -2241,7 +2241,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val);
if (val != RT5640_DEVICE_ID) {
dev_err(&i2c->dev,
- "Device with ID register %x is not rt5640/39\n", val);
+ "Device with ID register %#x is not rt5640/39\n", val);
return -ENODEV;
}
@@ -2276,7 +2276,6 @@ static int rt5640_i2c_remove(struct i2c_client *i2c)
static struct i2c_driver rt5640_i2c_driver = {
.driver = {
.name = "rt5640",
- .owner = THIS_MODULE,
.acpi_match_table = ACPI_PTR(rt5640_acpi_match),
.of_match_table = of_match_ptr(rt5640_of_match),
},
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 58713733d..5c101af0a 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -21,6 +21,7 @@
#include <linux/gpio/consumer.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
+#include <linux/regulator/consumer.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -54,7 +55,7 @@ static const struct regmap_range_cfg rt5645_ranges[] = {
},
};
-static const struct reg_default init_list[] = {
+static const struct reg_sequence init_list[] = {
{RT5645_PR_BASE + 0x3d, 0x3600},
{RT5645_PR_BASE + 0x1c, 0xfd20},
{RT5645_PR_BASE + 0x20, 0x611f},
@@ -63,7 +64,7 @@ static const struct reg_default init_list[] = {
};
#define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list)
-static const struct reg_default rt5650_init_list[] = {
+static const struct reg_sequence rt5650_init_list[] = {
{0xf6, 0x0100},
};
@@ -223,6 +224,39 @@ static const struct reg_default rt5645_reg[] = {
{ 0xff, 0x6308 },
};
+static const char *const rt5645_supply_names[] = {
+ "avdd",
+ "cpvdd",
+};
+
+struct rt5645_priv {
+ struct snd_soc_codec *codec;
+ struct rt5645_platform_data pdata;
+ struct regmap *regmap;
+ struct i2c_client *i2c;
+ struct gpio_desc *gpiod_hp_det;
+ struct snd_soc_jack *hp_jack;
+ struct snd_soc_jack *mic_jack;
+ struct snd_soc_jack *btn_jack;
+ struct delayed_work jack_detect_work;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(rt5645_supply_names)];
+
+ int codec_type;
+ int sysclk;
+ int sysclk_src;
+ int lrck[RT5645_AIFS];
+ int bclk[RT5645_AIFS];
+ int master[RT5645_AIFS];
+
+ int pll_src;
+ int pll_in;
+ int pll_out;
+
+ int jack_type;
+ bool en_button_func;
+ bool hp_on;
+};
+
static int rt5645_reset(struct snd_soc_codec *codec)
{
return snd_soc_write(codec, RT5645_RESET, 0);
@@ -360,6 +394,7 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg)
case RT5645_DEPOP_M1:
case RT5645_DEPOP_M2:
case RT5645_DEPOP_M3:
+ case RT5645_CHARGE_PUMP:
case RT5645_MICBIAS:
case RT5645_A_JD_CTRL1:
case RT5645_VAD_CTRL4:
@@ -424,16 +459,15 @@ static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0);
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
-static unsigned int bst_tlv[] = {
- TLV_DB_RANGE_HEAD(7),
+static const DECLARE_TLV_DB_RANGE(bst_tlv,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
- 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
-};
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0)
+);
static const struct snd_kcontrol_new rt5645_snd_controls[] = {
/* Speaker Output Volume */
@@ -485,11 +519,11 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = {
RT5645_L_VOL_SFT + 1, RT5645_R_VOL_SFT + 1, 63, 0, adc_vol_tlv),
/* ADC Boost Volume Control */
- SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5645_ADC_BST_VOL1,
+ SOC_DOUBLE_TLV("ADC Boost Capture Volume", RT5645_ADC_BST_VOL1,
RT5645_STO1_ADC_L_BST_SFT, RT5645_STO1_ADC_R_BST_SFT, 3, 0,
adc_bst_tlv),
- SOC_DOUBLE_TLV("STO2 ADC Boost Gain", RT5645_ADC_BST_VOL1,
- RT5645_STO2_ADC_L_BST_SFT, RT5645_STO2_ADC_R_BST_SFT, 3, 0,
+ SOC_DOUBLE_TLV("Mono ADC Boost Capture Volume", RT5645_ADC_BST_VOL2,
+ RT5645_MONO_ADC_L_BST_SFT, RT5645_MONO_ADC_R_BST_SFT, 3, 0,
adc_bst_tlv),
/* I2S2 function select */
@@ -510,10 +544,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
- int idx = -EINVAL;
-
- idx = rl6231_calc_dmic_clk(rt5645->sysclk);
+ int idx, rate;
+ rate = rt5645->sysclk / rl6231_get_pre_div(rt5645->regmap,
+ RT5645_ADDA_CLK1, RT5645_I2S_PD1_SFT);
+ idx = rl6231_calc_dmic_clk(rate);
if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n");
else
@@ -697,14 +732,14 @@ static const struct snd_kcontrol_new rt5645_mono_adc_r_mix[] = {
static const struct snd_kcontrol_new rt5645_dac_l_mix[] = {
SOC_DAPM_SINGLE("Stereo ADC Switch", RT5645_AD_DA_MIXER,
RT5645_M_ADCMIX_L_SFT, 1, 1),
- SOC_DAPM_SINGLE("DAC1 Switch", RT5645_AD_DA_MIXER,
+ SOC_DAPM_SINGLE_AUTODISABLE("DAC1 Switch", RT5645_AD_DA_MIXER,
RT5645_M_DAC1_L_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5645_dac_r_mix[] = {
SOC_DAPM_SINGLE("Stereo ADC Switch", RT5645_AD_DA_MIXER,
RT5645_M_ADCMIX_R_SFT, 1, 1),
- SOC_DAPM_SINGLE("DAC1 Switch", RT5645_AD_DA_MIXER,
+ SOC_DAPM_SINGLE_AUTODISABLE("DAC1 Switch", RT5645_AD_DA_MIXER,
RT5645_M_DAC1_R_SFT, 1, 1),
};
@@ -1331,15 +1366,23 @@ static void hp_amp_power(struct snd_soc_codec *codec, int on)
if (on) {
if (hp_amp_power_count <= 0) {
if (rt5645->codec_type == CODEC_TYPE_RT5650) {
+ snd_soc_write(codec, RT5645_DEPOP_M2, 0x3100);
snd_soc_write(codec, RT5645_CHARGE_PUMP,
0x0e06);
- snd_soc_write(codec, RT5645_DEPOP_M1, 0x001d);
+ snd_soc_write(codec, RT5645_DEPOP_M1, 0x000d);
+ regmap_write(rt5645->regmap, RT5645_PR_BASE +
+ RT5645_HP_DCC_INT1, 0x9f01);
+ msleep(20);
+ snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+ RT5645_HP_CO_MASK, RT5645_HP_CO_EN);
regmap_write(rt5645->regmap, RT5645_PR_BASE +
0x3e, 0x7400);
snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737);
regmap_write(rt5645->regmap, RT5645_PR_BASE +
RT5645_MAMP_INT_REG2, 0xfc00);
snd_soc_write(codec, RT5645_DEPOP_M2, 0x1140);
+ msleep(40);
+ rt5645->hp_on = true;
} else {
/* depop parameters */
snd_soc_update_bits(codec, RT5645_DEPOP_M2,
@@ -1553,6 +1596,27 @@ static int rt5645_bst2_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static int rt5650_hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ if (rt5645->hp_on) {
+ msleep(100);
+ rt5645->hp_on = false;
+ }
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("LDO2", RT5645_PWR_MIXER,
RT5645_PWR_LDO2_BIT, 0, NULL, 0),
@@ -1697,15 +1761,6 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = {
SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0),
/* IF1 2 Mux */
- SND_SOC_DAPM_MUX("RT5645 IF1 ADC1 Swap Mux", SND_SOC_NOPM,
- 0, 0, &rt5645_if1_adc1_in_mux),
- SND_SOC_DAPM_MUX("RT5645 IF1 ADC2 Swap Mux", SND_SOC_NOPM,
- 0, 0, &rt5645_if1_adc2_in_mux),
- SND_SOC_DAPM_MUX("RT5645 IF1 ADC3 Swap Mux", SND_SOC_NOPM,
- 0, 0, &rt5645_if1_adc3_in_mux),
- SND_SOC_DAPM_MUX("RT5645 IF1 ADC Mux", SND_SOC_NOPM,
- 0, 0, &rt5645_if1_adc_in_mux),
-
SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM,
0, 0, &rt5645_if2_adc_in_mux),
@@ -1716,14 +1771,6 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = {
SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 DAC3", SND_SOC_NOPM, 0, 0, NULL, 0),
- SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 L Mux", SND_SOC_NOPM, 0, 0,
- &rt5645_if1_dac0_tdm_sel_mux),
- SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 R Mux", SND_SOC_NOPM, 0, 0,
- &rt5645_if1_dac1_tdm_sel_mux),
- SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 L Mux", SND_SOC_NOPM, 0, 0,
- &rt5645_if1_dac2_tdm_sel_mux),
- SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 R Mux", SND_SOC_NOPM, 0, 0,
- &rt5645_if1_dac3_tdm_sel_mux),
SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -1854,6 +1901,26 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("PDM1R"),
SND_SOC_DAPM_OUTPUT("SPOL"),
SND_SOC_DAPM_OUTPUT("SPOR"),
+ SND_SOC_DAPM_POST("DAPM_POST", rt5650_hp_event),
+};
+
+static const struct snd_soc_dapm_widget rt5645_specific_dapm_widgets[] = {
+ SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_if1_dac0_tdm_sel_mux),
+ SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_if1_dac1_tdm_sel_mux),
+ SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_if1_dac2_tdm_sel_mux),
+ SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5645_if1_dac3_tdm_sel_mux),
+ SND_SOC_DAPM_MUX("RT5645 IF1 ADC Mux", SND_SOC_NOPM,
+ 0, 0, &rt5645_if1_adc_in_mux),
+ SND_SOC_DAPM_MUX("RT5645 IF1 ADC1 Swap Mux", SND_SOC_NOPM,
+ 0, 0, &rt5645_if1_adc1_in_mux),
+ SND_SOC_DAPM_MUX("RT5645 IF1 ADC2 Swap Mux", SND_SOC_NOPM,
+ 0, 0, &rt5645_if1_adc2_in_mux),
+ SND_SOC_DAPM_MUX("RT5645 IF1 ADC3 Swap Mux", SND_SOC_NOPM,
+ 0, 0, &rt5645_if1_adc3_in_mux),
};
static const struct snd_soc_dapm_widget rt5650_specific_dapm_widgets[] = {
@@ -2642,7 +2709,7 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec,
switch (level) {
case SND_SOC_BIAS_PREPARE:
- if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) {
+ if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) {
snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
RT5645_PWR_VREF1 | RT5645_PWR_MB |
RT5645_PWR_BG | RT5645_PWR_VREF2,
@@ -2686,94 +2753,15 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int rt5650_calibration(struct rt5645_priv *rt5645)
-{
- int val, i;
- int ret = -1;
-
- regcache_cache_bypass(rt5645->regmap, true);
- regmap_write(rt5645->regmap, RT5645_RESET, 0);
- regmap_write(rt5645->regmap, RT5645_GEN_CTRL3, 0x0800);
- regmap_write(rt5645->regmap, RT5645_PR_BASE + RT5645_CHOP_DAC_ADC,
- 0x3600);
- regmap_write(rt5645->regmap, RT5645_PR_BASE + 0x25, 0x7000);
- regmap_write(rt5645->regmap, RT5645_I2S1_SDP, 0x8008);
- /* headset type */
- regmap_write(rt5645->regmap, RT5645_GEN_CTRL1, 0x2061);
- regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0006);
- regmap_write(rt5645->regmap, RT5645_PWR_ANLG1, 0x2012);
- regmap_write(rt5645->regmap, RT5645_PWR_MIXER, 0x0002);
- regmap_write(rt5645->regmap, RT5645_PWR_VOL, 0x0020);
- regmap_write(rt5645->regmap, RT5645_JD_CTRL3, 0x00f0);
- regmap_write(rt5645->regmap, RT5645_IN1_CTRL1, 0x0006);
- regmap_write(rt5645->regmap, RT5645_IN1_CTRL2, 0x1827);
- regmap_write(rt5645->regmap, RT5645_IN1_CTRL2, 0x0827);
- msleep(400);
- /* Inline command */
- regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x0001);
- regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD2, 0xc000);
- regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD1, 0x0008);
- /* Calbration */
- regmap_write(rt5645->regmap, RT5645_GLB_CLK, 0x8000);
- regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x0000);
- regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD2, 0xc000);
- regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD1, 0x0008);
- regmap_write(rt5645->regmap, RT5645_PWR_DIG2, 0x8800);
- regmap_write(rt5645->regmap, RT5645_PWR_ANLG1, 0xe8fa);
- regmap_write(rt5645->regmap, RT5645_PWR_ANLG2, 0x8c04);
- regmap_write(rt5645->regmap, RT5645_DEPOP_M2, 0x3100);
- regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0e06);
- regmap_write(rt5645->regmap, RT5645_BASS_BACK, 0x8a13);
- regmap_write(rt5645->regmap, RT5645_GEN_CTRL3, 0x0820);
- regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x000d);
- /* Power on and Calbration */
- regmap_write(rt5645->regmap, RT5645_PR_BASE + RT5645_HP_DCC_INT1,
- 0x9f01);
- msleep(200);
- for (i = 0; i < 5; i++) {
- regmap_read(rt5645->regmap, RT5645_PR_BASE + 0x7a, &val);
- if (val != 0 && val != 0x3f3f) {
- ret = 0;
- break;
- }
- msleep(50);
- }
- pr_debug("%s: PR-7A = 0x%x\n", __func__, val);
-
- /* mute */
- regmap_write(rt5645->regmap, RT5645_PR_BASE + 0x3e, 0x7400);
- regmap_write(rt5645->regmap, RT5645_DEPOP_M3, 0x0737);
- regmap_write(rt5645->regmap, RT5645_PR_BASE + RT5645_MAMP_INT_REG2,
- 0xfc00);
- regmap_write(rt5645->regmap, RT5645_DEPOP_M2, 0x1140);
- regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x0000);
- regmap_write(rt5645->regmap, RT5645_GEN_CTRL2, 0x4020);
- regmap_write(rt5645->regmap, RT5645_PWR_ANLG2, 0x0006);
- regmap_write(rt5645->regmap, RT5645_PWR_DIG2, 0x0000);
- msleep(350);
-
- regcache_cache_bypass(rt5645->regmap, false);
-
- return ret;
-}
-
static void rt5645_enable_push_button_irq(struct snd_soc_codec *codec,
bool enable)
{
- struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
if (enable) {
- snd_soc_dapm_mutex_lock(&codec->dapm);
- snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm,
- "ADC L power");
- snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm,
- "ADC R power");
- snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm,
- "LDO2");
- snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm,
- "Mic Det Power");
- snd_soc_dapm_sync_unlocked(&codec->dapm);
- snd_soc_dapm_mutex_unlock(&codec->dapm);
+ snd_soc_dapm_force_enable_pin(dapm, "ADC L power");
+ snd_soc_dapm_force_enable_pin(dapm, "ADC R power");
+ snd_soc_dapm_sync(dapm);
snd_soc_update_bits(codec,
RT5645_INT_IRQ_ST, 0x8, 0x8);
@@ -2786,36 +2774,26 @@ static void rt5645_enable_push_button_irq(struct snd_soc_codec *codec,
snd_soc_update_bits(codec, RT5650_4BTN_IL_CMD2, 0x8000, 0x0);
snd_soc_update_bits(codec, RT5645_INT_IRQ_ST, 0x8, 0x0);
- snd_soc_dapm_mutex_lock(&codec->dapm);
- snd_soc_dapm_disable_pin_unlocked(&codec->dapm,
- "ADC L power");
- snd_soc_dapm_disable_pin_unlocked(&codec->dapm,
- "ADC R power");
- if (rt5645->pdata.jd_mode == 0)
- snd_soc_dapm_disable_pin_unlocked(&codec->dapm,
- "LDO2");
- snd_soc_dapm_disable_pin_unlocked(&codec->dapm,
- "Mic Det Power");
- snd_soc_dapm_sync_unlocked(&codec->dapm);
- snd_soc_dapm_mutex_unlock(&codec->dapm);
+ snd_soc_dapm_disable_pin(dapm, "ADC L power");
+ snd_soc_dapm_disable_pin(dapm, "ADC R power");
+ snd_soc_dapm_sync(dapm);
}
}
static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert)
{
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
unsigned int val;
if (jack_insert) {
regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0006);
- if (codec->component.card->instantiated) {
- /* for jack type detect */
- snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2");
- snd_soc_dapm_force_enable_pin(&codec->dapm,
- "Mic Det Power");
- snd_soc_dapm_sync(&codec->dapm);
- } else {
+ /* for jack type detect */
+ snd_soc_dapm_force_enable_pin(dapm, "LDO2");
+ snd_soc_dapm_force_enable_pin(dapm, "Mic Det Power");
+ snd_soc_dapm_sync(dapm);
+ if (!dapm->card->instantiated) {
/* Power up necessary bits for JD if dapm is
not ready yet */
regmap_update_bits(rt5645->regmap, RT5645_PWR_ANLG1,
@@ -2828,14 +2806,15 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert)
}
regmap_write(rt5645->regmap, RT5645_JD_CTRL3, 0x00f0);
- regmap_write(rt5645->regmap, RT5645_IN1_CTRL1, 0x0006);
- regmap_update_bits(rt5645->regmap,
- RT5645_IN1_CTRL2, 0x1000, 0x1000);
+ regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2,
+ RT5645_CBJ_MN_JD, RT5645_CBJ_MN_JD);
+ regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1,
+ RT5645_CBJ_BST1_EN, RT5645_CBJ_BST1_EN);
msleep(100);
- regmap_update_bits(rt5645->regmap,
- RT5645_IN1_CTRL2, 0x1000, 0x0000);
+ regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2,
+ RT5645_CBJ_MN_JD, 0);
- msleep(450);
+ msleep(600);
regmap_read(rt5645->regmap, RT5645_IN1_CTRL3, &val);
val &= 0x7;
dev_dbg(codec->dev, "val = %d\n", val);
@@ -2846,43 +2825,45 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert)
rt5645_enable_push_button_irq(codec, true);
}
} else {
- if (codec->component.card->instantiated) {
- snd_soc_dapm_disable_pin(&codec->dapm,
- "Mic Det Power");
- snd_soc_dapm_sync(&codec->dapm);
- } else
- regmap_update_bits(rt5645->regmap,
- RT5645_PWR_VOL, RT5645_PWR_MIC_DET, 0);
+ snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
+ snd_soc_dapm_sync(dapm);
rt5645->jack_type = SND_JACK_HEADPHONE;
}
-
} else { /* jack out */
rt5645->jack_type = 0;
+
+ regmap_update_bits(rt5645->regmap, RT5645_HP_VOL,
+ RT5645_L_MUTE | RT5645_R_MUTE,
+ RT5645_L_MUTE | RT5645_R_MUTE);
+ regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2,
+ RT5645_CBJ_MN_JD, RT5645_CBJ_MN_JD);
+ regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1,
+ RT5645_CBJ_BST1_EN, 0);
+
if (rt5645->en_button_func)
rt5645_enable_push_button_irq(codec, false);
- else {
- if (codec->component.card->instantiated) {
- if (rt5645->pdata.jd_mode == 0)
- snd_soc_dapm_disable_pin(&codec->dapm,
- "LDO2");
- snd_soc_dapm_disable_pin(&codec->dapm,
- "Mic Det Power");
- snd_soc_dapm_sync(&codec->dapm);
- } else {
- if (rt5645->pdata.jd_mode == 0)
- regmap_update_bits(rt5645->regmap,
- RT5645_PWR_MIXER,
- RT5645_PWR_LDO2, 0);
- regmap_update_bits(rt5645->regmap,
- RT5645_PWR_VOL, RT5645_PWR_MIC_DET, 0);
- }
- }
+
+ if (rt5645->pdata.jd_mode == 0)
+ snd_soc_dapm_disable_pin(dapm, "LDO2");
+ snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
+ snd_soc_dapm_sync(dapm);
}
return rt5645->jack_type;
}
-static int rt5645_irq_detection(struct rt5645_priv *rt5645);
+static int rt5645_button_detect(struct snd_soc_codec *codec)
+{
+ int btn_type, val;
+
+ val = snd_soc_read(codec, RT5650_4BTN_IL_CMD1);
+ pr_debug("val=0x%x\n", val);
+ btn_type = val & 0xfff0;
+ snd_soc_write(codec, RT5650_4BTN_IL_CMD1, val);
+
+ return btn_type;
+}
+
static irqreturn_t rt5645_irq(int irq, void *data);
int rt5645_set_jack_detect(struct snd_soc_codec *codec,
@@ -2898,8 +2879,6 @@ int rt5645_set_jack_detect(struct snd_soc_codec *codec,
rt5645->en_button_func = true;
regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
RT5645_GP1_PIN_IRQ, RT5645_GP1_PIN_IRQ);
- regmap_update_bits(rt5645->regmap, RT5645_DEPOP_M1,
- RT5645_HP_CB_MASK, RT5645_HP_CB_PU);
regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL1,
RT5645_DIG_GATE_CTRL, RT5645_DIG_GATE_CTRL);
}
@@ -2913,38 +2892,10 @@ static void rt5645_jack_detect_work(struct work_struct *work)
{
struct rt5645_priv *rt5645 =
container_of(work, struct rt5645_priv, jack_detect_work.work);
-
- rt5645_irq_detection(rt5645);
-}
-
-static irqreturn_t rt5645_irq(int irq, void *data)
-{
- struct rt5645_priv *rt5645 = data;
-
- queue_delayed_work(system_power_efficient_wq,
- &rt5645->jack_detect_work, msecs_to_jiffies(250));
-
- return IRQ_HANDLED;
-}
-
-static int rt5645_button_detect(struct snd_soc_codec *codec)
-{
- int btn_type, val;
-
- val = snd_soc_read(codec, RT5650_4BTN_IL_CMD1);
- pr_debug("val=0x%x\n", val);
- btn_type = val & 0xfff0;
- snd_soc_write(codec, RT5650_4BTN_IL_CMD1, val);
-
- return btn_type;
-}
-
-static int rt5645_irq_detection(struct rt5645_priv *rt5645)
-{
int val, btn_type, gpio_state = 0, report = 0;
if (!rt5645->codec)
- return -EINVAL;
+ return;
switch (rt5645->pdata.jd_mode) {
case 0: /* Not using rt5645 JD */
@@ -2958,7 +2909,7 @@ static int rt5645_irq_detection(struct rt5645_priv *rt5645)
report, SND_JACK_HEADPHONE);
snd_soc_jack_report(rt5645->mic_jack,
report, SND_JACK_MICROPHONE);
- return report;
+ return;
case 1: /* 2 port */
val = snd_soc_read(rt5645->codec, RT5645_A_JD_CTRL1) & 0x0070;
break;
@@ -3040,27 +2991,39 @@ static int rt5645_irq_detection(struct rt5645_priv *rt5645)
snd_soc_jack_report(rt5645->btn_jack,
report, SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3);
+}
- return report;
+static irqreturn_t rt5645_irq(int irq, void *data)
+{
+ struct rt5645_priv *rt5645 = data;
+
+ queue_delayed_work(system_power_efficient_wq,
+ &rt5645->jack_detect_work, msecs_to_jiffies(250));
+
+ return IRQ_HANDLED;
}
static int rt5645_probe(struct snd_soc_codec *codec)
{
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
rt5645->codec = codec;
switch (rt5645->codec_type) {
case CODEC_TYPE_RT5645:
- snd_soc_dapm_add_routes(&codec->dapm,
+ snd_soc_dapm_new_controls(dapm,
+ rt5645_specific_dapm_widgets,
+ ARRAY_SIZE(rt5645_specific_dapm_widgets));
+ snd_soc_dapm_add_routes(dapm,
rt5645_specific_dapm_routes,
ARRAY_SIZE(rt5645_specific_dapm_routes));
break;
case CODEC_TYPE_RT5650:
- snd_soc_dapm_new_controls(&codec->dapm,
+ snd_soc_dapm_new_controls(dapm,
rt5650_specific_dapm_widgets,
ARRAY_SIZE(rt5650_specific_dapm_widgets));
- snd_soc_dapm_add_routes(&codec->dapm,
+ snd_soc_dapm_add_routes(dapm,
rt5650_specific_dapm_routes,
ARRAY_SIZE(rt5650_specific_dapm_routes));
break;
@@ -3070,9 +3033,9 @@ static int rt5645_probe(struct snd_soc_codec *codec)
/* for JD function */
if (rt5645->pdata.jd_mode) {
- snd_soc_dapm_force_enable_pin(&codec->dapm, "JD Power");
- snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2");
- snd_soc_dapm_sync(&codec->dapm);
+ snd_soc_dapm_force_enable_pin(dapm, "JD Power");
+ snd_soc_dapm_force_enable_pin(dapm, "LDO2");
+ snd_soc_dapm_sync(dapm);
}
return 0;
@@ -3113,7 +3076,7 @@ static int rt5645_resume(struct snd_soc_codec *codec)
#define RT5645_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
-static struct snd_soc_dai_ops rt5645_aif_dai_ops = {
+static const struct snd_soc_dai_ops rt5645_aif_dai_ops = {
.hw_params = rt5645_hw_params,
.set_fmt = rt5645_set_dai_fmt,
.set_sysclk = rt5645_set_dai_sysclk,
@@ -3224,7 +3187,7 @@ static int strago_quirk_cb(const struct dmi_system_id *id)
return 1;
}
-static struct dmi_system_id dmi_platform_intel_braswell[] = {
+static const struct dmi_system_id dmi_platform_intel_braswell[] = {
{
.ident = "Intel Strago",
.callback = strago_quirk_cb,
@@ -3239,6 +3202,13 @@ static struct dmi_system_id dmi_platform_intel_braswell[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
},
},
+ {
+ .ident = "Google Ultima",
+ .callback = strago_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "Ultima"),
+ },
+ },
{ }
};
@@ -3261,7 +3231,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
{
struct rt5645_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct rt5645_priv *rt5645;
- int ret;
+ int ret, i;
unsigned int val;
rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv),
@@ -3295,6 +3265,24 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
return ret;
}
+ for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++)
+ rt5645->supplies[i].supply = rt5645_supply_names[i];
+
+ ret = devm_regulator_bulk_get(&i2c->dev,
+ ARRAY_SIZE(rt5645->supplies),
+ rt5645->supplies);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(rt5645->supplies),
+ rt5645->supplies);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val);
switch (val) {
@@ -3306,16 +3294,10 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
break;
default:
dev_err(&i2c->dev,
- "Device with ID register %x is not rt5645 or rt5650\n",
+ "Device with ID register %#x is not rt5645 or rt5650\n",
val);
- return -ENODEV;
- }
-
- if (rt5645->codec_type == CODEC_TYPE_RT5650) {
- ret = rt5650_calibration(rt5645);
-
- if (ret < 0)
- pr_err("calibration failed!\n");
+ ret = -ENODEV;
+ goto err_enable;
}
regmap_write(rt5645->regmap, RT5645_RESET, 0);
@@ -3405,8 +3387,6 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3,
RT5645_IRQ_CLK_GATE_CTRL,
RT5645_IRQ_CLK_GATE_CTRL);
- regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1,
- RT5645_CBJ_BST1_EN, RT5645_CBJ_BST1_EN);
regmap_update_bits(rt5645->regmap, RT5645_MICBIAS,
RT5645_IRQ_CLK_INT, RT5645_IRQ_CLK_INT);
regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
@@ -3446,12 +3426,25 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
| IRQF_ONESHOT, "rt5645", rt5645);
- if (ret)
+ if (ret) {
dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
+ goto err_enable;
+ }
}
- return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645,
- rt5645_dai, ARRAY_SIZE(rt5645_dai));
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645,
+ rt5645_dai, ARRAY_SIZE(rt5645_dai));
+ if (ret)
+ goto err_irq;
+
+ return 0;
+
+err_irq:
+ if (rt5645->i2c->irq)
+ free_irq(rt5645->i2c->irq, rt5645);
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies);
+ return ret;
}
static int rt5645_i2c_remove(struct i2c_client *i2c)
@@ -3464,18 +3457,31 @@ static int rt5645_i2c_remove(struct i2c_client *i2c)
cancel_delayed_work_sync(&rt5645->jack_detect_work);
snd_soc_unregister_codec(&i2c->dev);
+ regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies);
return 0;
}
+static void rt5645_i2c_shutdown(struct i2c_client *i2c)
+{
+ struct rt5645_priv *rt5645 = i2c_get_clientdata(i2c);
+
+ regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3,
+ RT5645_RING2_SLEEVE_GND, RT5645_RING2_SLEEVE_GND);
+ regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2, RT5645_CBJ_MN_JD,
+ RT5645_CBJ_MN_JD);
+ regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, RT5645_CBJ_BST1_EN,
+ 0);
+}
+
static struct i2c_driver rt5645_i2c_driver = {
.driver = {
.name = "rt5645",
- .owner = THIS_MODULE,
.acpi_match_table = ACPI_PTR(rt5645_acpi_match),
},
.probe = rt5645_i2c_probe,
- .remove = rt5645_i2c_remove,
+ .remove = rt5645_i2c_remove,
+ .shutdown = rt5645_i2c_shutdown,
.id_table = rt5645_i2c_id,
};
module_i2c_driver(rt5645_i2c_driver);
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h
index 278bb9f46..8c964cfb1 100644
--- a/sound/soc/codecs/rt5645.h
+++ b/sound/soc/codecs/rt5645.h
@@ -39,8 +39,8 @@
#define RT5645_STO1_ADC_DIG_VOL 0x1c
#define RT5645_MONO_ADC_DIG_VOL 0x1d
#define RT5645_ADC_BST_VOL1 0x1e
-/* Mixer - D-D */
#define RT5645_ADC_BST_VOL2 0x20
+/* Mixer - D-D */
#define RT5645_STO1_ADC_MIXER 0x27
#define RT5645_MONO_ADC_MIXER 0x28
#define RT5645_AD_DA_MIXER 0x29
@@ -315,12 +315,14 @@
#define RT5645_STO1_ADC_R_BST_SFT 12
#define RT5645_STO1_ADC_COMP_MASK (0x3 << 10)
#define RT5645_STO1_ADC_COMP_SFT 10
-#define RT5645_STO2_ADC_L_BST_MASK (0x3 << 8)
-#define RT5645_STO2_ADC_L_BST_SFT 8
-#define RT5645_STO2_ADC_R_BST_MASK (0x3 << 6)
-#define RT5645_STO2_ADC_R_BST_SFT 6
-#define RT5645_STO2_ADC_COMP_MASK (0x3 << 4)
-#define RT5645_STO2_ADC_COMP_SFT 4
+
+/* ADC Boost Volume Control (0x20) */
+#define RT5645_MONO_ADC_L_BST_MASK (0x3 << 14)
+#define RT5645_MONO_ADC_L_BST_SFT 14
+#define RT5645_MONO_ADC_R_BST_MASK (0x3 << 12)
+#define RT5645_MONO_ADC_R_BST_SFT 12
+#define RT5645_MONO_ADC_COMP_MASK (0x3 << 10)
+#define RT5645_MONO_ADC_COMP_SFT 10
/* Stereo2 ADC Mixer Control (0x26) */
#define RT5645_STO2_ADC_SRC_MASK (0x1 << 15)
@@ -2115,6 +2117,7 @@ enum {
#define RT5645_JD_PSV_MODE (0x1 << 12)
#define RT5645_IRQ_CLK_GATE_CTRL (0x1 << 11)
#define RT5645_MICINDET_MANU (0x1 << 7)
+#define RT5645_RING2_SLEEVE_GND (0x1 << 5)
/* Vendor ID (0xfd) */
#define RT5645_VER_C 0x2
@@ -2181,32 +2184,6 @@ enum {
int rt5645_sel_asrc_clk_src(struct snd_soc_codec *codec,
unsigned int filter_mask, unsigned int clk_src);
-struct rt5645_priv {
- struct snd_soc_codec *codec;
- struct rt5645_platform_data pdata;
- struct regmap *regmap;
- struct i2c_client *i2c;
- struct gpio_desc *gpiod_hp_det;
- struct snd_soc_jack *hp_jack;
- struct snd_soc_jack *mic_jack;
- struct snd_soc_jack *btn_jack;
- struct delayed_work jack_detect_work;
-
- int codec_type;
- int sysclk;
- int sysclk_src;
- int lrck[RT5645_AIFS];
- int bclk[RT5645_AIFS];
- int master[RT5645_AIFS];
-
- int pll_src;
- int pll_in;
- int pll_out;
-
- int jack_type;
- bool en_button_func;
-};
-
int rt5645_set_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack,
struct snd_soc_jack *btn_jack);
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index a3506e193..1d4031818 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -46,7 +46,7 @@ static const struct regmap_range_cfg rt5651_ranges[] = {
.window_len = 0x1, },
};
-static struct reg_default init_list[] = {
+static const struct reg_sequence init_list[] = {
{RT5651_PR_BASE + 0x3d, 0x3e00},
};
@@ -292,16 +292,15 @@ static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
-static unsigned int bst_tlv[] = {
- TLV_DB_RANGE_HEAD(7),
+static const DECLARE_TLV_DB_RANGE(bst_tlv,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
- 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
-};
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0)
+);
/* Interface data select */
static const char * const rt5651_data_select[] = {
@@ -378,10 +377,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
- int idx = -EINVAL;
-
- idx = rl6231_calc_dmic_clk(rt5651->sysclk);
+ int idx, rate;
+ rate = rt5651->sysclk / rl6231_get_pre_div(rt5651->regmap,
+ RT5651_ADDA_CLK1, RT5651_I2S_PD1_SFT);
+ idx = rl6231_calc_dmic_clk(rate);
if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n");
else
@@ -1769,7 +1769,7 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
regmap_read(rt5651->regmap, RT5651_DEVICE_ID, &ret);
if (ret != RT5651_DEVICE_ID_VALUE) {
dev_err(&i2c->dev,
- "Device with ID register %x is not rt5651\n", ret);
+ "Device with ID register %#x is not rt5651\n", ret);
return -ENODEV;
}
@@ -1806,7 +1806,6 @@ static int rt5651_i2c_remove(struct i2c_client *i2c)
static struct i2c_driver rt5651_i2c_driver = {
.driver = {
.name = "rt5651",
- .owner = THIS_MODULE,
},
.probe = rt5651_i2c_probe,
.remove = rt5651_i2c_remove,
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
index a9123d414..49a9e7049 100644
--- a/sound/soc/codecs/rt5670.c
+++ b/sound/soc/codecs/rt5670.c
@@ -51,7 +51,7 @@ static const struct regmap_range_cfg rt5670_ranges[] = {
.window_len = 0x1, },
};
-static const struct reg_default init_list[] = {
+static const struct reg_sequence init_list[] = {
{ RT5670_PR_BASE + 0x14, 0x9a8a },
{ RT5670_PR_BASE + 0x38, 0x3ba1 },
{ RT5670_PR_BASE + 0x3d, 0x3640 },
@@ -592,16 +592,15 @@ static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
-static unsigned int bst_tlv[] = {
- TLV_DB_RANGE_HEAD(7),
+static const DECLARE_TLV_DB_RANGE(bst_tlv,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
- 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
-};
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0)
+);
/* Interface data select */
static const char * const rt5670_data_select[] = {
@@ -683,10 +682,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
- int idx = -EINVAL;
-
- idx = rl6231_calc_dmic_clk(rt5670->sysclk);
+ int idx, rate;
+ rate = rt5670->sysclk / rl6231_get_pre_div(rt5670->regmap,
+ RT5670_ADDA_CLK1, RT5670_I2S_PD1_SFT);
+ idx = rl6231_calc_dmic_clk(rate);
if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n");
else
@@ -2720,7 +2720,7 @@ static int rt5670_resume(struct snd_soc_codec *codec)
#define RT5670_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
-static struct snd_soc_dai_ops rt5670_aif_dai_ops = {
+static const struct snd_soc_dai_ops rt5670_aif_dai_ops = {
.hw_params = rt5670_hw_params,
.set_fmt = rt5670_set_dai_fmt,
.set_sysclk = rt5670_set_dai_sysclk,
@@ -2863,7 +2863,7 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
regmap_read(rt5670->regmap, RT5670_VENDOR_ID2, &val);
if (val != RT5670_DEVICE_ID) {
dev_err(&i2c->dev,
- "Device with ID register %x is not rt5670/72\n", val);
+ "Device with ID register %#x is not rt5670/72\n", val);
return -ENODEV;
}
@@ -3043,7 +3043,6 @@ static int rt5670_i2c_remove(struct i2c_client *i2c)
static struct i2c_driver rt5670_i2c_driver = {
.driver = {
.name = "rt5670",
- .owner = THIS_MODULE,
.acpi_match_table = ACPI_PTR(rt5670_acpi_match),
},
.probe = rt5670_i2c_probe,
diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c
index ef6348cb9..3505aafba 100644
--- a/sound/soc/codecs/rt5677-spi.c
+++ b/sound/soc/codecs/rt5677-spi.c
@@ -31,84 +31,197 @@
#include "rt5677-spi.h"
+#define RT5677_SPI_BURST_LEN 240
+#define RT5677_SPI_HEADER 5
+#define RT5677_SPI_FREQ 6000000
+
+/* The AddressPhase and DataPhase of SPI commands are MSB first on the wire.
+ * DataPhase word size of 16-bit commands is 2 bytes.
+ * DataPhase word size of 32-bit commands is 4 bytes.
+ * DataPhase word size of burst commands is 8 bytes.
+ * The DSP CPU is little-endian.
+ */
+#define RT5677_SPI_WRITE_BURST 0x5
+#define RT5677_SPI_READ_BURST 0x4
+#define RT5677_SPI_WRITE_32 0x3
+#define RT5677_SPI_READ_32 0x2
+#define RT5677_SPI_WRITE_16 0x1
+#define RT5677_SPI_READ_16 0x0
+
static struct spi_device *g_spi;
+static DEFINE_MUTEX(spi_mutex);
-/**
- * rt5677_spi_write - Write data to SPI.
- * @txbuf: Data Buffer for writing.
- * @len: Data length.
+/* Select a suitable transfer command for the next transfer to ensure
+ * the transfer address is always naturally aligned while minimizing
+ * the total number of transfers required.
+ *
+ * 3 transfer commands are available:
+ * RT5677_SPI_READ/WRITE_16: Transfer 2 bytes
+ * RT5677_SPI_READ/WRITE_32: Transfer 4 bytes
+ * RT5677_SPI_READ/WRITE_BURST: Transfer any multiples of 8 bytes
+ *
+ * For example, reading 260 bytes at 0x60030002 uses the following commands:
+ * 0x60030002 RT5677_SPI_READ_16 2 bytes
+ * 0x60030004 RT5677_SPI_READ_32 4 bytes
+ * 0x60030008 RT5677_SPI_READ_BURST 240 bytes
+ * 0x600300F8 RT5677_SPI_READ_BURST 8 bytes
+ * 0x60030100 RT5677_SPI_READ_32 4 bytes
+ * 0x60030104 RT5677_SPI_READ_16 2 bytes
*
+ * Input:
+ * @read: true for read commands; false for write commands
+ * @align: alignment of the next transfer address
+ * @remain: number of bytes remaining to transfer
*
- * Returns true for success.
+ * Output:
+ * @len: number of bytes to transfer with the selected command
+ * Returns the selected command
*/
-int rt5677_spi_write(u8 *txbuf, size_t len)
+static u8 rt5677_spi_select_cmd(bool read, u32 align, u32 remain, u32 *len)
{
- int status;
-
- status = spi_write(g_spi, txbuf, len);
-
- if (status)
- dev_err(&g_spi->dev, "rt5677_spi_write error %d\n", status);
-
- return status;
+ u8 cmd;
+
+ if (align == 2 || align == 6 || remain == 2) {
+ cmd = RT5677_SPI_READ_16;
+ *len = 2;
+ } else if (align == 4 || remain <= 6) {
+ cmd = RT5677_SPI_READ_32;
+ *len = 4;
+ } else {
+ cmd = RT5677_SPI_READ_BURST;
+ *len = min_t(u32, remain & ~7, RT5677_SPI_BURST_LEN);
+ }
+ return read ? cmd : cmd + 1;
}
-EXPORT_SYMBOL_GPL(rt5677_spi_write);
-/**
- * rt5677_spi_burst_write - Write data to SPI by rt5677 dsp memory address.
- * @addr: Start address.
- * @txbuf: Data Buffer for writng.
- * @len: Data length, it must be a multiple of 8.
- *
- *
- * Returns true for success.
+/* Copy dstlen bytes from src to dst, while reversing byte order for each word.
+ * If srclen < dstlen, zeros are padded.
*/
-int rt5677_spi_burst_write(u32 addr, const struct firmware *fw)
+static void rt5677_spi_reverse(u8 *dst, u32 dstlen, const u8 *src, u32 srclen)
{
- u8 spi_cmd = RT5677_SPI_CMD_BURST_WRITE;
- u8 *write_buf;
- unsigned int i, end, offset = 0;
-
- write_buf = kmalloc(RT5677_SPI_BUF_LEN + 6, GFP_KERNEL);
-
- if (write_buf == NULL)
- return -ENOMEM;
-
- while (offset < fw->size) {
- if (offset + RT5677_SPI_BUF_LEN <= fw->size)
- end = RT5677_SPI_BUF_LEN;
- else
- end = fw->size % RT5677_SPI_BUF_LEN;
-
- write_buf[0] = spi_cmd;
- write_buf[1] = ((addr + offset) & 0xff000000) >> 24;
- write_buf[2] = ((addr + offset) & 0x00ff0000) >> 16;
- write_buf[3] = ((addr + offset) & 0x0000ff00) >> 8;
- write_buf[4] = ((addr + offset) & 0x000000ff) >> 0;
-
- for (i = 0; i < end; i += 8) {
- write_buf[i + 12] = fw->data[offset + i + 0];
- write_buf[i + 11] = fw->data[offset + i + 1];
- write_buf[i + 10] = fw->data[offset + i + 2];
- write_buf[i + 9] = fw->data[offset + i + 3];
- write_buf[i + 8] = fw->data[offset + i + 4];
- write_buf[i + 7] = fw->data[offset + i + 5];
- write_buf[i + 6] = fw->data[offset + i + 6];
- write_buf[i + 5] = fw->data[offset + i + 7];
+ u32 w, i, si;
+ u32 word_size = min_t(u32, dstlen, 8);
+
+ for (w = 0; w < dstlen; w += word_size) {
+ for (i = 0; i < word_size; i++) {
+ si = w + word_size - i - 1;
+ dst[w + i] = si < srclen ? src[si] : 0;
}
+ }
+}
- write_buf[end + 5] = spi_cmd;
+/* Read DSP address space using SPI. addr and len have to be 2-byte aligned. */
+int rt5677_spi_read(u32 addr, void *rxbuf, size_t len)
+{
+ u32 offset;
+ int status = 0;
+ struct spi_transfer t[2];
+ struct spi_message m;
+ /* +4 bytes is for the DummyPhase following the AddressPhase */
+ u8 header[RT5677_SPI_HEADER + 4];
+ u8 body[RT5677_SPI_BURST_LEN];
+ u8 spi_cmd;
+ u8 *cb = rxbuf;
+
+ if (!g_spi)
+ return -ENODEV;
+
+ if ((addr & 1) || (len & 1)) {
+ dev_err(&g_spi->dev, "Bad read align 0x%x(%zu)\n", addr, len);
+ return -EACCES;
+ }
- rt5677_spi_write(write_buf, end + 6);
+ memset(t, 0, sizeof(t));
+ t[0].tx_buf = header;
+ t[0].len = sizeof(header);
+ t[0].speed_hz = RT5677_SPI_FREQ;
+ t[1].rx_buf = body;
+ t[1].speed_hz = RT5677_SPI_FREQ;
+ spi_message_init_with_transfers(&m, t, ARRAY_SIZE(t));
+
+ for (offset = 0; offset < len; offset += t[1].len) {
+ spi_cmd = rt5677_spi_select_cmd(true, (addr + offset) & 7,
+ len - offset, &t[1].len);
+
+ /* Construct SPI message header */
+ header[0] = spi_cmd;
+ header[1] = ((addr + offset) & 0xff000000) >> 24;
+ header[2] = ((addr + offset) & 0x00ff0000) >> 16;
+ header[3] = ((addr + offset) & 0x0000ff00) >> 8;
+ header[4] = ((addr + offset) & 0x000000ff) >> 0;
+
+ mutex_lock(&spi_mutex);
+ status |= spi_sync(g_spi, &m);
+ mutex_unlock(&spi_mutex);
+
+ /* Copy data back to caller buffer */
+ rt5677_spi_reverse(cb + offset, t[1].len, body, t[1].len);
+ }
+ return status;
+}
+EXPORT_SYMBOL_GPL(rt5677_spi_read);
- offset += RT5677_SPI_BUF_LEN;
+/* Write DSP address space using SPI. addr has to be 2-byte aligned.
+ * If len is not 2-byte aligned, an extra byte of zero is written at the end
+ * as padding.
+ */
+int rt5677_spi_write(u32 addr, const void *txbuf, size_t len)
+{
+ u32 offset, len_with_pad = len;
+ int status = 0;
+ struct spi_transfer t;
+ struct spi_message m;
+ /* +1 byte is for the DummyPhase following the DataPhase */
+ u8 buf[RT5677_SPI_HEADER + RT5677_SPI_BURST_LEN + 1];
+ u8 *body = buf + RT5677_SPI_HEADER;
+ u8 spi_cmd;
+ const u8 *cb = txbuf;
+
+ if (!g_spi)
+ return -ENODEV;
+
+ if (addr & 1) {
+ dev_err(&g_spi->dev, "Bad write align 0x%x(%zu)\n", addr, len);
+ return -EACCES;
}
- kfree(write_buf);
+ if (len & 1)
+ len_with_pad = len + 1;
+
+ memset(&t, 0, sizeof(t));
+ t.tx_buf = buf;
+ t.speed_hz = RT5677_SPI_FREQ;
+ spi_message_init_with_transfers(&m, &t, 1);
+
+ for (offset = 0; offset < len_with_pad;) {
+ spi_cmd = rt5677_spi_select_cmd(false, (addr + offset) & 7,
+ len_with_pad - offset, &t.len);
+
+ /* Construct SPI message header */
+ buf[0] = spi_cmd;
+ buf[1] = ((addr + offset) & 0xff000000) >> 24;
+ buf[2] = ((addr + offset) & 0x00ff0000) >> 16;
+ buf[3] = ((addr + offset) & 0x0000ff00) >> 8;
+ buf[4] = ((addr + offset) & 0x000000ff) >> 0;
+
+ /* Fetch data from caller buffer */
+ rt5677_spi_reverse(body, t.len, cb + offset, len - offset);
+ offset += t.len;
+ t.len += RT5677_SPI_HEADER + 1;
+
+ mutex_lock(&spi_mutex);
+ status |= spi_sync(g_spi, &m);
+ mutex_unlock(&spi_mutex);
+ }
+ return status;
+}
+EXPORT_SYMBOL_GPL(rt5677_spi_write);
- return 0;
+int rt5677_spi_write_firmware(u32 addr, const struct firmware *fw)
+{
+ return rt5677_spi_write(addr, fw->data, fw->size);
}
-EXPORT_SYMBOL_GPL(rt5677_spi_burst_write);
+EXPORT_SYMBOL_GPL(rt5677_spi_write_firmware);
static int rt5677_spi_probe(struct spi_device *spi)
{
diff --git a/sound/soc/codecs/rt5677-spi.h b/sound/soc/codecs/rt5677-spi.h
index ec41b2b3b..662db16cf 100644
--- a/sound/soc/codecs/rt5677-spi.h
+++ b/sound/soc/codecs/rt5677-spi.h
@@ -12,10 +12,8 @@
#ifndef __RT5677_SPI_H__
#define __RT5677_SPI_H__
-#define RT5677_SPI_BUF_LEN 240
-#define RT5677_SPI_CMD_BURST_WRITE 0x05
-
-int rt5677_spi_write(u8 *txbuf, size_t len);
-int rt5677_spi_burst_write(u32 addr, const struct firmware *fw);
+int rt5677_spi_read(u32 addr, void *rxbuf, size_t len);
+int rt5677_spi_write(u32 addr, const void *txbuf, size_t len);
+int rt5677_spi_write_firmware(u32 addr, const struct firmware *fw);
#endif /* __RT5677_SPI_H__ */
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
index 92280f844..f6e92b7b0 100644
--- a/sound/soc/codecs/rt5677.c
+++ b/sound/soc/codecs/rt5677.c
@@ -15,13 +15,12 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
-#include <linux/of_gpio.h>
#include <linux/regmap.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/firmware.h>
-#include <linux/gpio.h>
+#include <linux/property.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -54,7 +53,7 @@ static const struct regmap_range_cfg rt5677_ranges[] = {
},
};
-static const struct reg_default init_list[] = {
+static const struct reg_sequence init_list[] = {
{RT5677_ASRC_12, 0x0018},
{RT5677_PR_BASE + 0x3d, 0x364d},
{RT5677_PR_BASE + 0x17, 0x4fc0},
@@ -746,14 +745,14 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
ret = reject_firmware(&rt5677->fw1, RT5677_FIRMWARE1,
codec->dev);
if (ret == 0) {
- rt5677_spi_burst_write(0x50000000, rt5677->fw1);
+ rt5677_spi_write_firmware(0x50000000, rt5677->fw1);
release_firmware(rt5677->fw1);
}
ret = reject_firmware(&rt5677->fw2, RT5677_FIRMWARE2,
codec->dev);
if (ret == 0) {
- rt5677_spi_burst_write(0x60000000, rt5677->fw2);
+ rt5677_spi_write_firmware(0x60000000, rt5677->fw2);
release_firmware(rt5677->fw2);
}
@@ -789,16 +788,15 @@ static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
static const DECLARE_TLV_DB_SCALE(st_vol_tlv, -4650, 150, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
-static unsigned int bst_tlv[] = {
- TLV_DB_RANGE_HEAD(7),
+static const DECLARE_TLV_DB_RANGE(bst_tlv,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
- 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
-};
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0)
+);
static int rt5677_dsp_vad_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -917,8 +915,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
- int idx = rl6231_calc_dmic_clk(rt5677->lrck[RT5677_AIF1] << 8);
+ int idx, rate;
+ rate = rt5677->sysclk / rl6231_get_pre_div(rt5677->regmap,
+ RT5677_CLK_TREE_CTRL1, RT5677_I2S_PD1_SFT);
+ idx = rl6231_calc_dmic_clk(rate);
if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n");
else
@@ -4764,10 +4765,8 @@ static int rt5677_remove(struct snd_soc_codec *codec)
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec);
- if (gpio_is_valid(rt5677->pow_ldo2))
- gpio_set_value_cansleep(rt5677->pow_ldo2, 0);
- if (gpio_is_valid(rt5677->reset_pin))
- gpio_set_value_cansleep(rt5677->reset_pin, 0);
+ gpiod_set_value_cansleep(rt5677->pow_ldo2, 0);
+ gpiod_set_value_cansleep(rt5677->reset_pin, 0);
return 0;
}
@@ -4781,10 +4780,8 @@ static int rt5677_suspend(struct snd_soc_codec *codec)
regcache_cache_only(rt5677->regmap, true);
regcache_mark_dirty(rt5677->regmap);
- if (gpio_is_valid(rt5677->pow_ldo2))
- gpio_set_value_cansleep(rt5677->pow_ldo2, 0);
- if (gpio_is_valid(rt5677->reset_pin))
- gpio_set_value_cansleep(rt5677->reset_pin, 0);
+ gpiod_set_value_cansleep(rt5677->pow_ldo2, 0);
+ gpiod_set_value_cansleep(rt5677->reset_pin, 0);
}
return 0;
@@ -4795,12 +4792,9 @@ static int rt5677_resume(struct snd_soc_codec *codec)
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
if (!rt5677->dsp_vad_en) {
- if (gpio_is_valid(rt5677->pow_ldo2))
- gpio_set_value_cansleep(rt5677->pow_ldo2, 1);
- if (gpio_is_valid(rt5677->reset_pin))
- gpio_set_value_cansleep(rt5677->reset_pin, 1);
- if (gpio_is_valid(rt5677->pow_ldo2) ||
- gpio_is_valid(rt5677->reset_pin))
+ gpiod_set_value_cansleep(rt5677->pow_ldo2, 1);
+ gpiod_set_value_cansleep(rt5677->reset_pin, 1);
+ if (rt5677->pow_ldo2 || rt5677->reset_pin)
msleep(10);
regcache_cache_only(rt5677->regmap, false);
@@ -4863,7 +4857,7 @@ static int rt5677_write(void *context, unsigned int reg, unsigned int val)
#define RT5677_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
-static struct snd_soc_dai_ops rt5677_aif_dai_ops = {
+static const struct snd_soc_dai_ops rt5677_aif_dai_ops = {
.hw_params = rt5677_hw_params,
.set_fmt = rt5677_set_dai_fmt,
.set_sysclk = rt5677_set_dai_sysclk,
@@ -5024,45 +5018,29 @@ static const struct i2c_device_id rt5677_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id);
-static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np)
+static void rt5677_read_device_properties(struct rt5677_priv *rt5677,
+ struct device *dev)
{
- rt5677->pdata.in1_diff = of_property_read_bool(np,
- "realtek,in1-differential");
- rt5677->pdata.in2_diff = of_property_read_bool(np,
- "realtek,in2-differential");
- rt5677->pdata.lout1_diff = of_property_read_bool(np,
- "realtek,lout1-differential");
- rt5677->pdata.lout2_diff = of_property_read_bool(np,
- "realtek,lout2-differential");
- rt5677->pdata.lout3_diff = of_property_read_bool(np,
- "realtek,lout3-differential");
-
- rt5677->pow_ldo2 = of_get_named_gpio(np,
- "realtek,pow-ldo2-gpio", 0);
- rt5677->reset_pin = of_get_named_gpio(np,
- "realtek,reset-gpio", 0);
-
- /*
- * POW_LDO2 is optional (it may be statically tied on the board).
- * -ENOENT means that the property doesn't exist, i.e. there is no
- * GPIO, so is not an error. Any other error code means the property
- * exists, but could not be parsed.
- */
- if (!gpio_is_valid(rt5677->pow_ldo2) &&
- (rt5677->pow_ldo2 != -ENOENT))
- return rt5677->pow_ldo2;
- if (!gpio_is_valid(rt5677->reset_pin) &&
- (rt5677->reset_pin != -ENOENT))
- return rt5677->reset_pin;
-
- of_property_read_u8_array(np, "realtek,gpio-config",
- rt5677->pdata.gpio_config, RT5677_GPIO_NUM);
-
- of_property_read_u32(np, "realtek,jd1-gpio", &rt5677->pdata.jd1_gpio);
- of_property_read_u32(np, "realtek,jd2-gpio", &rt5677->pdata.jd2_gpio);
- of_property_read_u32(np, "realtek,jd3-gpio", &rt5677->pdata.jd3_gpio);
-
- return 0;
+ rt5677->pdata.in1_diff = device_property_read_bool(dev,
+ "realtek,in1-differential");
+ rt5677->pdata.in2_diff = device_property_read_bool(dev,
+ "realtek,in2-differential");
+ rt5677->pdata.lout1_diff = device_property_read_bool(dev,
+ "realtek,lout1-differential");
+ rt5677->pdata.lout2_diff = device_property_read_bool(dev,
+ "realtek,lout2-differential");
+ rt5677->pdata.lout3_diff = device_property_read_bool(dev,
+ "realtek,lout3-differential");
+
+ device_property_read_u8_array(dev, "realtek,gpio-config",
+ rt5677->pdata.gpio_config, RT5677_GPIO_NUM);
+
+ device_property_read_u32(dev, "realtek,jd1-gpio",
+ &rt5677->pdata.jd1_gpio);
+ device_property_read_u32(dev, "realtek,jd2-gpio",
+ &rt5677->pdata.jd2_gpio);
+ device_property_read_u32(dev, "realtek,jd3-gpio",
+ &rt5677->pdata.jd3_gpio);
}
static struct regmap_irq rt5677_irqs[] = {
@@ -5145,43 +5123,29 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
if (pdata)
rt5677->pdata = *pdata;
+ else
+ rt5677_read_device_properties(rt5677, &i2c->dev);
- if (i2c->dev.of_node) {
- ret = rt5677_parse_dt(rt5677, i2c->dev.of_node);
- if (ret) {
- dev_err(&i2c->dev, "Failed to parse device tree: %d\n",
- ret);
- return ret;
- }
- } else {
- rt5677->pow_ldo2 = -EINVAL;
- rt5677->reset_pin = -EINVAL;
- }
-
- if (gpio_is_valid(rt5677->pow_ldo2)) {
- ret = devm_gpio_request_one(&i2c->dev, rt5677->pow_ldo2,
- GPIOF_OUT_INIT_HIGH,
- "RT5677 POW_LDO2");
- if (ret < 0) {
- dev_err(&i2c->dev, "Failed to request POW_LDO2 %d: %d\n",
- rt5677->pow_ldo2, ret);
- return ret;
- }
+ /* pow-ldo2 and reset are optional. The codec pins may be statically
+ * connected on the board without gpios. If the gpio device property
+ * isn't specified, devm_gpiod_get_optional returns NULL.
+ */
+ rt5677->pow_ldo2 = devm_gpiod_get_optional(&i2c->dev,
+ "realtek,pow-ldo2", GPIOD_OUT_HIGH);
+ if (IS_ERR(rt5677->pow_ldo2)) {
+ ret = PTR_ERR(rt5677->pow_ldo2);
+ dev_err(&i2c->dev, "Failed to request POW_LDO2: %d\n", ret);
+ return ret;
}
-
- if (gpio_is_valid(rt5677->reset_pin)) {
- ret = devm_gpio_request_one(&i2c->dev, rt5677->reset_pin,
- GPIOF_OUT_INIT_HIGH,
- "RT5677 RESET");
- if (ret < 0) {
- dev_err(&i2c->dev, "Failed to request RESET %d: %d\n",
- rt5677->reset_pin, ret);
- return ret;
- }
+ rt5677->reset_pin = devm_gpiod_get_optional(&i2c->dev,
+ "realtek,reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(rt5677->reset_pin)) {
+ ret = PTR_ERR(rt5677->reset_pin);
+ dev_err(&i2c->dev, "Failed to request RESET: %d\n", ret);
+ return ret;
}
- if (gpio_is_valid(rt5677->pow_ldo2) ||
- gpio_is_valid(rt5677->reset_pin)) {
+ if (rt5677->pow_ldo2 || rt5677->reset_pin) {
/* Wait a while until I2C bus becomes available. The datasheet
* does not specify the exact we should wait but startup
* sequence mentiones at least a few milliseconds.
@@ -5209,7 +5173,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
regmap_read(rt5677->regmap, RT5677_VENDOR_ID2, &val);
if (val != RT5677_DEVICE_ID) {
dev_err(&i2c->dev,
- "Device with ID register %x is not rt5677\n", val);
+ "Device with ID register %#x is not rt5677\n", val);
return -ENODEV;
}
@@ -5273,7 +5237,6 @@ static int rt5677_i2c_remove(struct i2c_client *i2c)
static struct i2c_driver rt5677_i2c_driver = {
.driver = {
.name = "rt5677",
- .owner = THIS_MODULE,
},
.probe = rt5677_i2c_probe,
.remove = rt5677_i2c_remove,
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h
index a15407454..9a3f729da 100644
--- a/sound/soc/codecs/rt5677.h
+++ b/sound/soc/codecs/rt5677.h
@@ -14,6 +14,7 @@
#include <sound/rt5677.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/consumer.h>
/* Info */
#define RT5677_RESET 0x00
@@ -1775,8 +1776,8 @@ struct rt5677_priv {
int pll_src;
int pll_in;
int pll_out;
- int pow_ldo2; /* POW_LDO2 pin */
- int reset_pin; /* RESET pin */
+ struct gpio_desc *pow_ldo2; /* POW_LDO2 pin */
+ struct gpio_desc *reset_pin; /* RESET pin */
enum rt5677_type type;
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio_chip;
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 7c411297b..f540f82b1 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -406,11 +406,10 @@ static int dac_put_volsw(struct snd_kcontrol *kcontrol,
static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0);
/* tlv for mic gain, 0db 20db 30db 40db */
-static const unsigned int mic_gain_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(mic_gain_tlv,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
- 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
-};
+ 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0)
+);
/* tlv for hp volume, -51.5db to 12.0db, step .5db */
static const DECLARE_TLV_DB_SCALE(headphone_volume, -5150, 50, 0);
@@ -1550,7 +1549,7 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
else {
sgtl5000->micbias_voltage = 0;
dev_err(&client->dev,
- "Unsuitable MicBias resistor\n");
+ "Unsuitable MicBias voltage\n");
}
} else {
sgtl5000->micbias_voltage = 0;
@@ -1601,7 +1600,6 @@ MODULE_DEVICE_TABLE(of, sgtl5000_dt_ids);
static struct i2c_driver sgtl5000_i2c_driver = {
.driver = {
.name = "sgtl5000",
- .owner = THIS_MODULE,
.of_match_table = sgtl5000_dt_ids,
},
.probe = sgtl5000_i2c_probe,
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index 3e7296428..a8402d0af 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -208,7 +208,7 @@ out:
return err;
}
-static struct snd_soc_dai_ops si476x_dai_ops = {
+static const struct snd_soc_dai_ops si476x_dai_ops = {
.hw_params = si476x_codec_hw_params,
.set_fmt = si476x_codec_set_dai_fmt,
};
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c
index 29cb44256..6bfd25c28 100644
--- a/sound/soc/codecs/sirf-audio-codec.c
+++ b/sound/soc/codecs/sirf-audio-codec.c
@@ -370,11 +370,11 @@ static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
return 0;
}
-struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
+static const struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
.trigger = sirf_audio_codec_trigger,
};
-struct snd_soc_dai_driver sirf_audio_codec_dai = {
+static struct snd_soc_dai_driver sirf_audio_codec_dai = {
.name = "sirf-audio-codec",
.playback = {
.stream_name = "Playback",
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c
index f30de7639..ddb0203fc 100644
--- a/sound/soc/codecs/ssm2518.c
+++ b/sound/soc/codecs/ssm2518.c
@@ -806,6 +806,14 @@ static int ssm2518_i2c_remove(struct i2c_client *client)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id ssm2518_dt_ids[] = {
+ { .compatible = "adi,ssm2518", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ssm2518_dt_ids);
+#endif
+
static const struct i2c_device_id ssm2518_i2c_ids[] = {
{ "ssm2518", 0 },
{ }
@@ -815,7 +823,7 @@ MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids);
static struct i2c_driver ssm2518_driver = {
.driver = {
.name = "ssm2518",
- .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(ssm2518_dt_ids),
},
.probe = ssm2518_i2c_probe,
.remove = ssm2518_i2c_remove,
diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c
index 0d9779d6b..173ba85ff 100644
--- a/sound/soc/codecs/ssm2602-i2c.c
+++ b/sound/soc/codecs/ssm2602-i2c.c
@@ -52,7 +52,6 @@ MODULE_DEVICE_TABLE(of, ssm2602_of_match);
static struct i2c_driver ssm2602_i2c_driver = {
.driver = {
.name = "ssm2602",
- .owner = THIS_MODULE,
.of_match_table = ssm2602_of_match,
},
.probe = ssm2602_i2c_probe,
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 69a773aeb..4452fea0b 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -75,11 +75,10 @@ static const struct soc_enum ssm2602_enum[] = {
ssm2602_deemph),
};
-static const unsigned int ssm260x_outmix_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(ssm260x_outmix_tlv,
0, 47, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
- 48, 127, TLV_DB_SCALE_ITEM(-7400, 100, 0),
-};
+ 48, 127, TLV_DB_SCALE_ITEM(-7400, 100, 0)
+);
static const DECLARE_TLV_DB_SCALE(ssm260x_inpga_tlv, -3450, 150, 0);
static const DECLARE_TLV_DB_SCALE(ssm260x_sidetone_tlv, -1500, 300, 0);
diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c
index 84a4f5ad8..e619d5651 100644
--- a/sound/soc/codecs/ssm4567.c
+++ b/sound/soc/codecs/ssm4567.c
@@ -10,6 +10,7 @@
* Licensed under the GPL-2.
*/
+#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
@@ -173,6 +174,12 @@ static const struct snd_soc_dapm_widget ssm4567_dapm_widgets[] = {
SND_SOC_DAPM_SWITCH("Amplifier Boost", SSM4567_REG_POWER_CTRL, 3, 1,
&ssm4567_amplifier_boost_control),
+ SND_SOC_DAPM_SIGGEN("Sense"),
+
+ SND_SOC_DAPM_PGA("Current Sense", SSM4567_REG_POWER_CTRL, 4, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Voltage Sense", SSM4567_REG_POWER_CTRL, 5, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("VBAT Sense", SSM4567_REG_POWER_CTRL, 6, 1, NULL, 0),
+
SND_SOC_DAPM_OUTPUT("OUT"),
};
@@ -180,6 +187,13 @@ static const struct snd_soc_dapm_route ssm4567_routes[] = {
{ "OUT", NULL, "Amplifier Boost" },
{ "Amplifier Boost", "Switch", "DAC" },
{ "OUT", NULL, "DAC" },
+
+ { "Current Sense", NULL, "Sense" },
+ { "Voltage Sense", NULL, "Sense" },
+ { "VBAT Sense", NULL, "Sense" },
+ { "Capture Sense", NULL, "Current Sense" },
+ { "Capture Sense", NULL, "Voltage Sense" },
+ { "Capture Sense", NULL, "VBAT Sense" },
};
static int ssm4567_hw_params(struct snd_pcm_substream *substream,
@@ -387,6 +401,14 @@ static struct snd_soc_dai_driver ssm4567_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32,
},
+ .capture = {
+ .stream_name = "Capture Sense",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32,
+ },
.ops = &ssm4567_dai_ops,
};
@@ -456,10 +478,20 @@ static const struct i2c_device_id ssm4567_i2c_ids[] = {
};
MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids);
+#ifdef CONFIG_ACPI
+
+static const struct acpi_device_id ssm4567_acpi_match[] = {
+ { "INT343B", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, ssm4567_acpi_match);
+
+#endif
+
static struct i2c_driver ssm4567_driver = {
.driver = {
.name = "ssm4567",
- .owner = THIS_MODULE,
+ .acpi_match_table = ACPI_PTR(ssm4567_acpi_match),
},
.probe = ssm4567_i2c_probe,
.remove = ssm4567_i2c_remove,
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index 60eff3626..a9844b2ac 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -1144,7 +1144,6 @@ MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id);
static struct i2c_driver sta32x_i2c_driver = {
.driver = {
.name = "sta32x",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(st32x_dt_ids),
},
.probe = sta32x_i2c_probe,
diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c
index bd819a3f2..33a4612f0 100644
--- a/sound/soc/codecs/sta350.c
+++ b/sound/soc/codecs/sta350.c
@@ -1264,7 +1264,6 @@ MODULE_DEVICE_TABLE(i2c, sta350_i2c_id);
static struct i2c_driver sta350_i2c_driver = {
.driver = {
.name = "sta350",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(st350_dt_ids),
},
.probe = sta350_i2c_probe,
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c
index 4f70378b2..2cdaca943 100644
--- a/sound/soc/codecs/sta529.c
+++ b/sound/soc/codecs/sta529.c
@@ -339,9 +339,6 @@ static int sta529_i2c_probe(struct i2c_client *i2c,
struct sta529 *sta529;
int ret;
- if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -EINVAL;
-
sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL);
if (!sta529)
return -ENOMEM;
@@ -379,7 +376,6 @@ MODULE_DEVICE_TABLE(i2c, sta529_i2c_id);
static struct i2c_driver sta529_i2c_driver = {
.driver = {
.name = "sta529",
- .owner = THIS_MODULE,
},
.probe = sta529_i2c_probe,
.remove = sta529_i2c_remove,
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index ed4cca7f6..0945c51df 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -28,6 +28,9 @@
#include "stac9766.h"
+#define STAC9766_VENDOR_ID 0x83847666
+#define STAC9766_VENDOR_ID_MASK 0xffffffff
+
/*
* STAC9766 register cache
*/
@@ -239,45 +242,12 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
-{
- struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
-
- if (try_warm && soc_ac97_ops->warm_reset) {
- soc_ac97_ops->warm_reset(ac97);
- if (stac9766_ac97_read(codec, 0) == stac9766_reg[0])
- return 1;
- }
-
- soc_ac97_ops->reset(ac97);
- if (soc_ac97_ops->warm_reset)
- soc_ac97_ops->warm_reset(ac97);
- if (stac9766_ac97_read(codec, 0) != stac9766_reg[0])
- return -EIO;
- return 0;
-}
-
static int stac9766_codec_resume(struct snd_soc_codec *codec)
{
struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
- u16 id, reset;
- reset = 0;
- /* give the codec an AC97 warm reset to start the link */
-reset:
- if (reset > 5) {
- dev_err(codec->dev, "Failed to resume\n");
- return -EIO;
- }
- ac97->bus->ops->warm_reset(ac97);
- id = soc_ac97_ops->read(ac97, AC97_VENDOR_ID2);
- if (id != 0x4c13) {
- stac9766_reset(codec, 0);
- reset++;
- goto reset;
- }
-
- return 0;
+ return snd_ac97_reset(ac97, true, STAC9766_VENDOR_ID,
+ STAC9766_VENDOR_ID_MASK);
}
static const struct snd_soc_dai_ops stac9766_dai_ops_analog = {
@@ -330,28 +300,15 @@ static struct snd_soc_dai_driver stac9766_dai[] = {
static int stac9766_codec_probe(struct snd_soc_codec *codec)
{
struct snd_ac97 *ac97;
- int ret = 0;
- ac97 = snd_soc_new_ac97_codec(codec);
+ ac97 = snd_soc_new_ac97_codec(codec, STAC9766_VENDOR_ID,
+ STAC9766_VENDOR_ID_MASK);
if (IS_ERR(ac97))
return PTR_ERR(ac97);
snd_soc_codec_set_drvdata(codec, ac97);
- /* do a cold reset for the controller and then try
- * a warm reset followed by an optional cold reset for codec */
- stac9766_reset(codec, 0);
- ret = stac9766_reset(codec, 1);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to reset: AC97 link error\n");
- goto codec_err;
- }
-
return 0;
-
-codec_err:
- snd_soc_free_ac97_codec(ac97);
- return ret;
}
static int stac9766_codec_remove(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c
new file mode 100644
index 000000000..160d61a66
--- /dev/null
+++ b/sound/soc/codecs/sti-sas.c
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2015
+ * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/mfd/syscon.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+/* chipID supported */
+#define CHIPID_STIH416 0
+#define CHIPID_STIH407 1
+
+/* DAC definitions */
+
+/* stih416 DAC registers */
+/* sysconf 2517: Audio-DAC-Control */
+#define STIH416_AUDIO_DAC_CTRL 0x00000814
+/* sysconf 2519: Audio-Gue-Control */
+#define STIH416_AUDIO_GLUE_CTRL 0x0000081C
+
+#define STIH416_DAC_NOT_STANDBY 0x3
+#define STIH416_DAC_SOFTMUTE 0x4
+#define STIH416_DAC_ANA_NOT_PWR 0x5
+#define STIH416_DAC_NOT_PNDBG 0x6
+
+#define STIH416_DAC_NOT_STANDBY_MASK BIT(STIH416_DAC_NOT_STANDBY)
+#define STIH416_DAC_SOFTMUTE_MASK BIT(STIH416_DAC_SOFTMUTE)
+#define STIH416_DAC_ANA_NOT_PWR_MASK BIT(STIH416_DAC_ANA_NOT_PWR)
+#define STIH416_DAC_NOT_PNDBG_MASK BIT(STIH416_DAC_NOT_PNDBG)
+
+/* stih407 DAC registers */
+/* sysconf 5041: Audio-Gue-Control */
+#define STIH407_AUDIO_GLUE_CTRL 0x000000A4
+/* sysconf 5042: Audio-DAC-Control */
+#define STIH407_AUDIO_DAC_CTRL 0x000000A8
+
+/* DAC definitions */
+#define STIH407_DAC_SOFTMUTE 0x0
+#define STIH407_DAC_STANDBY_ANA 0x1
+#define STIH407_DAC_STANDBY 0x2
+
+#define STIH407_DAC_SOFTMUTE_MASK BIT(STIH407_DAC_SOFTMUTE)
+#define STIH407_DAC_STANDBY_ANA_MASK BIT(STIH407_DAC_STANDBY_ANA)
+#define STIH407_DAC_STANDBY_MASK BIT(STIH407_DAC_STANDBY)
+
+/* SPDIF definitions */
+#define SPDIF_BIPHASE_ENABLE 0x6
+#define SPDIF_BIPHASE_IDLE 0x7
+
+#define SPDIF_BIPHASE_ENABLE_MASK BIT(SPDIF_BIPHASE_ENABLE)
+#define SPDIF_BIPHASE_IDLE_MASK BIT(SPDIF_BIPHASE_IDLE)
+
+enum {
+ STI_SAS_DAI_SPDIF_OUT,
+ STI_SAS_DAI_ANALOG_OUT,
+};
+
+static const struct reg_default stih416_sas_reg_defaults[] = {
+ { STIH407_AUDIO_GLUE_CTRL, 0x00000040 },
+ { STIH407_AUDIO_DAC_CTRL, 0x000000000 },
+};
+
+static const struct reg_default stih407_sas_reg_defaults[] = {
+ { STIH416_AUDIO_DAC_CTRL, 0x000000000 },
+ { STIH416_AUDIO_GLUE_CTRL, 0x00000040 },
+};
+
+struct sti_dac_audio {
+ struct regmap *regmap;
+ struct regmap *virt_regmap;
+ struct regmap_field **field;
+ struct reset_control *rst;
+ int mclk;
+};
+
+struct sti_spdif_audio {
+ struct regmap *regmap;
+ struct regmap_field **field;
+ int mclk;
+};
+
+/* device data structure */
+struct sti_sas_dev_data {
+ const int chipid; /* IC version */
+ const struct regmap_config *regmap;
+ const struct snd_soc_dai_ops *dac_ops; /* DAC function callbacks */
+ const struct snd_soc_dapm_widget *dapm_widgets; /* dapms declaration */
+ const int num_dapm_widgets; /* dapms declaration */
+ const struct snd_soc_dapm_route *dapm_routes; /* route declaration */
+ const int num_dapm_routes; /* route declaration */
+};
+
+/* driver data structure */
+struct sti_sas_data {
+ struct device *dev;
+ const struct sti_sas_dev_data *dev_data;
+ struct sti_dac_audio dac;
+ struct sti_spdif_audio spdif;
+};
+
+/* Read a register from the sysconf reg bank */
+static int sti_sas_read_reg(void *context, unsigned int reg,
+ unsigned int *value)
+{
+ struct sti_sas_data *drvdata = context;
+ int status;
+ u32 val;
+
+ status = regmap_read(drvdata->dac.regmap, reg, &val);
+ *value = (unsigned int)val;
+
+ return status;
+}
+
+/* Read a register from the sysconf reg bank */
+static int sti_sas_write_reg(void *context, unsigned int reg,
+ unsigned int value)
+{
+ struct sti_sas_data *drvdata = context;
+ int status;
+
+ status = regmap_write(drvdata->dac.regmap, reg, value);
+
+ return status;
+}
+
+static int sti_sas_init_sas_registers(struct snd_soc_codec *codec,
+ struct sti_sas_data *data)
+{
+ int ret;
+ /*
+ * DAC and SPDIF are activated by default
+ * put them in IDLE to save power
+ */
+
+ /* Initialise bi-phase formatter to disabled */
+ ret = snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
+ SPDIF_BIPHASE_ENABLE_MASK, 0);
+
+ if (!ret)
+ /* Initialise bi-phase formatter idle value to 0 */
+ ret = snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
+ SPDIF_BIPHASE_IDLE_MASK, 0);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to update SPDIF registers");
+ return ret;
+ }
+
+ /* Init DAC configuration */
+ switch (data->dev_data->chipid) {
+ case CHIPID_STIH407:
+ /* init configuration */
+ ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
+ STIH407_DAC_STANDBY_MASK,
+ STIH407_DAC_STANDBY_MASK);
+
+ if (!ret)
+ ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
+ STIH407_DAC_STANDBY_ANA_MASK,
+ STIH407_DAC_STANDBY_ANA_MASK);
+ if (!ret)
+ ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
+ STIH407_DAC_SOFTMUTE_MASK,
+ STIH407_DAC_SOFTMUTE_MASK);
+ break;
+ case CHIPID_STIH416:
+ ret = snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL,
+ STIH416_DAC_NOT_STANDBY_MASK, 0);
+ if (!ret)
+ ret = snd_soc_update_bits(codec,
+ STIH416_AUDIO_DAC_CTRL,
+ STIH416_DAC_ANA_NOT_PWR, 0);
+ if (!ret)
+ ret = snd_soc_update_bits(codec,
+ STIH416_AUDIO_DAC_CTRL,
+ STIH416_DAC_NOT_PNDBG_MASK,
+ 0);
+ if (!ret)
+ ret = snd_soc_update_bits(codec,
+ STIH416_AUDIO_DAC_CTRL,
+ STIH416_DAC_SOFTMUTE_MASK,
+ STIH416_DAC_SOFTMUTE_MASK);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to update DAC registers");
+ return ret;
+ }
+
+ return ret;
+}
+
+/*
+ * DAC
+ */
+static int sti_sas_dac_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ /* Sanity check only */
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
+ dev_err(dai->codec->dev,
+ "%s: ERROR: Unsupporter master mask 0x%x\n",
+ __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int stih416_dac_probe(struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
+ struct sti_dac_audio *dac = &drvdata->dac;
+
+ /* Get reset control */
+ dac->rst = devm_reset_control_get(codec->dev, "dac_rst");
+ if (IS_ERR(dac->rst)) {
+ dev_err(dai->codec->dev,
+ "%s: ERROR: DAC reset control not defined !\n",
+ __func__);
+ dac->rst = NULL;
+ return -EFAULT;
+ }
+ /* Put the DAC into reset */
+ reset_control_assert(dac->rst);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget stih416_sas_dapm_widgets[] = {
+ SND_SOC_DAPM_PGA("DAC bandgap", STIH416_AUDIO_DAC_CTRL,
+ STIH416_DAC_NOT_PNDBG_MASK, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("DAC standby ana", STIH416_AUDIO_DAC_CTRL,
+ STIH416_DAC_ANA_NOT_PWR, 0, NULL, 0),
+ SND_SOC_DAPM_DAC("DAC standby", "dac_p", STIH416_AUDIO_DAC_CTRL,
+ STIH416_DAC_NOT_STANDBY, 0),
+ SND_SOC_DAPM_OUTPUT("DAC Output"),
+};
+
+static const struct snd_soc_dapm_widget stih407_sas_dapm_widgets[] = {
+ SND_SOC_DAPM_OUT_DRV("DAC standby ana", STIH407_AUDIO_DAC_CTRL,
+ STIH407_DAC_STANDBY_ANA, 1, NULL, 0),
+ SND_SOC_DAPM_DAC("DAC standby", "dac_p", STIH407_AUDIO_DAC_CTRL,
+ STIH407_DAC_STANDBY, 1),
+ SND_SOC_DAPM_OUTPUT("DAC Output"),
+};
+
+static const struct snd_soc_dapm_route stih416_sas_route[] = {
+ {"DAC Output", NULL, "DAC bandgap"},
+ {"DAC Output", NULL, "DAC standby ana"},
+ {"DAC standby ana", NULL, "DAC standby"},
+};
+
+static const struct snd_soc_dapm_route stih407_sas_route[] = {
+ {"DAC Output", NULL, "DAC standby ana"},
+ {"DAC standby ana", NULL, "DAC standby"},
+};
+
+static int stih416_sas_dac_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ if (mute) {
+ return snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL,
+ STIH416_DAC_SOFTMUTE_MASK,
+ STIH416_DAC_SOFTMUTE_MASK);
+ } else {
+ return snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL,
+ STIH416_DAC_SOFTMUTE_MASK, 0);
+ }
+}
+
+static int stih407_sas_dac_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ if (mute) {
+ return snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
+ STIH407_DAC_SOFTMUTE_MASK,
+ STIH407_DAC_SOFTMUTE_MASK);
+ } else {
+ return snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
+ STIH407_DAC_SOFTMUTE_MASK,
+ 0);
+ }
+}
+
+/*
+ * SPDIF
+ */
+static int sti_sas_spdif_set_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
+ dev_err(dai->codec->dev,
+ "%s: ERROR: Unsupporter master mask 0x%x\n",
+ __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * sti_sas_spdif_trigger:
+ * Trigger function is used to ensure that BiPhase Formater is disabled
+ * before CPU dai is stopped.
+ * This is mandatory to avoid that BPF is stalled
+ */
+static int sti_sas_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ return snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
+ SPDIF_BIPHASE_ENABLE_MASK,
+ SPDIF_BIPHASE_ENABLE_MASK);
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ return snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
+ SPDIF_BIPHASE_ENABLE_MASK,
+ 0);
+ default:
+ return -EINVAL;
+ }
+}
+
+static bool sti_sas_volatile_register(struct device *dev, unsigned int reg)
+{
+ if (reg == STIH407_AUDIO_GLUE_CTRL)
+ return true;
+
+ return false;
+}
+
+/*
+ * CODEC DAIS
+ */
+
+/*
+ * sti_sas_set_sysclk:
+ * get MCLK input frequency to check that MCLK-FS ratio is coherent
+ */
+static int sti_sas_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+ unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
+
+ if (dir == SND_SOC_CLOCK_OUT)
+ return 0;
+
+ if (clk_id != 0)
+ return -EINVAL;
+
+ switch (dai->id) {
+ case STI_SAS_DAI_SPDIF_OUT:
+ drvdata->spdif.mclk = freq;
+ break;
+
+ case STI_SAS_DAI_ANALOG_OUT:
+ drvdata->dac.mclk = freq;
+ break;
+ }
+
+ return 0;
+}
+
+static int sti_sas_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ switch (dai->id) {
+ case STI_SAS_DAI_SPDIF_OUT:
+ if ((drvdata->spdif.mclk / runtime->rate) != 128) {
+ dev_err(codec->dev, "unexpected mclk-fs ratio");
+ return -EINVAL;
+ }
+ break;
+ case STI_SAS_DAI_ANALOG_OUT:
+ if ((drvdata->dac.mclk / runtime->rate) != 256) {
+ dev_err(codec->dev, "unexpected mclk-fs ratio");
+ return -EINVAL;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops stih416_dac_ops = {
+ .set_fmt = sti_sas_dac_set_fmt,
+ .mute_stream = stih416_sas_dac_mute,
+ .prepare = sti_sas_prepare,
+ .set_sysclk = sti_sas_set_sysclk,
+};
+
+static const struct snd_soc_dai_ops stih407_dac_ops = {
+ .set_fmt = sti_sas_dac_set_fmt,
+ .mute_stream = stih407_sas_dac_mute,
+ .prepare = sti_sas_prepare,
+ .set_sysclk = sti_sas_set_sysclk,
+};
+
+static const struct regmap_config stih407_sas_regmap = {
+ .reg_bits = 32,
+ .val_bits = 32,
+
+ .max_register = STIH407_AUDIO_DAC_CTRL,
+ .reg_defaults = stih407_sas_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(stih407_sas_reg_defaults),
+ .volatile_reg = sti_sas_volatile_register,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_read = sti_sas_read_reg,
+ .reg_write = sti_sas_write_reg,
+};
+
+static const struct regmap_config stih416_sas_regmap = {
+ .reg_bits = 32,
+ .val_bits = 32,
+
+ .max_register = STIH416_AUDIO_DAC_CTRL,
+ .reg_defaults = stih416_sas_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(stih416_sas_reg_defaults),
+ .volatile_reg = sti_sas_volatile_register,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_read = sti_sas_read_reg,
+ .reg_write = sti_sas_write_reg,
+};
+
+static const struct sti_sas_dev_data stih416_data = {
+ .chipid = CHIPID_STIH416,
+ .regmap = &stih416_sas_regmap,
+ .dac_ops = &stih416_dac_ops,
+ .dapm_widgets = stih416_sas_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(stih416_sas_dapm_widgets),
+ .dapm_routes = stih416_sas_route,
+ .num_dapm_routes = ARRAY_SIZE(stih416_sas_route),
+};
+
+static const struct sti_sas_dev_data stih407_data = {
+ .chipid = CHIPID_STIH407,
+ .regmap = &stih407_sas_regmap,
+ .dac_ops = &stih407_dac_ops,
+ .dapm_widgets = stih407_sas_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(stih407_sas_dapm_widgets),
+ .dapm_routes = stih407_sas_route,
+ .num_dapm_routes = ARRAY_SIZE(stih407_sas_route),
+};
+
+static struct snd_soc_dai_driver sti_sas_dai[] = {
+ {
+ .name = "sas-dai-spdif-out",
+ .id = STI_SAS_DAI_SPDIF_OUT,
+ .playback = {
+ .stream_name = "spdif_p",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 |
+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = (struct snd_soc_dai_ops[]) {
+ {
+ .set_fmt = sti_sas_spdif_set_fmt,
+ .trigger = sti_sas_spdif_trigger,
+ .set_sysclk = sti_sas_set_sysclk,
+ .prepare = sti_sas_prepare,
+ }
+ },
+ },
+ {
+ .name = "sas-dai-dac",
+ .id = STI_SAS_DAI_ANALOG_OUT,
+ .playback = {
+ .stream_name = "dac_p",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ },
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int sti_sas_resume(struct snd_soc_codec *codec)
+{
+ struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
+
+ return sti_sas_init_sas_registers(codec, drvdata);
+}
+#else
+#define sti_sas_resume NULL
+#endif
+
+static int sti_sas_codec_probe(struct snd_soc_codec *codec)
+{
+ struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
+ int ret;
+
+ ret = sti_sas_init_sas_registers(codec, drvdata);
+
+ return ret;
+}
+
+static struct snd_soc_codec_driver sti_sas_driver = {
+ .probe = sti_sas_codec_probe,
+ .resume = sti_sas_resume,
+};
+
+static const struct of_device_id sti_sas_dev_match[] = {
+ {
+ .compatible = "st,stih416-sas-codec",
+ .data = &stih416_data,
+ },
+ {
+ .compatible = "st,stih407-sas-codec",
+ .data = &stih407_data,
+ },
+ {},
+};
+
+static int sti_sas_driver_probe(struct platform_device *pdev)
+{
+ struct device_node *pnode = pdev->dev.of_node;
+ struct sti_sas_data *drvdata;
+ const struct of_device_id *of_id;
+
+ /* Allocate device structure */
+ drvdata = devm_kzalloc(&pdev->dev, sizeof(struct sti_sas_data),
+ GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ /* Populate data structure depending on compatibility */
+ of_id = of_match_node(sti_sas_dev_match, pnode);
+ if (!of_id->data) {
+ dev_err(&pdev->dev, "data associated to device is missing");
+ return -EINVAL;
+ }
+
+ drvdata->dev_data = (struct sti_sas_dev_data *)of_id->data;
+
+ /* Initialise device structure */
+ drvdata->dev = &pdev->dev;
+
+ /* Request the DAC & SPDIF registers memory region */
+ drvdata->dac.virt_regmap = devm_regmap_init(&pdev->dev, NULL, drvdata,
+ drvdata->dev_data->regmap);
+ if (IS_ERR(drvdata->dac.virt_regmap)) {
+ dev_err(&pdev->dev, "audio registers not enabled\n");
+ return PTR_ERR(drvdata->dac.virt_regmap);
+ }
+
+ /* Request the syscon region */
+ drvdata->dac.regmap =
+ syscon_regmap_lookup_by_phandle(pnode, "st,syscfg");
+ if (IS_ERR(drvdata->dac.regmap)) {
+ dev_err(&pdev->dev, "syscon registers not available\n");
+ return PTR_ERR(drvdata->dac.regmap);
+ }
+ drvdata->spdif.regmap = drvdata->dac.regmap;
+
+ /* Set DAC dai probe */
+ if (drvdata->dev_data->chipid == CHIPID_STIH416)
+ sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].probe = stih416_dac_probe;
+
+ sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops;
+
+ /* Set dapms*/
+ sti_sas_driver.dapm_widgets = drvdata->dev_data->dapm_widgets;
+ sti_sas_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets;
+
+ sti_sas_driver.dapm_routes = drvdata->dev_data->dapm_routes;
+ sti_sas_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes;
+
+ /* Store context */
+ dev_set_drvdata(&pdev->dev, drvdata);
+
+ return snd_soc_register_codec(&pdev->dev, &sti_sas_driver,
+ sti_sas_dai,
+ ARRAY_SIZE(sti_sas_dai));
+}
+
+static int sti_sas_driver_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+
+ return 0;
+}
+
+static struct platform_driver sti_sas_platform_driver = {
+ .driver = {
+ .name = "sti-sas-codec",
+ .of_match_table = sti_sas_dev_match,
+ },
+ .probe = sti_sas_driver_probe,
+ .remove = sti_sas_driver_remove,
+};
+
+module_platform_driver(sti_sas_platform_driver);
+
+MODULE_DESCRIPTION("audio codec for STMicroelectronics sti platforms");
+MODULE_AUTHOR("Arnaud.pouliquen@st.com");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c
index b3e5685ac..cc1d3981f 100644
--- a/sound/soc/codecs/tas2552.c
+++ b/sound/soc/codecs/tas2552.c
@@ -38,7 +38,7 @@
#include "tas2552.h"
-static struct reg_default tas2552_reg_defs[] = {
+static const struct reg_default tas2552_reg_defs[] = {
{TAS2552_CFG_1, 0x22},
{TAS2552_CFG_3, 0x80},
{TAS2552_DOUT, 0x00},
@@ -493,8 +493,7 @@ static int tas2552_runtime_suspend(struct device *dev)
regcache_cache_only(tas2552->regmap, true);
regcache_mark_dirty(tas2552->regmap);
- if (tas2552->enable_gpio)
- gpiod_set_value(tas2552->enable_gpio, 0);
+ gpiod_set_value(tas2552->enable_gpio, 0);
return 0;
}
@@ -503,8 +502,7 @@ static int tas2552_runtime_resume(struct device *dev)
{
struct tas2552_data *tas2552 = dev_get_drvdata(dev);
- if (tas2552->enable_gpio)
- gpiod_set_value(tas2552->enable_gpio, 1);
+ gpiod_set_value(tas2552->enable_gpio, 1);
tas2552_sw_shutdown(tas2552, 0);
@@ -520,7 +518,7 @@ static const struct dev_pm_ops tas2552_pm = {
NULL)
};
-static struct snd_soc_dai_ops tas2552_speaker_dai_ops = {
+static const struct snd_soc_dai_ops tas2552_speaker_dai_ops = {
.hw_params = tas2552_hw_params,
.prepare = tas2552_prepare,
.set_sysclk = tas2552_set_dai_sysclk,
@@ -585,8 +583,7 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec)
return ret;
}
- if (tas2552->enable_gpio)
- gpiod_set_value(tas2552->enable_gpio, 1);
+ gpiod_set_value(tas2552->enable_gpio, 1);
ret = pm_runtime_get_sync(codec->dev);
if (ret < 0) {
@@ -610,8 +607,7 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec)
return 0;
probe_fail:
- if (tas2552->enable_gpio)
- gpiod_set_value(tas2552->enable_gpio, 0);
+ gpiod_set_value(tas2552->enable_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
tas2552->supplies);
@@ -624,8 +620,7 @@ static int tas2552_codec_remove(struct snd_soc_codec *codec)
pm_runtime_put(codec->dev);
- if (tas2552->enable_gpio)
- gpiod_set_value(tas2552->enable_gpio, 0);
+ gpiod_set_value(tas2552->enable_gpio, 0);
return 0;
};
@@ -769,7 +764,6 @@ MODULE_DEVICE_TABLE(of, tas2552_of_match);
static struct i2c_driver tas2552_i2c_driver = {
.driver = {
.name = "tas2552",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(tas2552_of_match),
.pm = &tas2552_pm,
},
diff --git a/sound/soc/codecs/tas2552.h b/sound/soc/codecs/tas2552.h
index 5746f8fd0..e34752b8a 100644
--- a/sound/soc/codecs/tas2552.h
+++ b/sound/soc/codecs/tas2552.h
@@ -42,7 +42,7 @@
#define TAS2552_BOOST_APT_CTRL 0x14
#define TAS2552_VER_NUM 0x16
#define TAS2552_VBAT_DATA 0x19
-#define TAS2552_MAX_REG 0x20
+#define TAS2552_MAX_REG TAS2552_VBAT_DATA
/* CFG1 Register Masks */
#define TAS2552_DEV_RESET (1 << 0)
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
index 32942bed3..d49d25d51 100644
--- a/sound/soc/codecs/tas5086.c
+++ b/sound/soc/codecs/tas5086.c
@@ -266,10 +266,14 @@ static int tas5086_set_deemph(struct snd_soc_codec *codec)
struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
int i, val = 0;
- if (priv->deemph)
- for (i = 0; i < ARRAY_SIZE(tas5086_deemph); i++)
- if (tas5086_deemph[i] == priv->rate)
+ if (priv->deemph) {
+ for (i = 0; i < ARRAY_SIZE(tas5086_deemph); i++) {
+ if (tas5086_deemph[i] == priv->rate) {
val = i;
+ break;
+ }
+ }
+ }
return regmap_update_bits(priv->regmap, TAS5086_SYS_CONTROL_1,
TAS5086_DEEMPH_MASK, val);
@@ -994,7 +998,6 @@ static int tas5086_i2c_remove(struct i2c_client *i2c)
static struct i2c_driver tas5086_i2c_driver = {
.driver = {
.name = "tas5086",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(tas5086_dt_ids),
},
.id_table = tas5086_i2c_id,
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
index 85bcc374c..39307ad41 100644
--- a/sound/soc/codecs/tas571x.c
+++ b/sound/soc/codecs/tas571x.c
@@ -179,7 +179,7 @@ static int tas571x_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
- if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
if (!IS_ERR(priv->mclk)) {
ret = clk_prepare_enable(priv->mclk);
if (ret) {
diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c
index aab0af681..cb5310d89 100644
--- a/sound/soc/codecs/tfa9879.c
+++ b/sound/soc/codecs/tfa9879.c
@@ -160,7 +160,7 @@ static int tfa9879_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0;
}
-static struct reg_default tfa9879_regs[] = {
+static const struct reg_default tfa9879_regs[] = {
{ TFA9879_DEVICE_CONTROL, 0x0000 }, /* 0x00 */
{ TFA9879_SERIAL_INTERFACE_1, 0x0a18 }, /* 0x01 */
{ TFA9879_PCM_IOM2_FORMAT_1, 0x0007 }, /* 0x02 */
@@ -314,7 +314,6 @@ MODULE_DEVICE_TABLE(i2c, tfa9879_i2c_id);
static struct i2c_driver tfa9879_i2c_driver = {
.driver = {
.name = "tfa9879",
- .owner = THIS_MODULE,
},
.probe = tfa9879_i2c_probe,
.remove = tfa9879_i2c_remove,
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index c4c960f59..ee4def4f8 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1121,7 +1121,7 @@ static struct snd_soc_codec_driver soc_codec_driver_aic31xx = {
.num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map),
};
-static struct snd_soc_dai_ops aic31xx_dai_ops = {
+static const struct snd_soc_dai_ops aic31xx_dai_ops = {
.hw_params = aic31xx_hw_params,
.set_sysclk = aic31xx_set_dai_sysclk,
.set_fmt = aic31xx_set_dai_fmt,
@@ -1283,7 +1283,6 @@ MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id);
static struct i2c_driver aic31xx_i2c_driver = {
.driver = {
.name = "tlv320aic31xx-codec",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(tlv320aic31xx_of_match),
},
.probe = aic31xx_i2c_probe,
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index ad6cb90e5..f2d319196 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -871,7 +871,6 @@ MODULE_DEVICE_TABLE(of, aic32x4_of_id);
static struct i2c_driver aic32x4_i2c_driver = {
.driver = {
.name = "tlv320aic32x4",
- .owner = THIS_MODULE,
.of_match_table = aic32x4_of_id,
},
.probe = aic32x4_i2c_probe,
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index a7cf19b53..8739126a1 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1509,14 +1509,17 @@ static int aic3x_init(struct snd_soc_codec *codec)
snd_soc_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL);
snd_soc_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL);
- /* Line2 to HP Bypass default volume, disconnect from Output Mixer */
- snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL);
- snd_soc_write(codec, LINE2R_2_HPROUT_VOL, DEFAULT_VOL);
- snd_soc_write(codec, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL);
- snd_soc_write(codec, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL);
- /* Line2 Line Out default volume, disconnect from Output Mixer */
- snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL);
- snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL);
+ /* On tlv320aic3104, these registers are reserved and must not be written */
+ if (aic3x->model != AIC3X_MODEL_3104) {
+ /* Line2 to HP Bypass default volume, disconnect from Output Mixer */
+ snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2R_2_HPROUT_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL);
+ /* Line2 Line Out default volume, disconnect from Output Mixer */
+ snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL);
+ }
switch (aic3x->model) {
case AIC3X_MODEL_3X:
@@ -1668,7 +1671,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
-static const struct reg_default aic3007_class_d[] = {
+static const struct reg_sequence aic3007_class_d[] = {
/* Class-D speaker driver init; datasheet p. 46 */
{ AIC3X_PAGE_SELECT, 0x0D },
{ 0xD, 0x0D },
@@ -1825,7 +1828,6 @@ MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match);
static struct i2c_driver aic3x_i2c_driver = {
.driver = {
.name = "tlv320aic3x-codec",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(tlv320aic3x_of_match),
},
.probe = aic3x_i2c_probe,
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index d67a311f0..781398fb2 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -1585,7 +1585,6 @@ MODULE_DEVICE_TABLE(i2c, tlv320dac33_i2c_id);
static struct i2c_driver tlv320dac33_i2c_driver = {
.driver = {
.name = "tlv320dac33-codec",
- .owner = THIS_MODULE,
},
.probe = dac33_i2c_probe,
.remove = dac33_i2c_remove,
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 6fac9e034..11d85c5c7 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -259,8 +259,7 @@ static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol,
* TPA6130 volume. From -59.5 to 4 dB with increasing step size when going
* down in gain.
*/
-static const unsigned int tpa6130_tlv[] = {
- TLV_DB_RANGE_HEAD(10),
+static const DECLARE_TLV_DB_RANGE(tpa6130_tlv,
0, 1, TLV_DB_SCALE_ITEM(-5950, 600, 0),
2, 3, TLV_DB_SCALE_ITEM(-5000, 250, 0),
4, 5, TLV_DB_SCALE_ITEM(-4550, 160, 0),
@@ -270,8 +269,8 @@ static const unsigned int tpa6130_tlv[] = {
12, 13, TLV_DB_SCALE_ITEM(-3040, 180, 0),
14, 20, TLV_DB_SCALE_ITEM(-2710, 110, 0),
21, 37, TLV_DB_SCALE_ITEM(-1960, 74, 0),
- 38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0),
-};
+ 38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0)
+);
static const struct snd_kcontrol_new tpa6130a2_controls[] = {
SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume",
@@ -280,12 +279,11 @@ static const struct snd_kcontrol_new tpa6130a2_controls[] = {
tpa6130_tlv),
};
-static const unsigned int tpa6140_tlv[] = {
- TLV_DB_RANGE_HEAD(3),
+static const DECLARE_TLV_DB_RANGE(tpa6140_tlv,
0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0),
9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0),
- 17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0),
-};
+ 17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0)
+);
static const struct snd_kcontrol_new tpa6140a2_controls[] = {
SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume",
@@ -488,7 +486,6 @@ MODULE_DEVICE_TABLE(of, tpa6130a2_of_match);
static struct i2c_driver tpa6130a2_i2c_driver = {
.driver = {
.name = "tpa6130a2",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(tpa6130a2_of_match),
},
.probe = tpa6130a2_probe,
diff --git a/sound/soc/codecs/ts3a227e.c b/sound/soc/codecs/ts3a227e.c
index 12232d7db..43568435c 100644
--- a/sound/soc/codecs/ts3a227e.c
+++ b/sound/soc/codecs/ts3a227e.c
@@ -23,11 +23,13 @@
#include "ts3a227e.h"
struct ts3a227e {
+ struct device *dev;
struct regmap *regmap;
struct snd_soc_jack *jack;
bool plugged;
bool mic_present;
unsigned int buttons_held;
+ int irq;
};
/* Button values to be reported on the jack */
@@ -189,16 +191,28 @@ static irqreturn_t ts3a227e_interrupt(int irq, void *data)
struct ts3a227e *ts3a227e = (struct ts3a227e *)data;
struct regmap *regmap = ts3a227e->regmap;
unsigned int int_reg, kp_int_reg, acc_reg, i;
+ struct device *dev = ts3a227e->dev;
+ int ret;
/* Check for plug/unplug. */
- regmap_read(regmap, TS3A227E_REG_INTERRUPT, &int_reg);
+ ret = regmap_read(regmap, TS3A227E_REG_INTERRUPT, &int_reg);
+ if (ret) {
+ dev_err(dev, "failed to clear interrupt ret=%d\n", ret);
+ return IRQ_NONE;
+ }
+
if (int_reg & (DETECTION_COMPLETE_EVENT | INS_REM_EVENT)) {
regmap_read(regmap, TS3A227E_REG_ACCESSORY_STATUS, &acc_reg);
ts3a227e_new_jack_state(ts3a227e, acc_reg);
}
/* Report any key events. */
- regmap_read(regmap, TS3A227E_REG_KP_INTERRUPT, &kp_int_reg);
+ ret = regmap_read(regmap, TS3A227E_REG_KP_INTERRUPT, &kp_int_reg);
+ if (ret) {
+ dev_err(dev, "failed to clear key interrupt ret=%d\n", ret);
+ return IRQ_NONE;
+ }
+
for (i = 0; i < TS3A227E_NUM_BUTTONS; i++) {
if (kp_int_reg & PRESS_MASK(i))
ts3a227e->buttons_held |= (1 << i);
@@ -283,6 +297,8 @@ static int ts3a227e_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
i2c_set_clientdata(i2c, ts3a227e);
+ ts3a227e->dev = dev;
+ ts3a227e->irq = i2c->irq;
ts3a227e->regmap = devm_regmap_init_i2c(i2c, &ts3a227e_regmap_config);
if (IS_ERR(ts3a227e->regmap))
@@ -320,6 +336,32 @@ static int ts3a227e_i2c_probe(struct i2c_client *i2c,
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int ts3a227e_suspend(struct device *dev)
+{
+ struct ts3a227e *ts3a227e = dev_get_drvdata(dev);
+
+ dev_dbg(ts3a227e->dev, "suspend disable irq\n");
+ disable_irq(ts3a227e->irq);
+
+ return 0;
+}
+
+static int ts3a227e_resume(struct device *dev)
+{
+ struct ts3a227e *ts3a227e = dev_get_drvdata(dev);
+
+ dev_dbg(ts3a227e->dev, "resume enable irq\n");
+ enable_irq(ts3a227e->irq);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops ts3a227e_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(ts3a227e_suspend, ts3a227e_resume)
+};
+
static const struct i2c_device_id ts3a227e_i2c_ids[] = {
{ "ts3a227e", 0 },
{ }
@@ -335,7 +377,7 @@ MODULE_DEVICE_TABLE(of, ts3a227e_of_match);
static struct i2c_driver ts3a227e_driver = {
.driver = {
.name = "ts3a227e",
- .owner = THIS_MODULE,
+ .pm = &ts3a227e_pm,
.of_match_table = of_match_ptr(ts3a227e_of_match),
},
.probe = ts3a227e_i2c_probe,
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 90f5f04ec..2713e1845 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -524,12 +524,11 @@ static const struct snd_kcontrol_new twl4030_dapm_abypassv_control =
SOC_DAPM_SINGLE("Switch", TWL4030_REG_VDL_APGA_CTL, 2, 1, 0);
/* Digital bypass gain, mute instead of -30dB */
-static const unsigned int twl4030_dapm_dbypass_tlv[] = {
- TLV_DB_RANGE_HEAD(3),
+static const DECLARE_TLV_DB_RANGE(twl4030_dapm_dbypass_tlv,
0, 1, TLV_DB_SCALE_ITEM(-3000, 600, 1),
2, 3, TLV_DB_SCALE_ITEM(-2400, 0, 0),
- 4, 7, TLV_DB_SCALE_ITEM(-1800, 600, 0),
-};
+ 4, 7, TLV_DB_SCALE_ITEM(-1800, 600, 0)
+);
/* Digital bypass left (TX1L -> RX2L) */
static const struct snd_kcontrol_new twl4030_dapm_dbypassl_control =
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index 913edf283..e19026380 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -37,74 +37,53 @@ struct uda134x_priv {
struct snd_pcm_substream *master_substream;
struct snd_pcm_substream *slave_substream;
-};
-/* In-data addresses are hard-coded into the reg-cache values */
-static const char uda134x_reg[UDA134X_REGS_NUM] = {
- /* Extended address registers */
- 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* Status, data regs */
- 0x00, 0x83, 0x00, 0x40, 0x80, 0xC0, 0x00,
+ struct regmap *regmap;
+ struct uda134x_platform_data *pd;
};
-/*
- * The codec has no support for reading its registers except for peak level...
- */
-static inline unsigned int uda134x_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- u8 *cache = codec->reg_cache;
-
- if (reg >= UDA134X_REGS_NUM)
- return -1;
- return cache[reg];
-}
-
-/*
- * Write the register cache
- */
-static inline void uda134x_write_reg_cache(struct snd_soc_codec *codec,
- u8 reg, unsigned int value)
-{
- u8 *cache = codec->reg_cache;
-
- if (reg >= UDA134X_REGS_NUM)
- return;
- cache[reg] = value;
-}
+static const struct reg_default uda134x_reg_defaults[] = {
+ { UDA134X_EA000, 0x04 },
+ { UDA134X_EA001, 0x04 },
+ { UDA134X_EA010, 0x04 },
+ { UDA134X_EA011, 0x00 },
+ { UDA134X_EA100, 0x00 },
+ { UDA134X_EA101, 0x00 },
+ { UDA134X_EA110, 0x00 },
+ { UDA134X_EA111, 0x00 },
+ { UDA134X_STATUS0, 0x00 },
+ { UDA134X_STATUS1, 0x03 },
+ { UDA134X_DATA000, 0x00 },
+ { UDA134X_DATA001, 0x00 },
+ { UDA134X_DATA010, 0x00 },
+ { UDA134X_DATA011, 0x00 },
+ { UDA134X_DATA1, 0x00 },
+};
/*
* Write to the uda134x registers
*
*/
-static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg,
+static int uda134x_regmap_write(void *context, unsigned int reg,
unsigned int value)
{
+ struct uda134x_platform_data *pd = context;
int ret;
u8 addr;
u8 data = value;
- struct uda134x_platform_data *pd = codec->control_data;
-
- pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value);
-
- if (reg >= UDA134X_REGS_NUM) {
- printk(KERN_ERR "%s unknown register: reg: %u",
- __func__, reg);
- return -EINVAL;
- }
-
- uda134x_write_reg_cache(codec, reg, value);
switch (reg) {
case UDA134X_STATUS0:
case UDA134X_STATUS1:
addr = UDA134X_STATUS_ADDR;
+ data |= (reg - UDA134X_STATUS0) << 7;
break;
case UDA134X_DATA000:
case UDA134X_DATA001:
case UDA134X_DATA010:
case UDA134X_DATA011:
addr = UDA134X_DATA0_ADDR;
+ data |= (reg - UDA134X_DATA000) << 6;
break;
case UDA134X_DATA1:
addr = UDA134X_DATA1_ADDR;
@@ -133,27 +112,28 @@ static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg,
static inline void uda134x_reset(struct snd_soc_codec *codec)
{
- u8 reset_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
- uda134x_write(codec, UDA134X_STATUS0, reset_reg | (1<<6));
+ struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
+ unsigned int mask = 1<<6;
+
+ regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, mask);
msleep(1);
- uda134x_write(codec, UDA134X_STATUS0, reset_reg & ~(1<<6));
+ regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, 0);
}
static int uda134x_mute(struct snd_soc_dai *dai, int mute)
{
- struct snd_soc_codec *codec = dai->codec;
- u8 mute_reg = uda134x_read_reg_cache(codec, UDA134X_DATA010);
+ struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(dai->codec);
+ unsigned int mask = 1<<2;
+ unsigned int val;
pr_debug("%s mute: %d\n", __func__, mute);
if (mute)
- mute_reg |= (1<<2);
+ val = mask;
else
- mute_reg &= ~(1<<2);
+ val = 0;
- uda134x_write(codec, UDA134X_DATA010, mute_reg);
-
- return 0;
+ return regmap_update_bits(uda134x->regmap, UDA134X_DATA010, mask, val);
}
static int uda134x_startup(struct snd_pcm_substream *substream,
@@ -205,7 +185,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_codec *codec = dai->codec;
struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
- u8 hw_params;
+ unsigned int hw_params = 0;
if (substream == uda134x->slave_substream) {
pr_debug("%s ignoring hw_params for slave substream\n",
@@ -213,10 +193,6 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream,
return 0;
}
- hw_params = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
- hw_params &= STATUS0_SYSCLK_MASK;
- hw_params &= STATUS0_DAIFMT_MASK;
-
pr_debug("%s sysclk: %d, rate:%d\n", __func__,
uda134x->sysclk, params_rate(params));
@@ -267,9 +243,8 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- uda134x_write(codec, UDA134X_STATUS0, hw_params);
-
- return 0;
+ return regmap_update_bits(uda134x->regmap, UDA134X_STATUS0,
+ STATUS0_SYSCLK_MASK | STATUS0_DAIFMT_MASK, hw_params);
}
static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
@@ -324,10 +299,8 @@ static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
static int uda134x_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- struct uda134x_platform_data *pd = codec->control_data;
- int i;
- u8 *cache = codec->reg_cache;
-
+ struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
+ struct uda134x_platform_data *pd = uda134x->pd;
pr_debug("%s bias level %d\n", __func__, level);
switch (level) {
@@ -337,17 +310,17 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
/* power on */
if (pd->power) {
pd->power(1);
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
- codec->driver->write(codec, i, *cache++);
+ regcache_sync(uda134x->regmap);
}
break;
case SND_SOC_BIAS_STANDBY:
break;
case SND_SOC_BIAS_OFF:
/* power off */
- if (pd->power)
+ if (pd->power) {
pd->power(0);
+ regcache_mark_dirty(uda134x->regmap);
+ }
break;
}
return 0;
@@ -478,21 +451,14 @@ static struct snd_soc_dai_driver uda134x_dai = {
static int uda134x_soc_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
- struct uda134x_priv *uda134x;
- struct uda134x_platform_data *pd = codec->component.card->dev->platform_data;
+ struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
+ struct uda134x_platform_data *pd = uda134x->pd;
const struct snd_soc_dapm_widget *widgets;
unsigned num_widgets;
-
int ret;
printk(KERN_INFO "UDA134X SoC Audio Codec\n");
- if (!pd) {
- printk(KERN_ERR "UDA134X SoC codec: "
- "missing L3 bitbang function\n");
- return -ENODEV;
- }
-
switch (pd->model) {
case UDA134X_UDA1340:
case UDA134X_UDA1341:
@@ -506,13 +472,6 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
return -EINVAL;
}
- uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
- if (uda134x == NULL)
- return -ENOMEM;
- snd_soc_codec_set_drvdata(codec, uda134x);
-
- codec->control_data = pd;
-
if (pd->power)
pd->power(1);
@@ -530,7 +489,6 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
if (ret) {
printk(KERN_ERR "%s failed to register dapm controls: %d",
__func__, ret);
- kfree(uda134x);
return ret;
}
@@ -551,36 +509,19 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
default:
printk(KERN_ERR "%s unknown codec type: %d",
__func__, pd->model);
- kfree(uda134x);
return -EINVAL;
}
if (ret < 0) {
printk(KERN_ERR "UDA134X: failed to register controls\n");
- kfree(uda134x);
return ret;
}
return 0;
}
-/* power down chip */
-static int uda134x_soc_remove(struct snd_soc_codec *codec)
-{
- struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
-
- kfree(uda134x);
- return 0;
-}
-
static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
.probe = uda134x_soc_probe,
- .remove = uda134x_soc_remove,
- .reg_cache_size = sizeof(uda134x_reg),
- .reg_word_size = sizeof(u8),
- .reg_cache_default = uda134x_reg,
- .reg_cache_step = 1,
- .read = uda134x_read_reg_cache,
.set_bias_level = uda134x_set_bias_level,
.suspend_bias_off = true,
@@ -590,8 +531,39 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
.num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes),
};
+static const struct regmap_config uda134x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = UDA134X_DATA1,
+ .reg_defaults = uda134x_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(uda134x_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+
+ .reg_write = uda134x_regmap_write,
+};
+
static int uda134x_codec_probe(struct platform_device *pdev)
{
+ struct uda134x_platform_data *pd = pdev->dev.platform_data;
+ struct uda134x_priv *uda134x;
+
+ if (!pd) {
+ dev_err(&pdev->dev, "Missing L3 bitbang function\n");
+ return -ENODEV;
+ }
+
+ uda134x = devm_kzalloc(&pdev->dev, sizeof(*uda134x), GFP_KERNEL);
+ if (!uda134x)
+ return -ENOMEM;
+
+ uda134x->pd = pd;
+ platform_set_drvdata(pdev, uda134x);
+
+ uda134x->regmap = devm_regmap_init(&pdev->dev, NULL, pd,
+ &uda134x_regmap_config);
+ if (IS_ERR(uda134x->regmap))
+ return PTR_ERR(uda134x->regmap);
+
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_uda134x, &uda134x_dai, 1);
}
diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h
index 9faae0697..e41ab38c6 100644
--- a/sound/soc/codecs/uda134x.h
+++ b/sound/soc/codecs/uda134x.h
@@ -26,8 +26,6 @@
#define UDA134X_DATA011 13
#define UDA134X_DATA1 14
-#define UDA134X_REGS_NUM 15
-
#define STATUS0_DAIFMT_MASK (~(7<<1))
#define STATUS0_SYSCLK_MASK (~(3<<4))
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 6e159f59d..35f0469eb 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -269,12 +269,11 @@ static DECLARE_TLV_DB_SCALE(amix_tlv, -4950, 150, 1);
* from -66 dB in 0.5 dB steps (2 dB steps, really) and
* from -52 dB in 0.25 dB steps
*/
-static const unsigned int mvol_tlv[] = {
- TLV_DB_RANGE_HEAD(3),
+static const DECLARE_TLV_DB_RANGE(mvol_tlv,
0, 15, TLV_DB_SCALE_ITEM(-8200, 100, 1),
16, 43, TLV_DB_SCALE_ITEM(-6600, 50, 0),
- 44, 252, TLV_DB_SCALE_ITEM(-5200, 25, 0),
-};
+ 44, 252, TLV_DB_SCALE_ITEM(-5200, 25, 0)
+);
/*
* from -72 dB in 1.5 dB steps (6 dB steps really),
@@ -282,13 +281,12 @@ static const unsigned int mvol_tlv[] = {
* from -60 dB in 0.5 dB steps (2 dB steps really) and
* from -46 dB in 0.25 dB steps
*/
-static const unsigned int vc_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+static const DECLARE_TLV_DB_RANGE(vc_tlv,
0, 7, TLV_DB_SCALE_ITEM(-7800, 150, 1),
8, 15, TLV_DB_SCALE_ITEM(-6600, 75, 0),
16, 43, TLV_DB_SCALE_ITEM(-6000, 50, 0),
- 44, 228, TLV_DB_SCALE_ITEM(-4600, 25, 0),
-};
+ 44, 228, TLV_DB_SCALE_ITEM(-4600, 25, 0)
+);
/* from 0 to 6 dB in 2 dB steps if SPF mode != flat */
static DECLARE_TLV_DB_SCALE(tr_tlv, 0, 200, 0);
@@ -810,7 +808,6 @@ MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);
static struct i2c_driver uda1380_i2c_driver = {
.driver = {
.name = "uda1380-codec",
- .owner = THIS_MODULE,
},
.probe = uda1380_i2c_probe,
.remove = uda1380_i2c_remove,
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
index 35b3d919f..d1c9ede6f 100644
--- a/sound/soc/codecs/wm0010.c
+++ b/sound/soc/codecs/wm0010.c
@@ -577,7 +577,6 @@ static int wm0010_boot(struct snd_soc_codec *codec)
struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
unsigned long flags;
int ret;
- const struct firmware *fw;
struct spi_message m;
struct spi_transfer t;
struct dfw_pllrec pll_rec;
@@ -623,14 +622,6 @@ static int wm0010_boot(struct snd_soc_codec *codec)
wm0010->state = WM0010_OUT_OF_RESET;
spin_unlock_irqrestore(&wm0010->irq_lock, flags);
- /* First the bootloader */
- ret = reject_firmware(&fw, "/*(DEBLOBBED)*/", codec->dev);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to request stage2 loader: %d\n",
- ret);
- goto abort;
- }
-
if (!wait_for_completion_timeout(&wm0010->boot_completion,
msecs_to_jiffies(20)))
dev_err(codec->dev, "Failed to get interrupt from DSP\n");
@@ -673,7 +664,7 @@ static int wm0010_boot(struct snd_soc_codec *codec)
img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA);
if (!img_swap)
- goto abort;
+ goto abort_out;
/* We need to re-order for 0010 */
byte_swap_64((u64 *)&pll_rec, img_swap, len);
@@ -688,16 +679,16 @@ static int wm0010_boot(struct snd_soc_codec *codec)
spi_message_add_tail(&t, &m);
ret = spi_sync(spi, &m);
- if (ret != 0) {
+ if (ret) {
dev_err(codec->dev, "First PLL write failed: %d\n", ret);
- goto abort;
+ goto abort_swap;
}
/* Use a second send of the message to get the return status */
ret = spi_sync(spi, &m);
- if (ret != 0) {
+ if (ret) {
dev_err(codec->dev, "Second PLL write failed: %d\n", ret);
- goto abort;
+ goto abort_swap;
}
p = (u32 *)out;
@@ -730,6 +721,10 @@ static int wm0010_boot(struct snd_soc_codec *codec)
return 0;
+abort_swap:
+ kfree(img_swap);
+abort_out:
+ kfree(out);
abort:
/* Put the chip back into reset */
wm0010_halt(codec);
@@ -953,7 +948,7 @@ static int wm0010_spi_probe(struct spi_device *spi)
trigger = IRQF_TRIGGER_FALLING;
trigger |= IRQF_ONESHOT;
- ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger | IRQF_ONESHOT,
+ ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger,
"wm0010", wm0010);
if (ret) {
dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n",
@@ -1003,7 +998,6 @@ static int wm0010_spi_remove(struct spi_device *spi)
static struct spi_driver wm0010_spi_driver = {
.driver = {
.name = "wm0010",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = wm0010_spi_probe,
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
index 048f00568..ec45c5b22 100644
--- a/sound/soc/codecs/wm1250-ev1.c
+++ b/sound/soc/codecs/wm1250-ev1.c
@@ -251,7 +251,6 @@ MODULE_DEVICE_TABLE(i2c, wm1250_ev1_i2c_id);
static struct i2c_driver wm1250_ev1_i2c_driver = {
.driver = {
.name = "wm1250-ev1",
- .owner = THIS_MODULE,
},
.probe = wm1250_ev1_probe,
.remove = wm1250_ev1_remove,
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 819cb3ba2..ff96447ef 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -932,7 +932,6 @@ MODULE_DEVICE_TABLE(i2c, wm2000_i2c_id);
static struct i2c_driver wm2000_i2c_driver = {
.driver = {
.name = "wm2000",
- .owner = THIS_MODULE,
},
.probe = wm2000_i2c_probe,
.remove = wm2000_i2c_remove,
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
index c83083285..fd1439ecb 100644
--- a/sound/soc/codecs/wm2200.c
+++ b/sound/soc/codecs/wm2200.c
@@ -166,7 +166,7 @@ static const struct wm_adsp_region wm2200_dsp2_regions[] = {
{ .type = WMFW_ADSP1_ZM, .base = WM2200_DSP2_ZM_BASE },
};
-static struct reg_default wm2200_reg_defaults[] = {
+static const struct reg_default wm2200_reg_defaults[] = {
{ 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */
{ 0x0102, 0x0000 }, /* R258 - Clocking 3 */
{ 0x0103, 0x0011 }, /* R259 - Clocking 4 */
@@ -897,7 +897,7 @@ static bool wm2200_readable_register(struct device *dev, unsigned int reg)
}
}
-static const struct reg_default wm2200_reva_patch[] = {
+static const struct reg_sequence wm2200_reva_patch[] = {
{ 0x07, 0x0003 },
{ 0x102, 0x0200 },
{ 0x203, 0x0084 },
@@ -1702,7 +1702,7 @@ static int wm2200_hw_params(struct snd_pcm_substream *substream,
int *bclk_rates;
/* Data sizes if not using TDM */
- wl = snd_pcm_format_width(params_format(params));
+ wl = params_width(params);
if (wl < 0)
return wl;
fl = snd_soc_params_to_frame_size(params);
@@ -2481,7 +2481,7 @@ static int wm2200_runtime_resume(struct device *dev)
}
#endif
-static struct dev_pm_ops wm2200_pm = {
+static const struct dev_pm_ops wm2200_pm = {
SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume,
NULL)
};
@@ -2495,7 +2495,6 @@ MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id);
static struct i2c_driver wm2200_i2c_driver = {
.driver = {
.name = "wm2200",
- .owner = THIS_MODULE,
.pm = &wm2200_pm,
},
.probe = wm2200_i2c_probe,
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 4c10cd88c..c2cdcae18 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -1247,7 +1247,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
{ "PWM2", NULL, "PWM2 Driver" },
};
-static const struct reg_default wm5100_reva_patches[] = {
+static const struct reg_sequence wm5100_reva_patches[] = {
{ WM5100_AUDIO_IF_1_10, 0 },
{ WM5100_AUDIO_IF_1_11, 1 },
{ WM5100_AUDIO_IF_1_12, 2 },
@@ -1408,7 +1408,7 @@ static int wm5100_hw_params(struct snd_pcm_substream *substream,
base = dai->driver->base;
/* Data sizes if not using TDM */
- wl = snd_pcm_format_width(params_format(params));
+ wl = params_width(params);
if (wl < 0)
return wl;
fl = snd_soc_params_to_frame_size(params);
@@ -2570,13 +2570,11 @@ static int wm5100_i2c_probe(struct i2c_client *i2c,
if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
ret = request_threaded_irq(i2c->irq, NULL,
- wm5100_edge_irq,
- irq_flags | IRQF_ONESHOT,
+ wm5100_edge_irq, irq_flags,
"wm5100", wm5100);
else
ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
- irq_flags | IRQF_ONESHOT,
- "wm5100",
+ irq_flags, "wm5100",
wm5100);
if (ret != 0) {
@@ -2708,7 +2706,7 @@ static int wm5100_runtime_resume(struct device *dev)
}
#endif
-static struct dev_pm_ops wm5100_pm = {
+static const struct dev_pm_ops wm5100_pm = {
SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume,
NULL)
};
@@ -2722,7 +2720,6 @@ MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id);
static struct i2c_driver wm5100_i2c_driver = {
.driver = {
.name = "wm5100",
- .owner = THIS_MODULE,
.pm = &wm5100_pm,
},
.probe = wm5100_i2c_probe,
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index d097f09e5..64637d1cf 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -788,8 +788,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
-SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
-SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2),
SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -801,8 +800,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
24, 0, eq_tlv),
-SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19),
-SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2),
SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
@@ -814,8 +812,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
24, 0, eq_tlv),
-SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19),
-SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2),
SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
@@ -827,8 +824,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
24, 0, eq_tlv),
-SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19),
-SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2),
SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
@@ -851,10 +847,10 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
-SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
-SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
-SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
-SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2),
+ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),
+ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2),
+ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2),
ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
@@ -1883,7 +1879,7 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
ret = snd_soc_add_codec_controls(codec,
arizona_adsp2_rate_controls, 1);
if (ret)
- return ret;
+ goto err_adsp2_codec_probe;
arizona_init_spk(codec);
arizona_init_gpio(codec);
@@ -1893,6 +1889,11 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
priv->core.arizona->dapm = dapm;
return 0;
+
+err_adsp2_codec_probe:
+ wm_adsp2_codec_remove(&priv->core.adsp[0], codec);
+
+ return ret;
}
static int wm5102_codec_remove(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 709fcc616..9756578fc 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -131,6 +131,25 @@ static const struct reg_default wm5110_sysclk_revd_patch[] = {
{ 0x33fb, 0xfe00 },
};
+static const struct reg_default wm5110_sysclk_reve_patch[] = {
+ { 0x3270, 0xE410 },
+ { 0x3271, 0x3078 },
+ { 0x3272, 0xE410 },
+ { 0x3273, 0x3070 },
+ { 0x3274, 0xE410 },
+ { 0x3275, 0x3066 },
+ { 0x3276, 0xE410 },
+ { 0x3277, 0x3056 },
+ { 0x327A, 0xE414 },
+ { 0x327B, 0x3078 },
+ { 0x327C, 0xE414 },
+ { 0x327D, 0x3070 },
+ { 0x327E, 0xE414 },
+ { 0x327F, 0x3066 },
+ { 0x3280, 0xE414 },
+ { 0x3281, 0x3056 },
+};
+
static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -146,7 +165,9 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w,
patch_size = ARRAY_SIZE(wm5110_sysclk_revd_patch);
break;
default:
- return 0;
+ patch = wm5110_sysclk_reve_patch;
+ patch_size = ARRAY_SIZE(wm5110_sysclk_reve_patch);
+ break;
}
switch (event) {
@@ -164,6 +185,249 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w,
return 0;
}
+static const struct reg_sequence wm5110_no_dre_left_enable[] = {
+ { 0x3024, 0xE410 },
+ { 0x3025, 0x0056 },
+ { 0x301B, 0x0224 },
+ { 0x301F, 0x4263 },
+ { 0x3021, 0x5291 },
+ { 0x3030, 0xE410 },
+ { 0x3031, 0x3066 },
+ { 0x3032, 0xE410 },
+ { 0x3033, 0x3070 },
+ { 0x3034, 0xE410 },
+ { 0x3035, 0x3078 },
+ { 0x3036, 0xE410 },
+ { 0x3037, 0x3080 },
+ { 0x3038, 0xE410 },
+ { 0x3039, 0x3080 },
+};
+
+static const struct reg_sequence wm5110_dre_left_enable[] = {
+ { 0x3024, 0x0231 },
+ { 0x3025, 0x0B00 },
+ { 0x301B, 0x0227 },
+ { 0x301F, 0x4266 },
+ { 0x3021, 0x5294 },
+ { 0x3030, 0xE231 },
+ { 0x3031, 0x0266 },
+ { 0x3032, 0x8231 },
+ { 0x3033, 0x4B15 },
+ { 0x3034, 0x8231 },
+ { 0x3035, 0x0B15 },
+ { 0x3036, 0xE231 },
+ { 0x3037, 0x5294 },
+ { 0x3038, 0x0231 },
+ { 0x3039, 0x0B00 },
+};
+
+static const struct reg_sequence wm5110_no_dre_right_enable[] = {
+ { 0x3074, 0xE414 },
+ { 0x3075, 0x0056 },
+ { 0x306B, 0x0224 },
+ { 0x306F, 0x4263 },
+ { 0x3071, 0x5291 },
+ { 0x3080, 0xE414 },
+ { 0x3081, 0x3066 },
+ { 0x3082, 0xE414 },
+ { 0x3083, 0x3070 },
+ { 0x3084, 0xE414 },
+ { 0x3085, 0x3078 },
+ { 0x3086, 0xE414 },
+ { 0x3087, 0x3080 },
+ { 0x3088, 0xE414 },
+ { 0x3089, 0x3080 },
+};
+
+static const struct reg_sequence wm5110_dre_right_enable[] = {
+ { 0x3074, 0x0231 },
+ { 0x3075, 0x0B00 },
+ { 0x306B, 0x0227 },
+ { 0x306F, 0x4266 },
+ { 0x3071, 0x5294 },
+ { 0x3080, 0xE231 },
+ { 0x3081, 0x0266 },
+ { 0x3082, 0x8231 },
+ { 0x3083, 0x4B17 },
+ { 0x3084, 0x8231 },
+ { 0x3085, 0x0B17 },
+ { 0x3086, 0xE231 },
+ { 0x3087, 0x5294 },
+ { 0x3088, 0x0231 },
+ { 0x3089, 0x0B00 },
+};
+
+static int wm5110_hp_pre_enable(struct snd_soc_dapm_widget *w)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct arizona *arizona = priv->arizona;
+ unsigned int val = snd_soc_read(codec, ARIZONA_DRE_ENABLE);
+ const struct reg_sequence *wseq;
+ int nregs;
+
+ switch (w->shift) {
+ case ARIZONA_OUT1L_ENA_SHIFT:
+ if (val & ARIZONA_DRE1L_ENA_MASK) {
+ wseq = wm5110_dre_left_enable;
+ nregs = ARRAY_SIZE(wm5110_dre_left_enable);
+ } else {
+ wseq = wm5110_no_dre_left_enable;
+ nregs = ARRAY_SIZE(wm5110_no_dre_left_enable);
+ priv->out_up_delay += 10;
+ }
+ break;
+ case ARIZONA_OUT1R_ENA_SHIFT:
+ if (val & ARIZONA_DRE1R_ENA_MASK) {
+ wseq = wm5110_dre_right_enable;
+ nregs = ARRAY_SIZE(wm5110_dre_right_enable);
+ } else {
+ wseq = wm5110_no_dre_right_enable;
+ nregs = ARRAY_SIZE(wm5110_no_dre_right_enable);
+ priv->out_up_delay += 10;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return regmap_multi_reg_write(arizona->regmap, wseq, nregs);
+}
+
+static int wm5110_hp_pre_disable(struct snd_soc_dapm_widget *w)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+ unsigned int val = snd_soc_read(codec, ARIZONA_DRE_ENABLE);
+
+ switch (w->shift) {
+ case ARIZONA_OUT1L_ENA_SHIFT:
+ if (!(val & ARIZONA_DRE1L_ENA_MASK)) {
+ snd_soc_update_bits(codec, ARIZONA_SPARE_TRIGGERS,
+ ARIZONA_WS_TRG1, ARIZONA_WS_TRG1);
+ snd_soc_update_bits(codec, ARIZONA_SPARE_TRIGGERS,
+ ARIZONA_WS_TRG1, 0);
+ priv->out_down_delay += 27;
+ }
+ break;
+ case ARIZONA_OUT1R_ENA_SHIFT:
+ if (!(val & ARIZONA_DRE1R_ENA_MASK)) {
+ snd_soc_update_bits(codec, ARIZONA_SPARE_TRIGGERS,
+ ARIZONA_WS_TRG2, ARIZONA_WS_TRG2);
+ snd_soc_update_bits(codec, ARIZONA_SPARE_TRIGGERS,
+ ARIZONA_WS_TRG2, 0);
+ priv->out_down_delay += 27;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int wm5110_hp_ev(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ switch (priv->arizona->rev) {
+ case 0 ... 3:
+ break;
+ default:
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ wm5110_hp_pre_enable(w);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ wm5110_hp_pre_disable(w);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ return arizona_hp_ev(w, kcontrol, event);
+}
+
+static int wm5110_clear_pga_volume(struct arizona *arizona, int output)
+{
+ struct reg_sequence clear_pga = {
+ ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4, 0x80
+ };
+ int ret;
+
+ ret = regmap_multi_reg_write_bypassed(arizona->regmap, &clear_pga, 1);
+ if (ret)
+ dev_err(arizona->dev, "Failed to clear PGA (0x%x): %d\n",
+ clear_pga.reg, ret);
+
+ return ret;
+}
+
+static int wm5110_put_dre(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+ struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ unsigned int ena, dre;
+ unsigned int mask = (0x1 << mc->shift) | (0x1 << mc->rshift);
+ unsigned int lnew = (!!ucontrol->value.integer.value[0]) << mc->shift;
+ unsigned int rnew = (!!ucontrol->value.integer.value[1]) << mc->rshift;
+ unsigned int lold, rold;
+ unsigned int lena, rena;
+ int ret;
+
+ snd_soc_dapm_mutex_lock(dapm);
+
+ ret = regmap_read(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, &ena);
+ if (ret) {
+ dev_err(arizona->dev, "Failed to read output state: %d\n", ret);
+ goto err;
+ }
+ ret = regmap_read(arizona->regmap, ARIZONA_DRE_ENABLE, &dre);
+ if (ret) {
+ dev_err(arizona->dev, "Failed to read DRE state: %d\n", ret);
+ goto err;
+ }
+
+ lold = dre & (1 << mc->shift);
+ rold = dre & (1 << mc->rshift);
+ /* Enables are channel wise swapped from the DRE enables */
+ lena = ena & (1 << mc->rshift);
+ rena = ena & (1 << mc->shift);
+
+ if ((lena && lnew != lold) || (rena && rnew != rold)) {
+ dev_err(arizona->dev, "Can't change DRE on active outputs\n");
+ ret = -EBUSY;
+ goto err;
+ }
+
+ ret = regmap_update_bits(arizona->regmap, ARIZONA_DRE_ENABLE,
+ mask, lnew | rnew);
+ if (ret) {
+ dev_err(arizona->dev, "Failed to set DRE: %d\n", ret);
+ goto err;
+ }
+
+ /* Force reset of PGA volumes, if turning DRE off */
+ if (!lnew && lold)
+ wm5110_clear_pga_volume(arizona, mc->shift);
+
+ if (!rnew && rold)
+ wm5110_clear_pga_volume(arizona, mc->rshift);
+
+err:
+ snd_soc_dapm_mutex_unlock(dapm);
+
+ return ret;
+}
+
static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
@@ -247,8 +511,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
-SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
-SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2),
SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -260,8 +523,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
24, 0, eq_tlv),
-SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19),
-SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2),
SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
@@ -273,8 +535,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
24, 0, eq_tlv),
-SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19),
-SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2),
SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
@@ -286,8 +547,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
24, 0, eq_tlv),
-SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19),
-SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2),
SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
@@ -314,10 +574,10 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
-SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
-SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
-SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
-SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2),
+ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),
+ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2),
+ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2),
SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
@@ -409,12 +669,15 @@ SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
ARIZONA_SPK2R_MUTE_SHIFT, 1, 1),
-SOC_DOUBLE("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE,
- ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0),
-SOC_DOUBLE("HPOUT2 DRE Switch", ARIZONA_DRE_ENABLE,
- ARIZONA_DRE2L_ENA_SHIFT, ARIZONA_DRE2R_ENA_SHIFT, 1, 0),
-SOC_DOUBLE("HPOUT3 DRE Switch", ARIZONA_DRE_ENABLE,
- ARIZONA_DRE3L_ENA_SHIFT, ARIZONA_DRE3R_ENA_SHIFT, 1, 0),
+SOC_DOUBLE_EXT("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE,
+ ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0,
+ snd_soc_get_volsw, wm5110_put_dre),
+SOC_DOUBLE_EXT("HPOUT2 DRE Switch", ARIZONA_DRE_ENABLE,
+ ARIZONA_DRE2L_ENA_SHIFT, ARIZONA_DRE2R_ENA_SHIFT, 1, 0,
+ snd_soc_get_volsw, wm5110_put_dre),
+SOC_DOUBLE_EXT("HPOUT3 DRE Switch", ARIZONA_DRE_ENABLE,
+ ARIZONA_DRE3L_ENA_SHIFT, ARIZONA_DRE3R_ENA_SHIFT, 1, 0,
+ snd_soc_get_volsw, wm5110_put_dre),
SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
@@ -904,11 +1167,11 @@ SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
- ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
+ ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, wm5110_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
- ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
+ ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, wm5110_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
@@ -1611,18 +1874,24 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
for (i = 0; i < WM5110_NUM_ADSP; ++i) {
ret = wm_adsp2_codec_probe(&priv->core.adsp[i], codec);
if (ret)
- return ret;
+ goto err_adsp2_codec_probe;
}
ret = snd_soc_add_codec_controls(codec,
arizona_adsp2_rate_controls,
WM5110_NUM_ADSP);
if (ret)
- return ret;
+ goto err_adsp2_codec_probe;
snd_soc_dapm_disable_pin(dapm, "HAPTICS");
return 0;
+
+err_adsp2_codec_probe:
+ for (--i; i >= 0; --i)
+ wm_adsp2_codec_remove(&priv->core.adsp[i], codec);
+
+ return ret;
}
static int wm5110_codec_remove(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 41c62c1e6..ffbf3df8a 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -394,11 +394,10 @@ static DECLARE_TLV_DB_SCALE(dac_pcm_tlv, -7163, 36, 1);
static DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -12700, 50, 1);
static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1);
-static const unsigned int capture_sd_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(capture_sd_tlv,
0, 12, TLV_DB_SCALE_ITEM(-3600, 300, 1),
- 13, 15, TLV_DB_SCALE_ITEM(0, 0, 0),
-};
+ 13, 15, TLV_DB_SCALE_ITEM(0, 0, 0)
+);
static const struct snd_kcontrol_new wm8350_snd_controls[] = {
SOC_ENUM("Playback Deemphasis", wm8350_enum[0]),
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index d7555085e..b1d346aa4 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -370,10 +370,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w,
}
/* INMIX dB values */
-static const unsigned int in_mix_tlv[] = {
- TLV_DB_RANGE_HEAD(1),
- 0,7, TLV_DB_SCALE_ITEM(-1200, 600, 0),
-};
+static const DECLARE_TLV_DB_SCALE(in_mix_tlv, -1200, 600, 0);
/* Left In PGA Connections */
static const struct snd_kcontrol_new wm8400_dapm_lin12_pga_controls[] = {
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index dac5beb4d..b098a83a4 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -598,6 +598,7 @@ static const struct of_device_id wm8510_of_match[] = {
{ .compatible = "wlf,wm8510" },
{ },
};
+MODULE_DEVICE_TABLE(of, wm8510_of_match);
static const struct regmap_config wm8510_regmap = {
.reg_bits = 7,
@@ -690,7 +691,6 @@ MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
static struct i2c_driver wm8510_i2c_driver = {
.driver = {
.name = "wm8510",
- .owner = THIS_MODULE,
.of_match_table = wm8510_of_match,
},
.probe = wm8510_i2c_probe,
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 43ea8ae5f..aa287a396 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -430,6 +430,7 @@ static const struct of_device_id wm8523_of_match[] = {
{ .compatible = "wlf,wm8523" },
{ },
};
+MODULE_DEVICE_TABLE(of, wm8523_of_match);
static const struct regmap_config wm8523_regmap = {
.reg_bits = 8,
@@ -534,7 +535,6 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
static struct i2c_driver wm8523_i2c_driver = {
.driver = {
.name = "wm8523",
- .owner = THIS_MODULE,
.of_match_table = wm8523_of_match,
},
.probe = wm8523_i2c_probe,
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 759a7928a..66602bf02 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -916,6 +916,7 @@ static const struct of_device_id wm8580_of_match[] = {
{ .compatible = "wlf,wm8580" },
{ },
};
+MODULE_DEVICE_TABLE(of, wm8580_of_match);
static const struct regmap_config wm8580_regmap = {
.reg_bits = 7,
@@ -978,7 +979,6 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
static struct i2c_driver wm8580_i2c_driver = {
.driver = {
.name = "wm8580",
- .owner = THIS_MODULE,
.of_match_table = wm8580_of_match,
},
.probe = wm8580_i2c_probe,
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index cc8251f09..44b9e0ae7 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -478,7 +478,6 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id);
static struct i2c_driver wm8711_i2c_driver = {
.driver = {
.name = "wm8711",
- .owner = THIS_MODULE,
.of_match_table = wm8711_of_match,
},
.probe = wm8711_i2c_probe,
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index f1a173e6e..cd7b02413 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -319,7 +319,6 @@ MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
static struct i2c_driver wm8728_i2c_driver = {
.driver = {
.name = "wm8728",
- .owner = THIS_MODULE,
.of_match_table = wm8728_of_match,
},
.probe = wm8728_i2c_probe,
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 915ea11ad..ace864524 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -79,12 +79,7 @@ static bool wm8731_volatile(struct device *dev, unsigned int reg)
return reg == WM8731_RESET;
}
-static bool wm8731_writeable(struct device *dev, unsigned int reg)
-{
- return reg <= WM8731_RESET;
-}
-
-#define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0)
+#define wm8731_reset(m) regmap_write(m, WM8731_RESET, 0)
static const char *wm8731_input_select[] = {"Line In", "Mic"};
@@ -496,8 +491,11 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
switch (level) {
case SND_SOC_BIAS_ON:
- if (wm8731->mclk)
- clk_prepare_enable(wm8731->mclk);
+ if (wm8731->mclk) {
+ ret = clk_prepare_enable(wm8731->mclk);
+ if (ret)
+ return ret;
+ }
break;
case SND_SOC_BIAS_PREPARE:
break;
@@ -571,69 +569,63 @@ static struct snd_soc_dai_driver wm8731_dai = {
.symmetric_rates = 1,
};
-static int wm8731_probe(struct snd_soc_codec *codec)
+static int wm8731_request_supplies(struct device *dev,
+ struct wm8731_priv *wm8731)
{
- struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
int ret = 0, i;
for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
wm8731->supplies[i].supply = wm8731_supply_names[i];
- ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies),
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(wm8731->supplies),
wm8731->supplies);
if (ret != 0) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+ dev_err(dev, "Failed to request supplies: %d\n", ret);
return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
wm8731->supplies);
if (ret != 0) {
- dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+ dev_err(dev, "Failed to enable supplies: %d\n", ret);
return ret;
}
- ret = wm8731_reset(codec);
+ return 0;
+}
+
+static int wm8731_hw_init(struct device *dev, struct wm8731_priv *wm8731)
+{
+ int ret = 0;
+
+ ret = wm8731_reset(wm8731->regmap);
if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+ dev_err(dev, "Failed to issue reset: %d\n", ret);
goto err_regulator_enable;
}
- snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ /* Clear POWEROFF, keep everything else disabled */
+ regmap_write(wm8731->regmap, WM8731_PWR, 0x7f);
/* Latch the update bits */
- snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0);
- snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0);
- snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0);
- snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0);
+ regmap_update_bits(wm8731->regmap, WM8731_LOUT1V, 0x100, 0);
+ regmap_update_bits(wm8731->regmap, WM8731_ROUT1V, 0x100, 0);
+ regmap_update_bits(wm8731->regmap, WM8731_LINVOL, 0x100, 0);
+ regmap_update_bits(wm8731->regmap, WM8731_RINVOL, 0x100, 0);
/* Disable bypass path by default */
- snd_soc_update_bits(codec, WM8731_APANA, 0x8, 0);
+ regmap_update_bits(wm8731->regmap, WM8731_APANA, 0x8, 0);
- /* Regulators will have been enabled by bias management */
- regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
-
- return 0;
+ regcache_mark_dirty(wm8731->regmap);
err_regulator_enable:
+ /* Regulators will be enabled by bias management */
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
return ret;
}
-/* power down chip */
-static int wm8731_remove(struct snd_soc_codec *codec)
-{
- struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
-
- regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
-
- return 0;
-}
-
static struct snd_soc_codec_driver soc_codec_dev_wm8731 = {
- .probe = wm8731_probe,
- .remove = wm8731_remove,
.set_bias_level = wm8731_set_bias_level,
.suspend_bias_off = true,
@@ -658,7 +650,6 @@ static const struct regmap_config wm8731_regmap = {
.max_register = WM8731_RESET,
.volatile_reg = wm8731_volatile,
- .writeable_reg = wm8731_writeable,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = wm8731_reg_defaults,
@@ -690,6 +681,12 @@ static int wm8731_spi_probe(struct spi_device *spi)
mutex_init(&wm8731->lock);
+ spi_set_drvdata(spi, wm8731);
+
+ ret = wm8731_request_supplies(&spi->dev, wm8731);
+ if (ret != 0)
+ return ret;
+
wm8731->regmap = devm_regmap_init_spi(spi, &wm8731_regmap);
if (IS_ERR(wm8731->regmap)) {
ret = PTR_ERR(wm8731->regmap);
@@ -698,7 +695,9 @@ static int wm8731_spi_probe(struct spi_device *spi)
return ret;
}
- spi_set_drvdata(spi, wm8731);
+ ret = wm8731_hw_init(&spi->dev, wm8731);
+ if (ret != 0)
+ return ret;
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8731, &wm8731_dai, 1);
@@ -754,6 +753,12 @@ static int wm8731_i2c_probe(struct i2c_client *i2c,
mutex_init(&wm8731->lock);
+ i2c_set_clientdata(i2c, wm8731);
+
+ ret = wm8731_request_supplies(&i2c->dev, wm8731);
+ if (ret != 0)
+ return ret;
+
wm8731->regmap = devm_regmap_init_i2c(i2c, &wm8731_regmap);
if (IS_ERR(wm8731->regmap)) {
ret = PTR_ERR(wm8731->regmap);
@@ -762,7 +767,9 @@ static int wm8731_i2c_probe(struct i2c_client *i2c,
return ret;
}
- i2c_set_clientdata(i2c, wm8731);
+ ret = wm8731_hw_init(&i2c->dev, wm8731);
+ if (ret != 0)
+ return ret;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8731, &wm8731_dai, 1);
@@ -789,7 +796,6 @@ MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id);
static struct i2c_driver wm8731_i2c_driver = {
.driver = {
.name = "wm8731",
- .owner = THIS_MODULE,
.of_match_table = wm8731_of_match,
},
.probe = wm8731_i2c_probe,
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index 6ad606fd8..e4a03d98a 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -79,13 +79,12 @@ static int wm8737_reset(struct snd_soc_codec *codec)
return snd_soc_write(codec, WM8737_RESET, 0);
}
-static const unsigned int micboost_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+static const DECLARE_TLV_DB_RANGE(micboost_tlv,
0, 0, TLV_DB_SCALE_ITEM(1300, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(2800, 0, 0),
- 3, 3, TLV_DB_SCALE_ITEM(3300, 0, 0),
-};
+ 3, 3, TLV_DB_SCALE_ITEM(3300, 0, 0)
+);
static const DECLARE_TLV_DB_SCALE(pga_tlv, -9750, 50, 1);
static const DECLARE_TLV_DB_SCALE(adc_tlv, -600, 600, 0);
static const DECLARE_TLV_DB_SCALE(ng_tlv, -7800, 600, 0);
@@ -657,7 +656,6 @@ MODULE_DEVICE_TABLE(i2c, wm8737_i2c_id);
static struct i2c_driver wm8737_i2c_driver = {
.driver = {
.name = "wm8737",
- .owner = THIS_MODULE,
.of_match_table = wm8737_of_match,
},
.probe = wm8737_i2c_probe,
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index b34623786..de42c0388 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -61,25 +61,6 @@ static const struct reg_default wm8741_reg_defaults[] = {
{ 32, 0x0002 }, /* R32 - ADDITONAL_CONTROL_1 */
};
-static bool wm8741_readable(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case WM8741_DACLLSB_ATTENUATION:
- case WM8741_DACLMSB_ATTENUATION:
- case WM8741_DACRLSB_ATTENUATION:
- case WM8741_DACRMSB_ATTENUATION:
- case WM8741_VOLUME_CONTROL:
- case WM8741_FORMAT_CONTROL:
- case WM8741_FILTER_CONTROL:
- case WM8741_MODE_CONTROL_1:
- case WM8741_MODE_CONTROL_2:
- case WM8741_ADDITIONAL_CONTROL_1:
- return true;
- default:
- return false;
- }
-}
-
static int wm8741_reset(struct snd_soc_codec *codec)
{
return snd_soc_write(codec, WM8741_RESET, 0);
@@ -278,51 +259,38 @@ static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai,
switch (freq) {
case 0:
wm8741->sysclk_constraints = NULL;
- wm8741->sysclk = freq;
- return 0;
-
+ break;
case 11289600:
wm8741->sysclk_constraints = &constraints_11289;
- wm8741->sysclk = freq;
- return 0;
-
+ break;
case 12288000:
wm8741->sysclk_constraints = &constraints_12288;
- wm8741->sysclk = freq;
- return 0;
-
+ break;
case 16384000:
wm8741->sysclk_constraints = &constraints_16384;
- wm8741->sysclk = freq;
- return 0;
-
+ break;
case 16934400:
wm8741->sysclk_constraints = &constraints_16934;
- wm8741->sysclk = freq;
- return 0;
-
+ break;
case 18432000:
wm8741->sysclk_constraints = &constraints_18432;
- wm8741->sysclk = freq;
- return 0;
-
+ break;
case 22579200:
case 33868800:
wm8741->sysclk_constraints = &constraints_22579;
- wm8741->sysclk = freq;
- return 0;
-
+ break;
case 24576000:
wm8741->sysclk_constraints = &constraints_24576;
- wm8741->sysclk = freq;
- return 0;
-
+ break;
case 36864000:
wm8741->sysclk_constraints = &constraints_36864;
- wm8741->sysclk = freq;
- return 0;
+ break;
+ default:
+ return -EINVAL;
}
- return -EINVAL;
+
+ wm8741->sysclk = freq;
+ return 0;
}
static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -554,8 +522,6 @@ static const struct regmap_config wm8741_regmap = {
.reg_defaults = wm8741_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults),
.cache_type = REGCACHE_RBTREE,
-
- .readable_reg = wm8741_readable,
};
static int wm8741_set_pdata(struct device *dev, struct wm8741_priv *wm8741)
@@ -633,7 +599,6 @@ MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id);
static struct i2c_driver wm8741_i2c_driver = {
.driver = {
.name = "wm8741",
- .owner = THIS_MODULE,
.of_match_table = wm8741_of_match,
},
.probe = wm8741_i2c_probe,
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 56d89b086..873933a79 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -826,7 +826,6 @@ MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
static struct i2c_driver wm8750_i2c_driver = {
.driver = {
.name = "wm8750",
- .owner = THIS_MODULE,
.of_match_table = wm8750_of_match,
},
.probe = wm8750_i2c_probe,
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index feb2997a3..a801c6d75 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -138,11 +138,6 @@ static bool wm8753_volatile(struct device *dev, unsigned int reg)
return reg == WM8753_RESET;
}
-static bool wm8753_writeable(struct device *dev, unsigned int reg)
-{
- return reg <= WM8753_ADCTL2;
-}
-
/* codec private data */
struct wm8753_priv {
struct regmap *regmap;
@@ -276,12 +271,11 @@ static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 300, 0);
static const DECLARE_TLV_DB_SCALE(mic_preamp_tlv, 1200, 600, 0);
static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
-static const unsigned int out_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(out_tlv,
/* 0000000 - 0101111 = "Analogue mute" */
0, 48, TLV_DB_SCALE_ITEM(-25500, 0, 0),
- 48, 127, TLV_DB_SCALE_ITEM(-7300, 100, 0),
-};
+ 48, 127, TLV_DB_SCALE_ITEM(-7300, 100, 0)
+);
static const DECLARE_TLV_DB_SCALE(mix_tlv, -1500, 300, 0);
static const DECLARE_TLV_DB_SCALE(voice_mix_tlv, -1200, 300, 0);
static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0);
@@ -1510,7 +1504,6 @@ static const struct regmap_config wm8753_regmap = {
.val_bits = 9,
.max_register = WM8753_ADCTL2,
- .writeable_reg = wm8753_writeable,
.volatile_reg = wm8753_volatile,
.cache_type = REGCACHE_RBTREE,
@@ -1609,7 +1602,6 @@ MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
static struct i2c_driver wm8753_i2c_driver = {
.driver = {
.name = "wm8753",
- .owner = THIS_MODULE,
.of_match_table = wm8753_of_match,
},
.probe = wm8753_i2c_probe,
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index ece9b4456..183c9a496 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -265,7 +265,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
}
/* Set word length */
- switch (snd_pcm_format_width(params_format(params))) {
+ switch (params_width(params)) {
case 16:
iface = 0;
break;
@@ -280,7 +280,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
break;
default:
dev_err(codec->dev, "Unsupported sample size: %i\n",
- snd_pcm_format_width(params_format(params)));
+ params_width(params));
return -EINVAL;
}
@@ -536,7 +536,6 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
static struct i2c_driver wm8776_i2c_driver = {
.driver = {
.name = "wm8776",
- .owner = THIS_MODULE,
.of_match_table = wm8776_of_match,
},
.probe = wm8776_i2c_probe,
diff --git a/sound/soc/codecs/wm8804-i2c.c b/sound/soc/codecs/wm8804-i2c.c
index 6596f5f3a..f27464c2c 100644
--- a/sound/soc/codecs/wm8804-i2c.c
+++ b/sound/soc/codecs/wm8804-i2c.c
@@ -49,7 +49,6 @@ MODULE_DEVICE_TABLE(of, wm8804_of_match);
static struct i2c_driver wm8804_i2c_driver = {
.driver = {
.name = "wm8804",
- .owner = THIS_MODULE,
.pm = &wm8804_pm,
.of_match_table = wm8804_of_match,
},
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index c195c2e8a..8d914702c 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -98,7 +98,7 @@ WM8804_REGULATOR_EVENT(0)
WM8804_REGULATOR_EVENT(1)
static const char *txsrc_text[] = { "S/PDIF RX", "AIF" };
-static const SOC_ENUM_SINGLE_DECL(txsrc, WM8804_SPDTX4, 6, txsrc_text);
+static SOC_ENUM_SINGLE_DECL(txsrc, WM8804_SPDTX4, 6, txsrc_text);
static const struct snd_kcontrol_new wm8804_tx_source_mux[] = {
SOC_DAPM_ENUM_EXT("Input Source", txsrc,
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index f3759ec5a..98900aa66 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -1312,7 +1312,6 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
static struct i2c_driver wm8900_i2c_driver = {
.driver = {
.name = "wm8900",
- .owner = THIS_MODULE,
},
.probe = wm8900_i2c_probe,
.remove = wm8900_i2c_remove,
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index b5322c154..b01125345 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -2193,7 +2193,6 @@ MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id);
static struct i2c_driver wm8903_i2c_driver = {
.driver = {
.name = "wm8903",
- .owner = THIS_MODULE,
.of_match_table = wm8903_of_match,
},
.probe = wm8903_i2c_probe,
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 265a4a58a..b783743dc 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -1837,7 +1837,9 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec,
switch (level) {
case SND_SOC_BIAS_ON:
- clk_prepare_enable(wm8904->mclk);
+ ret = clk_prepare_enable(wm8904->mclk);
+ if (ret)
+ return ret;
break;
case SND_SOC_BIAS_PREPARE:
@@ -2292,7 +2294,6 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id);
static struct i2c_driver wm8904_i2c_driver = {
.driver = {
.name = "wm8904",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(wm8904_of_match),
},
.probe = wm8904_i2c_probe,
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 98ef0ba5c..f6f9395ea 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -787,7 +787,6 @@ MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);
static struct i2c_driver wm8940_i2c_driver = {
.driver = {
.name = "wm8940",
- .owner = THIS_MODULE,
},
.probe = wm8940_i2c_probe,
.remove = wm8940_i2c_remove,
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 2d591c247..12e4435f0 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -1009,7 +1009,6 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id);
static struct i2c_driver wm8955_i2c_driver = {
.driver = {
.name = "wm8955",
- .owner = THIS_MODULE,
},
.probe = wm8955_i2c_probe,
.remove = wm8955_i2c_remove,
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 94c5c4681..dbd884088 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -48,6 +48,9 @@
#define WM8960_DISOP 0x40
#define WM8960_DRES_MASK 0x30
+static bool is_pll_freq_available(unsigned int source, unsigned int target);
+static int wm8960_set_pll(struct snd_soc_codec *codec,
+ unsigned int freq_in, unsigned int freq_out);
/*
* wm8960 register cache
* We can't read the WM8960 register space when we are
@@ -126,9 +129,12 @@ struct wm8960_priv {
struct snd_soc_dapm_widget *rout1;
struct snd_soc_dapm_widget *out3;
bool deemph;
- int playback_fs;
+ int lrclk;
int bclk;
int sysclk;
+ int clk_id;
+ int freq_in;
+ bool is_stream_in_use[2];
struct wm8960_data pdata;
};
@@ -164,8 +170,8 @@ static int wm8960_set_deemph(struct snd_soc_codec *codec)
if (wm8960->deemph) {
best = 1;
for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) {
- if (abs(deemph_settings[i] - wm8960->playback_fs) <
- abs(deemph_settings[best] - wm8960->playback_fs))
+ if (abs(deemph_settings[i] - wm8960->lrclk) <
+ abs(deemph_settings[best] - wm8960->lrclk))
best = i;
}
@@ -205,28 +211,38 @@ static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
return wm8960_set_deemph(codec);
}
-static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0);
-static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1725, 75, 0);
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
-static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1);
+static const DECLARE_TLV_DB_SCALE(lineinboost_tlv, -1500, 300, 1);
+static const unsigned int micboost_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 1, TLV_DB_SCALE_ITEM(0, 1300, 0),
+ 2, 3, TLV_DB_SCALE_ITEM(2000, 900, 0),
+};
static const struct snd_kcontrol_new wm8960_snd_controls[] = {
SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
- 0, 63, 0, adc_tlv),
+ 0, 63, 0, inpga_tlv),
SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL,
6, 1, 0),
SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL,
7, 1, 0),
SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT3 Volume",
- WM8960_INBMIX1, 4, 7, 0, boost_tlv),
+ WM8960_INBMIX1, 4, 7, 0, lineinboost_tlv),
SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT2 Volume",
- WM8960_INBMIX1, 1, 7, 0, boost_tlv),
+ WM8960_INBMIX1, 1, 7, 0, lineinboost_tlv),
SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT3 Volume",
- WM8960_INBMIX2, 4, 7, 0, boost_tlv),
+ WM8960_INBMIX2, 4, 7, 0, lineinboost_tlv),
SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT2 Volume",
- WM8960_INBMIX2, 1, 7, 0, boost_tlv),
+ WM8960_INBMIX2, 1, 7, 0, lineinboost_tlv),
+SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT1 Volume",
+ WM8960_RINPATH, 4, 3, 0, micboost_tlv),
+SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT1 Volume",
+ WM8960_LINPATH, 4, 3, 0, micboost_tlv),
SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC,
0, 255, 0, dac_tlv),
@@ -565,6 +581,9 @@ static struct {
{ 8000, 5 },
};
+/* -1 for reserved value */
+static const int sysclk_divs[] = { 1, -1, 2, -1 };
+
/* Multiply 256 for internal 256 div */
static const int dac_divs[] = { 256, 384, 512, 768, 1024, 1408, 1536 };
@@ -574,61 +593,110 @@ static const int bclk_divs[] = {
120, 160, 220, 240, 320, 320, 320
};
-static void wm8960_configure_clocking(struct snd_soc_codec *codec,
- bool tx, int lrclk)
+static int wm8960_configure_clocking(struct snd_soc_codec *codec)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+ int sysclk, bclk, lrclk, freq_out, freq_in;
u16 iface1 = snd_soc_read(codec, WM8960_IFACE1);
- u16 iface2 = snd_soc_read(codec, WM8960_IFACE2);
- u32 sysclk;
- int i, j;
+ int i, j, k;
if (!(iface1 & (1<<6))) {
dev_dbg(codec->dev,
"Codec is slave mode, no need to configure clock\n");
- return;
+ return 0;
}
- if (!wm8960->sysclk) {
- dev_dbg(codec->dev, "No SYSCLK configured\n");
- return;
+ if (wm8960->clk_id != WM8960_SYSCLK_MCLK && !wm8960->freq_in) {
+ dev_err(codec->dev, "No MCLK configured\n");
+ return -EINVAL;
}
- if (!wm8960->bclk || !lrclk) {
- dev_dbg(codec->dev, "No audio clocks configured\n");
- return;
+ freq_in = wm8960->freq_in;
+ bclk = wm8960->bclk;
+ lrclk = wm8960->lrclk;
+ /*
+ * If it's sysclk auto mode, check if the MCLK can provide sysclk or
+ * not. If MCLK can provide sysclk, using MCLK to provide sysclk
+ * directly. Otherwise, auto select a available pll out frequency
+ * and set PLL.
+ */
+ if (wm8960->clk_id == WM8960_SYSCLK_AUTO) {
+ /* disable the PLL and using MCLK to provide sysclk */
+ wm8960_set_pll(codec, 0, 0);
+ freq_out = freq_in;
+ } else if (wm8960->sysclk) {
+ freq_out = wm8960->sysclk;
+ } else {
+ dev_err(codec->dev, "No SYSCLK configured\n");
+ return -EINVAL;
}
- for (i = 0; i < ARRAY_SIZE(dac_divs); ++i) {
- if (wm8960->sysclk == lrclk * dac_divs[i]) {
- for (j = 0; j < ARRAY_SIZE(bclk_divs); ++j) {
- sysclk = wm8960->bclk * bclk_divs[j] / 10;
- if (wm8960->sysclk == sysclk)
+ /* check if the sysclk frequency is available. */
+ for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
+ if (sysclk_divs[i] == -1)
+ continue;
+ sysclk = freq_out / sysclk_divs[i];
+ for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {
+ if (sysclk == dac_divs[j] * lrclk) {
+ for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k)
+ if (sysclk == bclk * bclk_divs[k] / 10)
+ break;
+ if (k != ARRAY_SIZE(bclk_divs))
break;
}
- if(j != ARRAY_SIZE(bclk_divs))
+ }
+ if (j != ARRAY_SIZE(dac_divs))
+ break;
+ }
+
+ if (i != ARRAY_SIZE(sysclk_divs)) {
+ goto configure_clock;
+ } else if (wm8960->clk_id != WM8960_SYSCLK_AUTO) {
+ dev_err(codec->dev, "failed to configure clock\n");
+ return -EINVAL;
+ }
+ /* get a available pll out frequency and set pll */
+ for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
+ if (sysclk_divs[i] == -1)
+ continue;
+ for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {
+ sysclk = lrclk * dac_divs[j];
+ freq_out = sysclk * sysclk_divs[i];
+
+ for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) {
+ if (sysclk == bclk * bclk_divs[k] / 10 &&
+ is_pll_freq_available(freq_in, freq_out)) {
+ wm8960_set_pll(codec,
+ freq_in, freq_out);
+ break;
+ } else {
+ continue;
+ }
+ }
+ if (k != ARRAY_SIZE(bclk_divs))
break;
}
+ if (j != ARRAY_SIZE(dac_divs))
+ break;
}
- if (i == ARRAY_SIZE(dac_divs)) {
- dev_err(codec->dev, "Unsupported sysclk %d\n", wm8960->sysclk);
- return;
+ if (i == ARRAY_SIZE(sysclk_divs)) {
+ dev_err(codec->dev, "failed to configure clock\n");
+ return -EINVAL;
}
- /*
- * configure frame clock. If ADCLRC configure as GPIO pin, DACLRC
- * pin is used as a frame clock for ADCs and DACs.
- */
- if (iface2 & (1<<6))
- snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3);
- else if (tx)
- snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3);
- else if (!tx)
- snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 6, i << 6);
+configure_clock:
+ /* configure sysclk clock */
+ snd_soc_update_bits(codec, WM8960_CLOCK1, 3 << 1, i << 1);
+
+ /* configure frame clock */
+ snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, j << 3);
+ snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 6, j << 6);
/* configure bit clock */
- snd_soc_update_bits(codec, WM8960_CLOCK2, 0xf, j);
+ snd_soc_update_bits(codec, WM8960_CLOCK2, 0xf, k);
+
+ return 0;
}
static int wm8960_hw_params(struct snd_pcm_substream *substream,
@@ -667,9 +735,9 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
+ wm8960->lrclk = params_rate(params);
/* Update filters for the new rate */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- wm8960->playback_fs = params_rate(params);
+ if (tx) {
wm8960_set_deemph(codec);
} else {
for (i = 0; i < ARRAY_SIZE(alc_rates); i++)
@@ -682,7 +750,23 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
/* set iface */
snd_soc_write(codec, WM8960_IFACE1, iface);
- wm8960_configure_clocking(codec, tx, params_rate(params));
+ wm8960->is_stream_in_use[tx] = true;
+
+ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON &&
+ !wm8960->is_stream_in_use[!tx])
+ return wm8960_configure_clocking(codec);
+
+ return 0;
+}
+
+static int wm8960_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+
+ wm8960->is_stream_in_use[tx] = false;
return 0;
}
@@ -702,6 +786,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+ u16 pm2 = snd_soc_read(codec, WM8960_POWER2);
int ret;
switch (level) {
@@ -721,11 +806,22 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
}
}
+ ret = wm8960_configure_clocking(codec);
+ if (ret)
+ return ret;
+
/* Set VMID to 2x50k */
snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80);
break;
case SND_SOC_BIAS_ON:
+ /*
+ * If it's sysclk auto mode, and the pll is enabled,
+ * disable the pll
+ */
+ if (wm8960->clk_id == WM8960_SYSCLK_AUTO && (pm2 & 0x1))
+ wm8960_set_pll(codec, 0, 0);
+
if (!IS_ERR(wm8960->mclk))
clk_disable_unprepare(wm8960->mclk);
break;
@@ -780,6 +876,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+ u16 pm2 = snd_soc_read(codec, WM8960_POWER2);
int reg, ret;
switch (level) {
@@ -831,9 +928,21 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec,
return ret;
}
}
+
+ ret = wm8960_configure_clocking(codec);
+ if (ret)
+ return ret;
+
break;
case SND_SOC_BIAS_ON:
+ /*
+ * If it's sysclk auto mode, and the pll is enabled,
+ * disable the pll
+ */
+ if (wm8960->clk_id == WM8960_SYSCLK_AUTO && (pm2 & 0x1))
+ wm8960_set_pll(codec, 0, 0);
+
if (!IS_ERR(wm8960->mclk))
clk_disable_unprepare(wm8960->mclk);
@@ -892,6 +1001,28 @@ struct _pll_div {
u32 k:24;
};
+static bool is_pll_freq_available(unsigned int source, unsigned int target)
+{
+ unsigned int Ndiv;
+
+ if (source == 0 || target == 0)
+ return false;
+
+ /* Scale up target to PLL operating frequency */
+ target *= 4;
+ Ndiv = target / source;
+
+ if (Ndiv < 6) {
+ source >>= 1;
+ Ndiv = target / source;
+ }
+
+ if ((Ndiv < 6) || (Ndiv > 12))
+ return false;
+
+ return true;
+}
+
/* The size in bits of the pll divide multiplied by 10
* to allow rounding later */
#define FIXED_PLL_SIZE ((1 << 24) * 10)
@@ -943,10 +1074,9 @@ static int pll_factors(unsigned int source, unsigned int target,
return 0;
}
-static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
- int source, unsigned int freq_in, unsigned int freq_out)
+static int wm8960_set_pll(struct snd_soc_codec *codec,
+ unsigned int freq_in, unsigned int freq_out)
{
- struct snd_soc_codec *codec = codec_dai->codec;
u16 reg;
static struct _pll_div pll_div;
int ret;
@@ -986,6 +1116,20 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
return 0;
}
+static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
+ int source, unsigned int freq_in, unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+
+ wm8960->freq_in = freq_in;
+
+ if (pll_id == WM8960_SYSCLK_AUTO)
+ return 0;
+
+ return wm8960_set_pll(codec, freq_in, freq_out);
+}
+
static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
int div_id, int div)
{
@@ -1043,11 +1187,14 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
snd_soc_update_bits(codec, WM8960_CLOCK1,
0x1, WM8960_SYSCLK_PLL);
break;
+ case WM8960_SYSCLK_AUTO:
+ break;
default:
return -EINVAL;
}
wm8960->sysclk = freq;
+ wm8960->clk_id = clk_id;
return 0;
}
@@ -1060,6 +1207,7 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
static const struct snd_soc_dai_ops wm8960_dai_ops = {
.hw_params = wm8960_hw_params,
+ .hw_free = wm8960_hw_free,
.digital_mute = wm8960_mute,
.set_fmt = wm8960_set_dai_fmt,
.set_clkdiv = wm8960_set_dai_clkdiv,
@@ -1216,7 +1364,6 @@ MODULE_DEVICE_TABLE(of, wm8960_of_match);
static struct i2c_driver wm8960_i2c_driver = {
.driver = {
.name = "wm8960",
- .owner = THIS_MODULE,
.of_match_table = wm8960_of_match,
},
.probe = wm8960_i2c_probe,
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h
index 2d8163d70..ab3220d34 100644
--- a/sound/soc/codecs/wm8960.h
+++ b/sound/soc/codecs/wm8960.h
@@ -82,6 +82,7 @@
#define WM8960_SYSCLK_MCLK (0 << 0)
#define WM8960_SYSCLK_PLL (1 << 0)
+#define WM8960_SYSCLK_AUTO (2 << 0)
#define WM8960_DAC_DIV_1 (0 << 3)
#define WM8960_DAC_DIV_1_5 (1 << 3)
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index a05766263..e30446a04 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -331,13 +331,12 @@ static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0);
static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
-static unsigned int boost_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+static const DECLARE_TLV_DB_RANGE(boost_tlv,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(13, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(20, 0, 0),
- 3, 3, TLV_DB_SCALE_ITEM(29, 0, 0),
-};
+ 3, 3, TLV_DB_SCALE_ITEM(29, 0, 0)
+);
static const DECLARE_TLV_DB_SCALE(pga_tlv, -2325, 75, 0);
static const struct snd_kcontrol_new wm8961_snd_controls[] = {
@@ -982,7 +981,6 @@ MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);
static struct i2c_driver wm8961_i2c_driver = {
.driver = {
.name = "wm8961",
- .owner = THIS_MODULE,
},
.probe = wm8961_i2c_probe,
.remove = wm8961_i2c_remove,
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index c5748fd4f..39ebd7bf4 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -113,7 +113,7 @@ WM8962_REGULATOR_EVENT(5)
WM8962_REGULATOR_EVENT(6)
WM8962_REGULATOR_EVENT(7)
-static struct reg_default wm8962_reg[] = {
+static const struct reg_default wm8962_reg[] = {
{ 0, 0x009F }, /* R0 - Left Input volume */
{ 1, 0x049F }, /* R1 - Right Input volume */
{ 2, 0x0000 }, /* R2 - HPOUTL volume */
@@ -1456,14 +1456,13 @@ static int wm8962_reset(struct wm8962_priv *wm8962)
static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0);
static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0);
-static const unsigned int mixinpga_tlv[] = {
- TLV_DB_RANGE_HEAD(5),
+static const DECLARE_TLV_DB_RANGE(mixinpga_tlv,
0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0),
3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0),
5, 5, TLV_DB_SCALE_ITEM(2400, 0, 0),
- 6, 7, TLV_DB_SCALE_ITEM(2700, 300, 0),
-};
+ 6, 7, TLV_DB_SCALE_ITEM(2700, 300, 0)
+);
static const DECLARE_TLV_DB_SCALE(beep_tlv, -9600, 600, 1);
static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0);
@@ -1471,11 +1470,10 @@ static const DECLARE_TLV_DB_SCALE(inmix_tlv, -600, 600, 0);
static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0);
-static const unsigned int classd_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(classd_tlv,
0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
- 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
-};
+ 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0)
+);
static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
static int wm8962_dsp2_write_config(struct snd_soc_codec *codec)
@@ -2946,7 +2944,8 @@ static int wm8962_mute(struct snd_soc_dai *dai, int mute)
WM8962_DAC_MUTE, val);
}
-#define WM8962_RATES SNDRV_PCM_RATE_8000_96000
+#define WM8962_RATES (SNDRV_PCM_RATE_8000_48000 |\
+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
#define WM8962_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -3495,7 +3494,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
};
/* Improve power consumption for IN4 DC measurement mode */
-static const struct reg_default wm8962_dc_measure[] = {
+static const struct reg_sequence wm8962_dc_measure[] = {
{ 0xfd, 0x1 },
{ 0xcc, 0x40 },
{ 0xfd, 0 },
@@ -3761,7 +3760,7 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8962, &wm8962_dai, 1);
if (ret < 0)
- goto err_enable;
+ goto err_pm_runtime;
regcache_cache_only(wm8962->regmap, true);
@@ -3770,6 +3769,8 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
return 0;
+err_pm_runtime:
+ pm_runtime_disable(&i2c->dev);
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
err:
@@ -3779,6 +3780,7 @@ err:
static int wm8962_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
+ pm_runtime_disable(&client->dev);
return 0;
}
@@ -3806,6 +3808,8 @@ static int wm8962_runtime_resume(struct device *dev)
wm8962_reset(wm8962);
+ regcache_mark_dirty(wm8962->regmap);
+
/* SYSCLK defaults to on; make sure it is off so we can safely
* write to registers if the device is declocked.
*/
@@ -3859,7 +3863,7 @@ static int wm8962_runtime_suspend(struct device *dev)
}
#endif
-static struct dev_pm_ops wm8962_pm = {
+static const struct dev_pm_ops wm8962_pm = {
SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL)
};
@@ -3878,7 +3882,6 @@ MODULE_DEVICE_TABLE(of, wm8962_of_match);
static struct i2c_driver wm8962_i2c_driver = {
.driver = {
.name = "wm8962",
- .owner = THIS_MODULE,
.of_match_table = wm8962_of_match,
.pm = &wm8962_pm,
},
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index b51184c4e..2cdde32c4 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -710,7 +710,6 @@ MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id);
static struct i2c_driver wm8971_i2c_driver = {
.driver = {
.name = "wm8971",
- .owner = THIS_MODULE,
},
.probe = wm8971_i2c_probe,
.remove = wm8971_i2c_remove,
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 33b16a7ba..0a6067739 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -634,7 +634,6 @@ MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id);
static struct i2c_driver wm8974_i2c_driver = {
.driver = {
.name = "wm8974",
- .owner = THIS_MODULE,
},
.probe = wm8974_i2c_probe,
.remove = wm8974_i2c_remove,
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index cfc8cdf49..d36d6001f 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -1072,7 +1072,6 @@ MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id);
static struct i2c_driver wm8978_i2c_driver = {
.driver = {
.name = "wm8978",
- .owner = THIS_MODULE,
},
.probe = wm8978_i2c_probe,
.remove = wm8978_i2c_remove,
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index 2fdd2c6cc..f3193fb75 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -84,66 +84,6 @@ static const struct reg_default wm8983_defaults[] = {
{ 0x3D, 0x0000 }, /* R61 - BIAS CTRL */
};
-static const struct wm8983_reg_access {
- u16 read; /* Mask of readable bits */
- u16 write; /* Mask of writable bits */
-} wm8983_access_masks[WM8983_MAX_REGISTER + 1] = {
- [0x00] = { 0x0000, 0x01FF }, /* R0 - Software Reset */
- [0x01] = { 0x0000, 0x01FF }, /* R1 - Power management 1 */
- [0x02] = { 0x0000, 0x01FF }, /* R2 - Power management 2 */
- [0x03] = { 0x0000, 0x01EF }, /* R3 - Power management 3 */
- [0x04] = { 0x0000, 0x01FF }, /* R4 - Audio Interface */
- [0x05] = { 0x0000, 0x003F }, /* R5 - Companding control */
- [0x06] = { 0x0000, 0x01FD }, /* R6 - Clock Gen control */
- [0x07] = { 0x0000, 0x000F }, /* R7 - Additional control */
- [0x08] = { 0x0000, 0x003F }, /* R8 - GPIO Control */
- [0x09] = { 0x0000, 0x0070 }, /* R9 - Jack Detect Control 1 */
- [0x0A] = { 0x0000, 0x004F }, /* R10 - DAC Control */
- [0x0B] = { 0x0000, 0x01FF }, /* R11 - Left DAC digital Vol */
- [0x0C] = { 0x0000, 0x01FF }, /* R12 - Right DAC digital vol */
- [0x0D] = { 0x0000, 0x00FF }, /* R13 - Jack Detect Control 2 */
- [0x0E] = { 0x0000, 0x01FB }, /* R14 - ADC Control */
- [0x0F] = { 0x0000, 0x01FF }, /* R15 - Left ADC Digital Vol */
- [0x10] = { 0x0000, 0x01FF }, /* R16 - Right ADC Digital Vol */
- [0x12] = { 0x0000, 0x017F }, /* R18 - EQ1 - low shelf */
- [0x13] = { 0x0000, 0x017F }, /* R19 - EQ2 - peak 1 */
- [0x14] = { 0x0000, 0x017F }, /* R20 - EQ3 - peak 2 */
- [0x15] = { 0x0000, 0x017F }, /* R21 - EQ4 - peak 3 */
- [0x16] = { 0x0000, 0x007F }, /* R22 - EQ5 - high shelf */
- [0x18] = { 0x0000, 0x01FF }, /* R24 - DAC Limiter 1 */
- [0x19] = { 0x0000, 0x007F }, /* R25 - DAC Limiter 2 */
- [0x1B] = { 0x0000, 0x01FF }, /* R27 - Notch Filter 1 */
- [0x1C] = { 0x0000, 0x017F }, /* R28 - Notch Filter 2 */
- [0x1D] = { 0x0000, 0x017F }, /* R29 - Notch Filter 3 */
- [0x1E] = { 0x0000, 0x017F }, /* R30 - Notch Filter 4 */
- [0x20] = { 0x0000, 0x01BF }, /* R32 - ALC control 1 */
- [0x21] = { 0x0000, 0x00FF }, /* R33 - ALC control 2 */
- [0x22] = { 0x0000, 0x01FF }, /* R34 - ALC control 3 */
- [0x23] = { 0x0000, 0x000F }, /* R35 - Noise Gate */
- [0x24] = { 0x0000, 0x001F }, /* R36 - PLL N */
- [0x25] = { 0x0000, 0x003F }, /* R37 - PLL K 1 */
- [0x26] = { 0x0000, 0x01FF }, /* R38 - PLL K 2 */
- [0x27] = { 0x0000, 0x01FF }, /* R39 - PLL K 3 */
- [0x29] = { 0x0000, 0x000F }, /* R41 - 3D control */
- [0x2A] = { 0x0000, 0x01E7 }, /* R42 - OUT4 to ADC */
- [0x2B] = { 0x0000, 0x01BF }, /* R43 - Beep control */
- [0x2C] = { 0x0000, 0x0177 }, /* R44 - Input ctrl */
- [0x2D] = { 0x0000, 0x01FF }, /* R45 - Left INP PGA gain ctrl */
- [0x2E] = { 0x0000, 0x01FF }, /* R46 - Right INP PGA gain ctrl */
- [0x2F] = { 0x0000, 0x0177 }, /* R47 - Left ADC BOOST ctrl */
- [0x30] = { 0x0000, 0x0177 }, /* R48 - Right ADC BOOST ctrl */
- [0x31] = { 0x0000, 0x007F }, /* R49 - Output ctrl */
- [0x32] = { 0x0000, 0x01FF }, /* R50 - Left mixer ctrl */
- [0x33] = { 0x0000, 0x01FF }, /* R51 - Right mixer ctrl */
- [0x34] = { 0x0000, 0x01FF }, /* R52 - LOUT1 (HP) volume ctrl */
- [0x35] = { 0x0000, 0x01FF }, /* R53 - ROUT1 (HP) volume ctrl */
- [0x36] = { 0x0000, 0x01FF }, /* R54 - LOUT2 (SPK) volume ctrl */
- [0x37] = { 0x0000, 0x01FF }, /* R55 - ROUT2 (SPK) volume ctrl */
- [0x38] = { 0x0000, 0x004F }, /* R56 - OUT3 mixer ctrl */
- [0x39] = { 0x0000, 0x00FF }, /* R57 - OUT4 (MONO) mix ctrl */
- [0x3D] = { 0x0000, 0x0100 } /* R61 - BIAS CTRL */
-};
-
/* vol/gain update regs */
static const int vol_update_regs[] = {
WM8983_LEFT_DAC_DIGITAL_VOL,
@@ -605,12 +545,19 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static bool wm8983_readable(struct device *dev, unsigned int reg)
+static bool wm8983_writeable(struct device *dev, unsigned int reg)
{
- if (reg > WM8983_MAX_REGISTER)
- return 0;
-
- return wm8983_access_masks[reg].read != 0;
+ switch (reg) {
+ case WM8983_SOFTWARE_RESET ... WM8983_RIGHT_ADC_DIGITAL_VOL:
+ case WM8983_EQ1_LOW_SHELF ... WM8983_DAC_LIMITER_2:
+ case WM8983_NOTCH_FILTER_1 ... WM8983_NOTCH_FILTER_4:
+ case WM8983_ALC_CONTROL_1 ... WM8983_PLL_K_3:
+ case WM8983_3D_CONTROL ... WM8983_OUT4_MONO_MIX_CTRL:
+ case WM8983_BIAS_CTRL:
+ return true;
+ default:
+ return false;
+ }
}
static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute)
@@ -1048,8 +995,9 @@ static const struct regmap_config wm8983_regmap = {
.reg_defaults = wm8983_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8983_defaults),
.cache_type = REGCACHE_RBTREE,
+ .max_register = WM8983_MAX_REGISTER,
- .readable_reg = wm8983_readable,
+ .writeable_reg = wm8983_writeable,
};
#if defined(CONFIG_SPI_MASTER)
@@ -1133,7 +1081,6 @@ MODULE_DEVICE_TABLE(i2c, wm8983_i2c_id);
static struct i2c_driver wm8983_i2c_driver = {
.driver = {
.name = "wm8983",
- .owner = THIS_MODULE,
},
.probe = wm8983_i2c_probe,
.remove = wm8983_i2c_remove,
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index 8a85f5004..9c3c1517a 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -1144,7 +1144,6 @@ MODULE_DEVICE_TABLE(i2c, wm8985_i2c_id);
static struct i2c_driver wm8985_i2c_driver = {
.driver = {
.name = "wm8985",
- .owner = THIS_MODULE,
},
.probe = wm8985_i2c_probe,
.remove = wm8985_i2c_remove,
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index f13a995af..c88ce99ce 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -919,7 +919,6 @@ MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
static struct i2c_driver wm8988_i2c_driver = {
.driver = {
.name = "wm8988",
- .owner = THIS_MODULE,
},
.probe = wm8988_i2c_probe,
.remove = wm8988_i2c_remove,
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 1993fd2a6..23ecd30d8 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -418,10 +418,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
}
/* INMIX dB values */
-static const unsigned int in_mix_tlv[] = {
- TLV_DB_RANGE_HEAD(1),
- 0, 7, TLV_DB_SCALE_ITEM(-1200, 600, 0),
-};
+static const DECLARE_TLV_DB_SCALE(in_mix_tlv, -1200, 600, 0);
/* Left In PGA Connections */
static const struct snd_kcontrol_new wm8990_dapm_lin12_pga_controls[] = {
@@ -1356,7 +1353,6 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id);
static struct i2c_driver wm8990_i2c_driver = {
.driver = {
.name = "wm8990",
- .owner = THIS_MODULE,
},
.probe = wm8990_i2c_probe,
.remove = wm8990_i2c_remove,
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index 44a677720..c9ee0ac6a 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -111,45 +111,14 @@ static bool wm8991_volatile(struct device *dev, unsigned int reg)
}
}
-static const unsigned int rec_mix_tlv[] = {
- TLV_DB_RANGE_HEAD(1),
- 0, 7, TLV_DB_LINEAR_ITEM(-1500, 600),
-};
-
-static const unsigned int in_pga_tlv[] = {
- TLV_DB_RANGE_HEAD(1),
- 0, 0x1F, TLV_DB_LINEAR_ITEM(-1650, 3000),
-};
-
-static const unsigned int out_mix_tlv[] = {
- TLV_DB_RANGE_HEAD(1),
- 0, 7, TLV_DB_LINEAR_ITEM(0, -2100),
-};
-
-static const unsigned int out_pga_tlv[] = {
- TLV_DB_RANGE_HEAD(1),
- 0, 127, TLV_DB_LINEAR_ITEM(-7300, 600),
-};
-
-static const unsigned int out_omix_tlv[] = {
- TLV_DB_RANGE_HEAD(1),
- 0, 7, TLV_DB_LINEAR_ITEM(-600, 0),
-};
-
-static const unsigned int out_dac_tlv[] = {
- TLV_DB_RANGE_HEAD(1),
- 0, 255, TLV_DB_LINEAR_ITEM(-7163, 0),
-};
-
-static const unsigned int in_adc_tlv[] = {
- TLV_DB_RANGE_HEAD(1),
- 0, 255, TLV_DB_LINEAR_ITEM(-7163, 1763),
-};
-
-static const unsigned int out_sidetone_tlv[] = {
- TLV_DB_RANGE_HEAD(1),
- 0, 31, TLV_DB_LINEAR_ITEM(-3600, 0),
-};
+static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
+static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000);
+static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, 0, -2100);
+static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600);
+static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0);
+static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0);
+static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763);
+static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0);
static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -429,10 +398,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
}
/* INMIX dB values */
-static const unsigned int in_mix_tlv[] = {
- TLV_DB_RANGE_HEAD(1),
- 0, 7, TLV_DB_LINEAR_ITEM(-1200, 600),
-};
+static const DECLARE_TLV_DB_LINEAR(in_mix_tlv, -1200, 600);
/* Left In PGA Connections */
static const struct snd_kcontrol_new wm8991_dapm_lin12_pga_controls[] = {
@@ -1363,7 +1329,6 @@ MODULE_DEVICE_TABLE(i2c, wm8991_i2c_id);
static struct i2c_driver wm8991_i2c_driver = {
.driver = {
.name = "wm8991",
- .owner = THIS_MODULE,
},
.probe = wm8991_i2c_probe,
.remove = wm8991_i2c_remove,
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 8a8db8605..8668c4c39 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -41,7 +41,7 @@ static const char *wm8993_supply_names[WM8993_NUM_SUPPLIES] = {
"SPKVDD",
};
-static struct reg_default wm8993_reg_defaults[] = {
+static const struct reg_default wm8993_reg_defaults[] = {
{ 1, 0x0000 }, /* R1 - Power Management (1) */
{ 2, 0x6000 }, /* R2 - Power Management (2) */
{ 3, 0x0000 }, /* R3 - Power Management (3) */
@@ -628,11 +628,10 @@ static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0);
static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0);
static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
-static const unsigned int drc_max_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(drc_max_tlv,
0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0),
- 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
-};
+ 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0)
+);
static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0);
static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -1800, 300, 0);
static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
@@ -1595,7 +1594,7 @@ static int wm8993_resume(struct snd_soc_codec *codec)
#endif
/* Tune DC servo configuration */
-static struct reg_default wm8993_regmap_patch[] = {
+static const struct reg_sequence wm8993_regmap_patch[] = {
{ 0x44, 3 },
{ 0x56, 3 },
{ 0x44, 0 },
@@ -1742,7 +1741,6 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);
static struct i2c_driver wm8993_i2c_driver = {
.driver = {
.name = "wm8993",
- .owner = THIS_MODULE,
},
.probe = wm8993_i2c_probe,
.remove = wm8993_i2c_remove,
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 962e1d31a..2ccbb322d 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -1942,14 +1942,16 @@ static const struct snd_soc_dapm_route intercon[] = {
{ "AIF2ADCDAT", NULL, "AIF2ADC Mux" },
/* AIF3 output */
- { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC1L" },
- { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC1R" },
- { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC2L" },
- { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC2R" },
- { "AIF3ADCDAT", "AIF2ADCDAT", "AIF2ADCL" },
- { "AIF3ADCDAT", "AIF2ADCDAT", "AIF2ADCR" },
- { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" },
- { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" },
+ { "AIF3ADC Mux", "AIF1ADCDAT", "AIF1ADC1L" },
+ { "AIF3ADC Mux", "AIF1ADCDAT", "AIF1ADC1R" },
+ { "AIF3ADC Mux", "AIF1ADCDAT", "AIF1ADC2L" },
+ { "AIF3ADC Mux", "AIF1ADCDAT", "AIF1ADC2R" },
+ { "AIF3ADC Mux", "AIF2ADCDAT", "AIF2ADCL" },
+ { "AIF3ADC Mux", "AIF2ADCDAT", "AIF2ADCR" },
+ { "AIF3ADC Mux", "AIF2DACDAT", "AIF2DACL" },
+ { "AIF3ADC Mux", "AIF2DACDAT", "AIF2DACR" },
+
+ { "AIF3ADCDAT", NULL, "AIF3ADC Mux" },
/* Loopback */
{ "AIF1 Loopback", "ADCDAT", "AIF1ADCDAT" },
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 505b65f57..eda52a96c 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -2298,7 +2298,6 @@ MODULE_DEVICE_TABLE(i2c, wm8995_i2c_id);
static struct i2c_driver wm8995_i2c_driver = {
.driver = {
.name = "wm8995",
- .owner = THIS_MODULE,
},
.probe = wm8995_i2c_probe,
.remove = wm8995_i2c_remove,
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 3dd063f68..f7ccd9fc5 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -117,7 +117,7 @@ WM8996_REGULATOR_EVENT(0)
WM8996_REGULATOR_EVENT(1)
WM8996_REGULATOR_EVENT(2)
-static struct reg_default wm8996_reg[] = {
+static const struct reg_default wm8996_reg[] = {
{ WM8996_POWER_MANAGEMENT_1, 0x0 },
{ WM8996_POWER_MANAGEMENT_2, 0x0 },
{ WM8996_POWER_MANAGEMENT_3, 0x0 },
@@ -1780,7 +1780,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
wm8996->rx_rate[dai->id] = params_rate(params);
/* Needs looking at for TDM */
- bits = snd_pcm_format_width(params_format(params));
+ bits = params_width(params);
if (bits < 0)
return bits;
aifdata |= (bits << WM8996_AIF1TX_WL_SHIFT) | bits;
@@ -2647,12 +2647,10 @@ static int wm8996_probe(struct snd_soc_codec *codec)
if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
ret = request_threaded_irq(i2c->irq, NULL,
wm8996_edge_irq,
- irq_flags | IRQF_ONESHOT,
- "wm8996", codec);
+ irq_flags, "wm8996", codec);
else
ret = request_threaded_irq(i2c->irq, NULL, wm8996_irq,
- irq_flags | IRQF_ONESHOT,
- "wm8996", codec);
+ irq_flags, "wm8996", codec);
if (ret == 0) {
/* Unmask the interrupt */
@@ -3100,7 +3098,6 @@ MODULE_DEVICE_TABLE(i2c, wm8996_i2c_id);
static struct i2c_driver wm8996_i2c_driver = {
.driver = {
.name = "wm8996",
- .owner = THIS_MODULE,
},
.probe = wm8996_i2c_probe,
.remove = wm8996_i2c_remove,
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c
index 4134dc7e1..b4dba3a02 100644
--- a/sound/soc/codecs/wm8997.c
+++ b/sound/soc/codecs/wm8997.c
@@ -174,8 +174,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
-SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
-SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2),
SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -187,8 +186,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
24, 0, eq_tlv),
-SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19),
-SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2),
SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
@@ -200,8 +198,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
24, 0, eq_tlv),
-SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19),
-SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2),
SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
@@ -213,8 +210,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
24, 0, eq_tlv),
-SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19),
-SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2),
SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
@@ -242,10 +238,10 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
-SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
-SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
-SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
-SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2),
+ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),
+ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2),
+ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2),
SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 8a8b1c0f9..ccb3b1513 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -30,7 +30,7 @@
#include <sound/wm9081.h>
#include "wm9081.h"
-static struct reg_default wm9081_reg[] = {
+static const struct reg_default wm9081_reg[] = {
{ 2, 0x00B9 }, /* R2 - Analogue Lineout */
{ 3, 0x00B9 }, /* R3 - Analogue Speaker PGA */
{ 4, 0x0001 }, /* R4 - VMID Control */
@@ -243,13 +243,12 @@ static int wm9081_reset(struct regmap *map)
static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0);
static const DECLARE_TLV_DB_SCALE(drc_out_tlv, -2250, 75, 0);
static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
-static unsigned int drc_max_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+static const DECLARE_TLV_DB_RANGE(drc_max_tlv,
0, 0, TLV_DB_SCALE_ITEM(1200, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
- 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
-};
+ 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0)
+);
static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0);
static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -300, 50, 0);
@@ -1378,7 +1377,6 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);
static struct i2c_driver wm9081_i2c_driver = {
.driver = {
.name = "wm9081",
- .owner = THIS_MODULE,
},
.probe = wm9081_i2c_probe,
.remove = wm9081_i2c_remove,
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 13d23fc79..5d737290f 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -162,23 +162,20 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec)
dev_err(codec->dev, "Timed out waiting for DC Servo\n");
}
-static const unsigned int in_tlv[] = {
- TLV_DB_RANGE_HEAD(3),
+static const DECLARE_TLV_DB_RANGE(in_tlv,
0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0),
1, 3, TLV_DB_SCALE_ITEM(-350, 350, 0),
- 4, 6, TLV_DB_SCALE_ITEM(600, 600, 0),
-};
-static const unsigned int mix_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+ 4, 6, TLV_DB_SCALE_ITEM(600, 600, 0)
+);
+static const DECLARE_TLV_DB_RANGE(mix_tlv,
0, 2, TLV_DB_SCALE_ITEM(-1200, 300, 0),
- 3, 3, TLV_DB_SCALE_ITEM(0, 0, 0),
-};
+ 3, 3, TLV_DB_SCALE_ITEM(0, 0, 0)
+);
static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
-static const unsigned int spkboost_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(spkboost_tlv,
0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
- 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
-};
+ 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0)
+);
static const struct snd_kcontrol_new wm9090_controls[] = {
SOC_SINGLE_TLV("IN1A Volume", WM9090_IN1_LINE_INPUT_A_VOLUME, 0, 6, 0,
@@ -636,7 +633,6 @@ MODULE_DEVICE_TABLE(i2c, wm9090_id);
static struct i2c_driver wm9090_i2c_driver = {
.driver = {
.name = "wm9090",
- .owner = THIS_MODULE,
},
.probe = wm9090_i2c_probe,
.remove = wm9090_i2c_remove,
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 5cc457ef8..744842c76 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -22,6 +22,9 @@
#include "wm9705.h"
+#define WM9705_VENDOR_ID 0x574d4c05
+#define WM9705_VENDOR_ID_MASK 0xffffffff
+
/*
* WM9705 register cache
*/
@@ -293,21 +296,6 @@ static struct snd_soc_dai_driver wm9705_dai[] = {
}
};
-static int wm9705_reset(struct snd_soc_codec *codec)
-{
- struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
-
- if (soc_ac97_ops->reset) {
- soc_ac97_ops->reset(ac97);
- if (ac97_read(codec, 0) == wm9705_reg[0])
- return 0; /* Success */
- }
-
- dev_err(codec->dev, "Failed to reset: AC97 link error\n");
-
- return -EIO;
-}
-
#ifdef CONFIG_PM
static int wm9705_soc_suspend(struct snd_soc_codec *codec)
{
@@ -324,7 +312,8 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec)
int i, ret;
u16 *cache = codec->reg_cache;
- ret = wm9705_reset(codec);
+ ret = snd_ac97_reset(ac97, true, WM9705_VENDOR_ID,
+ WM9705_VENDOR_ID_MASK);
if (ret < 0)
return ret;
@@ -342,30 +331,17 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec)
static int wm9705_soc_probe(struct snd_soc_codec *codec)
{
struct snd_ac97 *ac97;
- int ret = 0;
- ac97 = snd_soc_alloc_ac97_codec(codec);
+ ac97 = snd_soc_new_ac97_codec(codec, WM9705_VENDOR_ID,
+ WM9705_VENDOR_ID_MASK);
if (IS_ERR(ac97)) {
- ret = PTR_ERR(ac97);
dev_err(codec->dev, "Failed to register AC97 codec\n");
- return ret;
+ return PTR_ERR(ac97);
}
- ret = wm9705_reset(codec);
- if (ret)
- goto err_put_device;
-
- ret = device_add(&ac97->dev);
- if (ret)
- goto err_put_device;
-
snd_soc_codec_set_drvdata(codec, ac97);
return 0;
-
-err_put_device:
- put_device(&ac97->dev);
- return ret;
}
static int wm9705_soc_remove(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 1fda104df..488a92224 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -23,6 +23,9 @@
#include <sound/tlv.h>
#include "wm9712.h"
+#define WM9712_VENDOR_ID 0x574d4c12
+#define WM9712_VENDOR_ID_MASK 0xffffffff
+
struct wm9712_priv {
struct snd_ac97 *ac97;
unsigned int hp_mixer[2];
@@ -613,35 +616,14 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
-{
- struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
-
- if (try_warm && soc_ac97_ops->warm_reset) {
- soc_ac97_ops->warm_reset(wm9712->ac97);
- if (ac97_read(codec, 0) == wm9712_reg[0])
- return 1;
- }
-
- soc_ac97_ops->reset(wm9712->ac97);
- if (soc_ac97_ops->warm_reset)
- soc_ac97_ops->warm_reset(wm9712->ac97);
- if (ac97_read(codec, 0) != wm9712_reg[0])
- goto err;
- return 0;
-
-err:
- dev_err(codec->dev, "Failed to reset: AC97 link error\n");
- return -EIO;
-}
-
static int wm9712_soc_resume(struct snd_soc_codec *codec)
{
struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
int i, ret;
u16 *cache = codec->reg_cache;
- ret = wm9712_reset(codec, 1);
+ ret = snd_ac97_reset(wm9712->ac97, true, WM9712_VENDOR_ID,
+ WM9712_VENDOR_ID_MASK);
if (ret < 0)
return ret;
@@ -663,31 +645,20 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec)
static int wm9712_soc_probe(struct snd_soc_codec *codec)
{
struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
- int ret = 0;
+ int ret;
- wm9712->ac97 = snd_soc_alloc_ac97_codec(codec);
+ wm9712->ac97 = snd_soc_new_ac97_codec(codec, WM9712_VENDOR_ID,
+ WM9712_VENDOR_ID_MASK);
if (IS_ERR(wm9712->ac97)) {
ret = PTR_ERR(wm9712->ac97);
dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret);
return ret;
}
- ret = wm9712_reset(codec, 0);
- if (ret < 0)
- goto err_put_device;
-
- ret = device_add(&wm9712->ac97->dev);
- if (ret)
- goto err_put_device;
-
/* set alc mux to none */
ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
return 0;
-
-err_put_device:
- put_device(&wm9712->ac97->dev);
- return ret;
}
static int wm9712_soc_remove(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 89cd2d6f5..4083a5130 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -29,6 +29,9 @@
#include "wm9713.h"
+#define WM9713_VENDOR_ID 0x574d4c13
+#define WM9713_VENDOR_ID_MASK 0xffffffff
+
struct wm9713_priv {
struct snd_ac97 *ac97;
u32 pll_in; /* PLL input frequency */
@@ -116,11 +119,10 @@ SOC_ENUM_SINGLE_VIRT(2, wm9713_micb_select), /* mic selection 19 */
static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0);
static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0);
static const DECLARE_TLV_DB_SCALE(misc_tlv, -1500, 300, 0);
-static unsigned int mic_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(mic_tlv,
0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0),
- 3, 3, TLV_DB_SCALE_ITEM(3000, 0, 0),
-};
+ 3, 3, TLV_DB_SCALE_ITEM(3000, 0, 0)
+);
static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = {
SOC_DOUBLE_TLV("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1, out_tlv),
@@ -1123,28 +1125,6 @@ static struct snd_soc_dai_driver wm9713_dai[] = {
},
};
-int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
-{
- struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
-
- if (try_warm && soc_ac97_ops->warm_reset) {
- soc_ac97_ops->warm_reset(wm9713->ac97);
- if (ac97_read(codec, 0) == wm9713_reg[0])
- return 1;
- }
-
- soc_ac97_ops->reset(wm9713->ac97);
- if (soc_ac97_ops->warm_reset)
- soc_ac97_ops->warm_reset(wm9713->ac97);
- if (ac97_read(codec, 0) != wm9713_reg[0]) {
- dev_err(codec->dev, "Failed to reset: AC97 link error\n");
- return -EIO;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(wm9713_reset);
-
static int wm9713_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -1196,7 +1176,8 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
int i, ret;
u16 *cache = codec->reg_cache;
- ret = wm9713_reset(codec, 1);
+ ret = snd_ac97_reset(wm9713->ac97, true, WM9713_VENDOR_ID,
+ WM9713_VENDOR_ID_MASK);
if (ret < 0)
return ret;
@@ -1222,32 +1203,18 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
static int wm9713_soc_probe(struct snd_soc_codec *codec)
{
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
- int ret = 0, reg;
+ int reg;
- wm9713->ac97 = snd_soc_alloc_ac97_codec(codec);
+ wm9713->ac97 = snd_soc_new_ac97_codec(codec, WM9713_VENDOR_ID,
+ WM9713_VENDOR_ID_MASK);
if (IS_ERR(wm9713->ac97))
return PTR_ERR(wm9713->ac97);
- /* do a cold reset for the controller and then try
- * a warm reset followed by an optional cold reset for codec */
- wm9713_reset(codec, 0);
- ret = wm9713_reset(codec, 1);
- if (ret < 0)
- goto err_put_device;
-
- ret = device_add(&wm9713->ac97->dev);
- if (ret)
- goto err_put_device;
-
/* unmute the adc - move to kcontrol */
reg = ac97_read(codec, AC97_CD) & 0x7fff;
ac97_write(codec, AC97_CD, reg);
return 0;
-
-err_put_device:
- put_device(&wm9713->ac97->dev);
- return ret;
}
static int wm9713_soc_remove(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h
index 793da863a..53df11b1f 100644
--- a/sound/soc/codecs/wm9713.h
+++ b/sound/soc/codecs/wm9713.h
@@ -45,6 +45,4 @@
#define WM9713_DAI_AC97_AUX 1
#define WM9713_DAI_PCM_VOICE 2
-int wm9713_reset(struct snd_soc_codec *codec, int try_warm);
-
#endif
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index fd86bd105..624b3b9cb 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -38,11 +38,10 @@ static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0);
static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0);
static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1);
static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0);
-static const unsigned int spkboost_tlv[] = {
- TLV_DB_RANGE_HEAD(2),
+static const DECLARE_TLV_DB_RANGE(spkboost_tlv,
0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
- 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
-};
+ 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0)
+);
static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0);
static const char *speaker_ref_text[] = {