diff options
Diffstat (limited to 'sound/soc/codecs')
110 files changed, 5273 insertions, 2214 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index a68d1731a8fd..883c5778b309 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -50,7 +50,8 @@ config SND_SOC_ALL_CODECS | |||
50 | select SND_SOC_CS42L73 if I2C | 50 | select SND_SOC_CS42L73 if I2C |
51 | select SND_SOC_CS4265 if I2C | 51 | select SND_SOC_CS4265 if I2C |
52 | select SND_SOC_CS4270 if I2C | 52 | select SND_SOC_CS4270 if I2C |
53 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI | 53 | select SND_SOC_CS4271_I2C if I2C |
54 | select SND_SOC_CS4271_SPI if SPI_MASTER | ||
54 | select SND_SOC_CS42XX8_I2C if I2C | 55 | select SND_SOC_CS42XX8_I2C if I2C |
55 | select SND_SOC_CX20442 if TTY | 56 | select SND_SOC_CX20442 if TTY |
56 | select SND_SOC_DA7210 if I2C | 57 | select SND_SOC_DA7210 if I2C |
@@ -85,7 +86,7 @@ config SND_SOC_ALL_CODECS | |||
85 | select SND_SOC_RT5645 if I2C | 86 | select SND_SOC_RT5645 if I2C |
86 | select SND_SOC_RT5651 if I2C | 87 | select SND_SOC_RT5651 if I2C |
87 | select SND_SOC_RT5670 if I2C | 88 | select SND_SOC_RT5670 if I2C |
88 | select SND_SOC_RT5677 if I2C | 89 | select SND_SOC_RT5677 if I2C && SPI_MASTER |
89 | select SND_SOC_SGTL5000 if I2C | 90 | select SND_SOC_SGTL5000 if I2C |
90 | select SND_SOC_SI476X if MFD_SI476X_CORE | 91 | select SND_SOC_SI476X if MFD_SI476X_CORE |
91 | select SND_SOC_SIRF_AUDIO_CODEC | 92 | select SND_SOC_SIRF_AUDIO_CODEC |
@@ -101,6 +102,7 @@ config SND_SOC_ALL_CODECS | |||
101 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 102 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
102 | select SND_SOC_TAS2552 if I2C | 103 | select SND_SOC_TAS2552 if I2C |
103 | select SND_SOC_TAS5086 if I2C | 104 | select SND_SOC_TAS5086 if I2C |
105 | select SND_SOC_TFA9879 if I2C | ||
104 | select SND_SOC_TLV320AIC23_I2C if I2C | 106 | select SND_SOC_TLV320AIC23_I2C if I2C |
105 | select SND_SOC_TLV320AIC23_SPI if SPI_MASTER | 107 | select SND_SOC_TLV320AIC23_SPI if SPI_MASTER |
106 | select SND_SOC_TLV320AIC26 if SPI_MASTER | 108 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
@@ -109,6 +111,7 @@ config SND_SOC_ALL_CODECS | |||
109 | select SND_SOC_TLV320AIC3X if I2C | 111 | select SND_SOC_TLV320AIC3X if I2C |
110 | select SND_SOC_TPA6130A2 if I2C | 112 | select SND_SOC_TPA6130A2 if I2C |
111 | select SND_SOC_TLV320DAC33 if I2C | 113 | select SND_SOC_TLV320DAC33 if I2C |
114 | select SND_SOC_TS3A227E if I2C | ||
112 | select SND_SOC_TWL4030 if TWL4030_CORE | 115 | select SND_SOC_TWL4030 if TWL4030_CORE |
113 | select SND_SOC_TWL6040 if TWL6040_CORE | 116 | select SND_SOC_TWL6040 if TWL6040_CORE |
114 | select SND_SOC_UDA134X | 117 | select SND_SOC_UDA134X |
@@ -223,6 +226,7 @@ config SND_SOC_AD193X_I2C | |||
223 | select SND_SOC_AD193X | 226 | select SND_SOC_AD193X |
224 | 227 | ||
225 | config SND_SOC_AD1980 | 228 | config SND_SOC_AD1980 |
229 | select REGMAP_AC97 | ||
226 | tristate | 230 | tristate |
227 | 231 | ||
228 | config SND_SOC_AD73311 | 232 | config SND_SOC_AD73311 |
@@ -336,7 +340,8 @@ config SND_SOC_CS42L51 | |||
336 | tristate | 340 | tristate |
337 | 341 | ||
338 | config SND_SOC_CS42L51_I2C | 342 | config SND_SOC_CS42L51_I2C |
339 | tristate | 343 | tristate "Cirrus Logic CS42L51 CODEC (I2C)" |
344 | depends on I2C | ||
340 | select SND_SOC_CS42L51 | 345 | select SND_SOC_CS42L51 |
341 | 346 | ||
342 | config SND_SOC_CS42L52 | 347 | config SND_SOC_CS42L52 |
@@ -370,8 +375,19 @@ config SND_SOC_CS4270_VD33_ERRATA | |||
370 | depends on SND_SOC_CS4270 | 375 | depends on SND_SOC_CS4270 |
371 | 376 | ||
372 | config SND_SOC_CS4271 | 377 | config SND_SOC_CS4271 |
373 | tristate "Cirrus Logic CS4271 CODEC" | 378 | tristate |
374 | depends on SND_SOC_I2C_AND_SPI | 379 | |
380 | config SND_SOC_CS4271_I2C | ||
381 | tristate "Cirrus Logic CS4271 CODEC (I2C)" | ||
382 | depends on I2C | ||
383 | select SND_SOC_CS4271 | ||
384 | select REGMAP_I2C | ||
385 | |||
386 | config SND_SOC_CS4271_SPI | ||
387 | tristate "Cirrus Logic CS4271 CODEC (SPI)" | ||
388 | depends on SPI_MASTER | ||
389 | select SND_SOC_CS4271 | ||
390 | select REGMAP_SPI | ||
375 | 391 | ||
376 | config SND_SOC_CS42XX8 | 392 | config SND_SOC_CS42XX8 |
377 | tristate | 393 | tristate |
@@ -487,7 +503,8 @@ config SND_SOC_RT286 | |||
487 | depends on I2C | 503 | depends on I2C |
488 | 504 | ||
489 | config SND_SOC_RT5631 | 505 | config SND_SOC_RT5631 |
490 | tristate | 506 | tristate "Realtek ALC5631/RT5631 CODEC" |
507 | depends on I2C | ||
491 | 508 | ||
492 | config SND_SOC_RT5640 | 509 | config SND_SOC_RT5640 |
493 | tristate | 510 | tristate |
@@ -504,6 +521,10 @@ config SND_SOC_RT5670 | |||
504 | config SND_SOC_RT5677 | 521 | config SND_SOC_RT5677 |
505 | tristate | 522 | tristate |
506 | 523 | ||
524 | config SND_SOC_RT5677_SPI | ||
525 | tristate | ||
526 | default SND_SOC_RT5677 | ||
527 | |||
507 | #Freescale sgtl5000 codec | 528 | #Freescale sgtl5000 codec |
508 | config SND_SOC_SGTL5000 | 529 | config SND_SOC_SGTL5000 |
509 | tristate "Freescale SGTL5000 CODEC" | 530 | tristate "Freescale SGTL5000 CODEC" |
@@ -577,15 +598,21 @@ config SND_SOC_TAS5086 | |||
577 | tristate "Texas Instruments TAS5086 speaker amplifier" | 598 | tristate "Texas Instruments TAS5086 speaker amplifier" |
578 | depends on I2C | 599 | depends on I2C |
579 | 600 | ||
601 | config SND_SOC_TFA9879 | ||
602 | tristate "NXP Semiconductors TFA9879 amplifier" | ||
603 | depends on I2C | ||
604 | |||
580 | config SND_SOC_TLV320AIC23 | 605 | config SND_SOC_TLV320AIC23 |
581 | tristate | 606 | tristate |
582 | 607 | ||
583 | config SND_SOC_TLV320AIC23_I2C | 608 | config SND_SOC_TLV320AIC23_I2C |
584 | tristate | 609 | tristate "Texas Instruments TLV320AIC23 audio CODEC - I2C" |
610 | depends on I2C | ||
585 | select SND_SOC_TLV320AIC23 | 611 | select SND_SOC_TLV320AIC23 |
586 | 612 | ||
587 | config SND_SOC_TLV320AIC23_SPI | 613 | config SND_SOC_TLV320AIC23_SPI |
588 | tristate | 614 | tristate "Texas Instruments TLV320AIC23 audio CODEC - SPI" |
615 | depends on SPI_MASTER | ||
589 | select SND_SOC_TLV320AIC23 | 616 | select SND_SOC_TLV320AIC23 |
590 | 617 | ||
591 | config SND_SOC_TLV320AIC26 | 618 | config SND_SOC_TLV320AIC26 |
@@ -607,6 +634,10 @@ config SND_SOC_TLV320AIC3X | |||
607 | config SND_SOC_TLV320DAC33 | 634 | config SND_SOC_TLV320DAC33 |
608 | tristate | 635 | tristate |
609 | 636 | ||
637 | config SND_SOC_TS3A227E | ||
638 | tristate "TI Headset/Mic detect and keypress chip" | ||
639 | depends on I2C | ||
640 | |||
610 | config SND_SOC_TWL4030 | 641 | config SND_SOC_TWL4030 |
611 | select MFD_TWL4030_AUDIO | 642 | select MFD_TWL4030_AUDIO |
612 | tristate | 643 | tristate |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 5dce451661e4..bbdfd1e1c182 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -41,6 +41,8 @@ snd-soc-cs42l73-objs := cs42l73.o | |||
41 | snd-soc-cs4265-objs := cs4265.o | 41 | snd-soc-cs4265-objs := cs4265.o |
42 | snd-soc-cs4270-objs := cs4270.o | 42 | snd-soc-cs4270-objs := cs4270.o |
43 | snd-soc-cs4271-objs := cs4271.o | 43 | snd-soc-cs4271-objs := cs4271.o |
44 | snd-soc-cs4271-i2c-objs := cs4271-i2c.o | ||
45 | snd-soc-cs4271-spi-objs := cs4271-spi.o | ||
44 | snd-soc-cs42xx8-objs := cs42xx8.o | 46 | snd-soc-cs42xx8-objs := cs42xx8.o |
45 | snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o | 47 | snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o |
46 | snd-soc-cx20442-objs := cx20442.o | 48 | snd-soc-cx20442-objs := cx20442.o |
@@ -80,6 +82,7 @@ snd-soc-rt5645-objs := rt5645.o | |||
80 | snd-soc-rt5651-objs := rt5651.o | 82 | snd-soc-rt5651-objs := rt5651.o |
81 | snd-soc-rt5670-objs := rt5670.o | 83 | snd-soc-rt5670-objs := rt5670.o |
82 | snd-soc-rt5677-objs := rt5677.o | 84 | snd-soc-rt5677-objs := rt5677.o |
85 | snd-soc-rt5677-spi-objs := rt5677-spi.o | ||
83 | snd-soc-sgtl5000-objs := sgtl5000.o | 86 | snd-soc-sgtl5000-objs := sgtl5000.o |
84 | snd-soc-alc5623-objs := alc5623.o | 87 | snd-soc-alc5623-objs := alc5623.o |
85 | snd-soc-alc5632-objs := alc5632.o | 88 | snd-soc-alc5632-objs := alc5632.o |
@@ -101,6 +104,7 @@ snd-soc-sta350-objs := sta350.o | |||
101 | snd-soc-sta529-objs := sta529.o | 104 | snd-soc-sta529-objs := sta529.o |
102 | snd-soc-stac9766-objs := stac9766.o | 105 | snd-soc-stac9766-objs := stac9766.o |
103 | snd-soc-tas5086-objs := tas5086.o | 106 | snd-soc-tas5086-objs := tas5086.o |
107 | snd-soc-tfa9879-objs := tfa9879.o | ||
104 | snd-soc-tlv320aic23-objs := tlv320aic23.o | 108 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
105 | snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o | 109 | snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o |
106 | snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o | 110 | snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o |
@@ -109,6 +113,7 @@ snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o | |||
109 | snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o | 113 | snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o |
110 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o | 114 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o |
111 | snd-soc-tlv320dac33-objs := tlv320dac33.o | 115 | snd-soc-tlv320dac33-objs := tlv320dac33.o |
116 | snd-soc-ts3a227e-objs := ts3a227e.o | ||
112 | snd-soc-twl4030-objs := twl4030.o | 117 | snd-soc-twl4030-objs := twl4030.o |
113 | snd-soc-twl6040-objs := twl6040.o | 118 | snd-soc-twl6040-objs := twl6040.o |
114 | snd-soc-uda134x-objs := uda134x.o | 119 | snd-soc-uda134x-objs := uda134x.o |
@@ -217,6 +222,8 @@ obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o | |||
217 | obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o | 222 | obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o |
218 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | 223 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o |
219 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o | 224 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o |
225 | obj-$(CONFIG_SND_SOC_CS4271_I2C) += snd-soc-cs4271-i2c.o | ||
226 | obj-$(CONFIG_SND_SOC_CS4271_SPI) += snd-soc-cs4271-spi.o | ||
220 | obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o | 227 | obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o |
221 | obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o | 228 | obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o |
222 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 229 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
@@ -256,6 +263,7 @@ obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o | |||
256 | obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o | 263 | obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o |
257 | obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o | 264 | obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o |
258 | obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o | 265 | obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o |
266 | obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o | ||
259 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | 267 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
260 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o | 268 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o |
261 | obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o | 269 | obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o |
@@ -274,6 +282,7 @@ obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | |||
274 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | 282 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
275 | obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o | 283 | obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o |
276 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o | 284 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o |
285 | obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o | ||
277 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 286 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
278 | obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o | 287 | obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o |
279 | obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o | 288 | obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o |
@@ -282,6 +291,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC31XX) += snd-soc-tlv320aic31xx.o | |||
282 | obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o | 291 | obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o |
283 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o | 292 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o |
284 | obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o | 293 | obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o |
294 | obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o | ||
285 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o | 295 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o |
286 | obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o | 296 | obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o |
287 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o | 297 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index fd43827bb856..7dfbc9921e91 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c | |||
@@ -126,13 +126,13 @@ struct ab8500_codec_drvdata_dbg { | |||
126 | /* Private data for AB8500 device-driver */ | 126 | /* Private data for AB8500 device-driver */ |
127 | struct ab8500_codec_drvdata { | 127 | struct ab8500_codec_drvdata { |
128 | struct regmap *regmap; | 128 | struct regmap *regmap; |
129 | struct mutex ctrl_lock; | ||
129 | 130 | ||
130 | /* Sidetone */ | 131 | /* Sidetone */ |
131 | long *sid_fir_values; | 132 | long *sid_fir_values; |
132 | enum sid_state sid_status; | 133 | enum sid_state sid_status; |
133 | 134 | ||
134 | /* ANC */ | 135 | /* ANC */ |
135 | struct mutex anc_lock; | ||
136 | long *anc_fir_values; | 136 | long *anc_fir_values; |
137 | long *anc_iir_values; | 137 | long *anc_iir_values; |
138 | enum anc_state anc_status; | 138 | enum anc_state anc_status; |
@@ -1129,9 +1129,9 @@ static int sid_status_control_get(struct snd_kcontrol *kcontrol, | |||
1129 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 1129 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
1130 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | 1130 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); |
1131 | 1131 | ||
1132 | mutex_lock(&codec->mutex); | 1132 | mutex_lock(&drvdata->ctrl_lock); |
1133 | ucontrol->value.integer.value[0] = drvdata->sid_status; | 1133 | ucontrol->value.integer.value[0] = drvdata->sid_status; |
1134 | mutex_unlock(&codec->mutex); | 1134 | mutex_unlock(&drvdata->ctrl_lock); |
1135 | 1135 | ||
1136 | return 0; | 1136 | return 0; |
1137 | } | 1137 | } |
@@ -1154,7 +1154,7 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol, | |||
1154 | return -EIO; | 1154 | return -EIO; |
1155 | } | 1155 | } |
1156 | 1156 | ||
1157 | mutex_lock(&codec->mutex); | 1157 | mutex_lock(&drvdata->ctrl_lock); |
1158 | 1158 | ||
1159 | sidconf = snd_soc_read(codec, AB8500_SIDFIRCONF); | 1159 | sidconf = snd_soc_read(codec, AB8500_SIDFIRCONF); |
1160 | if (((sidconf & BIT(AB8500_SIDFIRCONF_FIRSIDBUSY)) != 0)) { | 1160 | if (((sidconf & BIT(AB8500_SIDFIRCONF_FIRSIDBUSY)) != 0)) { |
@@ -1185,7 +1185,7 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol, | |||
1185 | drvdata->sid_status = SID_FIR_CONFIGURED; | 1185 | drvdata->sid_status = SID_FIR_CONFIGURED; |
1186 | 1186 | ||
1187 | out: | 1187 | out: |
1188 | mutex_unlock(&codec->mutex); | 1188 | mutex_unlock(&drvdata->ctrl_lock); |
1189 | 1189 | ||
1190 | dev_dbg(codec->dev, "%s: Exit\n", __func__); | 1190 | dev_dbg(codec->dev, "%s: Exit\n", __func__); |
1191 | 1191 | ||
@@ -1198,9 +1198,9 @@ static int anc_status_control_get(struct snd_kcontrol *kcontrol, | |||
1198 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 1198 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
1199 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | 1199 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); |
1200 | 1200 | ||
1201 | mutex_lock(&codec->mutex); | 1201 | mutex_lock(&drvdata->ctrl_lock); |
1202 | ucontrol->value.integer.value[0] = drvdata->anc_status; | 1202 | ucontrol->value.integer.value[0] = drvdata->anc_status; |
1203 | mutex_unlock(&codec->mutex); | 1203 | mutex_unlock(&drvdata->ctrl_lock); |
1204 | 1204 | ||
1205 | return 0; | 1205 | return 0; |
1206 | } | 1206 | } |
@@ -1217,7 +1217,7 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, | |||
1217 | 1217 | ||
1218 | dev_dbg(dev, "%s: Enter.\n", __func__); | 1218 | dev_dbg(dev, "%s: Enter.\n", __func__); |
1219 | 1219 | ||
1220 | mutex_lock(&drvdata->anc_lock); | 1220 | mutex_lock(&drvdata->ctrl_lock); |
1221 | 1221 | ||
1222 | req = ucontrol->value.integer.value[0]; | 1222 | req = ucontrol->value.integer.value[0]; |
1223 | if (req >= ARRAY_SIZE(enum_anc_state)) { | 1223 | if (req >= ARRAY_SIZE(enum_anc_state)) { |
@@ -1244,9 +1244,7 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, | |||
1244 | } | 1244 | } |
1245 | snd_soc_dapm_sync(&codec->dapm); | 1245 | snd_soc_dapm_sync(&codec->dapm); |
1246 | 1246 | ||
1247 | mutex_lock(&codec->mutex); | ||
1248 | anc_configure(codec, apply_fir, apply_iir); | 1247 | anc_configure(codec, apply_fir, apply_iir); |
1249 | mutex_unlock(&codec->mutex); | ||
1250 | 1248 | ||
1251 | if (apply_fir) { | 1249 | if (apply_fir) { |
1252 | if (drvdata->anc_status == ANC_IIR_CONFIGURED) | 1250 | if (drvdata->anc_status == ANC_IIR_CONFIGURED) |
@@ -1265,7 +1263,7 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, | |||
1265 | snd_soc_dapm_sync(&codec->dapm); | 1263 | snd_soc_dapm_sync(&codec->dapm); |
1266 | 1264 | ||
1267 | cleanup: | 1265 | cleanup: |
1268 | mutex_unlock(&drvdata->anc_lock); | 1266 | mutex_unlock(&drvdata->ctrl_lock); |
1269 | 1267 | ||
1270 | if (status < 0) | 1268 | if (status < 0) |
1271 | dev_err(dev, "%s: Unable to configure ANC! (status = %d)\n", | 1269 | dev_err(dev, "%s: Unable to configure ANC! (status = %d)\n", |
@@ -1294,14 +1292,15 @@ static int filter_control_get(struct snd_kcontrol *kcontrol, | |||
1294 | struct snd_ctl_elem_value *ucontrol) | 1292 | struct snd_ctl_elem_value *ucontrol) |
1295 | { | 1293 | { |
1296 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 1294 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
1295 | struct ab8500_codec_drvdata *drvdata = snd_soc_codec_get_drvdata(codec); | ||
1297 | struct filter_control *fc = | 1296 | struct filter_control *fc = |
1298 | (struct filter_control *)kcontrol->private_value; | 1297 | (struct filter_control *)kcontrol->private_value; |
1299 | unsigned int i; | 1298 | unsigned int i; |
1300 | 1299 | ||
1301 | mutex_lock(&codec->mutex); | 1300 | mutex_lock(&drvdata->ctrl_lock); |
1302 | for (i = 0; i < fc->count; i++) | 1301 | for (i = 0; i < fc->count; i++) |
1303 | ucontrol->value.integer.value[i] = fc->value[i]; | 1302 | ucontrol->value.integer.value[i] = fc->value[i]; |
1304 | mutex_unlock(&codec->mutex); | 1303 | mutex_unlock(&drvdata->ctrl_lock); |
1305 | 1304 | ||
1306 | return 0; | 1305 | return 0; |
1307 | } | 1306 | } |
@@ -1310,14 +1309,15 @@ static int filter_control_put(struct snd_kcontrol *kcontrol, | |||
1310 | struct snd_ctl_elem_value *ucontrol) | 1309 | struct snd_ctl_elem_value *ucontrol) |
1311 | { | 1310 | { |
1312 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 1311 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
1312 | struct ab8500_codec_drvdata *drvdata = snd_soc_codec_get_drvdata(codec); | ||
1313 | struct filter_control *fc = | 1313 | struct filter_control *fc = |
1314 | (struct filter_control *)kcontrol->private_value; | 1314 | (struct filter_control *)kcontrol->private_value; |
1315 | unsigned int i; | 1315 | unsigned int i; |
1316 | 1316 | ||
1317 | mutex_lock(&codec->mutex); | 1317 | mutex_lock(&drvdata->ctrl_lock); |
1318 | for (i = 0; i < fc->count; i++) | 1318 | for (i = 0; i < fc->count; i++) |
1319 | fc->value[i] = ucontrol->value.integer.value[i]; | 1319 | fc->value[i] = ucontrol->value.integer.value[i]; |
1320 | mutex_unlock(&codec->mutex); | 1320 | mutex_unlock(&drvdata->ctrl_lock); |
1321 | 1321 | ||
1322 | return 0; | 1322 | return 0; |
1323 | } | 1323 | } |
@@ -2545,7 +2545,7 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) | |||
2545 | 2545 | ||
2546 | (void)snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); | 2546 | (void)snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); |
2547 | 2547 | ||
2548 | mutex_init(&drvdata->anc_lock); | 2548 | mutex_init(&drvdata->ctrl_lock); |
2549 | 2549 | ||
2550 | return status; | 2550 | return status; |
2551 | } | 2551 | } |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index bd9b1839c8b0..c6e5a313ebf4 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -37,10 +37,11 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
37 | struct snd_soc_dai *dai) | 37 | struct snd_soc_dai *dai) |
38 | { | 38 | { |
39 | struct snd_soc_codec *codec = dai->codec; | 39 | struct snd_soc_codec *codec = dai->codec; |
40 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
40 | 41 | ||
41 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 42 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
42 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; | 43 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; |
43 | return snd_ac97_set_rate(codec->ac97, reg, substream->runtime->rate); | 44 | return snd_ac97_set_rate(ac97, reg, substream->runtime->rate); |
44 | } | 45 | } |
45 | 46 | ||
46 | #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | 47 | #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |
@@ -53,7 +54,6 @@ static const struct snd_soc_dai_ops ac97_dai_ops = { | |||
53 | 54 | ||
54 | static struct snd_soc_dai_driver ac97_dai = { | 55 | static struct snd_soc_dai_driver ac97_dai = { |
55 | .name = "ac97-hifi", | 56 | .name = "ac97-hifi", |
56 | .ac97_control = 1, | ||
57 | .playback = { | 57 | .playback = { |
58 | .stream_name = "AC97 Playback", | 58 | .stream_name = "AC97 Playback", |
59 | .channels_min = 1, | 59 | .channels_min = 1, |
@@ -71,6 +71,7 @@ static struct snd_soc_dai_driver ac97_dai = { | |||
71 | 71 | ||
72 | static int ac97_soc_probe(struct snd_soc_codec *codec) | 72 | static int ac97_soc_probe(struct snd_soc_codec *codec) |
73 | { | 73 | { |
74 | struct snd_ac97 *ac97; | ||
74 | struct snd_ac97_bus *ac97_bus; | 75 | struct snd_ac97_bus *ac97_bus; |
75 | struct snd_ac97_template ac97_template; | 76 | struct snd_ac97_template ac97_template; |
76 | int ret; | 77 | int ret; |
@@ -82,24 +83,31 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) | |||
82 | return ret; | 83 | return ret; |
83 | 84 | ||
84 | memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); | 85 | memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); |
85 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); | 86 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97); |
86 | if (ret < 0) | 87 | if (ret < 0) |
87 | return ret; | 88 | return ret; |
88 | 89 | ||
90 | snd_soc_codec_set_drvdata(codec, ac97); | ||
91 | |||
89 | return 0; | 92 | return 0; |
90 | } | 93 | } |
91 | 94 | ||
92 | #ifdef CONFIG_PM | 95 | #ifdef CONFIG_PM |
93 | static int ac97_soc_suspend(struct snd_soc_codec *codec) | 96 | static int ac97_soc_suspend(struct snd_soc_codec *codec) |
94 | { | 97 | { |
95 | snd_ac97_suspend(codec->ac97); | 98 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
99 | |||
100 | snd_ac97_suspend(ac97); | ||
96 | 101 | ||
97 | return 0; | 102 | return 0; |
98 | } | 103 | } |
99 | 104 | ||
100 | static int ac97_soc_resume(struct snd_soc_codec *codec) | 105 | static int ac97_soc_resume(struct snd_soc_codec *codec) |
101 | { | 106 | { |
102 | snd_ac97_resume(codec->ac97); | 107 | |
108 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
109 | |||
110 | snd_ac97_resume(ac97); | ||
103 | 111 | ||
104 | return 0; | 112 | return 0; |
105 | } | 113 | } |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 6844d0b2af68..387530b0b0fd 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -72,11 +72,13 @@ static const struct snd_kcontrol_new ad193x_snd_controls[] = { | |||
72 | }; | 72 | }; |
73 | 73 | ||
74 | static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { | 74 | static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { |
75 | SND_SOC_DAPM_DAC("DAC", "Playback", AD193X_DAC_CTRL0, 0, 1), | 75 | SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), |
76 | SND_SOC_DAPM_PGA("DAC Output", AD193X_DAC_CTRL0, 0, 1, NULL, 0), | ||
76 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), | 77 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), |
77 | SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), | 78 | SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), |
78 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), | 79 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), |
79 | SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0), | 80 | SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0), |
81 | SND_SOC_DAPM_VMID("VMID"), | ||
80 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), | 82 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), |
81 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), | 83 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), |
82 | SND_SOC_DAPM_OUTPUT("DAC3OUT"), | 84 | SND_SOC_DAPM_OUTPUT("DAC3OUT"), |
@@ -87,13 +89,15 @@ static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { | |||
87 | 89 | ||
88 | static const struct snd_soc_dapm_route audio_paths[] = { | 90 | static const struct snd_soc_dapm_route audio_paths[] = { |
89 | { "DAC", NULL, "SYSCLK" }, | 91 | { "DAC", NULL, "SYSCLK" }, |
92 | { "DAC Output", NULL, "DAC" }, | ||
93 | { "DAC Output", NULL, "VMID" }, | ||
90 | { "ADC", NULL, "SYSCLK" }, | 94 | { "ADC", NULL, "SYSCLK" }, |
91 | { "DAC", NULL, "ADC_PWR" }, | 95 | { "DAC", NULL, "ADC_PWR" }, |
92 | { "ADC", NULL, "ADC_PWR" }, | 96 | { "ADC", NULL, "ADC_PWR" }, |
93 | { "DAC1OUT", NULL, "DAC" }, | 97 | { "DAC1OUT", NULL, "DAC Output" }, |
94 | { "DAC2OUT", NULL, "DAC" }, | 98 | { "DAC2OUT", NULL, "DAC Output" }, |
95 | { "DAC3OUT", NULL, "DAC" }, | 99 | { "DAC3OUT", NULL, "DAC Output" }, |
96 | { "DAC4OUT", NULL, "DAC" }, | 100 | { "DAC4OUT", NULL, "DAC Output" }, |
97 | { "ADC", NULL, "ADC1IN" }, | 101 | { "ADC", NULL, "ADC1IN" }, |
98 | { "ADC", NULL, "ADC2IN" }, | 102 | { "ADC", NULL, "ADC2IN" }, |
99 | { "SYSCLK", NULL, "PLL_PWR" }, | 103 | { "SYSCLK", NULL, "PLL_PWR" }, |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 304d3003339a..2860eef8610c 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -24,34 +24,86 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include <linux/regmap.h> | ||
27 | #include <sound/core.h> | 28 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 29 | #include <sound/pcm.h> |
29 | #include <sound/ac97_codec.h> | 30 | #include <sound/ac97_codec.h> |
30 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
31 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
32 | 33 | ||
33 | #include "ad1980.h" | 34 | static const struct reg_default ad1980_reg_defaults[] = { |
35 | { 0x02, 0x8000 }, | ||
36 | { 0x04, 0x8000 }, | ||
37 | { 0x06, 0x8000 }, | ||
38 | { 0x0c, 0x8008 }, | ||
39 | { 0x0e, 0x8008 }, | ||
40 | { 0x10, 0x8808 }, | ||
41 | { 0x12, 0x8808 }, | ||
42 | { 0x16, 0x8808 }, | ||
43 | { 0x18, 0x8808 }, | ||
44 | { 0x1a, 0x0000 }, | ||
45 | { 0x1c, 0x8000 }, | ||
46 | { 0x20, 0x0000 }, | ||
47 | { 0x28, 0x03c7 }, | ||
48 | { 0x2c, 0xbb80 }, | ||
49 | { 0x2e, 0xbb80 }, | ||
50 | { 0x30, 0xbb80 }, | ||
51 | { 0x32, 0xbb80 }, | ||
52 | { 0x36, 0x8080 }, | ||
53 | { 0x38, 0x8080 }, | ||
54 | { 0x3a, 0x2000 }, | ||
55 | { 0x60, 0x0000 }, | ||
56 | { 0x62, 0x0000 }, | ||
57 | { 0x72, 0x0000 }, | ||
58 | { 0x74, 0x1001 }, | ||
59 | { 0x76, 0x0000 }, | ||
60 | }; | ||
34 | 61 | ||
35 | /* | 62 | static bool ad1980_readable_reg(struct device *dev, unsigned int reg) |
36 | * AD1980 register cache | 63 | { |
37 | */ | 64 | switch (reg) { |
38 | static const u16 ad1980_reg[] = { | 65 | case AC97_RESET ... AC97_MASTER_MONO: |
39 | 0x0090, 0x8000, 0x8000, 0x8000, /* 0 - 6 */ | 66 | case AC97_PHONE ... AC97_CD: |
40 | 0x0000, 0x0000, 0x8008, 0x8008, /* 8 - e */ | 67 | case AC97_AUX ... AC97_GENERAL_PURPOSE: |
41 | 0x8808, 0x8808, 0x0000, 0x8808, /* 10 - 16 */ | 68 | case AC97_POWERDOWN ... AC97_PCM_LR_ADC_RATE: |
42 | 0x8808, 0x0000, 0x8000, 0x0000, /* 18 - 1e */ | 69 | case AC97_SPDIF: |
43 | 0x0000, 0x0000, 0x0000, 0x0000, /* 20 - 26 */ | 70 | case AC97_CODEC_CLASS_REV: |
44 | 0x03c7, 0x0000, 0xbb80, 0xbb80, /* 28 - 2e */ | 71 | case AC97_PCI_SVID: |
45 | 0xbb80, 0xbb80, 0x0000, 0x8080, /* 30 - 36 */ | 72 | case AC97_AD_CODEC_CFG: |
46 | 0x8080, 0x2000, 0x0000, 0x0000, /* 38 - 3e */ | 73 | case AC97_AD_JACK_SPDIF: |
47 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 74 | case AC97_AD_SERIAL_CFG: |
48 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 75 | case AC97_VENDOR_ID1: |
49 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 76 | case AC97_VENDOR_ID2: |
50 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 77 | return true; |
51 | 0x8080, 0x0000, 0x0000, 0x0000, /* 60 - 66 */ | 78 | default: |
52 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 79 | return false; |
53 | 0x0000, 0x0000, 0x1001, 0x0000, /* 70 - 76 */ | 80 | } |
54 | 0x0000, 0x0000, 0x4144, 0x5370 /* 78 - 7e */ | 81 | } |
82 | |||
83 | static bool ad1980_writeable_reg(struct device *dev, unsigned int reg) | ||
84 | { | ||
85 | switch (reg) { | ||
86 | case AC97_VENDOR_ID1: | ||
87 | case AC97_VENDOR_ID2: | ||
88 | return false; | ||
89 | default: | ||
90 | return ad1980_readable_reg(dev, reg); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | static const struct regmap_config ad1980_regmap_config = { | ||
95 | .reg_bits = 16, | ||
96 | .reg_stride = 2, | ||
97 | .val_bits = 16, | ||
98 | .max_register = 0x7e, | ||
99 | .cache_type = REGCACHE_RBTREE, | ||
100 | |||
101 | .volatile_reg = regmap_ac97_default_volatile, | ||
102 | .readable_reg = ad1980_readable_reg, | ||
103 | .writeable_reg = ad1980_writeable_reg, | ||
104 | |||
105 | .reg_defaults = ad1980_reg_defaults, | ||
106 | .num_reg_defaults = ARRAY_SIZE(ad1980_reg_defaults), | ||
55 | }; | 107 | }; |
56 | 108 | ||
57 | static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line", | 109 | static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line", |
@@ -134,45 +186,8 @@ static const struct snd_soc_dapm_route ad1980_dapm_routes[] = { | |||
134 | { "HP_OUT_R", NULL, "Playback" }, | 186 | { "HP_OUT_R", NULL, "Playback" }, |
135 | }; | 187 | }; |
136 | 188 | ||
137 | static unsigned int ac97_read(struct snd_soc_codec *codec, | ||
138 | unsigned int reg) | ||
139 | { | ||
140 | u16 *cache = codec->reg_cache; | ||
141 | |||
142 | switch (reg) { | ||
143 | case AC97_RESET: | ||
144 | case AC97_INT_PAGING: | ||
145 | case AC97_POWERDOWN: | ||
146 | case AC97_EXTENDED_STATUS: | ||
147 | case AC97_VENDOR_ID1: | ||
148 | case AC97_VENDOR_ID2: | ||
149 | return soc_ac97_ops->read(codec->ac97, reg); | ||
150 | default: | ||
151 | reg = reg >> 1; | ||
152 | |||
153 | if (reg >= ARRAY_SIZE(ad1980_reg)) | ||
154 | return -EINVAL; | ||
155 | |||
156 | return cache[reg]; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | ||
161 | unsigned int val) | ||
162 | { | ||
163 | u16 *cache = codec->reg_cache; | ||
164 | |||
165 | soc_ac97_ops->write(codec->ac97, reg, val); | ||
166 | reg = reg >> 1; | ||
167 | if (reg < ARRAY_SIZE(ad1980_reg)) | ||
168 | cache[reg] = val; | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static struct snd_soc_dai_driver ad1980_dai = { | 189 | static struct snd_soc_dai_driver ad1980_dai = { |
174 | .name = "ad1980-hifi", | 190 | .name = "ad1980-hifi", |
175 | .ac97_control = 1, | ||
176 | .playback = { | 191 | .playback = { |
177 | .stream_name = "Playback", | 192 | .stream_name = "Playback", |
178 | .channels_min = 2, | 193 | .channels_min = 2, |
@@ -189,108 +204,115 @@ static struct snd_soc_dai_driver ad1980_dai = { | |||
189 | 204 | ||
190 | static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) | 205 | static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) |
191 | { | 206 | { |
207 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
192 | unsigned int retry_cnt = 0; | 208 | unsigned int retry_cnt = 0; |
193 | 209 | ||
194 | do { | 210 | do { |
195 | if (try_warm && soc_ac97_ops->warm_reset) { | 211 | if (try_warm && soc_ac97_ops->warm_reset) { |
196 | soc_ac97_ops->warm_reset(codec->ac97); | 212 | soc_ac97_ops->warm_reset(ac97); |
197 | if (ac97_read(codec, AC97_RESET) == 0x0090) | 213 | if (snd_soc_read(codec, AC97_RESET) == 0x0090) |
198 | return 1; | 214 | return 1; |
199 | } | 215 | } |
200 | 216 | ||
201 | soc_ac97_ops->reset(codec->ac97); | 217 | soc_ac97_ops->reset(ac97); |
202 | /* | 218 | /* |
203 | * Set bit 16slot in register 74h, then every slot will has only | 219 | * Set bit 16slot in register 74h, then every slot will has only |
204 | * 16 bits. This command is sent out in 20bit mode, in which | 220 | * 16 bits. This command is sent out in 20bit mode, in which |
205 | * case the first nibble of data is eaten by the addr. (Tag is | 221 | * case the first nibble of data is eaten by the addr. (Tag is |
206 | * always 16 bit) | 222 | * always 16 bit) |
207 | */ | 223 | */ |
208 | ac97_write(codec, AC97_AD_SERIAL_CFG, 0x9900); | 224 | snd_soc_write(codec, AC97_AD_SERIAL_CFG, 0x9900); |
209 | 225 | ||
210 | if (ac97_read(codec, AC97_RESET) == 0x0090) | 226 | if (snd_soc_read(codec, AC97_RESET) == 0x0090) |
211 | return 0; | 227 | return 0; |
212 | } while (retry_cnt++ < 10); | 228 | } while (retry_cnt++ < 10); |
213 | 229 | ||
214 | printk(KERN_ERR "AD1980 AC97 reset failed\n"); | 230 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); |
231 | |||
215 | return -EIO; | 232 | return -EIO; |
216 | } | 233 | } |
217 | 234 | ||
218 | static int ad1980_soc_probe(struct snd_soc_codec *codec) | 235 | static int ad1980_soc_probe(struct snd_soc_codec *codec) |
219 | { | 236 | { |
237 | struct snd_ac97 *ac97; | ||
238 | struct regmap *regmap; | ||
220 | int ret; | 239 | int ret; |
221 | u16 vendor_id2; | 240 | u16 vendor_id2; |
222 | u16 ext_status; | 241 | u16 ext_status; |
223 | 242 | ||
224 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 243 | ac97 = snd_soc_new_ac97_codec(codec); |
225 | 244 | if (IS_ERR(ac97)) { | |
226 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 245 | ret = PTR_ERR(ac97); |
227 | if (ret < 0) { | 246 | dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); |
228 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); | ||
229 | return ret; | 247 | return ret; |
230 | } | 248 | } |
231 | 249 | ||
250 | regmap = regmap_init_ac97(ac97, &ad1980_regmap_config); | ||
251 | if (IS_ERR(regmap)) { | ||
252 | ret = PTR_ERR(regmap); | ||
253 | goto err_free_ac97; | ||
254 | } | ||
255 | |||
256 | snd_soc_codec_init_regmap(codec, regmap); | ||
257 | snd_soc_codec_set_drvdata(codec, ac97); | ||
258 | |||
232 | ret = ad1980_reset(codec, 0); | 259 | ret = ad1980_reset(codec, 0); |
233 | if (ret < 0) { | 260 | if (ret < 0) |
234 | printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); | ||
235 | goto reset_err; | 261 | goto reset_err; |
236 | } | ||
237 | 262 | ||
238 | /* Read out vendor ID to make sure it is ad1980 */ | 263 | /* Read out vendor ID to make sure it is ad1980 */ |
239 | if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) { | 264 | if (snd_soc_read(codec, AC97_VENDOR_ID1) != 0x4144) { |
240 | ret = -ENODEV; | 265 | ret = -ENODEV; |
241 | goto reset_err; | 266 | goto reset_err; |
242 | } | 267 | } |
243 | 268 | ||
244 | vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2); | 269 | vendor_id2 = snd_soc_read(codec, AC97_VENDOR_ID2); |
245 | 270 | ||
246 | if (vendor_id2 != 0x5370) { | 271 | if (vendor_id2 != 0x5370) { |
247 | if (vendor_id2 != 0x5374) { | 272 | if (vendor_id2 != 0x5374) { |
248 | ret = -ENODEV; | 273 | ret = -ENODEV; |
249 | goto reset_err; | 274 | goto reset_err; |
250 | } else { | 275 | } else { |
251 | printk(KERN_WARNING "ad1980: " | 276 | dev_warn(codec->dev, |
252 | "Found AD1981 - only 2/2 IN/OUT Channels " | 277 | "Found AD1981 - only 2/2 IN/OUT Channels supported\n"); |
253 | "supported\n"); | ||
254 | } | 278 | } |
255 | } | 279 | } |
256 | 280 | ||
257 | /* unmute captures and playbacks volume */ | 281 | /* unmute captures and playbacks volume */ |
258 | ac97_write(codec, AC97_MASTER, 0x0000); | 282 | snd_soc_write(codec, AC97_MASTER, 0x0000); |
259 | ac97_write(codec, AC97_PCM, 0x0000); | 283 | snd_soc_write(codec, AC97_PCM, 0x0000); |
260 | ac97_write(codec, AC97_REC_GAIN, 0x0000); | 284 | snd_soc_write(codec, AC97_REC_GAIN, 0x0000); |
261 | ac97_write(codec, AC97_CENTER_LFE_MASTER, 0x0000); | 285 | snd_soc_write(codec, AC97_CENTER_LFE_MASTER, 0x0000); |
262 | ac97_write(codec, AC97_SURROUND_MASTER, 0x0000); | 286 | snd_soc_write(codec, AC97_SURROUND_MASTER, 0x0000); |
263 | 287 | ||
264 | /*power on LFE/CENTER/Surround DACs*/ | 288 | /*power on LFE/CENTER/Surround DACs*/ |
265 | ext_status = ac97_read(codec, AC97_EXTENDED_STATUS); | 289 | ext_status = snd_soc_read(codec, AC97_EXTENDED_STATUS); |
266 | ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); | 290 | snd_soc_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); |
267 | |||
268 | snd_soc_add_codec_controls(codec, ad1980_snd_ac97_controls, | ||
269 | ARRAY_SIZE(ad1980_snd_ac97_controls)); | ||
270 | 291 | ||
271 | return 0; | 292 | return 0; |
272 | 293 | ||
273 | reset_err: | 294 | reset_err: |
274 | snd_soc_free_ac97_codec(codec); | 295 | snd_soc_codec_exit_regmap(codec); |
296 | err_free_ac97: | ||
297 | snd_soc_free_ac97_codec(ac97); | ||
275 | return ret; | 298 | return ret; |
276 | } | 299 | } |
277 | 300 | ||
278 | static int ad1980_soc_remove(struct snd_soc_codec *codec) | 301 | static int ad1980_soc_remove(struct snd_soc_codec *codec) |
279 | { | 302 | { |
280 | snd_soc_free_ac97_codec(codec); | 303 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
304 | |||
305 | snd_soc_codec_exit_regmap(codec); | ||
306 | snd_soc_free_ac97_codec(ac97); | ||
281 | return 0; | 307 | return 0; |
282 | } | 308 | } |
283 | 309 | ||
284 | static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { | 310 | static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { |
285 | .probe = ad1980_soc_probe, | 311 | .probe = ad1980_soc_probe, |
286 | .remove = ad1980_soc_remove, | 312 | .remove = ad1980_soc_remove, |
287 | .reg_cache_size = ARRAY_SIZE(ad1980_reg), | ||
288 | .reg_word_size = sizeof(u16), | ||
289 | .reg_cache_default = ad1980_reg, | ||
290 | .reg_cache_step = 2, | ||
291 | .write = ac97_write, | ||
292 | .read = ac97_read, | ||
293 | 313 | ||
314 | .controls = ad1980_snd_ac97_controls, | ||
315 | .num_controls = ARRAY_SIZE(ad1980_snd_ac97_controls), | ||
294 | .dapm_widgets = ad1980_dapm_widgets, | 316 | .dapm_widgets = ad1980_dapm_widgets, |
295 | .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets), | 317 | .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets), |
296 | .dapm_routes = ad1980_dapm_routes, | 318 | .dapm_routes = ad1980_dapm_routes, |
diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h deleted file mode 100644 index eb0af44ad3df..000000000000 --- a/sound/soc/codecs/ad1980.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * ad1980.h -- ad1980 Soc Audio driver | ||
3 | * | ||
4 | * WARNING: | ||
5 | * | ||
6 | * Because Analog Devices Inc. discontinued the ad1980 sound chip since | ||
7 | * Sep. 2009, this ad1980 driver is not maintained, tested and supported | ||
8 | * by ADI now. | ||
9 | */ | ||
10 | |||
11 | #ifndef _AD1980_H | ||
12 | #define _AD1980_H | ||
13 | /* Bit definition of Power-Down Control/Status Register */ | ||
14 | #define ADC 0x0001 | ||
15 | #define DAC 0x0002 | ||
16 | #define ANL 0x0004 | ||
17 | #define REF 0x0008 | ||
18 | #define PR0 0x0100 | ||
19 | #define PR1 0x0200 | ||
20 | #define PR2 0x0400 | ||
21 | #define PR3 0x0800 | ||
22 | #define PR4 0x1000 | ||
23 | #define PR5 0x2000 | ||
24 | #define PR6 0x4000 | ||
25 | |||
26 | #endif | ||
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 7c784ad3e8b2..783dcb57043a 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -551,7 +551,7 @@ static const struct snd_kcontrol_new adau1373_drc_controls[] = { | |||
551 | static int adau1373_pll_event(struct snd_soc_dapm_widget *w, | 551 | static int adau1373_pll_event(struct snd_soc_dapm_widget *w, |
552 | struct snd_kcontrol *kcontrol, int event) | 552 | struct snd_kcontrol *kcontrol, int event) |
553 | { | 553 | { |
554 | struct snd_soc_codec *codec = w->codec; | 554 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
555 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | 555 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); |
556 | unsigned int pll_id = w->name[3] - '1'; | 556 | unsigned int pll_id = w->name[3] - '1'; |
557 | unsigned int val; | 557 | unsigned int val; |
@@ -823,7 +823,7 @@ static const struct snd_soc_dapm_widget adau1373_dapm_widgets[] = { | |||
823 | static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, | 823 | static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, |
824 | struct snd_soc_dapm_widget *sink) | 824 | struct snd_soc_dapm_widget *sink) |
825 | { | 825 | { |
826 | struct snd_soc_codec *codec = source->codec; | 826 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
827 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | 827 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); |
828 | unsigned int dai; | 828 | unsigned int dai; |
829 | const char *clk; | 829 | const char *clk; |
@@ -844,7 +844,7 @@ static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, | |||
844 | static int adau1373_check_src(struct snd_soc_dapm_widget *source, | 844 | static int adau1373_check_src(struct snd_soc_dapm_widget *source, |
845 | struct snd_soc_dapm_widget *sink) | 845 | struct snd_soc_dapm_widget *sink) |
846 | { | 846 | { |
847 | struct snd_soc_codec *codec = source->codec; | 847 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
848 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | 848 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); |
849 | unsigned int dai; | 849 | unsigned int dai; |
850 | 850 | ||
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 370b742117ef..d4e219b6b98f 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
@@ -22,9 +22,14 @@ | |||
22 | #include <sound/pcm_params.h> | 22 | #include <sound/pcm_params.h> |
23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
24 | 24 | ||
25 | #include <asm/unaligned.h> | ||
26 | |||
25 | #include "sigmadsp.h" | 27 | #include "sigmadsp.h" |
26 | #include "adau1701.h" | 28 | #include "adau1701.h" |
27 | 29 | ||
30 | #define ADAU1701_SAFELOAD_DATA(i) (0x0810 + (i)) | ||
31 | #define ADAU1701_SAFELOAD_ADDR(i) (0x0815 + (i)) | ||
32 | |||
28 | #define ADAU1701_DSPCTRL 0x081c | 33 | #define ADAU1701_DSPCTRL 0x081c |
29 | #define ADAU1701_SEROCTL 0x081e | 34 | #define ADAU1701_SEROCTL 0x081e |
30 | #define ADAU1701_SERICTL 0x081f | 35 | #define ADAU1701_SERICTL 0x081f |
@@ -42,6 +47,7 @@ | |||
42 | #define ADAU1701_DSPCTRL_CR (1 << 2) | 47 | #define ADAU1701_DSPCTRL_CR (1 << 2) |
43 | #define ADAU1701_DSPCTRL_DAM (1 << 3) | 48 | #define ADAU1701_DSPCTRL_DAM (1 << 3) |
44 | #define ADAU1701_DSPCTRL_ADM (1 << 4) | 49 | #define ADAU1701_DSPCTRL_ADM (1 << 4) |
50 | #define ADAU1701_DSPCTRL_IST (1 << 5) | ||
45 | #define ADAU1701_DSPCTRL_SR_48 0x00 | 51 | #define ADAU1701_DSPCTRL_SR_48 0x00 |
46 | #define ADAU1701_DSPCTRL_SR_96 0x01 | 52 | #define ADAU1701_DSPCTRL_SR_96 0x01 |
47 | #define ADAU1701_DSPCTRL_SR_192 0x02 | 53 | #define ADAU1701_DSPCTRL_SR_192 0x02 |
@@ -102,7 +108,10 @@ struct adau1701 { | |||
102 | unsigned int pll_clkdiv; | 108 | unsigned int pll_clkdiv; |
103 | unsigned int sysclk; | 109 | unsigned int sysclk; |
104 | struct regmap *regmap; | 110 | struct regmap *regmap; |
111 | struct i2c_client *client; | ||
105 | u8 pin_config[12]; | 112 | u8 pin_config[12]; |
113 | |||
114 | struct sigmadsp *sigmadsp; | ||
106 | }; | 115 | }; |
107 | 116 | ||
108 | static const struct snd_kcontrol_new adau1701_controls[] = { | 117 | static const struct snd_kcontrol_new adau1701_controls[] = { |
@@ -159,6 +168,7 @@ static bool adau1701_volatile_reg(struct device *dev, unsigned int reg) | |||
159 | { | 168 | { |
160 | switch (reg) { | 169 | switch (reg) { |
161 | case ADAU1701_DACSET: | 170 | case ADAU1701_DACSET: |
171 | case ADAU1701_DSPCTRL: | ||
162 | return true; | 172 | return true; |
163 | default: | 173 | default: |
164 | return false; | 174 | return false; |
@@ -238,12 +248,58 @@ static int adau1701_reg_read(void *context, unsigned int reg, | |||
238 | return 0; | 248 | return 0; |
239 | } | 249 | } |
240 | 250 | ||
241 | static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv) | 251 | static int adau1701_safeload(struct sigmadsp *sigmadsp, unsigned int addr, |
252 | const uint8_t bytes[], size_t len) | ||
253 | { | ||
254 | struct i2c_client *client = to_i2c_client(sigmadsp->dev); | ||
255 | struct adau1701 *adau1701 = i2c_get_clientdata(client); | ||
256 | unsigned int val; | ||
257 | unsigned int i; | ||
258 | uint8_t buf[10]; | ||
259 | int ret; | ||
260 | |||
261 | ret = regmap_read(adau1701->regmap, ADAU1701_DSPCTRL, &val); | ||
262 | if (ret) | ||
263 | return ret; | ||
264 | |||
265 | if (val & ADAU1701_DSPCTRL_IST) | ||
266 | msleep(50); | ||
267 | |||
268 | for (i = 0; i < len / 4; i++) { | ||
269 | put_unaligned_le16(ADAU1701_SAFELOAD_DATA(i), buf); | ||
270 | buf[2] = 0x00; | ||
271 | memcpy(buf + 3, bytes + i * 4, 4); | ||
272 | ret = i2c_master_send(client, buf, 7); | ||
273 | if (ret < 0) | ||
274 | return ret; | ||
275 | else if (ret != 7) | ||
276 | return -EIO; | ||
277 | |||
278 | put_unaligned_le16(ADAU1701_SAFELOAD_ADDR(i), buf); | ||
279 | put_unaligned_le16(addr + i, buf + 2); | ||
280 | ret = i2c_master_send(client, buf, 4); | ||
281 | if (ret < 0) | ||
282 | return ret; | ||
283 | else if (ret != 4) | ||
284 | return -EIO; | ||
285 | } | ||
286 | |||
287 | return regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL, | ||
288 | ADAU1701_DSPCTRL_IST, ADAU1701_DSPCTRL_IST); | ||
289 | } | ||
290 | |||
291 | static const struct sigmadsp_ops adau1701_sigmadsp_ops = { | ||
292 | .safeload = adau1701_safeload, | ||
293 | }; | ||
294 | |||
295 | static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv, | ||
296 | unsigned int rate) | ||
242 | { | 297 | { |
243 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | 298 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); |
244 | struct i2c_client *client = to_i2c_client(codec->dev); | ||
245 | int ret; | 299 | int ret; |
246 | 300 | ||
301 | sigmadsp_reset(adau1701->sigmadsp); | ||
302 | |||
247 | if (clkdiv != ADAU1707_CLKDIV_UNSET && | 303 | if (clkdiv != ADAU1707_CLKDIV_UNSET && |
248 | gpio_is_valid(adau1701->gpio_pll_mode[0]) && | 304 | gpio_is_valid(adau1701->gpio_pll_mode[0]) && |
249 | gpio_is_valid(adau1701->gpio_pll_mode[1])) { | 305 | gpio_is_valid(adau1701->gpio_pll_mode[1])) { |
@@ -284,7 +340,7 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv) | |||
284 | * know the correct PLL setup | 340 | * know the correct PLL setup |
285 | */ | 341 | */ |
286 | if (clkdiv != ADAU1707_CLKDIV_UNSET) { | 342 | if (clkdiv != ADAU1707_CLKDIV_UNSET) { |
287 | ret = process_sigma_firmware(client, ADAU1701_FIRMWARE); | 343 | ret = sigmadsp_setup(adau1701->sigmadsp, rate); |
288 | if (ret) { | 344 | if (ret) { |
289 | dev_warn(codec->dev, "Failed to load firmware\n"); | 345 | dev_warn(codec->dev, "Failed to load firmware\n"); |
290 | return ret; | 346 | return ret; |
@@ -385,7 +441,7 @@ static int adau1701_hw_params(struct snd_pcm_substream *substream, | |||
385 | * firmware upload. | 441 | * firmware upload. |
386 | */ | 442 | */ |
387 | if (clkdiv != adau1701->pll_clkdiv) { | 443 | if (clkdiv != adau1701->pll_clkdiv) { |
388 | ret = adau1701_reset(codec, clkdiv); | 444 | ret = adau1701_reset(codec, clkdiv, params_rate(params)); |
389 | if (ret < 0) | 445 | if (ret < 0) |
390 | return ret; | 446 | return ret; |
391 | } | 447 | } |
@@ -554,6 +610,14 @@ static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
554 | return 0; | 610 | return 0; |
555 | } | 611 | } |
556 | 612 | ||
613 | static int adau1701_startup(struct snd_pcm_substream *substream, | ||
614 | struct snd_soc_dai *dai) | ||
615 | { | ||
616 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(dai->codec); | ||
617 | |||
618 | return sigmadsp_restrict_params(adau1701->sigmadsp, substream); | ||
619 | } | ||
620 | |||
557 | #define ADAU1701_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ | 621 | #define ADAU1701_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ |
558 | SNDRV_PCM_RATE_192000) | 622 | SNDRV_PCM_RATE_192000) |
559 | 623 | ||
@@ -564,6 +628,7 @@ static const struct snd_soc_dai_ops adau1701_dai_ops = { | |||
564 | .set_fmt = adau1701_set_dai_fmt, | 628 | .set_fmt = adau1701_set_dai_fmt, |
565 | .hw_params = adau1701_hw_params, | 629 | .hw_params = adau1701_hw_params, |
566 | .digital_mute = adau1701_digital_mute, | 630 | .digital_mute = adau1701_digital_mute, |
631 | .startup = adau1701_startup, | ||
567 | }; | 632 | }; |
568 | 633 | ||
569 | static struct snd_soc_dai_driver adau1701_dai = { | 634 | static struct snd_soc_dai_driver adau1701_dai = { |
@@ -600,6 +665,10 @@ static int adau1701_probe(struct snd_soc_codec *codec) | |||
600 | unsigned int val; | 665 | unsigned int val; |
601 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | 666 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); |
602 | 667 | ||
668 | ret = sigmadsp_attach(adau1701->sigmadsp, &codec->component); | ||
669 | if (ret) | ||
670 | return ret; | ||
671 | |||
603 | /* | 672 | /* |
604 | * Let the pll_clkdiv variable default to something that won't happen | 673 | * Let the pll_clkdiv variable default to something that won't happen |
605 | * at runtime. That way, we can postpone the firmware download from | 674 | * at runtime. That way, we can postpone the firmware download from |
@@ -609,7 +678,7 @@ static int adau1701_probe(struct snd_soc_codec *codec) | |||
609 | adau1701->pll_clkdiv = ADAU1707_CLKDIV_UNSET; | 678 | adau1701->pll_clkdiv = ADAU1707_CLKDIV_UNSET; |
610 | 679 | ||
611 | /* initalize with pre-configured pll mode settings */ | 680 | /* initalize with pre-configured pll mode settings */ |
612 | ret = adau1701_reset(codec, adau1701->pll_clkdiv); | 681 | ret = adau1701_reset(codec, adau1701->pll_clkdiv, 0); |
613 | if (ret < 0) | 682 | if (ret < 0) |
614 | return ret; | 683 | return ret; |
615 | 684 | ||
@@ -667,6 +736,7 @@ static int adau1701_i2c_probe(struct i2c_client *client, | |||
667 | if (!adau1701) | 736 | if (!adau1701) |
668 | return -ENOMEM; | 737 | return -ENOMEM; |
669 | 738 | ||
739 | adau1701->client = client; | ||
670 | adau1701->regmap = devm_regmap_init(dev, NULL, client, | 740 | adau1701->regmap = devm_regmap_init(dev, NULL, client, |
671 | &adau1701_regmap); | 741 | &adau1701_regmap); |
672 | if (IS_ERR(adau1701->regmap)) | 742 | if (IS_ERR(adau1701->regmap)) |
@@ -722,6 +792,12 @@ static int adau1701_i2c_probe(struct i2c_client *client, | |||
722 | adau1701->gpio_pll_mode[1] = gpio_pll_mode[1]; | 792 | adau1701->gpio_pll_mode[1] = gpio_pll_mode[1]; |
723 | 793 | ||
724 | i2c_set_clientdata(client, adau1701); | 794 | i2c_set_clientdata(client, adau1701); |
795 | |||
796 | adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, | ||
797 | &adau1701_sigmadsp_ops, ADAU1701_FIRMWARE); | ||
798 | if (IS_ERR(adau1701->sigmadsp)) | ||
799 | return PTR_ERR(adau1701->sigmadsp); | ||
800 | |||
725 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, | 801 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, |
726 | &adau1701_dai, 1); | 802 | &adau1701_dai, 1); |
727 | return ret; | 803 | return ret; |
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index 91f60282fd2f..a1baeee160f4 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c | |||
@@ -255,7 +255,8 @@ static const struct snd_kcontrol_new adau1761_input_mux_control = | |||
255 | static int adau1761_dejitter_fixup(struct snd_soc_dapm_widget *w, | 255 | static int adau1761_dejitter_fixup(struct snd_soc_dapm_widget *w, |
256 | struct snd_kcontrol *kcontrol, int event) | 256 | struct snd_kcontrol *kcontrol, int event) |
257 | { | 257 | { |
258 | struct adau *adau = snd_soc_codec_get_drvdata(w->codec); | 258 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
259 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | ||
259 | 260 | ||
260 | /* After any power changes have been made the dejitter circuit | 261 | /* After any power changes have been made the dejitter circuit |
261 | * has to be reinitialized. */ | 262 | * has to be reinitialized. */ |
@@ -702,11 +703,6 @@ static int adau1761_codec_probe(struct snd_soc_codec *codec) | |||
702 | ARRAY_SIZE(adau1761_dapm_routes)); | 703 | ARRAY_SIZE(adau1761_dapm_routes)); |
703 | if (ret) | 704 | if (ret) |
704 | return ret; | 705 | return ret; |
705 | |||
706 | ret = adau17x1_load_firmware(adau, codec->dev, | ||
707 | ADAU1761_FIRMWARE); | ||
708 | if (ret) | ||
709 | dev_warn(codec->dev, "Failed to firmware\n"); | ||
710 | } | 706 | } |
711 | 707 | ||
712 | ret = adau17x1_add_routes(codec); | 708 | ret = adau17x1_add_routes(codec); |
@@ -775,16 +771,20 @@ int adau1761_probe(struct device *dev, struct regmap *regmap, | |||
775 | enum adau17x1_type type, void (*switch_mode)(struct device *dev)) | 771 | enum adau17x1_type type, void (*switch_mode)(struct device *dev)) |
776 | { | 772 | { |
777 | struct snd_soc_dai_driver *dai_drv; | 773 | struct snd_soc_dai_driver *dai_drv; |
774 | const char *firmware_name; | ||
778 | int ret; | 775 | int ret; |
779 | 776 | ||
780 | ret = adau17x1_probe(dev, regmap, type, switch_mode); | 777 | if (type == ADAU1361) { |
781 | if (ret) | ||
782 | return ret; | ||
783 | |||
784 | if (type == ADAU1361) | ||
785 | dai_drv = &adau1361_dai_driver; | 778 | dai_drv = &adau1361_dai_driver; |
786 | else | 779 | firmware_name = NULL; |
780 | } else { | ||
787 | dai_drv = &adau1761_dai_driver; | 781 | dai_drv = &adau1761_dai_driver; |
782 | firmware_name = ADAU1761_FIRMWARE; | ||
783 | } | ||
784 | |||
785 | ret = adau17x1_probe(dev, regmap, type, switch_mode, firmware_name); | ||
786 | if (ret) | ||
787 | return ret; | ||
788 | 788 | ||
789 | return snd_soc_register_codec(dev, &adau1761_codec_driver, dai_drv, 1); | 789 | return snd_soc_register_codec(dev, &adau1761_codec_driver, dai_drv, 1); |
790 | } | 790 | } |
@@ -798,6 +798,7 @@ const struct regmap_config adau1761_regmap_config = { | |||
798 | .num_reg_defaults = ARRAY_SIZE(adau1761_reg_defaults), | 798 | .num_reg_defaults = ARRAY_SIZE(adau1761_reg_defaults), |
799 | .readable_reg = adau1761_readable_register, | 799 | .readable_reg = adau1761_readable_register, |
800 | .volatile_reg = adau17x1_volatile_register, | 800 | .volatile_reg = adau17x1_volatile_register, |
801 | .precious_reg = adau17x1_precious_register, | ||
801 | .cache_type = REGCACHE_RBTREE, | 802 | .cache_type = REGCACHE_RBTREE, |
802 | }; | 803 | }; |
803 | EXPORT_SYMBOL_GPL(adau1761_regmap_config); | 804 | EXPORT_SYMBOL_GPL(adau1761_regmap_config); |
diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c index e9fc00fb13dd..35581f43fa6d 100644 --- a/sound/soc/codecs/adau1781.c +++ b/sound/soc/codecs/adau1781.c | |||
@@ -174,7 +174,7 @@ static const struct snd_kcontrol_new adau1781_mono_mixer_controls[] = { | |||
174 | static int adau1781_dejitter_fixup(struct snd_soc_dapm_widget *w, | 174 | static int adau1781_dejitter_fixup(struct snd_soc_dapm_widget *w, |
175 | struct snd_kcontrol *kcontrol, int event) | 175 | struct snd_kcontrol *kcontrol, int event) |
176 | { | 176 | { |
177 | struct snd_soc_codec *codec = w->codec; | 177 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
178 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 178 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
179 | 179 | ||
180 | /* After any power changes have been made the dejitter circuit | 180 | /* After any power changes have been made the dejitter circuit |
@@ -385,7 +385,6 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec) | |||
385 | { | 385 | { |
386 | struct adau1781_platform_data *pdata = dev_get_platdata(codec->dev); | 386 | struct adau1781_platform_data *pdata = dev_get_platdata(codec->dev); |
387 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 387 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
388 | const char *firmware; | ||
389 | int ret; | 388 | int ret; |
390 | 389 | ||
391 | ret = adau17x1_add_widgets(codec); | 390 | ret = adau17x1_add_widgets(codec); |
@@ -422,25 +421,10 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec) | |||
422 | return ret; | 421 | return ret; |
423 | } | 422 | } |
424 | 423 | ||
425 | switch (adau->type) { | ||
426 | case ADAU1381: | ||
427 | firmware = ADAU1381_FIRMWARE; | ||
428 | break; | ||
429 | case ADAU1781: | ||
430 | firmware = ADAU1781_FIRMWARE; | ||
431 | break; | ||
432 | default: | ||
433 | return -EINVAL; | ||
434 | } | ||
435 | |||
436 | ret = adau17x1_add_routes(codec); | 424 | ret = adau17x1_add_routes(codec); |
437 | if (ret < 0) | 425 | if (ret < 0) |
438 | return ret; | 426 | return ret; |
439 | 427 | ||
440 | ret = adau17x1_load_firmware(adau, codec->dev, firmware); | ||
441 | if (ret) | ||
442 | dev_warn(codec->dev, "Failed to load firmware\n"); | ||
443 | |||
444 | return 0; | 428 | return 0; |
445 | } | 429 | } |
446 | 430 | ||
@@ -488,6 +472,7 @@ const struct regmap_config adau1781_regmap_config = { | |||
488 | .num_reg_defaults = ARRAY_SIZE(adau1781_reg_defaults), | 472 | .num_reg_defaults = ARRAY_SIZE(adau1781_reg_defaults), |
489 | .readable_reg = adau1781_readable_register, | 473 | .readable_reg = adau1781_readable_register, |
490 | .volatile_reg = adau17x1_volatile_register, | 474 | .volatile_reg = adau17x1_volatile_register, |
475 | .precious_reg = adau17x1_precious_register, | ||
491 | .cache_type = REGCACHE_RBTREE, | 476 | .cache_type = REGCACHE_RBTREE, |
492 | }; | 477 | }; |
493 | EXPORT_SYMBOL_GPL(adau1781_regmap_config); | 478 | EXPORT_SYMBOL_GPL(adau1781_regmap_config); |
@@ -495,9 +480,21 @@ EXPORT_SYMBOL_GPL(adau1781_regmap_config); | |||
495 | int adau1781_probe(struct device *dev, struct regmap *regmap, | 480 | int adau1781_probe(struct device *dev, struct regmap *regmap, |
496 | enum adau17x1_type type, void (*switch_mode)(struct device *dev)) | 481 | enum adau17x1_type type, void (*switch_mode)(struct device *dev)) |
497 | { | 482 | { |
483 | const char *firmware_name; | ||
498 | int ret; | 484 | int ret; |
499 | 485 | ||
500 | ret = adau17x1_probe(dev, regmap, type, switch_mode); | 486 | switch (type) { |
487 | case ADAU1381: | ||
488 | firmware_name = ADAU1381_FIRMWARE; | ||
489 | break; | ||
490 | case ADAU1781: | ||
491 | firmware_name = ADAU1781_FIRMWARE; | ||
492 | break; | ||
493 | default: | ||
494 | return -EINVAL; | ||
495 | } | ||
496 | |||
497 | ret = adau17x1_probe(dev, regmap, type, switch_mode, firmware_name); | ||
501 | if (ret) | 498 | if (ret) |
502 | return ret; | 499 | return ret; |
503 | 500 | ||
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 3e16c1c64115..fa2e690e51c8 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c | |||
@@ -61,7 +61,8 @@ static const struct snd_kcontrol_new adau17x1_controls[] = { | |||
61 | static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, | 61 | static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, |
62 | struct snd_kcontrol *kcontrol, int event) | 62 | struct snd_kcontrol *kcontrol, int event) |
63 | { | 63 | { |
64 | struct adau *adau = snd_soc_codec_get_drvdata(w->codec); | 64 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
65 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | ||
65 | int ret; | 66 | int ret; |
66 | 67 | ||
67 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 68 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
@@ -307,6 +308,7 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream, | |||
307 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 308 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
308 | unsigned int val, div, dsp_div; | 309 | unsigned int val, div, dsp_div; |
309 | unsigned int freq; | 310 | unsigned int freq; |
311 | int ret; | ||
310 | 312 | ||
311 | if (adau->clk_src == ADAU17X1_CLK_SRC_PLL) | 313 | if (adau->clk_src == ADAU17X1_CLK_SRC_PLL) |
312 | freq = adau->pll_freq; | 314 | freq = adau->pll_freq; |
@@ -356,6 +358,12 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream, | |||
356 | regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div); | 358 | regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div); |
357 | } | 359 | } |
358 | 360 | ||
361 | if (adau->sigmadsp) { | ||
362 | ret = adau17x1_setup_firmware(adau, params_rate(params)); | ||
363 | if (ret < 0) | ||
364 | return ret; | ||
365 | } | ||
366 | |||
359 | if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) | 367 | if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) |
360 | return 0; | 368 | return 0; |
361 | 369 | ||
@@ -661,12 +669,24 @@ static int adau17x1_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
661 | return 0; | 669 | return 0; |
662 | } | 670 | } |
663 | 671 | ||
672 | static int adau17x1_startup(struct snd_pcm_substream *substream, | ||
673 | struct snd_soc_dai *dai) | ||
674 | { | ||
675 | struct adau *adau = snd_soc_codec_get_drvdata(dai->codec); | ||
676 | |||
677 | if (adau->sigmadsp) | ||
678 | return sigmadsp_restrict_params(adau->sigmadsp, substream); | ||
679 | |||
680 | return 0; | ||
681 | } | ||
682 | |||
664 | const struct snd_soc_dai_ops adau17x1_dai_ops = { | 683 | const struct snd_soc_dai_ops adau17x1_dai_ops = { |
665 | .hw_params = adau17x1_hw_params, | 684 | .hw_params = adau17x1_hw_params, |
666 | .set_sysclk = adau17x1_set_dai_sysclk, | 685 | .set_sysclk = adau17x1_set_dai_sysclk, |
667 | .set_fmt = adau17x1_set_dai_fmt, | 686 | .set_fmt = adau17x1_set_dai_fmt, |
668 | .set_pll = adau17x1_set_dai_pll, | 687 | .set_pll = adau17x1_set_dai_pll, |
669 | .set_tdm_slot = adau17x1_set_dai_tdm_slot, | 688 | .set_tdm_slot = adau17x1_set_dai_tdm_slot, |
689 | .startup = adau17x1_startup, | ||
670 | }; | 690 | }; |
671 | EXPORT_SYMBOL_GPL(adau17x1_dai_ops); | 691 | EXPORT_SYMBOL_GPL(adau17x1_dai_ops); |
672 | 692 | ||
@@ -687,8 +707,22 @@ int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec, | |||
687 | } | 707 | } |
688 | EXPORT_SYMBOL_GPL(adau17x1_set_micbias_voltage); | 708 | EXPORT_SYMBOL_GPL(adau17x1_set_micbias_voltage); |
689 | 709 | ||
710 | bool adau17x1_precious_register(struct device *dev, unsigned int reg) | ||
711 | { | ||
712 | /* SigmaDSP parameter memory */ | ||
713 | if (reg < 0x400) | ||
714 | return true; | ||
715 | |||
716 | return false; | ||
717 | } | ||
718 | EXPORT_SYMBOL_GPL(adau17x1_precious_register); | ||
719 | |||
690 | bool adau17x1_readable_register(struct device *dev, unsigned int reg) | 720 | bool adau17x1_readable_register(struct device *dev, unsigned int reg) |
691 | { | 721 | { |
722 | /* SigmaDSP parameter memory */ | ||
723 | if (reg < 0x400) | ||
724 | return true; | ||
725 | |||
692 | switch (reg) { | 726 | switch (reg) { |
693 | case ADAU17X1_CLOCK_CONTROL: | 727 | case ADAU17X1_CLOCK_CONTROL: |
694 | case ADAU17X1_PLL_CONTROL: | 728 | case ADAU17X1_PLL_CONTROL: |
@@ -745,8 +779,7 @@ bool adau17x1_volatile_register(struct device *dev, unsigned int reg) | |||
745 | } | 779 | } |
746 | EXPORT_SYMBOL_GPL(adau17x1_volatile_register); | 780 | EXPORT_SYMBOL_GPL(adau17x1_volatile_register); |
747 | 781 | ||
748 | int adau17x1_load_firmware(struct adau *adau, struct device *dev, | 782 | int adau17x1_setup_firmware(struct adau *adau, unsigned int rate) |
749 | const char *firmware) | ||
750 | { | 783 | { |
751 | int ret; | 784 | int ret; |
752 | int dspsr; | 785 | int dspsr; |
@@ -758,7 +791,7 @@ int adau17x1_load_firmware(struct adau *adau, struct device *dev, | |||
758 | regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1); | 791 | regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1); |
759 | regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf); | 792 | regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf); |
760 | 793 | ||
761 | ret = process_sigma_firmware_regmap(dev, adau->regmap, firmware); | 794 | ret = sigmadsp_setup(adau->sigmadsp, rate); |
762 | if (ret) { | 795 | if (ret) { |
763 | regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0); | 796 | regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0); |
764 | return ret; | 797 | return ret; |
@@ -767,7 +800,7 @@ int adau17x1_load_firmware(struct adau *adau, struct device *dev, | |||
767 | 800 | ||
768 | return 0; | 801 | return 0; |
769 | } | 802 | } |
770 | EXPORT_SYMBOL_GPL(adau17x1_load_firmware); | 803 | EXPORT_SYMBOL_GPL(adau17x1_setup_firmware); |
771 | 804 | ||
772 | int adau17x1_add_widgets(struct snd_soc_codec *codec) | 805 | int adau17x1_add_widgets(struct snd_soc_codec *codec) |
773 | { | 806 | { |
@@ -787,8 +820,21 @@ int adau17x1_add_widgets(struct snd_soc_codec *codec) | |||
787 | ret = snd_soc_dapm_new_controls(&codec->dapm, | 820 | ret = snd_soc_dapm_new_controls(&codec->dapm, |
788 | adau17x1_dsp_dapm_widgets, | 821 | adau17x1_dsp_dapm_widgets, |
789 | ARRAY_SIZE(adau17x1_dsp_dapm_widgets)); | 822 | ARRAY_SIZE(adau17x1_dsp_dapm_widgets)); |
823 | if (ret) | ||
824 | return ret; | ||
825 | |||
826 | if (!adau->sigmadsp) | ||
827 | return 0; | ||
828 | |||
829 | ret = sigmadsp_attach(adau->sigmadsp, &codec->component); | ||
830 | if (ret) { | ||
831 | dev_err(codec->dev, "Failed to attach firmware: %d\n", | ||
832 | ret); | ||
833 | return ret; | ||
834 | } | ||
790 | } | 835 | } |
791 | return ret; | 836 | |
837 | return 0; | ||
792 | } | 838 | } |
793 | EXPORT_SYMBOL_GPL(adau17x1_add_widgets); | 839 | EXPORT_SYMBOL_GPL(adau17x1_add_widgets); |
794 | 840 | ||
@@ -829,7 +875,8 @@ int adau17x1_resume(struct snd_soc_codec *codec) | |||
829 | EXPORT_SYMBOL_GPL(adau17x1_resume); | 875 | EXPORT_SYMBOL_GPL(adau17x1_resume); |
830 | 876 | ||
831 | int adau17x1_probe(struct device *dev, struct regmap *regmap, | 877 | int adau17x1_probe(struct device *dev, struct regmap *regmap, |
832 | enum adau17x1_type type, void (*switch_mode)(struct device *dev)) | 878 | enum adau17x1_type type, void (*switch_mode)(struct device *dev), |
879 | const char *firmware_name) | ||
833 | { | 880 | { |
834 | struct adau *adau; | 881 | struct adau *adau; |
835 | 882 | ||
@@ -846,6 +893,16 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap, | |||
846 | 893 | ||
847 | dev_set_drvdata(dev, adau); | 894 | dev_set_drvdata(dev, adau); |
848 | 895 | ||
896 | if (firmware_name) { | ||
897 | adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap, NULL, | ||
898 | firmware_name); | ||
899 | if (IS_ERR(adau->sigmadsp)) { | ||
900 | dev_warn(dev, "Could not find firmware file: %ld\n", | ||
901 | PTR_ERR(adau->sigmadsp)); | ||
902 | adau->sigmadsp = NULL; | ||
903 | } | ||
904 | } | ||
905 | |||
849 | if (switch_mode) | 906 | if (switch_mode) |
850 | switch_mode(dev); | 907 | switch_mode(dev); |
851 | 908 | ||
diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h index e4a557fd7155..e13583e6ff56 100644 --- a/sound/soc/codecs/adau17x1.h +++ b/sound/soc/codecs/adau17x1.h | |||
@@ -4,6 +4,8 @@ | |||
4 | #include <linux/regmap.h> | 4 | #include <linux/regmap.h> |
5 | #include <linux/platform_data/adau17x1.h> | 5 | #include <linux/platform_data/adau17x1.h> |
6 | 6 | ||
7 | #include "sigmadsp.h" | ||
8 | |||
7 | enum adau17x1_type { | 9 | enum adau17x1_type { |
8 | ADAU1361, | 10 | ADAU1361, |
9 | ADAU1761, | 11 | ADAU1761, |
@@ -42,22 +44,24 @@ struct adau { | |||
42 | bool dsp_bypass[2]; | 44 | bool dsp_bypass[2]; |
43 | 45 | ||
44 | struct regmap *regmap; | 46 | struct regmap *regmap; |
47 | struct sigmadsp *sigmadsp; | ||
45 | }; | 48 | }; |
46 | 49 | ||
47 | int adau17x1_add_widgets(struct snd_soc_codec *codec); | 50 | int adau17x1_add_widgets(struct snd_soc_codec *codec); |
48 | int adau17x1_add_routes(struct snd_soc_codec *codec); | 51 | int adau17x1_add_routes(struct snd_soc_codec *codec); |
49 | int adau17x1_probe(struct device *dev, struct regmap *regmap, | 52 | int adau17x1_probe(struct device *dev, struct regmap *regmap, |
50 | enum adau17x1_type type, void (*switch_mode)(struct device *dev)); | 53 | enum adau17x1_type type, void (*switch_mode)(struct device *dev), |
54 | const char *firmware_name); | ||
51 | int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec, | 55 | int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec, |
52 | enum adau17x1_micbias_voltage micbias); | 56 | enum adau17x1_micbias_voltage micbias); |
53 | bool adau17x1_readable_register(struct device *dev, unsigned int reg); | 57 | bool adau17x1_readable_register(struct device *dev, unsigned int reg); |
54 | bool adau17x1_volatile_register(struct device *dev, unsigned int reg); | 58 | bool adau17x1_volatile_register(struct device *dev, unsigned int reg); |
59 | bool adau17x1_precious_register(struct device *dev, unsigned int reg); | ||
55 | int adau17x1_resume(struct snd_soc_codec *codec); | 60 | int adau17x1_resume(struct snd_soc_codec *codec); |
56 | 61 | ||
57 | extern const struct snd_soc_dai_ops adau17x1_dai_ops; | 62 | extern const struct snd_soc_dai_ops adau17x1_dai_ops; |
58 | 63 | ||
59 | int adau17x1_load_firmware(struct adau *adau, struct device *dev, | 64 | int adau17x1_setup_firmware(struct adau *adau, unsigned int rate); |
60 | const char *firmware); | ||
61 | bool adau17x1_has_dsp(struct adau *adau); | 65 | bool adau17x1_has_dsp(struct adau *adau); |
62 | 66 | ||
63 | #define ADAU17X1_CLOCK_CONTROL 0x4000 | 67 | #define ADAU17X1_CLOCK_CONTROL 0x4000 |
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index ce3cdca9fc62..b67480f1b1aa 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
@@ -212,7 +212,7 @@ static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = { | |||
212 | static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, | 212 | static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, |
213 | struct snd_soc_dapm_widget *sink) | 213 | struct snd_soc_dapm_widget *sink) |
214 | { | 214 | { |
215 | struct snd_soc_codec *codec = source->codec; | 215 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
216 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 216 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
217 | const char *clk; | 217 | const char *clk; |
218 | 218 | ||
@@ -236,7 +236,7 @@ static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, | |||
236 | static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, | 236 | static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, |
237 | struct snd_soc_dapm_widget *sink) | 237 | struct snd_soc_dapm_widget *sink) |
238 | { | 238 | { |
239 | struct snd_soc_codec *codec = source->codec; | 239 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
240 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 240 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
241 | 241 | ||
242 | return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; | 242 | return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; |
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 30e297890fec..9130d916f2f4 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -373,33 +373,9 @@ static struct snd_soc_dai_driver ak4535_dai = { | |||
373 | .ops = &ak4535_dai_ops, | 373 | .ops = &ak4535_dai_ops, |
374 | }; | 374 | }; |
375 | 375 | ||
376 | static int ak4535_suspend(struct snd_soc_codec *codec) | ||
377 | { | ||
378 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static int ak4535_resume(struct snd_soc_codec *codec) | 376 | static int ak4535_resume(struct snd_soc_codec *codec) |
383 | { | 377 | { |
384 | snd_soc_cache_sync(codec); | 378 | snd_soc_cache_sync(codec); |
385 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static int ak4535_probe(struct snd_soc_codec *codec) | ||
390 | { | ||
391 | /* power on device */ | ||
392 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
393 | |||
394 | snd_soc_add_codec_controls(codec, ak4535_snd_controls, | ||
395 | ARRAY_SIZE(ak4535_snd_controls)); | ||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | /* power down chip */ | ||
400 | static int ak4535_remove(struct snd_soc_codec *codec) | ||
401 | { | ||
402 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
403 | return 0; | 379 | return 0; |
404 | } | 380 | } |
405 | 381 | ||
@@ -416,11 +392,12 @@ static const struct regmap_config ak4535_regmap = { | |||
416 | }; | 392 | }; |
417 | 393 | ||
418 | static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { | 394 | static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { |
419 | .probe = ak4535_probe, | ||
420 | .remove = ak4535_remove, | ||
421 | .suspend = ak4535_suspend, | ||
422 | .resume = ak4535_resume, | 395 | .resume = ak4535_resume, |
423 | .set_bias_level = ak4535_set_bias_level, | 396 | .set_bias_level = ak4535_set_bias_level, |
397 | .suspend_bias_off = true, | ||
398 | |||
399 | .controls = ak4535_snd_controls, | ||
400 | .num_controls = ARRAY_SIZE(ak4535_snd_controls), | ||
424 | .dapm_widgets = ak4535_dapm_widgets, | 401 | .dapm_widgets = ak4535_dapm_widgets, |
425 | .num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets), | 402 | .num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets), |
426 | .dapm_routes = ak4535_audio_map, | 403 | .dapm_routes = ak4535_audio_map, |
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 7afe8f482088..70861c7b1631 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c | |||
@@ -505,39 +505,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = { | |||
505 | }, | 505 | }, |
506 | }; | 506 | }; |
507 | 507 | ||
508 | static int ak4641_suspend(struct snd_soc_codec *codec) | ||
509 | { | ||
510 | ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static int ak4641_resume(struct snd_soc_codec *codec) | ||
515 | { | ||
516 | ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | static int ak4641_probe(struct snd_soc_codec *codec) | ||
521 | { | ||
522 | /* power on device */ | ||
523 | ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int ak4641_remove(struct snd_soc_codec *codec) | ||
529 | { | ||
530 | ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | |||
536 | static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { | 508 | static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { |
537 | .probe = ak4641_probe, | ||
538 | .remove = ak4641_remove, | ||
539 | .suspend = ak4641_suspend, | ||
540 | .resume = ak4641_resume, | ||
541 | .controls = ak4641_snd_controls, | 509 | .controls = ak4641_snd_controls, |
542 | .num_controls = ARRAY_SIZE(ak4641_snd_controls), | 510 | .num_controls = ARRAY_SIZE(ak4641_snd_controls), |
543 | .dapm_widgets = ak4641_dapm_widgets, | 511 | .dapm_widgets = ak4641_dapm_widgets, |
@@ -545,6 +513,7 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { | |||
545 | .dapm_routes = ak4641_audio_map, | 513 | .dapm_routes = ak4641_audio_map, |
546 | .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), | 514 | .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), |
547 | .set_bias_level = ak4641_set_bias_level, | 515 | .set_bias_level = ak4641_set_bias_level, |
516 | .suspend_bias_off = true, | ||
548 | }; | 517 | }; |
549 | 518 | ||
550 | static const struct regmap_config ak4641_regmap = { | 519 | static const struct regmap_config ak4641_regmap = { |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 041712592e29..dde8b49c19ad 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -491,23 +491,7 @@ static int ak4642_resume(struct snd_soc_codec *codec) | |||
491 | return 0; | 491 | return 0; |
492 | } | 492 | } |
493 | 493 | ||
494 | |||
495 | static int ak4642_probe(struct snd_soc_codec *codec) | ||
496 | { | ||
497 | ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static int ak4642_remove(struct snd_soc_codec *codec) | ||
503 | { | ||
504 | ak4642_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { | 494 | static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { |
509 | .probe = ak4642_probe, | ||
510 | .remove = ak4642_remove, | ||
511 | .resume = ak4642_resume, | 495 | .resume = ak4642_resume, |
512 | .set_bias_level = ak4642_set_bias_level, | 496 | .set_bias_level = ak4642_set_bias_level, |
513 | .controls = ak4642_snd_controls, | 497 | .controls = ak4642_snd_controls, |
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 998fa0c5a0b9..686cacb0e835 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
@@ -611,20 +611,7 @@ static struct snd_soc_dai_driver ak4671_dai = { | |||
611 | .ops = &ak4671_dai_ops, | 611 | .ops = &ak4671_dai_ops, |
612 | }; | 612 | }; |
613 | 613 | ||
614 | static int ak4671_probe(struct snd_soc_codec *codec) | ||
615 | { | ||
616 | return ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
617 | } | ||
618 | |||
619 | static int ak4671_remove(struct snd_soc_codec *codec) | ||
620 | { | ||
621 | ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { | 614 | static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { |
626 | .probe = ak4671_probe, | ||
627 | .remove = ak4671_remove, | ||
628 | .set_bias_level = ak4671_set_bias_level, | 615 | .set_bias_level = ak4671_set_bias_level, |
629 | .controls = ak4671_snd_controls, | 616 | .controls = ak4671_snd_controls, |
630 | .num_controls = ARRAY_SIZE(ak4671_snd_controls), | 617 | .num_controls = ARRAY_SIZE(ak4671_snd_controls), |
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index 9d0755aa1d16..bdf8c5ac8ca4 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c | |||
@@ -866,7 +866,6 @@ static int alc5623_suspend(struct snd_soc_codec *codec) | |||
866 | { | 866 | { |
867 | struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); | 867 | struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); |
868 | 868 | ||
869 | alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
870 | regcache_cache_only(alc5623->regmap, true); | 869 | regcache_cache_only(alc5623->regmap, true); |
871 | 870 | ||
872 | return 0; | 871 | return 0; |
@@ -887,15 +886,6 @@ static int alc5623_resume(struct snd_soc_codec *codec) | |||
887 | return ret; | 886 | return ret; |
888 | } | 887 | } |
889 | 888 | ||
890 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
891 | |||
892 | /* charge alc5623 caps */ | ||
893 | if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { | ||
894 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
895 | codec->dapm.bias_level = SND_SOC_BIAS_ON; | ||
896 | alc5623_set_bias_level(codec, codec->dapm.bias_level); | ||
897 | } | ||
898 | |||
899 | return 0; | 889 | return 0; |
900 | } | 890 | } |
901 | 891 | ||
@@ -906,9 +896,6 @@ static int alc5623_probe(struct snd_soc_codec *codec) | |||
906 | 896 | ||
907 | alc5623_reset(codec); | 897 | alc5623_reset(codec); |
908 | 898 | ||
909 | /* power on device */ | ||
910 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
911 | |||
912 | if (alc5623->add_ctrl) { | 899 | if (alc5623->add_ctrl) { |
913 | snd_soc_write(codec, ALC5623_ADD_CTRL_REG, | 900 | snd_soc_write(codec, ALC5623_ADD_CTRL_REG, |
914 | alc5623->add_ctrl); | 901 | alc5623->add_ctrl); |
@@ -964,19 +951,12 @@ static int alc5623_probe(struct snd_soc_codec *codec) | |||
964 | return 0; | 951 | return 0; |
965 | } | 952 | } |
966 | 953 | ||
967 | /* power down chip */ | ||
968 | static int alc5623_remove(struct snd_soc_codec *codec) | ||
969 | { | ||
970 | alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
971 | return 0; | ||
972 | } | ||
973 | |||
974 | static struct snd_soc_codec_driver soc_codec_device_alc5623 = { | 954 | static struct snd_soc_codec_driver soc_codec_device_alc5623 = { |
975 | .probe = alc5623_probe, | 955 | .probe = alc5623_probe, |
976 | .remove = alc5623_remove, | ||
977 | .suspend = alc5623_suspend, | 956 | .suspend = alc5623_suspend, |
978 | .resume = alc5623_resume, | 957 | .resume = alc5623_resume, |
979 | .set_bias_level = alc5623_set_bias_level, | 958 | .set_bias_level = alc5623_set_bias_level, |
959 | .suspend_bias_off = true, | ||
980 | }; | 960 | }; |
981 | 961 | ||
982 | static const struct regmap_config alc5623_regmap = { | 962 | static const struct regmap_config alc5623_regmap = { |
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index 85942ca36cbf..d1fdbc266631 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c | |||
@@ -1038,23 +1038,15 @@ static struct snd_soc_dai_driver alc5632_dai = { | |||
1038 | }; | 1038 | }; |
1039 | 1039 | ||
1040 | #ifdef CONFIG_PM | 1040 | #ifdef CONFIG_PM |
1041 | static int alc5632_suspend(struct snd_soc_codec *codec) | ||
1042 | { | ||
1043 | alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | static int alc5632_resume(struct snd_soc_codec *codec) | 1041 | static int alc5632_resume(struct snd_soc_codec *codec) |
1048 | { | 1042 | { |
1049 | struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); | 1043 | struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); |
1050 | 1044 | ||
1051 | regcache_sync(alc5632->regmap); | 1045 | regcache_sync(alc5632->regmap); |
1052 | 1046 | ||
1053 | alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1054 | return 0; | 1047 | return 0; |
1055 | } | 1048 | } |
1056 | #else | 1049 | #else |
1057 | #define alc5632_suspend NULL | ||
1058 | #define alc5632_resume NULL | 1050 | #define alc5632_resume NULL |
1059 | #endif | 1051 | #endif |
1060 | 1052 | ||
@@ -1062,9 +1054,6 @@ static int alc5632_probe(struct snd_soc_codec *codec) | |||
1062 | { | 1054 | { |
1063 | struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); | 1055 | struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); |
1064 | 1056 | ||
1065 | /* power on device */ | ||
1066 | alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1067 | |||
1068 | switch (alc5632->id) { | 1057 | switch (alc5632->id) { |
1069 | case 0x5c: | 1058 | case 0x5c: |
1070 | snd_soc_add_codec_controls(codec, alc5632_vol_snd_controls, | 1059 | snd_soc_add_codec_controls(codec, alc5632_vol_snd_controls, |
@@ -1077,19 +1066,12 @@ static int alc5632_probe(struct snd_soc_codec *codec) | |||
1077 | return 0; | 1066 | return 0; |
1078 | } | 1067 | } |
1079 | 1068 | ||
1080 | /* power down chip */ | ||
1081 | static int alc5632_remove(struct snd_soc_codec *codec) | ||
1082 | { | ||
1083 | alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1084 | return 0; | ||
1085 | } | ||
1086 | |||
1087 | static struct snd_soc_codec_driver soc_codec_device_alc5632 = { | 1069 | static struct snd_soc_codec_driver soc_codec_device_alc5632 = { |
1088 | .probe = alc5632_probe, | 1070 | .probe = alc5632_probe, |
1089 | .remove = alc5632_remove, | ||
1090 | .suspend = alc5632_suspend, | ||
1091 | .resume = alc5632_resume, | 1071 | .resume = alc5632_resume, |
1092 | .set_bias_level = alc5632_set_bias_level, | 1072 | .set_bias_level = alc5632_set_bias_level, |
1073 | .suspend_bias_off = true, | ||
1074 | |||
1093 | .controls = alc5632_snd_controls, | 1075 | .controls = alc5632_snd_controls, |
1094 | .num_controls = ARRAY_SIZE(alc5632_snd_controls), | 1076 | .num_controls = ARRAY_SIZE(alc5632_snd_controls), |
1095 | .dapm_widgets = alc5632_dapm_widgets, | 1077 | .dapm_widgets = alc5632_dapm_widgets, |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 0c05e7a7945f..9550d7433ad0 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -61,6 +61,11 @@ | |||
61 | #define ARIZONA_FLL_MIN_OUTDIV 2 | 61 | #define ARIZONA_FLL_MIN_OUTDIV 2 |
62 | #define ARIZONA_FLL_MAX_OUTDIV 7 | 62 | #define ARIZONA_FLL_MAX_OUTDIV 7 |
63 | 63 | ||
64 | #define ARIZONA_FMT_DSP_MODE_A 0 | ||
65 | #define ARIZONA_FMT_DSP_MODE_B 1 | ||
66 | #define ARIZONA_FMT_I2S_MODE 2 | ||
67 | #define ARIZONA_FMT_LEFT_JUSTIFIED_MODE 3 | ||
68 | |||
64 | #define arizona_fll_err(_fll, fmt, ...) \ | 69 | #define arizona_fll_err(_fll, fmt, ...) \ |
65 | dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) | 70 | dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) |
66 | #define arizona_fll_warn(_fll, fmt, ...) \ | 71 | #define arizona_fll_warn(_fll, fmt, ...) \ |
@@ -648,7 +653,7 @@ SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum, | |||
648 | EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); | 653 | EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); |
649 | 654 | ||
650 | static const char * const arizona_in_dmic_osr_text[] = { | 655 | static const char * const arizona_in_dmic_osr_text[] = { |
651 | "1.536MHz", "3.072MHz", "6.144MHz", | 656 | "1.536MHz", "3.072MHz", "6.144MHz", "768kHz", |
652 | }; | 657 | }; |
653 | 658 | ||
654 | const struct soc_enum arizona_in_dmic_osr[] = { | 659 | const struct soc_enum arizona_in_dmic_osr[] = { |
@@ -946,10 +951,26 @@ static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
946 | 951 | ||
947 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 952 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
948 | case SND_SOC_DAIFMT_DSP_A: | 953 | case SND_SOC_DAIFMT_DSP_A: |
949 | mode = 0; | 954 | mode = ARIZONA_FMT_DSP_MODE_A; |
955 | break; | ||
956 | case SND_SOC_DAIFMT_DSP_B: | ||
957 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) | ||
958 | != SND_SOC_DAIFMT_CBM_CFM) { | ||
959 | arizona_aif_err(dai, "DSP_B not valid in slave mode\n"); | ||
960 | return -EINVAL; | ||
961 | } | ||
962 | mode = ARIZONA_FMT_DSP_MODE_B; | ||
950 | break; | 963 | break; |
951 | case SND_SOC_DAIFMT_I2S: | 964 | case SND_SOC_DAIFMT_I2S: |
952 | mode = 2; | 965 | mode = ARIZONA_FMT_I2S_MODE; |
966 | break; | ||
967 | case SND_SOC_DAIFMT_LEFT_J: | ||
968 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) | ||
969 | != SND_SOC_DAIFMT_CBM_CFM) { | ||
970 | arizona_aif_err(dai, "LEFT_J not valid in slave mode\n"); | ||
971 | return -EINVAL; | ||
972 | } | ||
973 | mode = ARIZONA_FMT_LEFT_JUSTIFIED_MODE; | ||
953 | break; | 974 | break; |
954 | default: | 975 | default: |
955 | arizona_aif_err(dai, "Unsupported DAI format %d\n", | 976 | arizona_aif_err(dai, "Unsupported DAI format %d\n", |
@@ -1164,13 +1185,13 @@ static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec, | |||
1164 | { 0x80, 0x0 }, | 1185 | { 0x80, 0x0 }, |
1165 | }; | 1186 | }; |
1166 | 1187 | ||
1167 | mutex_lock(&codec->mutex); | 1188 | mutex_lock(&arizona->dac_comp_lock); |
1168 | 1189 | ||
1169 | dac_comp[1].def = arizona->dac_comp_coeff; | 1190 | dac_comp[1].def = arizona->dac_comp_coeff; |
1170 | if (rate >= 176400) | 1191 | if (rate >= 176400) |
1171 | dac_comp[2].def = arizona->dac_comp_enabled; | 1192 | dac_comp[2].def = arizona->dac_comp_enabled; |
1172 | 1193 | ||
1173 | mutex_unlock(&codec->mutex); | 1194 | mutex_unlock(&arizona->dac_comp_lock); |
1174 | 1195 | ||
1175 | regmap_multi_reg_write(arizona->regmap, | 1196 | regmap_multi_reg_write(arizona->regmap, |
1176 | dac_comp, | 1197 | dac_comp, |
@@ -1298,7 +1319,8 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
1298 | 1319 | ||
1299 | /* Force multiple of 2 channels for I2S mode */ | 1320 | /* Force multiple of 2 channels for I2S mode */ |
1300 | val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); | 1321 | val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); |
1301 | if ((channels & 1) && (val & ARIZONA_AIF1_FMT_MASK)) { | 1322 | val &= ARIZONA_AIF1_FMT_MASK; |
1323 | if ((channels & 1) && (val == ARIZONA_FMT_I2S_MODE)) { | ||
1302 | arizona_aif_dbg(dai, "Forcing stereo mode\n"); | 1324 | arizona_aif_dbg(dai, "Forcing stereo mode\n"); |
1303 | bclk_target /= channels; | 1325 | bclk_target /= channels; |
1304 | bclk_target *= channels + 1; | 1326 | bclk_target *= channels + 1; |
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index 537327c7f7f1..8d638e8aa8eb 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c | |||
@@ -62,14 +62,10 @@ static int cq93vc_mute(struct snd_soc_dai *dai, int mute) | |||
62 | static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 62 | static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
63 | int clk_id, unsigned int freq, int dir) | 63 | int clk_id, unsigned int freq, int dir) |
64 | { | 64 | { |
65 | struct snd_soc_codec *codec = codec_dai->codec; | ||
66 | struct davinci_vc *davinci_vc = codec->dev->platform_data; | ||
67 | |||
68 | switch (freq) { | 65 | switch (freq) { |
69 | case 22579200: | 66 | case 22579200: |
70 | case 27000000: | 67 | case 27000000: |
71 | case 33868800: | 68 | case 33868800: |
72 | davinci_vc->cq93vc.sysclk = freq; | ||
73 | return 0; | 69 | return 0; |
74 | } | 70 | } |
75 | 71 | ||
@@ -126,32 +122,6 @@ static struct snd_soc_dai_driver cq93vc_dai = { | |||
126 | .ops = &cq93vc_dai_ops, | 122 | .ops = &cq93vc_dai_ops, |
127 | }; | 123 | }; |
128 | 124 | ||
129 | static int cq93vc_resume(struct snd_soc_codec *codec) | ||
130 | { | ||
131 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int cq93vc_probe(struct snd_soc_codec *codec) | ||
137 | { | ||
138 | struct davinci_vc *davinci_vc = codec->dev->platform_data; | ||
139 | |||
140 | davinci_vc->cq93vc.codec = codec; | ||
141 | |||
142 | /* Off, with power on */ | ||
143 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int cq93vc_remove(struct snd_soc_codec *codec) | ||
149 | { | ||
150 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static struct regmap *cq93vc_get_regmap(struct device *dev) | 125 | static struct regmap *cq93vc_get_regmap(struct device *dev) |
156 | { | 126 | { |
157 | struct davinci_vc *davinci_vc = dev->platform_data; | 127 | struct davinci_vc *davinci_vc = dev->platform_data; |
@@ -161,9 +131,6 @@ static struct regmap *cq93vc_get_regmap(struct device *dev) | |||
161 | 131 | ||
162 | static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { | 132 | static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { |
163 | .set_bias_level = cq93vc_set_bias_level, | 133 | .set_bias_level = cq93vc_set_bias_level, |
164 | .probe = cq93vc_probe, | ||
165 | .remove = cq93vc_remove, | ||
166 | .resume = cq93vc_resume, | ||
167 | .get_regmap = cq93vc_get_regmap, | 134 | .get_regmap = cq93vc_get_regmap, |
168 | .controls = cq93vc_snd_controls, | 135 | .controls = cq93vc_snd_controls, |
169 | .num_controls = ARRAY_SIZE(cq93vc_snd_controls), | 136 | .num_controls = ARRAY_SIZE(cq93vc_snd_controls), |
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 4fdd47d700e3..ce6086835ebd 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include "cs4265.h" | 32 | #include "cs4265.h" |
33 | 33 | ||
34 | struct cs4265_private { | 34 | struct cs4265_private { |
35 | struct device *dev; | ||
36 | struct regmap *regmap; | 35 | struct regmap *regmap; |
37 | struct gpio_desc *reset_gpio; | 36 | struct gpio_desc *reset_gpio; |
38 | u8 format; | 37 | u8 format; |
@@ -598,7 +597,6 @@ static int cs4265_i2c_probe(struct i2c_client *i2c_client, | |||
598 | GFP_KERNEL); | 597 | GFP_KERNEL); |
599 | if (cs4265 == NULL) | 598 | if (cs4265 == NULL) |
600 | return -ENOMEM; | 599 | return -ENOMEM; |
601 | cs4265->dev = &i2c_client->dev; | ||
602 | 600 | ||
603 | cs4265->regmap = devm_regmap_init_i2c(i2c_client, &cs4265_regmap); | 601 | cs4265->regmap = devm_regmap_init_i2c(i2c_client, &cs4265_regmap); |
604 | if (IS_ERR(cs4265->regmap)) { | 602 | if (IS_ERR(cs4265->regmap)) { |
diff --git a/sound/soc/codecs/cs4271-i2c.c b/sound/soc/codecs/cs4271-i2c.c new file mode 100644 index 000000000000..b264da030340 --- /dev/null +++ b/sound/soc/codecs/cs4271-i2c.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * CS4271 I2C audio driver | ||
3 | * | ||
4 | * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include "cs4271.h" | ||
22 | |||
23 | static int cs4271_i2c_probe(struct i2c_client *client, | ||
24 | const struct i2c_device_id *id) | ||
25 | { | ||
26 | struct regmap_config config; | ||
27 | |||
28 | config = cs4271_regmap_config; | ||
29 | config.reg_bits = 8; | ||
30 | config.val_bits = 8; | ||
31 | |||
32 | return cs4271_probe(&client->dev, | ||
33 | devm_regmap_init_i2c(client, &config)); | ||
34 | } | ||
35 | |||
36 | static int cs4271_i2c_remove(struct i2c_client *client) | ||
37 | { | ||
38 | snd_soc_unregister_codec(&client->dev); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static const struct i2c_device_id cs4271_i2c_id[] = { | ||
43 | { "cs4271", 0 }, | ||
44 | { } | ||
45 | }; | ||
46 | MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); | ||
47 | |||
48 | static struct i2c_driver cs4271_i2c_driver = { | ||
49 | .driver = { | ||
50 | .name = "cs4271", | ||
51 | .owner = THIS_MODULE, | ||
52 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
53 | }, | ||
54 | .probe = cs4271_i2c_probe, | ||
55 | .remove = cs4271_i2c_remove, | ||
56 | .id_table = cs4271_i2c_id, | ||
57 | }; | ||
58 | module_i2c_driver(cs4271_i2c_driver); | ||
59 | |||
60 | MODULE_DESCRIPTION("ASoC CS4271 I2C Driver"); | ||
61 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); | ||
62 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cs4271-spi.c b/sound/soc/codecs/cs4271-spi.c new file mode 100644 index 000000000000..acd49d86e706 --- /dev/null +++ b/sound/soc/codecs/cs4271-spi.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * CS4271 SPI audio driver | ||
3 | * | ||
4 | * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/spi/spi.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include "cs4271.h" | ||
22 | |||
23 | static int cs4271_spi_probe(struct spi_device *spi) | ||
24 | { | ||
25 | struct regmap_config config; | ||
26 | |||
27 | config = cs4271_regmap_config; | ||
28 | config.reg_bits = 16; | ||
29 | config.val_bits = 8; | ||
30 | config.read_flag_mask = 0x21; | ||
31 | config.write_flag_mask = 0x20; | ||
32 | |||
33 | return cs4271_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); | ||
34 | } | ||
35 | |||
36 | static int cs4271_spi_remove(struct spi_device *spi) | ||
37 | { | ||
38 | snd_soc_unregister_codec(&spi->dev); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static struct spi_driver cs4271_spi_driver = { | ||
43 | .driver = { | ||
44 | .name = "cs4271", | ||
45 | .owner = THIS_MODULE, | ||
46 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
47 | }, | ||
48 | .probe = cs4271_spi_probe, | ||
49 | .remove = cs4271_spi_remove, | ||
50 | }; | ||
51 | module_spi_driver(cs4271_spi_driver); | ||
52 | |||
53 | MODULE_DESCRIPTION("ASoC CS4271 SPI Driver"); | ||
54 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); | ||
55 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 93cec52f4733..79a4efcb894c 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
@@ -23,8 +23,6 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
26 | #include <linux/i2c.h> | ||
27 | #include <linux/spi/spi.h> | ||
28 | #include <linux/of.h> | 26 | #include <linux/of.h> |
29 | #include <linux/of_device.h> | 27 | #include <linux/of_device.h> |
30 | #include <linux/of_gpio.h> | 28 | #include <linux/of_gpio.h> |
@@ -32,6 +30,7 @@ | |||
32 | #include <sound/soc.h> | 30 | #include <sound/soc.h> |
33 | #include <sound/tlv.h> | 31 | #include <sound/tlv.h> |
34 | #include <sound/cs4271.h> | 32 | #include <sound/cs4271.h> |
33 | #include "cs4271.h" | ||
35 | 34 | ||
36 | #define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | 35 | #define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
37 | SNDRV_PCM_FMTBIT_S24_LE | \ | 36 | SNDRV_PCM_FMTBIT_S24_LE | \ |
@@ -527,14 +526,15 @@ static int cs4271_soc_resume(struct snd_soc_codec *codec) | |||
527 | #endif /* CONFIG_PM */ | 526 | #endif /* CONFIG_PM */ |
528 | 527 | ||
529 | #ifdef CONFIG_OF | 528 | #ifdef CONFIG_OF |
530 | static const struct of_device_id cs4271_dt_ids[] = { | 529 | const struct of_device_id cs4271_dt_ids[] = { |
531 | { .compatible = "cirrus,cs4271", }, | 530 | { .compatible = "cirrus,cs4271", }, |
532 | { } | 531 | { } |
533 | }; | 532 | }; |
534 | MODULE_DEVICE_TABLE(of, cs4271_dt_ids); | 533 | MODULE_DEVICE_TABLE(of, cs4271_dt_ids); |
534 | EXPORT_SYMBOL_GPL(cs4271_dt_ids); | ||
535 | #endif | 535 | #endif |
536 | 536 | ||
537 | static int cs4271_probe(struct snd_soc_codec *codec) | 537 | static int cs4271_codec_probe(struct snd_soc_codec *codec) |
538 | { | 538 | { |
539 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | 539 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); |
540 | struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; | 540 | struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; |
@@ -587,7 +587,7 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
587 | return 0; | 587 | return 0; |
588 | } | 588 | } |
589 | 589 | ||
590 | static int cs4271_remove(struct snd_soc_codec *codec) | 590 | static int cs4271_codec_remove(struct snd_soc_codec *codec) |
591 | { | 591 | { |
592 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | 592 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); |
593 | 593 | ||
@@ -599,8 +599,8 @@ static int cs4271_remove(struct snd_soc_codec *codec) | |||
599 | }; | 599 | }; |
600 | 600 | ||
601 | static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { | 601 | static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { |
602 | .probe = cs4271_probe, | 602 | .probe = cs4271_codec_probe, |
603 | .remove = cs4271_remove, | 603 | .remove = cs4271_codec_remove, |
604 | .suspend = cs4271_soc_suspend, | 604 | .suspend = cs4271_soc_suspend, |
605 | .resume = cs4271_soc_resume, | 605 | .resume = cs4271_soc_resume, |
606 | 606 | ||
@@ -642,14 +642,8 @@ static int cs4271_common_probe(struct device *dev, | |||
642 | return 0; | 642 | return 0; |
643 | } | 643 | } |
644 | 644 | ||
645 | #if defined(CONFIG_SPI_MASTER) | 645 | const struct regmap_config cs4271_regmap_config = { |
646 | |||
647 | static const struct regmap_config cs4271_spi_regmap = { | ||
648 | .reg_bits = 16, | ||
649 | .val_bits = 8, | ||
650 | .max_register = CS4271_LASTREG, | 646 | .max_register = CS4271_LASTREG, |
651 | .read_flag_mask = 0x21, | ||
652 | .write_flag_mask = 0x20, | ||
653 | 647 | ||
654 | .reg_defaults = cs4271_reg_defaults, | 648 | .reg_defaults = cs4271_reg_defaults, |
655 | .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), | 649 | .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), |
@@ -657,140 +651,27 @@ static const struct regmap_config cs4271_spi_regmap = { | |||
657 | 651 | ||
658 | .volatile_reg = cs4271_volatile_reg, | 652 | .volatile_reg = cs4271_volatile_reg, |
659 | }; | 653 | }; |
654 | EXPORT_SYMBOL_GPL(cs4271_regmap_config); | ||
660 | 655 | ||
661 | static int cs4271_spi_probe(struct spi_device *spi) | 656 | int cs4271_probe(struct device *dev, struct regmap *regmap) |
662 | { | 657 | { |
663 | struct cs4271_private *cs4271; | 658 | struct cs4271_private *cs4271; |
664 | int ret; | 659 | int ret; |
665 | 660 | ||
666 | ret = cs4271_common_probe(&spi->dev, &cs4271); | 661 | if (IS_ERR(regmap)) |
667 | if (ret < 0) | 662 | return PTR_ERR(regmap); |
668 | return ret; | ||
669 | |||
670 | spi_set_drvdata(spi, cs4271); | ||
671 | cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap); | ||
672 | if (IS_ERR(cs4271->regmap)) | ||
673 | return PTR_ERR(cs4271->regmap); | ||
674 | |||
675 | return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271, | ||
676 | &cs4271_dai, 1); | ||
677 | } | ||
678 | |||
679 | static int cs4271_spi_remove(struct spi_device *spi) | ||
680 | { | ||
681 | snd_soc_unregister_codec(&spi->dev); | ||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | static struct spi_driver cs4271_spi_driver = { | ||
686 | .driver = { | ||
687 | .name = "cs4271", | ||
688 | .owner = THIS_MODULE, | ||
689 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
690 | }, | ||
691 | .probe = cs4271_spi_probe, | ||
692 | .remove = cs4271_spi_remove, | ||
693 | }; | ||
694 | #endif /* defined(CONFIG_SPI_MASTER) */ | ||
695 | |||
696 | #if IS_ENABLED(CONFIG_I2C) | ||
697 | static const struct i2c_device_id cs4271_i2c_id[] = { | ||
698 | {"cs4271", 0}, | ||
699 | {} | ||
700 | }; | ||
701 | MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); | ||
702 | 663 | ||
703 | static const struct regmap_config cs4271_i2c_regmap = { | 664 | ret = cs4271_common_probe(dev, &cs4271); |
704 | .reg_bits = 8, | ||
705 | .val_bits = 8, | ||
706 | .max_register = CS4271_LASTREG, | ||
707 | |||
708 | .reg_defaults = cs4271_reg_defaults, | ||
709 | .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), | ||
710 | .cache_type = REGCACHE_RBTREE, | ||
711 | |||
712 | .volatile_reg = cs4271_volatile_reg, | ||
713 | }; | ||
714 | |||
715 | static int cs4271_i2c_probe(struct i2c_client *client, | ||
716 | const struct i2c_device_id *id) | ||
717 | { | ||
718 | struct cs4271_private *cs4271; | ||
719 | int ret; | ||
720 | |||
721 | ret = cs4271_common_probe(&client->dev, &cs4271); | ||
722 | if (ret < 0) | 665 | if (ret < 0) |
723 | return ret; | 666 | return ret; |
724 | 667 | ||
725 | i2c_set_clientdata(client, cs4271); | 668 | dev_set_drvdata(dev, cs4271); |
726 | cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap); | 669 | cs4271->regmap = regmap; |
727 | if (IS_ERR(cs4271->regmap)) | ||
728 | return PTR_ERR(cs4271->regmap); | ||
729 | 670 | ||
730 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271, | 671 | return snd_soc_register_codec(dev, &soc_codec_dev_cs4271, &cs4271_dai, |
731 | &cs4271_dai, 1); | 672 | 1); |
732 | } | ||
733 | |||
734 | static int cs4271_i2c_remove(struct i2c_client *client) | ||
735 | { | ||
736 | snd_soc_unregister_codec(&client->dev); | ||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static struct i2c_driver cs4271_i2c_driver = { | ||
741 | .driver = { | ||
742 | .name = "cs4271", | ||
743 | .owner = THIS_MODULE, | ||
744 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
745 | }, | ||
746 | .id_table = cs4271_i2c_id, | ||
747 | .probe = cs4271_i2c_probe, | ||
748 | .remove = cs4271_i2c_remove, | ||
749 | }; | ||
750 | #endif /* IS_ENABLED(CONFIG_I2C) */ | ||
751 | |||
752 | /* | ||
753 | * We only register our serial bus driver here without | ||
754 | * assignment to particular chip. So if any of the below | ||
755 | * fails, there is some problem with I2C or SPI subsystem. | ||
756 | * In most cases this module will be compiled with support | ||
757 | * of only one serial bus. | ||
758 | */ | ||
759 | static int __init cs4271_modinit(void) | ||
760 | { | ||
761 | int ret; | ||
762 | |||
763 | #if IS_ENABLED(CONFIG_I2C) | ||
764 | ret = i2c_add_driver(&cs4271_i2c_driver); | ||
765 | if (ret) { | ||
766 | pr_err("Failed to register CS4271 I2C driver: %d\n", ret); | ||
767 | return ret; | ||
768 | } | ||
769 | #endif | ||
770 | |||
771 | #if defined(CONFIG_SPI_MASTER) | ||
772 | ret = spi_register_driver(&cs4271_spi_driver); | ||
773 | if (ret) { | ||
774 | pr_err("Failed to register CS4271 SPI driver: %d\n", ret); | ||
775 | return ret; | ||
776 | } | ||
777 | #endif | ||
778 | |||
779 | return 0; | ||
780 | } | ||
781 | module_init(cs4271_modinit); | ||
782 | |||
783 | static void __exit cs4271_modexit(void) | ||
784 | { | ||
785 | #if defined(CONFIG_SPI_MASTER) | ||
786 | spi_unregister_driver(&cs4271_spi_driver); | ||
787 | #endif | ||
788 | |||
789 | #if IS_ENABLED(CONFIG_I2C) | ||
790 | i2c_del_driver(&cs4271_i2c_driver); | ||
791 | #endif | ||
792 | } | 673 | } |
793 | module_exit(cs4271_modexit); | 674 | EXPORT_SYMBOL_GPL(cs4271_probe); |
794 | 675 | ||
795 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); | 676 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); |
796 | MODULE_DESCRIPTION("Cirrus Logic CS4271 ALSA SoC Codec Driver"); | 677 | MODULE_DESCRIPTION("Cirrus Logic CS4271 ALSA SoC Codec Driver"); |
diff --git a/sound/soc/codecs/cs4271.h b/sound/soc/codecs/cs4271.h new file mode 100644 index 000000000000..9adad8eefdc9 --- /dev/null +++ b/sound/soc/codecs/cs4271.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef _CS4271_PRIV_H | ||
2 | #define _CS4271_PRIV_H | ||
3 | |||
4 | #include <linux/regmap.h> | ||
5 | |||
6 | extern const struct of_device_id cs4271_dt_ids[]; | ||
7 | extern const struct regmap_config cs4271_regmap_config; | ||
8 | |||
9 | int cs4271_probe(struct device *dev, struct regmap *regmap); | ||
10 | |||
11 | #endif | ||
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 669c38fc3034..b3951524339f 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c | |||
@@ -153,15 +153,17 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = { | |||
153 | static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w, | 153 | static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w, |
154 | struct snd_kcontrol *kcontrol, int event) | 154 | struct snd_kcontrol *kcontrol, int event) |
155 | { | 155 | { |
156 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
157 | |||
156 | switch (event) { | 158 | switch (event) { |
157 | case SND_SOC_DAPM_PRE_PMD: | 159 | case SND_SOC_DAPM_PRE_PMD: |
158 | snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1, | 160 | snd_soc_update_bits(codec, CS42L51_POWER_CTL1, |
159 | CS42L51_POWER_CTL1_PDN, | 161 | CS42L51_POWER_CTL1_PDN, |
160 | CS42L51_POWER_CTL1_PDN); | 162 | CS42L51_POWER_CTL1_PDN); |
161 | break; | 163 | break; |
162 | default: | 164 | default: |
163 | case SND_SOC_DAPM_POST_PMD: | 165 | case SND_SOC_DAPM_POST_PMD: |
164 | snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1, | 166 | snd_soc_update_bits(codec, CS42L51_POWER_CTL1, |
165 | CS42L51_POWER_CTL1_PDN, 0); | 167 | CS42L51_POWER_CTL1_PDN, 0); |
166 | break; | 168 | break; |
167 | } | 169 | } |
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 2f8b94683e83..7c55537c69cf 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -584,7 +584,7 @@ static const struct snd_kcontrol_new cs42l73_snd_controls[] = { | |||
584 | static int cs42l73_spklo_spk_amp_event(struct snd_soc_dapm_widget *w, | 584 | static int cs42l73_spklo_spk_amp_event(struct snd_soc_dapm_widget *w, |
585 | struct snd_kcontrol *kcontrol, int event) | 585 | struct snd_kcontrol *kcontrol, int event) |
586 | { | 586 | { |
587 | struct snd_soc_codec *codec = w->codec; | 587 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
588 | struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); | 588 | struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); |
589 | switch (event) { | 589 | switch (event) { |
590 | case SND_SOC_DAPM_POST_PMD: | 590 | case SND_SOC_DAPM_POST_PMD: |
@@ -600,7 +600,7 @@ static int cs42l73_spklo_spk_amp_event(struct snd_soc_dapm_widget *w, | |||
600 | static int cs42l73_ear_amp_event(struct snd_soc_dapm_widget *w, | 600 | static int cs42l73_ear_amp_event(struct snd_soc_dapm_widget *w, |
601 | struct snd_kcontrol *kcontrol, int event) | 601 | struct snd_kcontrol *kcontrol, int event) |
602 | { | 602 | { |
603 | struct snd_soc_codec *codec = w->codec; | 603 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
604 | struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); | 604 | struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); |
605 | switch (event) { | 605 | switch (event) { |
606 | case SND_SOC_DAPM_POST_PMD: | 606 | case SND_SOC_DAPM_POST_PMD: |
@@ -618,7 +618,7 @@ static int cs42l73_ear_amp_event(struct snd_soc_dapm_widget *w, | |||
618 | static int cs42l73_hp_amp_event(struct snd_soc_dapm_widget *w, | 618 | static int cs42l73_hp_amp_event(struct snd_soc_dapm_widget *w, |
619 | struct snd_kcontrol *kcontrol, int event) | 619 | struct snd_kcontrol *kcontrol, int event) |
620 | { | 620 | { |
621 | struct snd_soc_codec *codec = w->codec; | 621 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
622 | struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); | 622 | struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); |
623 | switch (event) { | 623 | switch (event) { |
624 | case SND_SOC_DAPM_POST_PMD: | 624 | case SND_SOC_DAPM_POST_PMD: |
diff --git a/sound/soc/codecs/hdmi.c b/sound/soc/codecs/hdmi.c index 1087fd5f9917..1391ad50f95d 100644 --- a/sound/soc/codecs/hdmi.c +++ b/sound/soc/codecs/hdmi.c | |||
@@ -47,6 +47,7 @@ static struct snd_soc_dai_driver hdmi_codec_dai = { | |||
47 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000, | 47 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000, |
48 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 48 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
49 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, | 49 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, |
50 | .sig_bits = 24, | ||
50 | }, | 51 | }, |
51 | .capture = { | 52 | .capture = { |
52 | .stream_name = "Capture", | 53 | .stream_name = "Capture", |
@@ -75,6 +76,7 @@ static struct snd_soc_codec_driver hdmi_codec = { | |||
75 | .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), | 76 | .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), |
76 | .dapm_routes = hdmi_routes, | 77 | .dapm_routes = hdmi_routes, |
77 | .num_dapm_routes = ARRAY_SIZE(hdmi_routes), | 78 | .num_dapm_routes = ARRAY_SIZE(hdmi_routes), |
79 | .ignore_pmdown_time = true, | ||
78 | }; | 80 | }; |
79 | 81 | ||
80 | static int hdmi_codec_probe(struct platform_device *pdev) | 82 | static int hdmi_codec_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index c1ae5764983f..c4dfde9bdf1c 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c | |||
@@ -1395,15 +1395,7 @@ static struct snd_soc_dai_driver lm49453_dai[] = { | |||
1395 | }, | 1395 | }, |
1396 | }; | 1396 | }; |
1397 | 1397 | ||
1398 | /* power down chip */ | ||
1399 | static int lm49453_remove(struct snd_soc_codec *codec) | ||
1400 | { | ||
1401 | lm49453_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1402 | return 0; | ||
1403 | } | ||
1404 | |||
1405 | static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { | 1398 | static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { |
1406 | .remove = lm49453_remove, | ||
1407 | .set_bias_level = lm49453_set_bias_level, | 1399 | .set_bias_level = lm49453_set_bias_level, |
1408 | .controls = lm49453_snd_controls, | 1400 | .controls = lm49453_snd_controls, |
1409 | .num_controls = ARRAY_SIZE(lm49453_snd_controls), | 1401 | .num_controls = ARRAY_SIZE(lm49453_snd_controls), |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 2cd3e5427441..805b3f8cd39d 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -875,7 +875,7 @@ static const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = { | |||
875 | static int max98088_mic_event(struct snd_soc_dapm_widget *w, | 875 | static int max98088_mic_event(struct snd_soc_dapm_widget *w, |
876 | struct snd_kcontrol *kcontrol, int event) | 876 | struct snd_kcontrol *kcontrol, int event) |
877 | { | 877 | { |
878 | struct snd_soc_codec *codec = w->codec; | 878 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
879 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 879 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); |
880 | 880 | ||
881 | switch (event) { | 881 | switch (event) { |
@@ -905,7 +905,7 @@ static int max98088_mic_event(struct snd_soc_dapm_widget *w, | |||
905 | static int max98088_line_pga(struct snd_soc_dapm_widget *w, | 905 | static int max98088_line_pga(struct snd_soc_dapm_widget *w, |
906 | int event, int line, u8 channel) | 906 | int event, int line, u8 channel) |
907 | { | 907 | { |
908 | struct snd_soc_codec *codec = w->codec; | 908 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
909 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 909 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); |
910 | u8 *state; | 910 | u8 *state; |
911 | 911 | ||
@@ -1887,25 +1887,6 @@ static void max98088_handle_pdata(struct snd_soc_codec *codec) | |||
1887 | max98088_handle_eq_pdata(codec); | 1887 | max98088_handle_eq_pdata(codec); |
1888 | } | 1888 | } |
1889 | 1889 | ||
1890 | #ifdef CONFIG_PM | ||
1891 | static int max98088_suspend(struct snd_soc_codec *codec) | ||
1892 | { | ||
1893 | max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1894 | |||
1895 | return 0; | ||
1896 | } | ||
1897 | |||
1898 | static int max98088_resume(struct snd_soc_codec *codec) | ||
1899 | { | ||
1900 | max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1901 | |||
1902 | return 0; | ||
1903 | } | ||
1904 | #else | ||
1905 | #define max98088_suspend NULL | ||
1906 | #define max98088_resume NULL | ||
1907 | #endif | ||
1908 | |||
1909 | static int max98088_probe(struct snd_soc_codec *codec) | 1890 | static int max98088_probe(struct snd_soc_codec *codec) |
1910 | { | 1891 | { |
1911 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 1892 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); |
@@ -1946,9 +1927,6 @@ static int max98088_probe(struct snd_soc_codec *codec) | |||
1946 | 1927 | ||
1947 | snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV); | 1928 | snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV); |
1948 | 1929 | ||
1949 | /* initialize registers cache to hardware default */ | ||
1950 | max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1951 | |||
1952 | snd_soc_write(codec, M98088_REG_0F_IRQ_ENABLE, 0x00); | 1930 | snd_soc_write(codec, M98088_REG_0F_IRQ_ENABLE, 0x00); |
1953 | 1931 | ||
1954 | snd_soc_write(codec, M98088_REG_22_MIX_DAC, | 1932 | snd_soc_write(codec, M98088_REG_22_MIX_DAC, |
@@ -1974,7 +1952,6 @@ static int max98088_remove(struct snd_soc_codec *codec) | |||
1974 | { | 1952 | { |
1975 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | 1953 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); |
1976 | 1954 | ||
1977 | max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1978 | kfree(max98088->eq_texts); | 1955 | kfree(max98088->eq_texts); |
1979 | 1956 | ||
1980 | return 0; | 1957 | return 0; |
@@ -1983,9 +1960,9 @@ static int max98088_remove(struct snd_soc_codec *codec) | |||
1983 | static struct snd_soc_codec_driver soc_codec_dev_max98088 = { | 1960 | static struct snd_soc_codec_driver soc_codec_dev_max98088 = { |
1984 | .probe = max98088_probe, | 1961 | .probe = max98088_probe, |
1985 | .remove = max98088_remove, | 1962 | .remove = max98088_remove, |
1986 | .suspend = max98088_suspend, | ||
1987 | .resume = max98088_resume, | ||
1988 | .set_bias_level = max98088_set_bias_level, | 1963 | .set_bias_level = max98088_set_bias_level, |
1964 | .suspend_bias_off = true, | ||
1965 | |||
1989 | .controls = max98088_snd_controls, | 1966 | .controls = max98088_snd_controls, |
1990 | .num_controls = ARRAY_SIZE(max98088_snd_controls), | 1967 | .num_controls = ARRAY_SIZE(max98088_snd_controls), |
1991 | .dapm_widgets = max98088_dapm_widgets, | 1968 | .dapm_widgets = max98088_dapm_widgets, |
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 1229554f1464..151f718241ea 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -806,7 +806,7 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = { | |||
806 | static int max98090_micinput_event(struct snd_soc_dapm_widget *w, | 806 | static int max98090_micinput_event(struct snd_soc_dapm_widget *w, |
807 | struct snd_kcontrol *kcontrol, int event) | 807 | struct snd_kcontrol *kcontrol, int event) |
808 | { | 808 | { |
809 | struct snd_soc_codec *codec = w->codec; | 809 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
810 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | 810 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); |
811 | 811 | ||
812 | unsigned int val = snd_soc_read(codec, w->reg); | 812 | unsigned int val = snd_soc_read(codec, w->reg); |
@@ -1311,6 +1311,10 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | |||
1311 | {"MIC1 Input", NULL, "MIC1"}, | 1311 | {"MIC1 Input", NULL, "MIC1"}, |
1312 | {"MIC2 Input", NULL, "MIC2"}, | 1312 | {"MIC2 Input", NULL, "MIC2"}, |
1313 | 1313 | ||
1314 | {"DMICL", NULL, "DMICL_ENA"}, | ||
1315 | {"DMICL", NULL, "DMICR_ENA"}, | ||
1316 | {"DMICR", NULL, "DMICL_ENA"}, | ||
1317 | {"DMICR", NULL, "DMICR_ENA"}, | ||
1314 | {"DMICL", NULL, "AHPF"}, | 1318 | {"DMICL", NULL, "AHPF"}, |
1315 | {"DMICR", NULL, "AHPF"}, | 1319 | {"DMICR", NULL, "AHPF"}, |
1316 | 1320 | ||
@@ -1368,8 +1372,6 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | |||
1368 | {"DMIC Mux", "ADC", "ADCR"}, | 1372 | {"DMIC Mux", "ADC", "ADCR"}, |
1369 | {"DMIC Mux", "DMIC", "DMICL"}, | 1373 | {"DMIC Mux", "DMIC", "DMICL"}, |
1370 | {"DMIC Mux", "DMIC", "DMICR"}, | 1374 | {"DMIC Mux", "DMIC", "DMICR"}, |
1371 | {"DMIC Mux", "DMIC", "DMICL_ENA"}, | ||
1372 | {"DMIC Mux", "DMIC", "DMICR_ENA"}, | ||
1373 | 1375 | ||
1374 | {"LBENL Mux", "Normal", "DMIC Mux"}, | 1376 | {"LBENL Mux", "Normal", "DMIC Mux"}, |
1375 | {"LBENL Mux", "Loopback", "LTENL Mux"}, | 1377 | {"LBENL Mux", "Loopback", "LTENL Mux"}, |
@@ -1395,8 +1397,8 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | |||
1395 | {"STENL Mux", "Sidetone Left", "DMICL"}, | 1397 | {"STENL Mux", "Sidetone Left", "DMICL"}, |
1396 | {"STENR Mux", "Sidetone Right", "ADCR"}, | 1398 | {"STENR Mux", "Sidetone Right", "ADCR"}, |
1397 | {"STENR Mux", "Sidetone Right", "DMICR"}, | 1399 | {"STENR Mux", "Sidetone Right", "DMICR"}, |
1398 | {"DACL", "NULL", "STENL Mux"}, | 1400 | {"DACL", NULL, "STENL Mux"}, |
1399 | {"DACR", "NULL", "STENL Mux"}, | 1401 | {"DACR", NULL, "STENR Mux"}, |
1400 | 1402 | ||
1401 | {"AIFINL", NULL, "SHDN"}, | 1403 | {"AIFINL", NULL, "SHDN"}, |
1402 | {"AIFINR", NULL, "SHDN"}, | 1404 | {"AIFINR", NULL, "SHDN"}, |
@@ -1826,27 +1828,155 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec, | |||
1826 | return 0; | 1828 | return 0; |
1827 | } | 1829 | } |
1828 | 1830 | ||
1829 | static const int comp_pclk_rates[] = { | 1831 | static const int dmic_divisors[] = { 2, 3, 4, 5, 6, 8 }; |
1830 | 11289600, 12288000, 12000000, 13000000, 19200000 | ||
1831 | }; | ||
1832 | |||
1833 | static const int dmic_micclk[] = { | ||
1834 | 2, 2, 2, 2, 4, 2 | ||
1835 | }; | ||
1836 | 1832 | ||
1837 | static const int comp_lrclk_rates[] = { | 1833 | static const int comp_lrclk_rates[] = { |
1838 | 8000, 16000, 32000, 44100, 48000, 96000 | 1834 | 8000, 16000, 32000, 44100, 48000, 96000 |
1839 | }; | 1835 | }; |
1840 | 1836 | ||
1841 | static const int dmic_comp[6][6] = { | 1837 | struct dmic_table { |
1842 | {7, 8, 3, 3, 3, 3}, | 1838 | int pclk; |
1843 | {7, 8, 3, 3, 3, 3}, | 1839 | struct { |
1844 | {7, 8, 3, 3, 3, 3}, | 1840 | int freq; |
1845 | {7, 8, 3, 1, 1, 1}, | 1841 | int comp[6]; /* One each for 8, 16, 32, 44.1, 48, and 96 kHz */ |
1846 | {7, 8, 3, 1, 2, 2}, | 1842 | } settings[6]; /* One for each dmic divisor. */ |
1847 | {7, 8, 3, 3, 3, 3} | ||
1848 | }; | 1843 | }; |
1849 | 1844 | ||
1845 | static const struct dmic_table dmic_table[] = { /* One for each pclk freq. */ | ||
1846 | { | ||
1847 | .pclk = 11289600, | ||
1848 | .settings = { | ||
1849 | { .freq = 2, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1850 | { .freq = 1, .comp = { 7, 8, 2, 2, 2, 2 } }, | ||
1851 | { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1852 | { .freq = 0, .comp = { 7, 8, 6, 6, 6, 6 } }, | ||
1853 | { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1854 | { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1855 | }, | ||
1856 | }, | ||
1857 | { | ||
1858 | .pclk = 12000000, | ||
1859 | .settings = { | ||
1860 | { .freq = 2, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1861 | { .freq = 1, .comp = { 7, 8, 2, 2, 2, 2 } }, | ||
1862 | { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1863 | { .freq = 0, .comp = { 7, 8, 5, 5, 6, 6 } }, | ||
1864 | { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1865 | { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1866 | } | ||
1867 | }, | ||
1868 | { | ||
1869 | .pclk = 12288000, | ||
1870 | .settings = { | ||
1871 | { .freq = 2, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1872 | { .freq = 1, .comp = { 7, 8, 2, 2, 2, 2 } }, | ||
1873 | { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1874 | { .freq = 0, .comp = { 7, 8, 6, 6, 6, 6 } }, | ||
1875 | { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1876 | { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, | ||
1877 | } | ||
1878 | }, | ||
1879 | { | ||
1880 | .pclk = 13000000, | ||
1881 | .settings = { | ||
1882 | { .freq = 2, .comp = { 7, 8, 1, 1, 1, 1 } }, | ||
1883 | { .freq = 1, .comp = { 7, 8, 0, 0, 0, 0 } }, | ||
1884 | { .freq = 0, .comp = { 7, 8, 1, 1, 1, 1 } }, | ||
1885 | { .freq = 0, .comp = { 7, 8, 4, 4, 5, 5 } }, | ||
1886 | { .freq = 0, .comp = { 7, 8, 1, 1, 1, 1 } }, | ||
1887 | { .freq = 0, .comp = { 7, 8, 1, 1, 1, 1 } }, | ||
1888 | } | ||
1889 | }, | ||
1890 | { | ||
1891 | .pclk = 19200000, | ||
1892 | .settings = { | ||
1893 | { .freq = 2, .comp = { 0, 0, 0, 0, 0, 0 } }, | ||
1894 | { .freq = 1, .comp = { 7, 8, 1, 1, 1, 1 } }, | ||
1895 | { .freq = 0, .comp = { 7, 8, 5, 5, 6, 6 } }, | ||
1896 | { .freq = 0, .comp = { 7, 8, 2, 2, 3, 3 } }, | ||
1897 | { .freq = 0, .comp = { 7, 8, 1, 1, 2, 2 } }, | ||
1898 | { .freq = 0, .comp = { 7, 8, 5, 5, 6, 6 } }, | ||
1899 | } | ||
1900 | }, | ||
1901 | }; | ||
1902 | |||
1903 | static int max98090_find_divisor(int target_freq, int pclk) | ||
1904 | { | ||
1905 | int current_diff = INT_MAX; | ||
1906 | int test_diff = INT_MAX; | ||
1907 | int divisor_index = 0; | ||
1908 | int i; | ||
1909 | |||
1910 | for (i = 0; i < ARRAY_SIZE(dmic_divisors); i++) { | ||
1911 | test_diff = abs(target_freq - (pclk / dmic_divisors[i])); | ||
1912 | if (test_diff < current_diff) { | ||
1913 | current_diff = test_diff; | ||
1914 | divisor_index = i; | ||
1915 | } | ||
1916 | } | ||
1917 | |||
1918 | return divisor_index; | ||
1919 | } | ||
1920 | |||
1921 | static int max98090_find_closest_pclk(int pclk) | ||
1922 | { | ||
1923 | int m1; | ||
1924 | int m2; | ||
1925 | int i; | ||
1926 | |||
1927 | for (i = 0; i < ARRAY_SIZE(dmic_table); i++) { | ||
1928 | if (pclk == dmic_table[i].pclk) | ||
1929 | return i; | ||
1930 | if (pclk < dmic_table[i].pclk) { | ||
1931 | if (i == 0) | ||
1932 | return i; | ||
1933 | m1 = pclk - dmic_table[i-1].pclk; | ||
1934 | m2 = dmic_table[i].pclk - pclk; | ||
1935 | if (m1 < m2) | ||
1936 | return i - 1; | ||
1937 | else | ||
1938 | return i; | ||
1939 | } | ||
1940 | } | ||
1941 | |||
1942 | return -EINVAL; | ||
1943 | } | ||
1944 | |||
1945 | static int max98090_configure_dmic(struct max98090_priv *max98090, | ||
1946 | int target_dmic_clk, int pclk, int fs) | ||
1947 | { | ||
1948 | int micclk_index; | ||
1949 | int pclk_index; | ||
1950 | int dmic_freq; | ||
1951 | int dmic_comp; | ||
1952 | int i; | ||
1953 | |||
1954 | pclk_index = max98090_find_closest_pclk(pclk); | ||
1955 | if (pclk_index < 0) | ||
1956 | return pclk_index; | ||
1957 | |||
1958 | micclk_index = max98090_find_divisor(target_dmic_clk, pclk); | ||
1959 | |||
1960 | for (i = 0; i < ARRAY_SIZE(comp_lrclk_rates) - 1; i++) { | ||
1961 | if (fs <= (comp_lrclk_rates[i] + comp_lrclk_rates[i+1]) / 2) | ||
1962 | break; | ||
1963 | } | ||
1964 | |||
1965 | dmic_freq = dmic_table[pclk_index].settings[micclk_index].freq; | ||
1966 | dmic_comp = dmic_table[pclk_index].settings[micclk_index].comp[i]; | ||
1967 | |||
1968 | regmap_update_bits(max98090->regmap, M98090_REG_DIGITAL_MIC_ENABLE, | ||
1969 | M98090_MICCLK_MASK, | ||
1970 | micclk_index << M98090_MICCLK_SHIFT); | ||
1971 | |||
1972 | regmap_update_bits(max98090->regmap, M98090_REG_DIGITAL_MIC_CONFIG, | ||
1973 | M98090_DMIC_COMP_MASK | M98090_DMIC_FREQ_MASK, | ||
1974 | dmic_comp << M98090_DMIC_COMP_SHIFT | | ||
1975 | dmic_freq << M98090_DMIC_FREQ_SHIFT); | ||
1976 | |||
1977 | return 0; | ||
1978 | } | ||
1979 | |||
1850 | static int max98090_dai_hw_params(struct snd_pcm_substream *substream, | 1980 | static int max98090_dai_hw_params(struct snd_pcm_substream *substream, |
1851 | struct snd_pcm_hw_params *params, | 1981 | struct snd_pcm_hw_params *params, |
1852 | struct snd_soc_dai *dai) | 1982 | struct snd_soc_dai *dai) |
@@ -1854,7 +1984,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, | |||
1854 | struct snd_soc_codec *codec = dai->codec; | 1984 | struct snd_soc_codec *codec = dai->codec; |
1855 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | 1985 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); |
1856 | struct max98090_cdata *cdata; | 1986 | struct max98090_cdata *cdata; |
1857 | int i, j; | ||
1858 | 1987 | ||
1859 | cdata = &max98090->dai[0]; | 1988 | cdata = &max98090->dai[0]; |
1860 | max98090->bclk = snd_soc_params_to_bclk(params); | 1989 | max98090->bclk = snd_soc_params_to_bclk(params); |
@@ -1893,27 +2022,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, | |||
1893 | snd_soc_update_bits(codec, M98090_REG_FILTER_CONFIG, | 2022 | snd_soc_update_bits(codec, M98090_REG_FILTER_CONFIG, |
1894 | M98090_DHF_MASK, M98090_DHF_MASK); | 2023 | M98090_DHF_MASK, M98090_DHF_MASK); |
1895 | 2024 | ||
1896 | /* Check for supported PCLK to LRCLK ratios */ | 2025 | max98090_configure_dmic(max98090, max98090->dmic_freq, max98090->pclk, |
1897 | for (j = 0; j < ARRAY_SIZE(comp_pclk_rates); j++) { | 2026 | max98090->lrclk); |
1898 | if (comp_pclk_rates[j] == max98090->sysclk) { | ||
1899 | break; | ||
1900 | } | ||
1901 | } | ||
1902 | |||
1903 | for (i = 0; i < ARRAY_SIZE(comp_lrclk_rates) - 1; i++) { | ||
1904 | if (max98090->lrclk <= (comp_lrclk_rates[i] + | ||
1905 | comp_lrclk_rates[i + 1]) / 2) { | ||
1906 | break; | ||
1907 | } | ||
1908 | } | ||
1909 | |||
1910 | snd_soc_update_bits(codec, M98090_REG_DIGITAL_MIC_ENABLE, | ||
1911 | M98090_MICCLK_MASK, | ||
1912 | dmic_micclk[j] << M98090_MICCLK_SHIFT); | ||
1913 | |||
1914 | snd_soc_update_bits(codec, M98090_REG_DIGITAL_MIC_CONFIG, | ||
1915 | M98090_DMIC_COMP_MASK, | ||
1916 | dmic_comp[j][i] << M98090_DMIC_COMP_SHIFT); | ||
1917 | 2027 | ||
1918 | return 0; | 2028 | return 0; |
1919 | } | 2029 | } |
@@ -1944,12 +2054,15 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai, | |||
1944 | if ((freq >= 10000000) && (freq <= 20000000)) { | 2054 | if ((freq >= 10000000) && (freq <= 20000000)) { |
1945 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, | 2055 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, |
1946 | M98090_PSCLK_DIV1); | 2056 | M98090_PSCLK_DIV1); |
2057 | max98090->pclk = freq; | ||
1947 | } else if ((freq > 20000000) && (freq <= 40000000)) { | 2058 | } else if ((freq > 20000000) && (freq <= 40000000)) { |
1948 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, | 2059 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, |
1949 | M98090_PSCLK_DIV2); | 2060 | M98090_PSCLK_DIV2); |
2061 | max98090->pclk = freq >> 1; | ||
1950 | } else if ((freq > 40000000) && (freq <= 60000000)) { | 2062 | } else if ((freq > 40000000) && (freq <= 60000000)) { |
1951 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, | 2063 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, |
1952 | M98090_PSCLK_DIV4); | 2064 | M98090_PSCLK_DIV4); |
2065 | max98090->pclk = freq >> 2; | ||
1953 | } else { | 2066 | } else { |
1954 | dev_err(codec->dev, "Invalid master clock frequency\n"); | 2067 | dev_err(codec->dev, "Invalid master clock frequency\n"); |
1955 | return -EINVAL; | 2068 | return -EINVAL; |
@@ -2324,6 +2437,7 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2324 | /* Initialize private data */ | 2437 | /* Initialize private data */ |
2325 | 2438 | ||
2326 | max98090->sysclk = (unsigned)-1; | 2439 | max98090->sysclk = (unsigned)-1; |
2440 | max98090->pclk = (unsigned)-1; | ||
2327 | max98090->master = false; | 2441 | max98090->master = false; |
2328 | 2442 | ||
2329 | cdata = &max98090->dai[0]; | 2443 | cdata = &max98090->dai[0]; |
@@ -2463,6 +2577,11 @@ static int max98090_i2c_probe(struct i2c_client *i2c, | |||
2463 | i2c_set_clientdata(i2c, max98090); | 2577 | i2c_set_clientdata(i2c, max98090); |
2464 | max98090->pdata = i2c->dev.platform_data; | 2578 | max98090->pdata = i2c->dev.platform_data; |
2465 | 2579 | ||
2580 | ret = of_property_read_u32(i2c->dev.of_node, "maxim,dmic-freq", | ||
2581 | &max98090->dmic_freq); | ||
2582 | if (ret < 0) | ||
2583 | max98090->dmic_freq = MAX98090_DEFAULT_DMIC_FREQ; | ||
2584 | |||
2466 | max98090->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap); | 2585 | max98090->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap); |
2467 | if (IS_ERR(max98090->regmap)) { | 2586 | if (IS_ERR(max98090->regmap)) { |
2468 | ret = PTR_ERR(max98090->regmap); | 2587 | ret = PTR_ERR(max98090->regmap); |
diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h index a5f6bada06da..21ff743f5af2 100644 --- a/sound/soc/codecs/max98090.h +++ b/sound/soc/codecs/max98090.h | |||
@@ -12,6 +12,12 @@ | |||
12 | #define _MAX98090_H | 12 | #define _MAX98090_H |
13 | 13 | ||
14 | /* | 14 | /* |
15 | * The default operating frequency for a DMIC attached to the codec. | ||
16 | * This can be overridden by a device tree property. | ||
17 | */ | ||
18 | #define MAX98090_DEFAULT_DMIC_FREQ 2500000 | ||
19 | |||
20 | /* | ||
15 | * MAX98090 Register Definitions | 21 | * MAX98090 Register Definitions |
16 | */ | 22 | */ |
17 | 23 | ||
@@ -1518,8 +1524,10 @@ struct max98090_priv { | |||
1518 | struct max98090_pdata *pdata; | 1524 | struct max98090_pdata *pdata; |
1519 | struct clk *mclk; | 1525 | struct clk *mclk; |
1520 | unsigned int sysclk; | 1526 | unsigned int sysclk; |
1527 | unsigned int pclk; | ||
1521 | unsigned int bclk; | 1528 | unsigned int bclk; |
1522 | unsigned int lrclk; | 1529 | unsigned int lrclk; |
1530 | u32 dmic_freq; | ||
1523 | struct max98090_cdata dai[1]; | 1531 | struct max98090_cdata dai[1]; |
1524 | int jack_state; | 1532 | int jack_state; |
1525 | struct delayed_work jack_work; | 1533 | struct delayed_work jack_work; |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 0ee6797d5083..8fba0c3db798 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/mutex.h> | ||
19 | #include <sound/core.h> | 20 | #include <sound/core.h> |
20 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
21 | #include <sound/pcm_params.h> | 22 | #include <sound/pcm_params.h> |
@@ -57,6 +58,7 @@ struct max98095_priv { | |||
57 | unsigned int mic2pre; | 58 | unsigned int mic2pre; |
58 | struct snd_soc_jack *headphone_jack; | 59 | struct snd_soc_jack *headphone_jack; |
59 | struct snd_soc_jack *mic_jack; | 60 | struct snd_soc_jack *mic_jack; |
61 | struct mutex lock; | ||
60 | }; | 62 | }; |
61 | 63 | ||
62 | static const struct reg_default max98095_reg_def[] = { | 64 | static const struct reg_default max98095_reg_def[] = { |
@@ -864,7 +866,7 @@ static const struct snd_kcontrol_new max98095_right_ADC_mixer_controls[] = { | |||
864 | static int max98095_mic_event(struct snd_soc_dapm_widget *w, | 866 | static int max98095_mic_event(struct snd_soc_dapm_widget *w, |
865 | struct snd_kcontrol *kcontrol, int event) | 867 | struct snd_kcontrol *kcontrol, int event) |
866 | { | 868 | { |
867 | struct snd_soc_codec *codec = w->codec; | 869 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
868 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | 870 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); |
869 | 871 | ||
870 | switch (event) { | 872 | switch (event) { |
@@ -894,7 +896,7 @@ static int max98095_mic_event(struct snd_soc_dapm_widget *w, | |||
894 | static int max98095_line_pga(struct snd_soc_dapm_widget *w, | 896 | static int max98095_line_pga(struct snd_soc_dapm_widget *w, |
895 | int event, u8 channel) | 897 | int event, u8 channel) |
896 | { | 898 | { |
897 | struct snd_soc_codec *codec = w->codec; | 899 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
898 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | 900 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); |
899 | u8 *state; | 901 | u8 *state; |
900 | 902 | ||
@@ -942,7 +944,7 @@ static int max98095_pga_in2_event(struct snd_soc_dapm_widget *w, | |||
942 | static int max98095_lineout_event(struct snd_soc_dapm_widget *w, | 944 | static int max98095_lineout_event(struct snd_soc_dapm_widget *w, |
943 | struct snd_kcontrol *kcontrol, int event) | 945 | struct snd_kcontrol *kcontrol, int event) |
944 | { | 946 | { |
945 | struct snd_soc_codec *codec = w->codec; | 947 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
946 | 948 | ||
947 | switch (event) { | 949 | switch (event) { |
948 | case SND_SOC_DAPM_POST_PMU: | 950 | case SND_SOC_DAPM_POST_PMU: |
@@ -1803,7 +1805,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol, | |||
1803 | regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); | 1805 | regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); |
1804 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); | 1806 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); |
1805 | 1807 | ||
1806 | mutex_lock(&codec->mutex); | 1808 | mutex_lock(&max98095->lock); |
1807 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); | 1809 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); |
1808 | m98095_eq_band(codec, channel, 0, coef_set->band1); | 1810 | m98095_eq_band(codec, channel, 0, coef_set->band1); |
1809 | m98095_eq_band(codec, channel, 1, coef_set->band2); | 1811 | m98095_eq_band(codec, channel, 1, coef_set->band2); |
@@ -1811,7 +1813,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol, | |||
1811 | m98095_eq_band(codec, channel, 3, coef_set->band4); | 1813 | m98095_eq_band(codec, channel, 3, coef_set->band4); |
1812 | m98095_eq_band(codec, channel, 4, coef_set->band5); | 1814 | m98095_eq_band(codec, channel, 4, coef_set->band5); |
1813 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); | 1815 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); |
1814 | mutex_unlock(&codec->mutex); | 1816 | mutex_unlock(&max98095->lock); |
1815 | 1817 | ||
1816 | /* Restore the original on/off state */ | 1818 | /* Restore the original on/off state */ |
1817 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); | 1819 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); |
@@ -1957,12 +1959,12 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol, | |||
1957 | regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); | 1959 | regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); |
1958 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); | 1960 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); |
1959 | 1961 | ||
1960 | mutex_lock(&codec->mutex); | 1962 | mutex_lock(&max98095->lock); |
1961 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); | 1963 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); |
1962 | m98095_biquad_band(codec, channel, 0, coef_set->band1); | 1964 | m98095_biquad_band(codec, channel, 0, coef_set->band1); |
1963 | m98095_biquad_band(codec, channel, 1, coef_set->band2); | 1965 | m98095_biquad_band(codec, channel, 1, coef_set->band2); |
1964 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); | 1966 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); |
1965 | mutex_unlock(&codec->mutex); | 1967 | mutex_unlock(&max98095->lock); |
1966 | 1968 | ||
1967 | /* Restore the original on/off state */ | 1969 | /* Restore the original on/off state */ |
1968 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); | 1970 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); |
@@ -2317,9 +2319,6 @@ static int max98095_probe(struct snd_soc_codec *codec) | |||
2317 | 2319 | ||
2318 | snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV); | 2320 | snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV); |
2319 | 2321 | ||
2320 | /* initialize registers cache to hardware default */ | ||
2321 | max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
2322 | |||
2323 | snd_soc_write(codec, M98095_048_MIX_DAC_LR, | 2322 | snd_soc_write(codec, M98095_048_MIX_DAC_LR, |
2324 | M98095_DAI1L_TO_DACL|M98095_DAI1R_TO_DACR); | 2323 | M98095_DAI1L_TO_DACL|M98095_DAI1R_TO_DACR); |
2325 | 2324 | ||
@@ -2359,8 +2358,6 @@ static int max98095_remove(struct snd_soc_codec *codec) | |||
2359 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | 2358 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); |
2360 | struct i2c_client *client = to_i2c_client(codec->dev); | 2359 | struct i2c_client *client = to_i2c_client(codec->dev); |
2361 | 2360 | ||
2362 | max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2363 | |||
2364 | if (max98095->headphone_jack || max98095->mic_jack) | 2361 | if (max98095->headphone_jack || max98095->mic_jack) |
2365 | max98095_jack_detect_disable(codec); | 2362 | max98095_jack_detect_disable(codec); |
2366 | 2363 | ||
@@ -2395,6 +2392,8 @@ static int max98095_i2c_probe(struct i2c_client *i2c, | |||
2395 | if (max98095 == NULL) | 2392 | if (max98095 == NULL) |
2396 | return -ENOMEM; | 2393 | return -ENOMEM; |
2397 | 2394 | ||
2395 | mutex_init(&max98095->lock); | ||
2396 | |||
2398 | max98095->regmap = devm_regmap_init_i2c(i2c, &max98095_regmap); | 2397 | max98095->regmap = devm_regmap_init_i2c(i2c, &max98095_regmap); |
2399 | if (IS_ERR(max98095->regmap)) { | 2398 | if (IS_ERR(max98095->regmap)) { |
2400 | ret = PTR_ERR(max98095->regmap); | 2399 | ret = PTR_ERR(max98095->regmap); |
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 4fdf5aaa236f..10f8e47ce2c2 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c | |||
@@ -291,25 +291,6 @@ static struct snd_soc_dai_driver max9850_dai = { | |||
291 | .ops = &max9850_dai_ops, | 291 | .ops = &max9850_dai_ops, |
292 | }; | 292 | }; |
293 | 293 | ||
294 | #ifdef CONFIG_PM | ||
295 | static int max9850_suspend(struct snd_soc_codec *codec) | ||
296 | { | ||
297 | max9850_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static int max9850_resume(struct snd_soc_codec *codec) | ||
303 | { | ||
304 | max9850_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | #else | ||
309 | #define max9850_suspend NULL | ||
310 | #define max9850_resume NULL | ||
311 | #endif | ||
312 | |||
313 | static int max9850_probe(struct snd_soc_codec *codec) | 294 | static int max9850_probe(struct snd_soc_codec *codec) |
314 | { | 295 | { |
315 | /* enable zero-detect */ | 296 | /* enable zero-detect */ |
@@ -324,9 +305,8 @@ static int max9850_probe(struct snd_soc_codec *codec) | |||
324 | 305 | ||
325 | static struct snd_soc_codec_driver soc_codec_dev_max9850 = { | 306 | static struct snd_soc_codec_driver soc_codec_dev_max9850 = { |
326 | .probe = max9850_probe, | 307 | .probe = max9850_probe, |
327 | .suspend = max9850_suspend, | ||
328 | .resume = max9850_resume, | ||
329 | .set_bias_level = max9850_set_bias_level, | 308 | .set_bias_level = max9850_set_bias_level, |
309 | .suspend_bias_off = true, | ||
330 | 310 | ||
331 | .controls = max9850_controls, | 311 | .controls = max9850_controls, |
332 | .num_controls = ARRAY_SIZE(max9850_controls), | 312 | .num_controls = ARRAY_SIZE(max9850_controls), |
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 4aa555cbcca8..2cd4fe463102 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/spi/spi.h> | 19 | #include <linux/spi/spi.h> |
20 | #include <linux/dmi.h> | ||
20 | #include <linux/acpi.h> | 21 | #include <linux/acpi.h> |
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
@@ -36,11 +37,13 @@ | |||
36 | 37 | ||
37 | struct rt286_priv { | 38 | struct rt286_priv { |
38 | struct regmap *regmap; | 39 | struct regmap *regmap; |
40 | struct snd_soc_codec *codec; | ||
39 | struct rt286_platform_data pdata; | 41 | struct rt286_platform_data pdata; |
40 | struct i2c_client *i2c; | 42 | struct i2c_client *i2c; |
41 | struct snd_soc_jack *jack; | 43 | struct snd_soc_jack *jack; |
42 | struct delayed_work jack_detect_work; | 44 | struct delayed_work jack_detect_work; |
43 | int sys_clk; | 45 | int sys_clk; |
46 | int clk_id; | ||
44 | struct reg_default *index_cache; | 47 | struct reg_default *index_cache; |
45 | }; | 48 | }; |
46 | 49 | ||
@@ -188,7 +191,7 @@ static int rt286_hw_write(void *context, unsigned int reg, unsigned int value) | |||
188 | u8 data[4]; | 191 | u8 data[4]; |
189 | int ret, i; | 192 | int ret, i; |
190 | 193 | ||
191 | /*handle index registers*/ | 194 | /* handle index registers */ |
192 | if (reg <= 0xff) { | 195 | if (reg <= 0xff) { |
193 | rt286_hw_write(client, RT286_COEF_INDEX, reg); | 196 | rt286_hw_write(client, RT286_COEF_INDEX, reg); |
194 | for (i = 0; i < INDEX_CACHE_SIZE; i++) { | 197 | for (i = 0; i < INDEX_CACHE_SIZE; i++) { |
@@ -231,7 +234,7 @@ static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value) | |||
231 | __be32 be_reg; | 234 | __be32 be_reg; |
232 | unsigned int index, vid, buf = 0x0; | 235 | unsigned int index, vid, buf = 0x0; |
233 | 236 | ||
234 | /*handle index registers*/ | 237 | /* handle index registers */ |
235 | if (reg <= 0xff) { | 238 | if (reg <= 0xff) { |
236 | rt286_hw_write(client, RT286_COEF_INDEX, reg); | 239 | rt286_hw_write(client, RT286_COEF_INDEX, reg); |
237 | reg = RT286_PROC_COEF; | 240 | reg = RT286_PROC_COEF; |
@@ -298,7 +301,6 @@ static int rt286_support_power_controls[] = { | |||
298 | static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | 301 | static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) |
299 | { | 302 | { |
300 | unsigned int val, buf; | 303 | unsigned int val, buf; |
301 | int i; | ||
302 | 304 | ||
303 | *hp = false; | 305 | *hp = false; |
304 | *mic = false; | 306 | *mic = false; |
@@ -309,67 +311,44 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | |||
309 | if (*hp) { | 311 | if (*hp) { |
310 | /* power on HV,VERF */ | 312 | /* power on HV,VERF */ |
311 | regmap_update_bits(rt286->regmap, | 313 | regmap_update_bits(rt286->regmap, |
312 | RT286_POWER_CTRL1, 0x1001, 0x0); | 314 | RT286_DC_GAIN, 0x200, 0x200); |
315 | |||
316 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, | ||
317 | "HV"); | ||
318 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, | ||
319 | "VREF"); | ||
313 | /* power LDO1 */ | 320 | /* power LDO1 */ |
314 | regmap_update_bits(rt286->regmap, | 321 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, |
315 | RT286_POWER_CTRL2, 0x4, 0x4); | 322 | "LDO1"); |
316 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); | 323 | snd_soc_dapm_sync(&rt286->codec->dapm); |
317 | regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val); | ||
318 | 324 | ||
319 | msleep(200); | 325 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); |
320 | i = 40; | 326 | msleep(50); |
321 | while (((val & 0x0800) == 0) && (i > 0)) { | ||
322 | regmap_read(rt286->regmap, | ||
323 | RT286_CBJ_CTRL2, &val); | ||
324 | i--; | ||
325 | msleep(20); | ||
326 | } | ||
327 | 327 | ||
328 | if (0x0400 == (val & 0x0700)) { | 328 | regmap_update_bits(rt286->regmap, |
329 | *mic = false; | 329 | RT286_CBJ_CTRL1, 0xfcc0, 0xd400); |
330 | msleep(300); | ||
331 | regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val); | ||
330 | 332 | ||
331 | regmap_write(rt286->regmap, | 333 | if (0x0070 == (val & 0x0070)) { |
332 | RT286_SET_MIC1, 0x20); | ||
333 | /* power off HV,VERF */ | ||
334 | regmap_update_bits(rt286->regmap, | ||
335 | RT286_POWER_CTRL1, 0x1001, 0x1001); | ||
336 | regmap_update_bits(rt286->regmap, | ||
337 | RT286_A_BIAS_CTRL3, 0xc000, 0x0000); | ||
338 | regmap_update_bits(rt286->regmap, | ||
339 | RT286_CBJ_CTRL1, 0x0030, 0x0000); | ||
340 | regmap_update_bits(rt286->regmap, | ||
341 | RT286_A_BIAS_CTRL2, 0xc000, 0x0000); | ||
342 | } else if ((0x0200 == (val & 0x0700)) || | ||
343 | (0x0100 == (val & 0x0700))) { | ||
344 | *mic = true; | 334 | *mic = true; |
345 | regmap_update_bits(rt286->regmap, | ||
346 | RT286_A_BIAS_CTRL3, 0xc000, 0x8000); | ||
347 | regmap_update_bits(rt286->regmap, | ||
348 | RT286_CBJ_CTRL1, 0x0030, 0x0020); | ||
349 | regmap_update_bits(rt286->regmap, | ||
350 | RT286_A_BIAS_CTRL2, 0xc000, 0x8000); | ||
351 | } else { | 335 | } else { |
352 | *mic = false; | 336 | regmap_update_bits(rt286->regmap, |
337 | RT286_CBJ_CTRL1, 0xfcc0, 0xe400); | ||
338 | msleep(300); | ||
339 | regmap_read(rt286->regmap, | ||
340 | RT286_CBJ_CTRL2, &val); | ||
341 | if (0x0070 == (val & 0x0070)) | ||
342 | *mic = true; | ||
343 | else | ||
344 | *mic = false; | ||
353 | } | 345 | } |
354 | |||
355 | regmap_update_bits(rt286->regmap, | ||
356 | RT286_MISC_CTRL1, | ||
357 | 0x0060, 0x0000); | ||
358 | } else { | ||
359 | regmap_update_bits(rt286->regmap, | ||
360 | RT286_MISC_CTRL1, | ||
361 | 0x0060, 0x0020); | ||
362 | regmap_update_bits(rt286->regmap, | 346 | regmap_update_bits(rt286->regmap, |
363 | RT286_A_BIAS_CTRL3, | 347 | RT286_DC_GAIN, 0x200, 0x0); |
364 | 0xc000, 0x8000); | ||
365 | regmap_update_bits(rt286->regmap, | ||
366 | RT286_CBJ_CTRL1, | ||
367 | 0x0030, 0x0020); | ||
368 | regmap_update_bits(rt286->regmap, | ||
369 | RT286_A_BIAS_CTRL2, | ||
370 | 0xc000, 0x8000); | ||
371 | 348 | ||
349 | } else { | ||
372 | *mic = false; | 350 | *mic = false; |
351 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x20); | ||
373 | } | 352 | } |
374 | } else { | 353 | } else { |
375 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); | 354 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); |
@@ -378,6 +357,12 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | |||
378 | *mic = buf & 0x80000000; | 357 | *mic = buf & 0x80000000; |
379 | } | 358 | } |
380 | 359 | ||
360 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "HV"); | ||
361 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "VREF"); | ||
362 | if (!*hp) | ||
363 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "LDO1"); | ||
364 | snd_soc_dapm_sync(&rt286->codec->dapm); | ||
365 | |||
381 | return 0; | 366 | return 0; |
382 | } | 367 | } |
383 | 368 | ||
@@ -415,6 +400,17 @@ int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
415 | } | 400 | } |
416 | EXPORT_SYMBOL_GPL(rt286_mic_detect); | 401 | EXPORT_SYMBOL_GPL(rt286_mic_detect); |
417 | 402 | ||
403 | static int is_mclk_mode(struct snd_soc_dapm_widget *source, | ||
404 | struct snd_soc_dapm_widget *sink) | ||
405 | { | ||
406 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(source->codec); | ||
407 | |||
408 | if (rt286->clk_id == RT286_SCLK_S_MCLK) | ||
409 | return 1; | ||
410 | else | ||
411 | return 0; | ||
412 | } | ||
413 | |||
418 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); | 414 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); |
419 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); | 415 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); |
420 | 416 | ||
@@ -568,7 +564,84 @@ static int rt286_adc_event(struct snd_soc_dapm_widget *w, | |||
568 | return 0; | 564 | return 0; |
569 | } | 565 | } |
570 | 566 | ||
567 | static int rt286_vref_event(struct snd_soc_dapm_widget *w, | ||
568 | struct snd_kcontrol *kcontrol, int event) | ||
569 | { | ||
570 | struct snd_soc_codec *codec = w->codec; | ||
571 | |||
572 | switch (event) { | ||
573 | case SND_SOC_DAPM_PRE_PMU: | ||
574 | snd_soc_update_bits(codec, | ||
575 | RT286_CBJ_CTRL1, 0x0400, 0x0000); | ||
576 | mdelay(50); | ||
577 | break; | ||
578 | default: | ||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | static int rt286_ldo2_event(struct snd_soc_dapm_widget *w, | ||
586 | struct snd_kcontrol *kcontrol, int event) | ||
587 | { | ||
588 | struct snd_soc_codec *codec = w->codec; | ||
589 | |||
590 | switch (event) { | ||
591 | case SND_SOC_DAPM_POST_PMU: | ||
592 | snd_soc_update_bits(codec, RT286_POWER_CTRL2, 0x38, 0x08); | ||
593 | break; | ||
594 | case SND_SOC_DAPM_PRE_PMD: | ||
595 | snd_soc_update_bits(codec, RT286_POWER_CTRL2, 0x38, 0x30); | ||
596 | break; | ||
597 | default: | ||
598 | return 0; | ||
599 | } | ||
600 | |||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static int rt286_mic1_event(struct snd_soc_dapm_widget *w, | ||
605 | struct snd_kcontrol *kcontrol, int event) | ||
606 | { | ||
607 | struct snd_soc_codec *codec = w->codec; | ||
608 | |||
609 | switch (event) { | ||
610 | case SND_SOC_DAPM_PRE_PMU: | ||
611 | snd_soc_update_bits(codec, | ||
612 | RT286_A_BIAS_CTRL3, 0xc000, 0x8000); | ||
613 | snd_soc_update_bits(codec, | ||
614 | RT286_A_BIAS_CTRL2, 0xc000, 0x8000); | ||
615 | break; | ||
616 | case SND_SOC_DAPM_POST_PMD: | ||
617 | snd_soc_update_bits(codec, | ||
618 | RT286_A_BIAS_CTRL3, 0xc000, 0x0000); | ||
619 | snd_soc_update_bits(codec, | ||
620 | RT286_A_BIAS_CTRL2, 0xc000, 0x0000); | ||
621 | break; | ||
622 | default: | ||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | return 0; | ||
627 | } | ||
628 | |||
571 | static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { | 629 | static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { |
630 | SND_SOC_DAPM_SUPPLY_S("HV", 1, RT286_POWER_CTRL1, | ||
631 | 12, 1, NULL, 0), | ||
632 | SND_SOC_DAPM_SUPPLY("VREF", RT286_POWER_CTRL1, | ||
633 | 0, 1, rt286_vref_event, SND_SOC_DAPM_PRE_PMU), | ||
634 | SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT286_POWER_CTRL2, | ||
635 | 2, 0, NULL, 0), | ||
636 | SND_SOC_DAPM_SUPPLY_S("LDO2", 2, RT286_POWER_CTRL1, | ||
637 | 13, 1, rt286_ldo2_event, SND_SOC_DAPM_PRE_PMD | | ||
638 | SND_SOC_DAPM_POST_PMU), | ||
639 | SND_SOC_DAPM_SUPPLY("MCLK MODE", RT286_PLL_CTRL1, | ||
640 | 5, 0, NULL, 0), | ||
641 | SND_SOC_DAPM_SUPPLY("MIC1 Input Buffer", SND_SOC_NOPM, | ||
642 | 0, 0, rt286_mic1_event, SND_SOC_DAPM_PRE_PMU | | ||
643 | SND_SOC_DAPM_POST_PMD), | ||
644 | |||
572 | /* Input Lines */ | 645 | /* Input Lines */ |
573 | SND_SOC_DAPM_INPUT("DMIC1 Pin"), | 646 | SND_SOC_DAPM_INPUT("DMIC1 Pin"), |
574 | SND_SOC_DAPM_INPUT("DMIC2 Pin"), | 647 | SND_SOC_DAPM_INPUT("DMIC2 Pin"), |
@@ -642,6 +715,25 @@ static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { | |||
642 | }; | 715 | }; |
643 | 716 | ||
644 | static const struct snd_soc_dapm_route rt286_dapm_routes[] = { | 717 | static const struct snd_soc_dapm_route rt286_dapm_routes[] = { |
718 | {"ADC 0", NULL, "MCLK MODE", is_mclk_mode}, | ||
719 | {"ADC 1", NULL, "MCLK MODE", is_mclk_mode}, | ||
720 | {"Front", NULL, "MCLK MODE", is_mclk_mode}, | ||
721 | {"Surround", NULL, "MCLK MODE", is_mclk_mode}, | ||
722 | |||
723 | {"HP Power", NULL, "LDO1"}, | ||
724 | {"HP Power", NULL, "LDO2"}, | ||
725 | |||
726 | {"MIC1", NULL, "LDO1"}, | ||
727 | {"MIC1", NULL, "LDO2"}, | ||
728 | {"MIC1", NULL, "HV"}, | ||
729 | {"MIC1", NULL, "VREF"}, | ||
730 | {"MIC1", NULL, "MIC1 Input Buffer"}, | ||
731 | |||
732 | {"SPO", NULL, "LDO1"}, | ||
733 | {"SPO", NULL, "LDO2"}, | ||
734 | {"SPO", NULL, "HV"}, | ||
735 | {"SPO", NULL, "VREF"}, | ||
736 | |||
645 | {"DMIC1", NULL, "DMIC1 Pin"}, | 737 | {"DMIC1", NULL, "DMIC1 Pin"}, |
646 | {"DMIC2", NULL, "DMIC2 Pin"}, | 738 | {"DMIC2", NULL, "DMIC2 Pin"}, |
647 | {"DMIC1", NULL, "DMIC Receiver"}, | 739 | {"DMIC1", NULL, "DMIC Receiver"}, |
@@ -880,6 +972,7 @@ static int rt286_set_dai_sysclk(struct snd_soc_dai *dai, | |||
880 | } | 972 | } |
881 | 973 | ||
882 | rt286->sys_clk = freq; | 974 | rt286->sys_clk = freq; |
975 | rt286->clk_id = clk_id; | ||
883 | 976 | ||
884 | return 0; | 977 | return 0; |
885 | } | 978 | } |
@@ -915,13 +1008,18 @@ static int rt286_set_bias_level(struct snd_soc_codec *codec, | |||
915 | 1008 | ||
916 | case SND_SOC_BIAS_ON: | 1009 | case SND_SOC_BIAS_ON: |
917 | mdelay(10); | 1010 | mdelay(10); |
1011 | snd_soc_update_bits(codec, | ||
1012 | RT286_CBJ_CTRL1, 0x0400, 0x0400); | ||
1013 | snd_soc_update_bits(codec, | ||
1014 | RT286_DC_GAIN, 0x200, 0x0); | ||
1015 | |||
918 | break; | 1016 | break; |
919 | 1017 | ||
920 | case SND_SOC_BIAS_STANDBY: | 1018 | case SND_SOC_BIAS_STANDBY: |
921 | snd_soc_write(codec, | 1019 | snd_soc_write(codec, |
922 | RT286_SET_AUDIO_POWER, AC_PWRST_D3); | 1020 | RT286_SET_AUDIO_POWER, AC_PWRST_D3); |
923 | snd_soc_update_bits(codec, | 1021 | snd_soc_update_bits(codec, |
924 | RT286_DC_GAIN, 0x200, 0x0); | 1022 | RT286_CBJ_CTRL1, 0x0400, 0x0000); |
925 | break; | 1023 | break; |
926 | 1024 | ||
927 | default: | 1025 | default: |
@@ -962,6 +1060,7 @@ static int rt286_probe(struct snd_soc_codec *codec) | |||
962 | { | 1060 | { |
963 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | 1061 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); |
964 | 1062 | ||
1063 | rt286->codec = codec; | ||
965 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | 1064 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; |
966 | 1065 | ||
967 | if (rt286->i2c->irq) { | 1066 | if (rt286->i2c->irq) { |
@@ -1107,6 +1206,16 @@ static const struct acpi_device_id rt286_acpi_match[] = { | |||
1107 | }; | 1206 | }; |
1108 | MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); | 1207 | MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); |
1109 | 1208 | ||
1209 | static struct dmi_system_id force_combo_jack_table[] = { | ||
1210 | { | ||
1211 | .ident = "Intel Wilson Beach", | ||
1212 | .matches = { | ||
1213 | DMI_MATCH(DMI_BOARD_NAME, "Wilson Beach SDS") | ||
1214 | } | ||
1215 | }, | ||
1216 | { } | ||
1217 | }; | ||
1218 | |||
1110 | static int rt286_i2c_probe(struct i2c_client *i2c, | 1219 | static int rt286_i2c_probe(struct i2c_client *i2c, |
1111 | const struct i2c_device_id *id) | 1220 | const struct i2c_device_id *id) |
1112 | { | 1221 | { |
@@ -1142,6 +1251,9 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1142 | if (pdata) | 1251 | if (pdata) |
1143 | rt286->pdata = *pdata; | 1252 | rt286->pdata = *pdata; |
1144 | 1253 | ||
1254 | if (dmi_check_system(force_combo_jack_table)) | ||
1255 | rt286->pdata.cbj_en = true; | ||
1256 | |||
1145 | regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); | 1257 | regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); |
1146 | 1258 | ||
1147 | for (i = 0; i < RT286_POWER_REG_LEN; i++) | 1259 | for (i = 0; i < RT286_POWER_REG_LEN; i++) |
@@ -1152,7 +1264,6 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1152 | if (!rt286->pdata.cbj_en) { | 1264 | if (!rt286->pdata.cbj_en) { |
1153 | regmap_write(rt286->regmap, RT286_CBJ_CTRL2, 0x0000); | 1265 | regmap_write(rt286->regmap, RT286_CBJ_CTRL2, 0x0000); |
1154 | regmap_write(rt286->regmap, RT286_MIC1_DET_CTRL, 0x0816); | 1266 | regmap_write(rt286->regmap, RT286_MIC1_DET_CTRL, 0x0816); |
1155 | regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000); | ||
1156 | regmap_update_bits(rt286->regmap, | 1267 | regmap_update_bits(rt286->regmap, |
1157 | RT286_CBJ_CTRL1, 0xf000, 0xb000); | 1268 | RT286_CBJ_CTRL1, 0xf000, 0xb000); |
1158 | } else { | 1269 | } else { |
@@ -1169,10 +1280,12 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1169 | 1280 | ||
1170 | mdelay(10); | 1281 | mdelay(10); |
1171 | 1282 | ||
1172 | /*Power down LDO2*/ | 1283 | regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000); |
1173 | regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0x8, 0x0); | 1284 | /* Power down LDO, VREF */ |
1285 | regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0xc, 0x0); | ||
1286 | regmap_update_bits(rt286->regmap, RT286_POWER_CTRL1, 0x1001, 0x1001); | ||
1174 | 1287 | ||
1175 | /*Set depop parameter*/ | 1288 | /* Set depop parameter */ |
1176 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL2, 0x403a, 0x401a); | 1289 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL2, 0x403a, 0x401a); |
1177 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); | 1290 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); |
1178 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); | 1291 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); |
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 1ba27db660a6..6d7b7ca7d530 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c | |||
@@ -1612,29 +1612,6 @@ static int rt5631_probe(struct snd_soc_codec *codec) | |||
1612 | return 0; | 1612 | return 0; |
1613 | } | 1613 | } |
1614 | 1614 | ||
1615 | static int rt5631_remove(struct snd_soc_codec *codec) | ||
1616 | { | ||
1617 | rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1618 | return 0; | ||
1619 | } | ||
1620 | |||
1621 | #ifdef CONFIG_PM | ||
1622 | static int rt5631_suspend(struct snd_soc_codec *codec) | ||
1623 | { | ||
1624 | rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1625 | return 0; | ||
1626 | } | ||
1627 | |||
1628 | static int rt5631_resume(struct snd_soc_codec *codec) | ||
1629 | { | ||
1630 | rt5631_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1631 | return 0; | ||
1632 | } | ||
1633 | #else | ||
1634 | #define rt5631_suspend NULL | ||
1635 | #define rt5631_resume NULL | ||
1636 | #endif | ||
1637 | |||
1638 | #define RT5631_STEREO_RATES SNDRV_PCM_RATE_8000_96000 | 1615 | #define RT5631_STEREO_RATES SNDRV_PCM_RATE_8000_96000 |
1639 | #define RT5631_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \ | 1616 | #define RT5631_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \ |
1640 | SNDRV_PCM_FMTBIT_S20_3LE | \ | 1617 | SNDRV_PCM_FMTBIT_S20_3LE | \ |
@@ -1672,10 +1649,8 @@ static struct snd_soc_dai_driver rt5631_dai[] = { | |||
1672 | 1649 | ||
1673 | static struct snd_soc_codec_driver soc_codec_dev_rt5631 = { | 1650 | static struct snd_soc_codec_driver soc_codec_dev_rt5631 = { |
1674 | .probe = rt5631_probe, | 1651 | .probe = rt5631_probe, |
1675 | .remove = rt5631_remove, | ||
1676 | .suspend = rt5631_suspend, | ||
1677 | .resume = rt5631_resume, | ||
1678 | .set_bias_level = rt5631_set_bias_level, | 1652 | .set_bias_level = rt5631_set_bias_level, |
1653 | .suspend_bias_off = true, | ||
1679 | .controls = rt5631_snd_controls, | 1654 | .controls = rt5631_snd_controls, |
1680 | .num_controls = ARRAY_SIZE(rt5631_snd_controls), | 1655 | .num_controls = ARRAY_SIZE(rt5631_snd_controls), |
1681 | .dapm_widgets = rt5631_dapm_widgets, | 1656 | .dapm_widgets = rt5631_dapm_widgets, |
@@ -1686,10 +1661,20 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5631 = { | |||
1686 | 1661 | ||
1687 | static const struct i2c_device_id rt5631_i2c_id[] = { | 1662 | static const struct i2c_device_id rt5631_i2c_id[] = { |
1688 | { "rt5631", 0 }, | 1663 | { "rt5631", 0 }, |
1664 | { "alc5631", 0 }, | ||
1689 | { } | 1665 | { } |
1690 | }; | 1666 | }; |
1691 | MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id); | 1667 | MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id); |
1692 | 1668 | ||
1669 | #ifdef CONFIG_OF | ||
1670 | static struct of_device_id rt5631_i2c_dt_ids[] = { | ||
1671 | { .compatible = "realtek,rt5631"}, | ||
1672 | { .compatible = "realtek,alc5631"}, | ||
1673 | { } | ||
1674 | }; | ||
1675 | MODULE_DEVICE_TABLE(of, rt5631_i2c_dt_ids); | ||
1676 | #endif | ||
1677 | |||
1693 | static const struct regmap_config rt5631_regmap_config = { | 1678 | static const struct regmap_config rt5631_regmap_config = { |
1694 | .reg_bits = 8, | 1679 | .reg_bits = 8, |
1695 | .val_bits = 16, | 1680 | .val_bits = 16, |
@@ -1734,6 +1719,7 @@ static struct i2c_driver rt5631_i2c_driver = { | |||
1734 | .driver = { | 1719 | .driver = { |
1735 | .name = "rt5631", | 1720 | .name = "rt5631", |
1736 | .owner = THIS_MODULE, | 1721 | .owner = THIS_MODULE, |
1722 | .of_match_table = of_match_ptr(rt5631_i2c_dt_ids), | ||
1737 | }, | 1723 | }, |
1738 | .probe = rt5631_i2c_probe, | 1724 | .probe = rt5631_i2c_probe, |
1739 | .remove = rt5631_i2c_remove, | 1725 | .remove = rt5631_i2c_remove, |
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index d16331e0b64d..a7789a8726e3 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -554,6 +554,53 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | |||
554 | return 0; | 554 | return 0; |
555 | } | 555 | } |
556 | 556 | ||
557 | static int is_using_asrc(struct snd_soc_dapm_widget *source, | ||
558 | struct snd_soc_dapm_widget *sink) | ||
559 | { | ||
560 | unsigned int reg, shift, val; | ||
561 | |||
562 | switch (source->shift) { | ||
563 | case 0: | ||
564 | reg = RT5645_ASRC_3; | ||
565 | shift = 0; | ||
566 | break; | ||
567 | case 1: | ||
568 | reg = RT5645_ASRC_3; | ||
569 | shift = 4; | ||
570 | break; | ||
571 | case 3: | ||
572 | reg = RT5645_ASRC_2; | ||
573 | shift = 0; | ||
574 | break; | ||
575 | case 8: | ||
576 | reg = RT5645_ASRC_2; | ||
577 | shift = 4; | ||
578 | break; | ||
579 | case 9: | ||
580 | reg = RT5645_ASRC_2; | ||
581 | shift = 8; | ||
582 | break; | ||
583 | case 10: | ||
584 | reg = RT5645_ASRC_2; | ||
585 | shift = 12; | ||
586 | break; | ||
587 | default: | ||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | val = (snd_soc_read(source->codec, reg) >> shift) & 0xf; | ||
592 | switch (val) { | ||
593 | case 1: | ||
594 | case 2: | ||
595 | case 3: | ||
596 | case 4: | ||
597 | return 1; | ||
598 | default: | ||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | } | ||
603 | |||
557 | /* Digital Mixer */ | 604 | /* Digital Mixer */ |
558 | static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = { | 605 | static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = { |
559 | SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER, | 606 | SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER, |
@@ -1246,6 +1293,30 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { | |||
1246 | SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5645_PWR_VOL, | 1293 | SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5645_PWR_VOL, |
1247 | RT5645_PWR_MIC_DET_BIT, 0, NULL, 0), | 1294 | RT5645_PWR_MIC_DET_BIT, 0, NULL, 0), |
1248 | 1295 | ||
1296 | /* ASRC */ | ||
1297 | SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5645_ASRC_1, | ||
1298 | 11, 0, NULL, 0), | ||
1299 | SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5645_ASRC_1, | ||
1300 | 12, 0, NULL, 0), | ||
1301 | SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5645_ASRC_1, | ||
1302 | 10, 0, NULL, 0), | ||
1303 | SND_SOC_DAPM_SUPPLY_S("DAC MONO L ASRC", 1, RT5645_ASRC_1, | ||
1304 | 9, 0, NULL, 0), | ||
1305 | SND_SOC_DAPM_SUPPLY_S("DAC MONO R ASRC", 1, RT5645_ASRC_1, | ||
1306 | 8, 0, NULL, 0), | ||
1307 | SND_SOC_DAPM_SUPPLY_S("DMIC STO1 ASRC", 1, RT5645_ASRC_1, | ||
1308 | 7, 0, NULL, 0), | ||
1309 | SND_SOC_DAPM_SUPPLY_S("DMIC MONO L ASRC", 1, RT5645_ASRC_1, | ||
1310 | 5, 0, NULL, 0), | ||
1311 | SND_SOC_DAPM_SUPPLY_S("DMIC MONO R ASRC", 1, RT5645_ASRC_1, | ||
1312 | 4, 0, NULL, 0), | ||
1313 | SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5645_ASRC_1, | ||
1314 | 3, 0, NULL, 0), | ||
1315 | SND_SOC_DAPM_SUPPLY_S("ADC MONO L ASRC", 1, RT5645_ASRC_1, | ||
1316 | 1, 0, NULL, 0), | ||
1317 | SND_SOC_DAPM_SUPPLY_S("ADC MONO R ASRC", 1, RT5645_ASRC_1, | ||
1318 | 0, 0, NULL, 0), | ||
1319 | |||
1249 | /* Input Side */ | 1320 | /* Input Side */ |
1250 | /* micbias */ | 1321 | /* micbias */ |
1251 | SND_SOC_DAPM_MICBIAS("micbias1", RT5645_PWR_ANLG2, | 1322 | SND_SOC_DAPM_MICBIAS("micbias1", RT5645_PWR_ANLG2, |
@@ -1504,6 +1575,17 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { | |||
1504 | }; | 1575 | }; |
1505 | 1576 | ||
1506 | static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { | 1577 | static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { |
1578 | { "adc stereo1 filter", NULL, "ADC STO1 ASRC", is_using_asrc }, | ||
1579 | { "adc stereo2 filter", NULL, "ADC STO2 ASRC", is_using_asrc }, | ||
1580 | { "adc mono left filter", NULL, "ADC MONO L ASRC", is_using_asrc }, | ||
1581 | { "adc mono right filter", NULL, "ADC MONO R ASRC", is_using_asrc }, | ||
1582 | { "dac mono left filter", NULL, "DAC MONO L ASRC", is_using_asrc }, | ||
1583 | { "dac mono right filter", NULL, "DAC MONO R ASRC", is_using_asrc }, | ||
1584 | { "dac stereo1 filter", NULL, "DAC STO ASRC", is_using_asrc }, | ||
1585 | |||
1586 | { "I2S1", NULL, "I2S1 ASRC" }, | ||
1587 | { "I2S2", NULL, "I2S2 ASRC" }, | ||
1588 | |||
1507 | { "IN1P", NULL, "LDO2" }, | 1589 | { "IN1P", NULL, "LDO2" }, |
1508 | { "IN2P", NULL, "LDO2" }, | 1590 | { "IN2P", NULL, "LDO2" }, |
1509 | 1591 | ||
@@ -1550,12 +1632,15 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { | |||
1550 | 1632 | ||
1551 | { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" }, | 1633 | { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" }, |
1552 | { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" }, | 1634 | { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" }, |
1635 | { "Stereo1 DMIC Mux", NULL, "DMIC STO1 ASRC" }, | ||
1553 | 1636 | ||
1554 | { "Mono DMIC L Mux", "DMIC1", "DMIC L1" }, | 1637 | { "Mono DMIC L Mux", "DMIC1", "DMIC L1" }, |
1555 | { "Mono DMIC L Mux", "DMIC2", "DMIC L2" }, | 1638 | { "Mono DMIC L Mux", "DMIC2", "DMIC L2" }, |
1639 | { "Mono DMIC L Mux", NULL, "DMIC MONO L ASRC" }, | ||
1556 | 1640 | ||
1557 | { "Mono DMIC R Mux", "DMIC1", "DMIC R1" }, | 1641 | { "Mono DMIC R Mux", "DMIC1", "DMIC R1" }, |
1558 | { "Mono DMIC R Mux", "DMIC2", "DMIC R2" }, | 1642 | { "Mono DMIC R Mux", "DMIC2", "DMIC R2" }, |
1643 | { "Mono DMIC R Mux", NULL, "DMIC MONO R ASRC" }, | ||
1559 | 1644 | ||
1560 | { "Stereo1 ADC L2 Mux", "DMIC", "Stereo1 DMIC Mux" }, | 1645 | { "Stereo1 ADC L2 Mux", "DMIC", "Stereo1 DMIC Mux" }, |
1561 | { "Stereo1 ADC L2 Mux", "DAC MIX", "DAC MIXL" }, | 1646 | { "Stereo1 ADC L2 Mux", "DAC MIX", "DAC MIXL" }, |
@@ -2029,8 +2114,11 @@ static int rt5645_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
2029 | struct snd_soc_codec *codec = dai->codec; | 2114 | struct snd_soc_codec *codec = dai->codec; |
2030 | unsigned int val = 0; | 2115 | unsigned int val = 0; |
2031 | 2116 | ||
2032 | if (rx_mask || tx_mask) | 2117 | if (rx_mask || tx_mask) { |
2033 | val |= (1 << 14); | 2118 | val |= (1 << 14); |
2119 | snd_soc_update_bits(codec, RT5645_BASS_BACK, | ||
2120 | RT5645_G_BB_BST_MASK, RT5645_G_BB_BST_25DB); | ||
2121 | } | ||
2034 | 2122 | ||
2035 | switch (slots) { | 2123 | switch (slots) { |
2036 | case 4: | 2124 | case 4: |
@@ -2071,8 +2159,8 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, | |||
2071 | enum snd_soc_bias_level level) | 2159 | enum snd_soc_bias_level level) |
2072 | { | 2160 | { |
2073 | switch (level) { | 2161 | switch (level) { |
2074 | case SND_SOC_BIAS_STANDBY: | 2162 | case SND_SOC_BIAS_PREPARE: |
2075 | if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) { | 2163 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { |
2076 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, | 2164 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, |
2077 | RT5645_PWR_VREF1 | RT5645_PWR_MB | | 2165 | RT5645_PWR_VREF1 | RT5645_PWR_MB | |
2078 | RT5645_PWR_BG | RT5645_PWR_VREF2, | 2166 | RT5645_PWR_BG | RT5645_PWR_VREF2, |
@@ -2087,15 +2175,24 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, | |||
2087 | } | 2175 | } |
2088 | break; | 2176 | break; |
2089 | 2177 | ||
2178 | case SND_SOC_BIAS_STANDBY: | ||
2179 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, | ||
2180 | RT5645_PWR_VREF1 | RT5645_PWR_MB | | ||
2181 | RT5645_PWR_BG | RT5645_PWR_VREF2, | ||
2182 | RT5645_PWR_VREF1 | RT5645_PWR_MB | | ||
2183 | RT5645_PWR_BG | RT5645_PWR_VREF2); | ||
2184 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, | ||
2185 | RT5645_PWR_FV1 | RT5645_PWR_FV2, | ||
2186 | RT5645_PWR_FV1 | RT5645_PWR_FV2); | ||
2187 | break; | ||
2188 | |||
2090 | case SND_SOC_BIAS_OFF: | 2189 | case SND_SOC_BIAS_OFF: |
2091 | snd_soc_write(codec, RT5645_DEPOP_M2, 0x1100); | 2190 | snd_soc_write(codec, RT5645_DEPOP_M2, 0x1100); |
2092 | snd_soc_write(codec, RT5645_GEN_CTRL1, 0x0128); | 2191 | snd_soc_write(codec, RT5645_GEN_CTRL1, 0x0128); |
2093 | snd_soc_write(codec, RT5645_PWR_DIG1, 0x0000); | 2192 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, |
2094 | snd_soc_write(codec, RT5645_PWR_DIG2, 0x0000); | 2193 | RT5645_PWR_VREF1 | RT5645_PWR_MB | |
2095 | snd_soc_write(codec, RT5645_PWR_VOL, 0x0000); | 2194 | RT5645_PWR_BG | RT5645_PWR_VREF2 | |
2096 | snd_soc_write(codec, RT5645_PWR_MIXER, 0x0000); | 2195 | RT5645_PWR_FV1 | RT5645_PWR_FV2, 0x0); |
2097 | snd_soc_write(codec, RT5645_PWR_ANLG1, 0x0000); | ||
2098 | snd_soc_write(codec, RT5645_PWR_ANLG2, 0x0000); | ||
2099 | break; | 2196 | break; |
2100 | 2197 | ||
2101 | default: | 2198 | default: |
@@ -2106,8 +2203,7 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, | |||
2106 | return 0; | 2203 | return 0; |
2107 | } | 2204 | } |
2108 | 2205 | ||
2109 | static int rt5645_jack_detect(struct snd_soc_codec *codec, | 2206 | static int rt5645_jack_detect(struct snd_soc_codec *codec) |
2110 | struct snd_soc_jack *jack) | ||
2111 | { | 2207 | { |
2112 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 2208 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); |
2113 | int gpio_state, jack_type = 0; | 2209 | int gpio_state, jack_type = 0; |
@@ -2145,34 +2241,44 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, | |||
2145 | 2241 | ||
2146 | snd_soc_dapm_disable_pin(&codec->dapm, "micbias1"); | 2242 | snd_soc_dapm_disable_pin(&codec->dapm, "micbias1"); |
2147 | snd_soc_dapm_disable_pin(&codec->dapm, "micbias2"); | 2243 | snd_soc_dapm_disable_pin(&codec->dapm, "micbias2"); |
2148 | snd_soc_dapm_disable_pin(&codec->dapm, "LDO2"); | 2244 | if (rt5645->pdata.jd_mode == 0) |
2245 | snd_soc_dapm_disable_pin(&codec->dapm, "LDO2"); | ||
2149 | snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); | 2246 | snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); |
2150 | snd_soc_dapm_sync(&codec->dapm); | 2247 | snd_soc_dapm_sync(&codec->dapm); |
2151 | } | 2248 | } |
2152 | 2249 | ||
2153 | snd_soc_jack_report(rt5645->jack, jack_type, SND_JACK_HEADSET); | 2250 | snd_soc_jack_report(rt5645->hp_jack, jack_type, SND_JACK_HEADPHONE); |
2154 | 2251 | snd_soc_jack_report(rt5645->mic_jack, jack_type, SND_JACK_MICROPHONE); | |
2155 | return 0; | 2252 | return 0; |
2156 | } | 2253 | } |
2157 | 2254 | ||
2158 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, | 2255 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, |
2159 | struct snd_soc_jack *jack) | 2256 | struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack) |
2160 | { | 2257 | { |
2161 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 2258 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); |
2162 | 2259 | ||
2163 | rt5645->jack = jack; | 2260 | rt5645->hp_jack = hp_jack; |
2164 | 2261 | rt5645->mic_jack = mic_jack; | |
2165 | rt5645_jack_detect(codec, rt5645->jack); | 2262 | rt5645_jack_detect(codec); |
2166 | 2263 | ||
2167 | return 0; | 2264 | return 0; |
2168 | } | 2265 | } |
2169 | EXPORT_SYMBOL_GPL(rt5645_set_jack_detect); | 2266 | EXPORT_SYMBOL_GPL(rt5645_set_jack_detect); |
2170 | 2267 | ||
2268 | static void rt5645_jack_detect_work(struct work_struct *work) | ||
2269 | { | ||
2270 | struct rt5645_priv *rt5645 = | ||
2271 | container_of(work, struct rt5645_priv, jack_detect_work.work); | ||
2272 | |||
2273 | rt5645_jack_detect(rt5645->codec); | ||
2274 | } | ||
2275 | |||
2171 | static irqreturn_t rt5645_irq(int irq, void *data) | 2276 | static irqreturn_t rt5645_irq(int irq, void *data) |
2172 | { | 2277 | { |
2173 | struct rt5645_priv *rt5645 = data; | 2278 | struct rt5645_priv *rt5645 = data; |
2174 | 2279 | ||
2175 | rt5645_jack_detect(rt5645->codec, rt5645->jack); | 2280 | queue_delayed_work(system_power_efficient_wq, |
2281 | &rt5645->jack_detect_work, msecs_to_jiffies(250)); | ||
2176 | 2282 | ||
2177 | return IRQ_HANDLED; | 2283 | return IRQ_HANDLED; |
2178 | } | 2284 | } |
@@ -2187,6 +2293,13 @@ static int rt5645_probe(struct snd_soc_codec *codec) | |||
2187 | 2293 | ||
2188 | snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200); | 2294 | snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200); |
2189 | 2295 | ||
2296 | /* for JD function */ | ||
2297 | if (rt5645->pdata.en_jd_func) { | ||
2298 | snd_soc_dapm_force_enable_pin(&codec->dapm, "JD Power"); | ||
2299 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); | ||
2300 | snd_soc_dapm_sync(&codec->dapm); | ||
2301 | } | ||
2302 | |||
2190 | return 0; | 2303 | return 0; |
2191 | } | 2304 | } |
2192 | 2305 | ||
@@ -2420,6 +2533,51 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2420 | 2533 | ||
2421 | } | 2534 | } |
2422 | 2535 | ||
2536 | if (rt5645->pdata.en_jd_func) { | ||
2537 | regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, | ||
2538 | RT5645_IRQ_CLK_GATE_CTRL | RT5645_MICINDET_MANU, | ||
2539 | RT5645_IRQ_CLK_GATE_CTRL | RT5645_MICINDET_MANU); | ||
2540 | regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, | ||
2541 | RT5645_CBJ_BST1_EN, RT5645_CBJ_BST1_EN); | ||
2542 | regmap_update_bits(rt5645->regmap, RT5645_JD_CTRL3, | ||
2543 | RT5645_JD_CBJ_EN | RT5645_JD_CBJ_POL, | ||
2544 | RT5645_JD_CBJ_EN | RT5645_JD_CBJ_POL); | ||
2545 | regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, | ||
2546 | RT5645_IRQ_CLK_INT, RT5645_IRQ_CLK_INT); | ||
2547 | } | ||
2548 | |||
2549 | if (rt5645->pdata.jd_mode) { | ||
2550 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, | ||
2551 | RT5645_IRQ_JD_1_1_EN, RT5645_IRQ_JD_1_1_EN); | ||
2552 | regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, | ||
2553 | RT5645_JD_PSV_MODE, RT5645_JD_PSV_MODE); | ||
2554 | regmap_update_bits(rt5645->regmap, RT5645_HPO_MIXER, | ||
2555 | RT5645_IRQ_PSV_MODE, RT5645_IRQ_PSV_MODE); | ||
2556 | regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, | ||
2557 | RT5645_MIC2_OVCD_EN, RT5645_MIC2_OVCD_EN); | ||
2558 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, | ||
2559 | RT5645_GP1_PIN_IRQ, RT5645_GP1_PIN_IRQ); | ||
2560 | switch (rt5645->pdata.jd_mode) { | ||
2561 | case 1: | ||
2562 | regmap_update_bits(rt5645->regmap, RT5645_A_JD_CTRL1, | ||
2563 | RT5645_JD1_MODE_MASK, | ||
2564 | RT5645_JD1_MODE_0); | ||
2565 | break; | ||
2566 | case 2: | ||
2567 | regmap_update_bits(rt5645->regmap, RT5645_A_JD_CTRL1, | ||
2568 | RT5645_JD1_MODE_MASK, | ||
2569 | RT5645_JD1_MODE_1); | ||
2570 | break; | ||
2571 | case 3: | ||
2572 | regmap_update_bits(rt5645->regmap, RT5645_A_JD_CTRL1, | ||
2573 | RT5645_JD1_MODE_MASK, | ||
2574 | RT5645_JD1_MODE_2); | ||
2575 | break; | ||
2576 | default: | ||
2577 | break; | ||
2578 | } | ||
2579 | } | ||
2580 | |||
2423 | if (rt5645->i2c->irq) { | 2581 | if (rt5645->i2c->irq) { |
2424 | ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, | 2582 | ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, |
2425 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | 2583 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
@@ -2438,6 +2596,8 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2438 | dev_err(&i2c->dev, "Fail gpio_direction hp_det_gpio\n"); | 2596 | dev_err(&i2c->dev, "Fail gpio_direction hp_det_gpio\n"); |
2439 | } | 2597 | } |
2440 | 2598 | ||
2599 | INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work); | ||
2600 | |||
2441 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, | 2601 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, |
2442 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); | 2602 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); |
2443 | } | 2603 | } |
@@ -2449,6 +2609,8 @@ static int rt5645_i2c_remove(struct i2c_client *i2c) | |||
2449 | if (i2c->irq) | 2609 | if (i2c->irq) |
2450 | free_irq(i2c->irq, rt5645); | 2610 | free_irq(i2c->irq, rt5645); |
2451 | 2611 | ||
2612 | cancel_delayed_work_sync(&rt5645->jack_detect_work); | ||
2613 | |||
2452 | if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) | 2614 | if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) |
2453 | gpio_free(rt5645->pdata.hp_det_gpio); | 2615 | gpio_free(rt5645->pdata.hp_det_gpio); |
2454 | 2616 | ||
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index 50c62c5668ea..a815e36a2bdb 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h | |||
@@ -594,6 +594,7 @@ | |||
594 | #define RT5645_M_DAC1_HM_SFT 14 | 594 | #define RT5645_M_DAC1_HM_SFT 14 |
595 | #define RT5645_M_HPVOL_HM (0x1 << 13) | 595 | #define RT5645_M_HPVOL_HM (0x1 << 13) |
596 | #define RT5645_M_HPVOL_HM_SFT 13 | 596 | #define RT5645_M_HPVOL_HM_SFT 13 |
597 | #define RT5645_IRQ_PSV_MODE (0x1 << 12) | ||
597 | 598 | ||
598 | /* SPK Left Mixer Control (0x46) */ | 599 | /* SPK Left Mixer Control (0x46) */ |
599 | #define RT5645_G_RM_L_SM_L_MASK (0x3 << 14) | 600 | #define RT5645_G_RM_L_SM_L_MASK (0x3 << 14) |
@@ -1348,6 +1349,12 @@ | |||
1348 | #define RT5645_PWR_CLK25M_SFT 4 | 1349 | #define RT5645_PWR_CLK25M_SFT 4 |
1349 | #define RT5645_PWR_CLK25M_PD (0x0 << 4) | 1350 | #define RT5645_PWR_CLK25M_PD (0x0 << 4) |
1350 | #define RT5645_PWR_CLK25M_PU (0x1 << 4) | 1351 | #define RT5645_PWR_CLK25M_PU (0x1 << 4) |
1352 | #define RT5645_IRQ_CLK_MCLK (0x0 << 3) | ||
1353 | #define RT5645_IRQ_CLK_INT (0x1 << 3) | ||
1354 | #define RT5645_JD1_MODE_MASK (0x3 << 0) | ||
1355 | #define RT5645_JD1_MODE_0 (0x0 << 0) | ||
1356 | #define RT5645_JD1_MODE_1 (0x1 << 0) | ||
1357 | #define RT5645_JD1_MODE_2 (0x2 << 0) | ||
1351 | 1358 | ||
1352 | /* VAD Control 4 (0x9d) */ | 1359 | /* VAD Control 4 (0x9d) */ |
1353 | #define RT5645_VAD_SEL_MASK (0x3 << 8) | 1360 | #define RT5645_VAD_SEL_MASK (0x3 << 8) |
@@ -1636,6 +1643,7 @@ | |||
1636 | #define RT5645_OT_P_SFT 10 | 1643 | #define RT5645_OT_P_SFT 10 |
1637 | #define RT5645_OT_P_NOR (0x0 << 10) | 1644 | #define RT5645_OT_P_NOR (0x0 << 10) |
1638 | #define RT5645_OT_P_INV (0x1 << 10) | 1645 | #define RT5645_OT_P_INV (0x1 << 10) |
1646 | #define RT5645_IRQ_JD_1_1_EN (0x1 << 9) | ||
1639 | 1647 | ||
1640 | /* IRQ Control 2 (0xbe) */ | 1648 | /* IRQ Control 2 (0xbe) */ |
1641 | #define RT5645_IRQ_MB1_OC_MASK (0x1 << 15) | 1649 | #define RT5645_IRQ_MB1_OC_MASK (0x1 << 15) |
@@ -1853,6 +1861,7 @@ | |||
1853 | #define RT5645_M_BB_HPF_R_SFT 6 | 1861 | #define RT5645_M_BB_HPF_R_SFT 6 |
1854 | #define RT5645_G_BB_BST_MASK (0x3f) | 1862 | #define RT5645_G_BB_BST_MASK (0x3f) |
1855 | #define RT5645_G_BB_BST_SFT 0 | 1863 | #define RT5645_G_BB_BST_SFT 0 |
1864 | #define RT5645_G_BB_BST_25DB 0x14 | ||
1856 | 1865 | ||
1857 | /* MP3 Plus Control 1 (0xd0) */ | 1866 | /* MP3 Plus Control 1 (0xd0) */ |
1858 | #define RT5645_M_MP3_L_MASK (0x1 << 15) | 1867 | #define RT5645_M_MP3_L_MASK (0x1 << 15) |
@@ -2116,6 +2125,10 @@ enum { | |||
2116 | #define RT5645_RXDP2_SEL_ADC (0x1 << 3) | 2125 | #define RT5645_RXDP2_SEL_ADC (0x1 << 3) |
2117 | #define RT5645_RXDP2_SEL_SFT (3) | 2126 | #define RT5645_RXDP2_SEL_SFT (3) |
2118 | 2127 | ||
2128 | /* General Control3 (0xfc) */ | ||
2129 | #define RT5645_JD_PSV_MODE (0x1 << 12) | ||
2130 | #define RT5645_IRQ_CLK_GATE_CTRL (0x1 << 11) | ||
2131 | #define RT5645_MICINDET_MANU (0x1 << 7) | ||
2119 | 2132 | ||
2120 | /* Vendor ID (0xfd) */ | 2133 | /* Vendor ID (0xfd) */ |
2121 | #define RT5645_VER_C 0x2 | 2134 | #define RT5645_VER_C 0x2 |
@@ -2167,7 +2180,9 @@ struct rt5645_priv { | |||
2167 | struct rt5645_platform_data pdata; | 2180 | struct rt5645_platform_data pdata; |
2168 | struct regmap *regmap; | 2181 | struct regmap *regmap; |
2169 | struct i2c_client *i2c; | 2182 | struct i2c_client *i2c; |
2170 | struct snd_soc_jack *jack; | 2183 | struct snd_soc_jack *hp_jack; |
2184 | struct snd_soc_jack *mic_jack; | ||
2185 | struct delayed_work jack_detect_work; | ||
2171 | 2186 | ||
2172 | int sysclk; | 2187 | int sysclk; |
2173 | int sysclk_src; | 2188 | int sysclk_src; |
@@ -2181,6 +2196,6 @@ struct rt5645_priv { | |||
2181 | }; | 2196 | }; |
2182 | 2197 | ||
2183 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, | 2198 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, |
2184 | struct snd_soc_jack *jack); | 2199 | struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack); |
2185 | 2200 | ||
2186 | #endif /* __RT5645_H__ */ | 2201 | #endif /* __RT5645_H__ */ |
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 9bd8b4f63303..8a0833de1665 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/acpi.h> | ||
19 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
@@ -575,6 +576,18 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source, | |||
575 | 576 | ||
576 | } | 577 | } |
577 | 578 | ||
579 | static int can_use_asrc(struct snd_soc_dapm_widget *source, | ||
580 | struct snd_soc_dapm_widget *sink) | ||
581 | { | ||
582 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
583 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
584 | |||
585 | if (rt5670->sysclk > rt5670->lrck[RT5670_AIF1] * 384) | ||
586 | return 1; | ||
587 | |||
588 | return 0; | ||
589 | } | ||
590 | |||
578 | /* Digital Mixer */ | 591 | /* Digital Mixer */ |
579 | static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = { | 592 | static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = { |
580 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, | 593 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, |
@@ -1281,6 +1294,14 @@ static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] = { | |||
1281 | 9, 0, NULL, 0), | 1294 | 9, 0, NULL, 0), |
1282 | SND_SOC_DAPM_SUPPLY_S("DAC MONO R ASRC", 1, RT5670_ASRC_1, | 1295 | SND_SOC_DAPM_SUPPLY_S("DAC MONO R ASRC", 1, RT5670_ASRC_1, |
1283 | 8, 0, NULL, 0), | 1296 | 8, 0, NULL, 0), |
1297 | SND_SOC_DAPM_SUPPLY_S("DMIC STO1 ASRC", 1, RT5670_ASRC_1, | ||
1298 | 7, 0, NULL, 0), | ||
1299 | SND_SOC_DAPM_SUPPLY_S("DMIC STO2 ASRC", 1, RT5670_ASRC_1, | ||
1300 | 6, 0, NULL, 0), | ||
1301 | SND_SOC_DAPM_SUPPLY_S("DMIC MONO L ASRC", 1, RT5670_ASRC_1, | ||
1302 | 5, 0, NULL, 0), | ||
1303 | SND_SOC_DAPM_SUPPLY_S("DMIC MONO R ASRC", 1, RT5670_ASRC_1, | ||
1304 | 4, 0, NULL, 0), | ||
1284 | SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5670_ASRC_1, | 1305 | SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5670_ASRC_1, |
1285 | 3, 0, NULL, 0), | 1306 | 3, 0, NULL, 0), |
1286 | SND_SOC_DAPM_SUPPLY_S("ADC STO2 ASRC", 1, RT5670_ASRC_1, | 1307 | SND_SOC_DAPM_SUPPLY_S("ADC STO2 ASRC", 1, RT5670_ASRC_1, |
@@ -1595,29 +1616,40 @@ static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] = { | |||
1595 | /* PDM */ | 1616 | /* PDM */ |
1596 | SND_SOC_DAPM_SUPPLY("PDM1 Power", RT5670_PWR_DIG2, | 1617 | SND_SOC_DAPM_SUPPLY("PDM1 Power", RT5670_PWR_DIG2, |
1597 | RT5670_PWR_PDM1_BIT, 0, NULL, 0), | 1618 | RT5670_PWR_PDM1_BIT, 0, NULL, 0), |
1598 | SND_SOC_DAPM_SUPPLY("PDM2 Power", RT5670_PWR_DIG2, | ||
1599 | RT5670_PWR_PDM2_BIT, 0, NULL, 0), | ||
1600 | 1619 | ||
1601 | SND_SOC_DAPM_MUX("PDM1 L Mux", RT5670_PDM_OUT_CTRL, | 1620 | SND_SOC_DAPM_MUX("PDM1 L Mux", RT5670_PDM_OUT_CTRL, |
1602 | RT5670_M_PDM1_L_SFT, 1, &rt5670_pdm1_l_mux), | 1621 | RT5670_M_PDM1_L_SFT, 1, &rt5670_pdm1_l_mux), |
1603 | SND_SOC_DAPM_MUX("PDM1 R Mux", RT5670_PDM_OUT_CTRL, | 1622 | SND_SOC_DAPM_MUX("PDM1 R Mux", RT5670_PDM_OUT_CTRL, |
1604 | RT5670_M_PDM1_R_SFT, 1, &rt5670_pdm1_r_mux), | 1623 | RT5670_M_PDM1_R_SFT, 1, &rt5670_pdm1_r_mux), |
1605 | SND_SOC_DAPM_MUX("PDM2 L Mux", RT5670_PDM_OUT_CTRL, | ||
1606 | RT5670_M_PDM2_L_SFT, 1, &rt5670_pdm2_l_mux), | ||
1607 | SND_SOC_DAPM_MUX("PDM2 R Mux", RT5670_PDM_OUT_CTRL, | ||
1608 | RT5670_M_PDM2_R_SFT, 1, &rt5670_pdm2_r_mux), | ||
1609 | 1624 | ||
1610 | /* Output Lines */ | 1625 | /* Output Lines */ |
1611 | SND_SOC_DAPM_OUTPUT("HPOL"), | 1626 | SND_SOC_DAPM_OUTPUT("HPOL"), |
1612 | SND_SOC_DAPM_OUTPUT("HPOR"), | 1627 | SND_SOC_DAPM_OUTPUT("HPOR"), |
1613 | SND_SOC_DAPM_OUTPUT("LOUTL"), | 1628 | SND_SOC_DAPM_OUTPUT("LOUTL"), |
1614 | SND_SOC_DAPM_OUTPUT("LOUTR"), | 1629 | SND_SOC_DAPM_OUTPUT("LOUTR"), |
1630 | }; | ||
1631 | |||
1632 | static const struct snd_soc_dapm_widget rt5670_specific_dapm_widgets[] = { | ||
1633 | SND_SOC_DAPM_SUPPLY("PDM2 Power", RT5670_PWR_DIG2, | ||
1634 | RT5670_PWR_PDM2_BIT, 0, NULL, 0), | ||
1635 | SND_SOC_DAPM_MUX("PDM2 L Mux", RT5670_PDM_OUT_CTRL, | ||
1636 | RT5670_M_PDM2_L_SFT, 1, &rt5670_pdm2_l_mux), | ||
1637 | SND_SOC_DAPM_MUX("PDM2 R Mux", RT5670_PDM_OUT_CTRL, | ||
1638 | RT5670_M_PDM2_R_SFT, 1, &rt5670_pdm2_r_mux), | ||
1615 | SND_SOC_DAPM_OUTPUT("PDM1L"), | 1639 | SND_SOC_DAPM_OUTPUT("PDM1L"), |
1616 | SND_SOC_DAPM_OUTPUT("PDM1R"), | 1640 | SND_SOC_DAPM_OUTPUT("PDM1R"), |
1617 | SND_SOC_DAPM_OUTPUT("PDM2L"), | 1641 | SND_SOC_DAPM_OUTPUT("PDM2L"), |
1618 | SND_SOC_DAPM_OUTPUT("PDM2R"), | 1642 | SND_SOC_DAPM_OUTPUT("PDM2R"), |
1619 | }; | 1643 | }; |
1620 | 1644 | ||
1645 | static const struct snd_soc_dapm_widget rt5672_specific_dapm_widgets[] = { | ||
1646 | SND_SOC_DAPM_PGA("SPO Amp", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1647 | SND_SOC_DAPM_OUTPUT("SPOLP"), | ||
1648 | SND_SOC_DAPM_OUTPUT("SPOLN"), | ||
1649 | SND_SOC_DAPM_OUTPUT("SPORP"), | ||
1650 | SND_SOC_DAPM_OUTPUT("SPORN"), | ||
1651 | }; | ||
1652 | |||
1621 | static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { | 1653 | static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { |
1622 | { "ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc }, | 1654 | { "ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc }, |
1623 | { "ADC Stereo2 Filter", NULL, "ADC STO2 ASRC", is_using_asrc }, | 1655 | { "ADC Stereo2 Filter", NULL, "ADC STO2 ASRC", is_using_asrc }, |
@@ -1626,9 +1658,13 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { | |||
1626 | { "DAC Mono Left Filter", NULL, "DAC MONO L ASRC", is_using_asrc }, | 1658 | { "DAC Mono Left Filter", NULL, "DAC MONO L ASRC", is_using_asrc }, |
1627 | { "DAC Mono Right Filter", NULL, "DAC MONO R ASRC", is_using_asrc }, | 1659 | { "DAC Mono Right Filter", NULL, "DAC MONO R ASRC", is_using_asrc }, |
1628 | { "DAC Stereo1 Filter", NULL, "DAC STO ASRC", is_using_asrc }, | 1660 | { "DAC Stereo1 Filter", NULL, "DAC STO ASRC", is_using_asrc }, |
1661 | { "Stereo1 DMIC Mux", NULL, "DMIC STO1 ASRC", can_use_asrc }, | ||
1662 | { "Stereo2 DMIC Mux", NULL, "DMIC STO2 ASRC", can_use_asrc }, | ||
1663 | { "Mono DMIC L Mux", NULL, "DMIC MONO L ASRC", can_use_asrc }, | ||
1664 | { "Mono DMIC R Mux", NULL, "DMIC MONO R ASRC", can_use_asrc }, | ||
1629 | 1665 | ||
1630 | { "I2S1", NULL, "I2S1 ASRC" }, | 1666 | { "I2S1", NULL, "I2S1 ASRC", can_use_asrc}, |
1631 | { "I2S2", NULL, "I2S2 ASRC" }, | 1667 | { "I2S2", NULL, "I2S2 ASRC", can_use_asrc}, |
1632 | 1668 | ||
1633 | { "DMIC1", NULL, "DMIC L1" }, | 1669 | { "DMIC1", NULL, "DMIC L1" }, |
1634 | { "DMIC1", NULL, "DMIC R1" }, | 1670 | { "DMIC1", NULL, "DMIC R1" }, |
@@ -1970,12 +2006,6 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { | |||
1970 | { "PDM1 R Mux", "Stereo DAC", "Stereo DAC MIXR" }, | 2006 | { "PDM1 R Mux", "Stereo DAC", "Stereo DAC MIXR" }, |
1971 | { "PDM1 R Mux", "Mono DAC", "Mono DAC MIXR" }, | 2007 | { "PDM1 R Mux", "Mono DAC", "Mono DAC MIXR" }, |
1972 | { "PDM1 R Mux", NULL, "PDM1 Power" }, | 2008 | { "PDM1 R Mux", NULL, "PDM1 Power" }, |
1973 | { "PDM2 L Mux", "Stereo DAC", "Stereo DAC MIXL" }, | ||
1974 | { "PDM2 L Mux", "Mono DAC", "Mono DAC MIXL" }, | ||
1975 | { "PDM2 L Mux", NULL, "PDM2 Power" }, | ||
1976 | { "PDM2 R Mux", "Stereo DAC", "Stereo DAC MIXR" }, | ||
1977 | { "PDM2 R Mux", "Mono DAC", "Mono DAC MIXR" }, | ||
1978 | { "PDM2 R Mux", NULL, "PDM2 Power" }, | ||
1979 | 2009 | ||
1980 | { "HP Amp", NULL, "HPO MIX" }, | 2010 | { "HP Amp", NULL, "HPO MIX" }, |
1981 | { "HP Amp", NULL, "Mic Det Power" }, | 2011 | { "HP Amp", NULL, "Mic Det Power" }, |
@@ -1993,13 +2023,30 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { | |||
1993 | { "LOUTR", NULL, "LOUT R Playback" }, | 2023 | { "LOUTR", NULL, "LOUT R Playback" }, |
1994 | { "LOUTL", NULL, "Improve HP Amp Drv" }, | 2024 | { "LOUTL", NULL, "Improve HP Amp Drv" }, |
1995 | { "LOUTR", NULL, "Improve HP Amp Drv" }, | 2025 | { "LOUTR", NULL, "Improve HP Amp Drv" }, |
2026 | }; | ||
1996 | 2027 | ||
2028 | static const struct snd_soc_dapm_route rt5670_specific_dapm_routes[] = { | ||
2029 | { "PDM2 L Mux", "Stereo DAC", "Stereo DAC MIXL" }, | ||
2030 | { "PDM2 L Mux", "Mono DAC", "Mono DAC MIXL" }, | ||
2031 | { "PDM2 L Mux", NULL, "PDM2 Power" }, | ||
2032 | { "PDM2 R Mux", "Stereo DAC", "Stereo DAC MIXR" }, | ||
2033 | { "PDM2 R Mux", "Mono DAC", "Mono DAC MIXR" }, | ||
2034 | { "PDM2 R Mux", NULL, "PDM2 Power" }, | ||
1997 | { "PDM1L", NULL, "PDM1 L Mux" }, | 2035 | { "PDM1L", NULL, "PDM1 L Mux" }, |
1998 | { "PDM1R", NULL, "PDM1 R Mux" }, | 2036 | { "PDM1R", NULL, "PDM1 R Mux" }, |
1999 | { "PDM2L", NULL, "PDM2 L Mux" }, | 2037 | { "PDM2L", NULL, "PDM2 L Mux" }, |
2000 | { "PDM2R", NULL, "PDM2 R Mux" }, | 2038 | { "PDM2R", NULL, "PDM2 R Mux" }, |
2001 | }; | 2039 | }; |
2002 | 2040 | ||
2041 | static const struct snd_soc_dapm_route rt5672_specific_dapm_routes[] = { | ||
2042 | { "SPO Amp", NULL, "PDM1 L Mux" }, | ||
2043 | { "SPO Amp", NULL, "PDM1 R Mux" }, | ||
2044 | { "SPOLP", NULL, "SPO Amp" }, | ||
2045 | { "SPOLN", NULL, "SPO Amp" }, | ||
2046 | { "SPORP", NULL, "SPO Amp" }, | ||
2047 | { "SPORN", NULL, "SPO Amp" }, | ||
2048 | }; | ||
2049 | |||
2003 | static int rt5670_hw_params(struct snd_pcm_substream *substream, | 2050 | static int rt5670_hw_params(struct snd_pcm_substream *substream, |
2004 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 2051 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
2005 | { | 2052 | { |
@@ -2287,6 +2334,8 @@ static int rt5670_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
2287 | static int rt5670_set_bias_level(struct snd_soc_codec *codec, | 2334 | static int rt5670_set_bias_level(struct snd_soc_codec *codec, |
2288 | enum snd_soc_bias_level level) | 2335 | enum snd_soc_bias_level level) |
2289 | { | 2336 | { |
2337 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2338 | |||
2290 | switch (level) { | 2339 | switch (level) { |
2291 | case SND_SOC_BIAS_PREPARE: | 2340 | case SND_SOC_BIAS_PREPARE: |
2292 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { | 2341 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { |
@@ -2308,16 +2357,27 @@ static int rt5670_set_bias_level(struct snd_soc_codec *codec, | |||
2308 | } | 2357 | } |
2309 | break; | 2358 | break; |
2310 | case SND_SOC_BIAS_STANDBY: | 2359 | case SND_SOC_BIAS_STANDBY: |
2311 | snd_soc_write(codec, RT5670_PWR_DIG1, 0x0000); | 2360 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, |
2312 | snd_soc_write(codec, RT5670_PWR_DIG2, 0x0001); | 2361 | RT5670_PWR_VREF1 | RT5670_PWR_VREF2 | |
2313 | snd_soc_write(codec, RT5670_PWR_VOL, 0x0000); | 2362 | RT5670_PWR_FV1 | RT5670_PWR_FV2, 0); |
2314 | snd_soc_write(codec, RT5670_PWR_MIXER, 0x0001); | ||
2315 | snd_soc_write(codec, RT5670_PWR_ANLG1, 0x2800); | ||
2316 | snd_soc_write(codec, RT5670_PWR_ANLG2, 0x0004); | ||
2317 | snd_soc_update_bits(codec, RT5670_DIG_MISC, 0x1, 0x0); | ||
2318 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | 2363 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, |
2319 | RT5670_LDO_SEL_MASK, 0x1); | 2364 | RT5670_LDO_SEL_MASK, 0x1); |
2320 | break; | 2365 | break; |
2366 | case SND_SOC_BIAS_OFF: | ||
2367 | if (rt5670->pdata.jd_mode) | ||
2368 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | ||
2369 | RT5670_PWR_VREF1 | RT5670_PWR_MB | | ||
2370 | RT5670_PWR_BG | RT5670_PWR_VREF2 | | ||
2371 | RT5670_PWR_FV1 | RT5670_PWR_FV2, | ||
2372 | RT5670_PWR_MB | RT5670_PWR_BG); | ||
2373 | else | ||
2374 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | ||
2375 | RT5670_PWR_VREF1 | RT5670_PWR_MB | | ||
2376 | RT5670_PWR_BG | RT5670_PWR_VREF2 | | ||
2377 | RT5670_PWR_FV1 | RT5670_PWR_FV2, 0); | ||
2378 | |||
2379 | snd_soc_update_bits(codec, RT5670_DIG_MISC, 0x1, 0x0); | ||
2380 | break; | ||
2321 | 2381 | ||
2322 | default: | 2382 | default: |
2323 | break; | 2383 | break; |
@@ -2331,6 +2391,29 @@ static int rt5670_probe(struct snd_soc_codec *codec) | |||
2331 | { | 2391 | { |
2332 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | 2392 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); |
2333 | 2393 | ||
2394 | switch (snd_soc_read(codec, RT5670_RESET) & RT5670_ID_MASK) { | ||
2395 | case RT5670_ID_5670: | ||
2396 | case RT5670_ID_5671: | ||
2397 | snd_soc_dapm_new_controls(&codec->dapm, | ||
2398 | rt5670_specific_dapm_widgets, | ||
2399 | ARRAY_SIZE(rt5670_specific_dapm_widgets)); | ||
2400 | snd_soc_dapm_add_routes(&codec->dapm, | ||
2401 | rt5670_specific_dapm_routes, | ||
2402 | ARRAY_SIZE(rt5670_specific_dapm_routes)); | ||
2403 | break; | ||
2404 | case RT5670_ID_5672: | ||
2405 | snd_soc_dapm_new_controls(&codec->dapm, | ||
2406 | rt5672_specific_dapm_widgets, | ||
2407 | ARRAY_SIZE(rt5672_specific_dapm_widgets)); | ||
2408 | snd_soc_dapm_add_routes(&codec->dapm, | ||
2409 | rt5672_specific_dapm_routes, | ||
2410 | ARRAY_SIZE(rt5672_specific_dapm_routes)); | ||
2411 | break; | ||
2412 | default: | ||
2413 | dev_err(codec->dev, | ||
2414 | "The driver is for RT5670 RT5671 or RT5672 only\n"); | ||
2415 | return -ENODEV; | ||
2416 | } | ||
2334 | rt5670->codec = codec; | 2417 | rt5670->codec = codec; |
2335 | 2418 | ||
2336 | return 0; | 2419 | return 0; |
@@ -2452,10 +2535,20 @@ static const struct regmap_config rt5670_regmap = { | |||
2452 | 2535 | ||
2453 | static const struct i2c_device_id rt5670_i2c_id[] = { | 2536 | static const struct i2c_device_id rt5670_i2c_id[] = { |
2454 | { "rt5670", 0 }, | 2537 | { "rt5670", 0 }, |
2538 | { "rt5671", 0 }, | ||
2539 | { "rt5672", 0 }, | ||
2455 | { } | 2540 | { } |
2456 | }; | 2541 | }; |
2457 | MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); | 2542 | MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); |
2458 | 2543 | ||
2544 | #ifdef CONFIG_ACPI | ||
2545 | static struct acpi_device_id rt5670_acpi_match[] = { | ||
2546 | { "10EC5670", 0}, | ||
2547 | { }, | ||
2548 | }; | ||
2549 | MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match); | ||
2550 | #endif | ||
2551 | |||
2459 | static int rt5670_i2c_probe(struct i2c_client *i2c, | 2552 | static int rt5670_i2c_probe(struct i2c_client *i2c, |
2460 | const struct i2c_device_id *id) | 2553 | const struct i2c_device_id *id) |
2461 | { | 2554 | { |
@@ -2644,6 +2737,7 @@ static struct i2c_driver rt5670_i2c_driver = { | |||
2644 | .driver = { | 2737 | .driver = { |
2645 | .name = "rt5670", | 2738 | .name = "rt5670", |
2646 | .owner = THIS_MODULE, | 2739 | .owner = THIS_MODULE, |
2740 | .acpi_match_table = ACPI_PTR(rt5670_acpi_match), | ||
2647 | }, | 2741 | }, |
2648 | .probe = rt5670_i2c_probe, | 2742 | .probe = rt5670_i2c_probe, |
2649 | .remove = rt5670_i2c_remove, | 2743 | .remove = rt5670_i2c_remove, |
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index a0b5c855b492..d11b9c207e26 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h | |||
@@ -228,6 +228,12 @@ | |||
228 | #define RT5670_R_VOL_MASK (0x3f) | 228 | #define RT5670_R_VOL_MASK (0x3f) |
229 | #define RT5670_R_VOL_SFT 0 | 229 | #define RT5670_R_VOL_SFT 0 |
230 | 230 | ||
231 | /* SW Reset & Device ID (0x00) */ | ||
232 | #define RT5670_ID_MASK (0x3 << 1) | ||
233 | #define RT5670_ID_5670 (0x0 << 1) | ||
234 | #define RT5670_ID_5672 (0x1 << 1) | ||
235 | #define RT5670_ID_5671 (0x2 << 1) | ||
236 | |||
231 | /* Combo Jack Control 1 (0x0a) */ | 237 | /* Combo Jack Control 1 (0x0a) */ |
232 | #define RT5670_CBJ_BST1_MASK (0xf << 12) | 238 | #define RT5670_CBJ_BST1_MASK (0xf << 12) |
233 | #define RT5670_CBJ_BST1_SFT (12) | 239 | #define RT5670_CBJ_BST1_SFT (12) |
diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c new file mode 100644 index 000000000000..ef6348cb9157 --- /dev/null +++ b/sound/soc/codecs/rt5677-spi.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * rt5677-spi.c -- RT5677 ALSA SoC audio codec driver | ||
3 | * | ||
4 | * Copyright 2013 Realtek Semiconductor Corp. | ||
5 | * Author: Oder Chiou <oder_chiou@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/input.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/kthread.h> | ||
24 | #include <linux/uaccess.h> | ||
25 | #include <linux/miscdevice.h> | ||
26 | #include <linux/regulator/consumer.h> | ||
27 | #include <linux/pm_qos.h> | ||
28 | #include <linux/sysfs.h> | ||
29 | #include <linux/clk.h> | ||
30 | #include <linux/firmware.h> | ||
31 | |||
32 | #include "rt5677-spi.h" | ||
33 | |||
34 | static struct spi_device *g_spi; | ||
35 | |||
36 | /** | ||
37 | * rt5677_spi_write - Write data to SPI. | ||
38 | * @txbuf: Data Buffer for writing. | ||
39 | * @len: Data length. | ||
40 | * | ||
41 | * | ||
42 | * Returns true for success. | ||
43 | */ | ||
44 | int rt5677_spi_write(u8 *txbuf, size_t len) | ||
45 | { | ||
46 | int status; | ||
47 | |||
48 | status = spi_write(g_spi, txbuf, len); | ||
49 | |||
50 | if (status) | ||
51 | dev_err(&g_spi->dev, "rt5677_spi_write error %d\n", status); | ||
52 | |||
53 | return status; | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(rt5677_spi_write); | ||
56 | |||
57 | /** | ||
58 | * rt5677_spi_burst_write - Write data to SPI by rt5677 dsp memory address. | ||
59 | * @addr: Start address. | ||
60 | * @txbuf: Data Buffer for writng. | ||
61 | * @len: Data length, it must be a multiple of 8. | ||
62 | * | ||
63 | * | ||
64 | * Returns true for success. | ||
65 | */ | ||
66 | int rt5677_spi_burst_write(u32 addr, const struct firmware *fw) | ||
67 | { | ||
68 | u8 spi_cmd = RT5677_SPI_CMD_BURST_WRITE; | ||
69 | u8 *write_buf; | ||
70 | unsigned int i, end, offset = 0; | ||
71 | |||
72 | write_buf = kmalloc(RT5677_SPI_BUF_LEN + 6, GFP_KERNEL); | ||
73 | |||
74 | if (write_buf == NULL) | ||
75 | return -ENOMEM; | ||
76 | |||
77 | while (offset < fw->size) { | ||
78 | if (offset + RT5677_SPI_BUF_LEN <= fw->size) | ||
79 | end = RT5677_SPI_BUF_LEN; | ||
80 | else | ||
81 | end = fw->size % RT5677_SPI_BUF_LEN; | ||
82 | |||
83 | write_buf[0] = spi_cmd; | ||
84 | write_buf[1] = ((addr + offset) & 0xff000000) >> 24; | ||
85 | write_buf[2] = ((addr + offset) & 0x00ff0000) >> 16; | ||
86 | write_buf[3] = ((addr + offset) & 0x0000ff00) >> 8; | ||
87 | write_buf[4] = ((addr + offset) & 0x000000ff) >> 0; | ||
88 | |||
89 | for (i = 0; i < end; i += 8) { | ||
90 | write_buf[i + 12] = fw->data[offset + i + 0]; | ||
91 | write_buf[i + 11] = fw->data[offset + i + 1]; | ||
92 | write_buf[i + 10] = fw->data[offset + i + 2]; | ||
93 | write_buf[i + 9] = fw->data[offset + i + 3]; | ||
94 | write_buf[i + 8] = fw->data[offset + i + 4]; | ||
95 | write_buf[i + 7] = fw->data[offset + i + 5]; | ||
96 | write_buf[i + 6] = fw->data[offset + i + 6]; | ||
97 | write_buf[i + 5] = fw->data[offset + i + 7]; | ||
98 | } | ||
99 | |||
100 | write_buf[end + 5] = spi_cmd; | ||
101 | |||
102 | rt5677_spi_write(write_buf, end + 6); | ||
103 | |||
104 | offset += RT5677_SPI_BUF_LEN; | ||
105 | } | ||
106 | |||
107 | kfree(write_buf); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | EXPORT_SYMBOL_GPL(rt5677_spi_burst_write); | ||
112 | |||
113 | static int rt5677_spi_probe(struct spi_device *spi) | ||
114 | { | ||
115 | g_spi = spi; | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static struct spi_driver rt5677_spi_driver = { | ||
120 | .driver = { | ||
121 | .name = "rt5677", | ||
122 | .owner = THIS_MODULE, | ||
123 | }, | ||
124 | .probe = rt5677_spi_probe, | ||
125 | }; | ||
126 | module_spi_driver(rt5677_spi_driver); | ||
127 | |||
128 | MODULE_DESCRIPTION("ASoC RT5677 SPI driver"); | ||
129 | MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); | ||
130 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/rt5677-spi.h b/sound/soc/codecs/rt5677-spi.h new file mode 100644 index 000000000000..ec41b2b3b2ca --- /dev/null +++ b/sound/soc/codecs/rt5677-spi.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * rt5677-spi.h -- RT5677 ALSA SoC audio codec driver | ||
3 | * | ||
4 | * Copyright 2013 Realtek Semiconductor Corp. | ||
5 | * Author: Oder Chiou <oder_chiou@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __RT5677_SPI_H__ | ||
13 | #define __RT5677_SPI_H__ | ||
14 | |||
15 | #define RT5677_SPI_BUF_LEN 240 | ||
16 | #define RT5677_SPI_CMD_BURST_WRITE 0x05 | ||
17 | |||
18 | int rt5677_spi_write(u8 *txbuf, size_t len); | ||
19 | int rt5677_spi_burst_write(u32 addr, const struct firmware *fw); | ||
20 | |||
21 | #endif /* __RT5677_SPI_H__ */ | ||
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 16aa4d99a713..81fe1464d268 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
23 | #include <linux/firmware.h> | ||
23 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
@@ -31,6 +32,7 @@ | |||
31 | 32 | ||
32 | #include "rl6231.h" | 33 | #include "rl6231.h" |
33 | #include "rt5677.h" | 34 | #include "rt5677.h" |
35 | #include "rt5677-spi.h" | ||
34 | 36 | ||
35 | #define RT5677_DEVICE_ID 0x6327 | 37 | #define RT5677_DEVICE_ID 0x6327 |
36 | 38 | ||
@@ -53,12 +55,13 @@ static const struct regmap_range_cfg rt5677_ranges[] = { | |||
53 | }; | 55 | }; |
54 | 56 | ||
55 | static const struct reg_default init_list[] = { | 57 | static const struct reg_default init_list[] = { |
58 | {RT5677_ASRC_12, 0x0018}, | ||
56 | {RT5677_PR_BASE + 0x3d, 0x364d}, | 59 | {RT5677_PR_BASE + 0x3d, 0x364d}, |
57 | {RT5677_PR_BASE + 0x17, 0x4fc0}, | 60 | {RT5677_PR_BASE + 0x17, 0x4fc0}, |
58 | {RT5677_PR_BASE + 0x13, 0x0312}, | 61 | {RT5677_PR_BASE + 0x13, 0x0312}, |
59 | {RT5677_PR_BASE + 0x1e, 0x0000}, | 62 | {RT5677_PR_BASE + 0x1e, 0x0000}, |
60 | {RT5677_PR_BASE + 0x12, 0x0eaa}, | 63 | {RT5677_PR_BASE + 0x12, 0x0eaa}, |
61 | {RT5677_PR_BASE + 0x14, 0x018a}, | 64 | {RT5677_PR_BASE + 0x14, 0x018a}, |
62 | }; | 65 | }; |
63 | #define RT5677_INIT_REG_LEN ARRAY_SIZE(init_list) | 66 | #define RT5677_INIT_REG_LEN ARRAY_SIZE(init_list) |
64 | 67 | ||
@@ -171,7 +174,7 @@ static const struct reg_default rt5677_reg[] = { | |||
171 | {RT5677_ASRC_9 , 0x0000}, | 174 | {RT5677_ASRC_9 , 0x0000}, |
172 | {RT5677_ASRC_10 , 0x0000}, | 175 | {RT5677_ASRC_10 , 0x0000}, |
173 | {RT5677_ASRC_11 , 0x0000}, | 176 | {RT5677_ASRC_11 , 0x0000}, |
174 | {RT5677_ASRC_12 , 0x0008}, | 177 | {RT5677_ASRC_12 , 0x0018}, |
175 | {RT5677_ASRC_13 , 0x0000}, | 178 | {RT5677_ASRC_13 , 0x0000}, |
176 | {RT5677_ASRC_14 , 0x0000}, | 179 | {RT5677_ASRC_14 , 0x0000}, |
177 | {RT5677_ASRC_15 , 0x0000}, | 180 | {RT5677_ASRC_15 , 0x0000}, |
@@ -537,10 +540,232 @@ static bool rt5677_readable_register(struct device *dev, unsigned int reg) | |||
537 | } | 540 | } |
538 | } | 541 | } |
539 | 542 | ||
543 | /** | ||
544 | * rt5677_dsp_mode_i2c_write_addr - Write value to address on DSP mode. | ||
545 | * @rt5677: Private Data. | ||
546 | * @addr: Address index. | ||
547 | * @value: Address data. | ||
548 | * | ||
549 | * | ||
550 | * Returns 0 for success or negative error code. | ||
551 | */ | ||
552 | static int rt5677_dsp_mode_i2c_write_addr(struct rt5677_priv *rt5677, | ||
553 | unsigned int addr, unsigned int value, unsigned int opcode) | ||
554 | { | ||
555 | struct snd_soc_codec *codec = rt5677->codec; | ||
556 | int ret; | ||
557 | |||
558 | mutex_lock(&rt5677->dsp_cmd_lock); | ||
559 | |||
560 | ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_ADDR_MSB, | ||
561 | addr >> 16); | ||
562 | if (ret < 0) { | ||
563 | dev_err(codec->dev, "Failed to set addr msb value: %d\n", ret); | ||
564 | goto err; | ||
565 | } | ||
566 | |||
567 | ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_ADDR_LSB, | ||
568 | addr & 0xffff); | ||
569 | if (ret < 0) { | ||
570 | dev_err(codec->dev, "Failed to set addr lsb value: %d\n", ret); | ||
571 | goto err; | ||
572 | } | ||
573 | |||
574 | ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_DATA_MSB, | ||
575 | value >> 16); | ||
576 | if (ret < 0) { | ||
577 | dev_err(codec->dev, "Failed to set data msb value: %d\n", ret); | ||
578 | goto err; | ||
579 | } | ||
580 | |||
581 | ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_DATA_LSB, | ||
582 | value & 0xffff); | ||
583 | if (ret < 0) { | ||
584 | dev_err(codec->dev, "Failed to set data lsb value: %d\n", ret); | ||
585 | goto err; | ||
586 | } | ||
587 | |||
588 | ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_OP_CODE, | ||
589 | opcode); | ||
590 | if (ret < 0) { | ||
591 | dev_err(codec->dev, "Failed to set op code value: %d\n", ret); | ||
592 | goto err; | ||
593 | } | ||
594 | |||
595 | err: | ||
596 | mutex_unlock(&rt5677->dsp_cmd_lock); | ||
597 | |||
598 | return ret; | ||
599 | } | ||
600 | |||
601 | /** | ||
602 | * rt5677_dsp_mode_i2c_read_addr - Read value from address on DSP mode. | ||
603 | * rt5677: Private Data. | ||
604 | * @addr: Address index. | ||
605 | * @value: Address data. | ||
606 | * | ||
607 | * | ||
608 | * Returns 0 for success or negative error code. | ||
609 | */ | ||
610 | static int rt5677_dsp_mode_i2c_read_addr( | ||
611 | struct rt5677_priv *rt5677, unsigned int addr, unsigned int *value) | ||
612 | { | ||
613 | struct snd_soc_codec *codec = rt5677->codec; | ||
614 | int ret; | ||
615 | unsigned int msb, lsb; | ||
616 | |||
617 | mutex_lock(&rt5677->dsp_cmd_lock); | ||
618 | |||
619 | ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_ADDR_MSB, | ||
620 | addr >> 16); | ||
621 | if (ret < 0) { | ||
622 | dev_err(codec->dev, "Failed to set addr msb value: %d\n", ret); | ||
623 | goto err; | ||
624 | } | ||
625 | |||
626 | ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_ADDR_LSB, | ||
627 | addr & 0xffff); | ||
628 | if (ret < 0) { | ||
629 | dev_err(codec->dev, "Failed to set addr lsb value: %d\n", ret); | ||
630 | goto err; | ||
631 | } | ||
632 | |||
633 | ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_OP_CODE, | ||
634 | 0x0002); | ||
635 | if (ret < 0) { | ||
636 | dev_err(codec->dev, "Failed to set op code value: %d\n", ret); | ||
637 | goto err; | ||
638 | } | ||
639 | |||
640 | regmap_read(rt5677->regmap_physical, RT5677_DSP_I2C_DATA_MSB, &msb); | ||
641 | regmap_read(rt5677->regmap_physical, RT5677_DSP_I2C_DATA_LSB, &lsb); | ||
642 | *value = (msb << 16) | lsb; | ||
643 | |||
644 | err: | ||
645 | mutex_unlock(&rt5677->dsp_cmd_lock); | ||
646 | |||
647 | return ret; | ||
648 | } | ||
649 | |||
650 | /** | ||
651 | * rt5677_dsp_mode_i2c_write - Write register on DSP mode. | ||
652 | * rt5677: Private Data. | ||
653 | * @reg: Register index. | ||
654 | * @value: Register data. | ||
655 | * | ||
656 | * | ||
657 | * Returns 0 for success or negative error code. | ||
658 | */ | ||
659 | static int rt5677_dsp_mode_i2c_write(struct rt5677_priv *rt5677, | ||
660 | unsigned int reg, unsigned int value) | ||
661 | { | ||
662 | return rt5677_dsp_mode_i2c_write_addr(rt5677, 0x18020000 + reg * 2, | ||
663 | value, 0x0001); | ||
664 | } | ||
665 | |||
666 | /** | ||
667 | * rt5677_dsp_mode_i2c_read - Read register on DSP mode. | ||
668 | * @codec: SoC audio codec device. | ||
669 | * @reg: Register index. | ||
670 | * @value: Register data. | ||
671 | * | ||
672 | * | ||
673 | * Returns 0 for success or negative error code. | ||
674 | */ | ||
675 | static int rt5677_dsp_mode_i2c_read( | ||
676 | struct rt5677_priv *rt5677, unsigned int reg, unsigned int *value) | ||
677 | { | ||
678 | int ret = rt5677_dsp_mode_i2c_read_addr(rt5677, 0x18020000 + reg * 2, | ||
679 | value); | ||
680 | |||
681 | *value &= 0xffff; | ||
682 | |||
683 | return ret; | ||
684 | } | ||
685 | |||
686 | static void rt5677_set_dsp_mode(struct snd_soc_codec *codec, bool on) | ||
687 | { | ||
688 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
689 | |||
690 | if (on) { | ||
691 | regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x2, 0x2); | ||
692 | rt5677->is_dsp_mode = true; | ||
693 | } else { | ||
694 | regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x2, 0x0); | ||
695 | rt5677->is_dsp_mode = false; | ||
696 | } | ||
697 | } | ||
698 | |||
699 | static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on) | ||
700 | { | ||
701 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
702 | static bool activity; | ||
703 | int ret; | ||
704 | |||
705 | if (on && !activity) { | ||
706 | activity = true; | ||
707 | |||
708 | regcache_cache_only(rt5677->regmap, false); | ||
709 | regcache_cache_bypass(rt5677->regmap, true); | ||
710 | |||
711 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x1); | ||
712 | regmap_update_bits(rt5677->regmap, | ||
713 | RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0f00); | ||
714 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, | ||
715 | RT5677_LDO1_SEL_MASK, 0x0); | ||
716 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2, | ||
717 | RT5677_PWR_LDO1, RT5677_PWR_LDO1); | ||
718 | regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1, | ||
719 | RT5677_MCLK_SRC_MASK, RT5677_MCLK2_SRC); | ||
720 | regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK2, | ||
721 | RT5677_PLL2_PR_SRC_MASK | RT5677_DSP_CLK_SRC_MASK, | ||
722 | RT5677_PLL2_PR_SRC_MCLK2 | RT5677_DSP_CLK_SRC_BYPASS); | ||
723 | regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x07ff); | ||
724 | regmap_write(rt5677->regmap, RT5677_PWR_DSP1, 0x07fd); | ||
725 | rt5677_set_dsp_mode(codec, true); | ||
726 | |||
727 | ret = request_firmware(&rt5677->fw1, RT5677_FIRMWARE1, | ||
728 | codec->dev); | ||
729 | if (ret == 0) { | ||
730 | rt5677_spi_burst_write(0x50000000, rt5677->fw1); | ||
731 | release_firmware(rt5677->fw1); | ||
732 | } | ||
733 | |||
734 | ret = request_firmware(&rt5677->fw2, RT5677_FIRMWARE2, | ||
735 | codec->dev); | ||
736 | if (ret == 0) { | ||
737 | rt5677_spi_burst_write(0x60000000, rt5677->fw2); | ||
738 | release_firmware(rt5677->fw2); | ||
739 | } | ||
740 | |||
741 | regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x1, 0x0); | ||
742 | |||
743 | regcache_cache_bypass(rt5677->regmap, false); | ||
744 | regcache_cache_only(rt5677->regmap, true); | ||
745 | } else if (!on && activity) { | ||
746 | activity = false; | ||
747 | |||
748 | regcache_cache_only(rt5677->regmap, false); | ||
749 | regcache_cache_bypass(rt5677->regmap, true); | ||
750 | |||
751 | regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x1, 0x1); | ||
752 | rt5677_set_dsp_mode(codec, false); | ||
753 | regmap_write(rt5677->regmap, RT5677_PWR_DSP1, 0x0001); | ||
754 | |||
755 | regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec); | ||
756 | |||
757 | regcache_cache_bypass(rt5677->regmap, false); | ||
758 | regcache_mark_dirty(rt5677->regmap); | ||
759 | regcache_sync(rt5677->regmap); | ||
760 | } | ||
761 | |||
762 | return 0; | ||
763 | } | ||
764 | |||
540 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); | 765 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); |
541 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); | 766 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0); |
542 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); | 767 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); |
543 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); | 768 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); |
544 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | 769 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); |
545 | static const DECLARE_TLV_DB_SCALE(st_vol_tlv, -4650, 150, 0); | 770 | static const DECLARE_TLV_DB_SCALE(st_vol_tlv, -4650, 150, 0); |
546 | 771 | ||
@@ -556,6 +781,31 @@ static unsigned int bst_tlv[] = { | |||
556 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), | 781 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), |
557 | }; | 782 | }; |
558 | 783 | ||
784 | static int rt5677_dsp_vad_get(struct snd_kcontrol *kcontrol, | ||
785 | struct snd_ctl_elem_value *ucontrol) | ||
786 | { | ||
787 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
788 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
789 | |||
790 | ucontrol->value.integer.value[0] = rt5677->dsp_vad_en; | ||
791 | |||
792 | return 0; | ||
793 | } | ||
794 | |||
795 | static int rt5677_dsp_vad_put(struct snd_kcontrol *kcontrol, | ||
796 | struct snd_ctl_elem_value *ucontrol) | ||
797 | { | ||
798 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
799 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
800 | |||
801 | rt5677->dsp_vad_en = !!ucontrol->value.integer.value[0]; | ||
802 | |||
803 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | ||
804 | rt5677_set_dsp_vad(codec, rt5677->dsp_vad_en); | ||
805 | |||
806 | return 0; | ||
807 | } | ||
808 | |||
559 | static const struct snd_kcontrol_new rt5677_snd_controls[] = { | 809 | static const struct snd_kcontrol_new rt5677_snd_controls[] = { |
560 | /* OUTPUT Control */ | 810 | /* OUTPUT Control */ |
561 | SOC_SINGLE("OUT1 Playback Switch", RT5677_LOUT1, | 811 | SOC_SINGLE("OUT1 Playback Switch", RT5677_LOUT1, |
@@ -567,13 +817,13 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = { | |||
567 | 817 | ||
568 | /* DAC Digital Volume */ | 818 | /* DAC Digital Volume */ |
569 | SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5677_DAC1_DIG_VOL, | 819 | SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5677_DAC1_DIG_VOL, |
570 | RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 175, 0, dac_vol_tlv), | 820 | RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv), |
571 | SOC_DOUBLE_TLV("DAC2 Playback Volume", RT5677_DAC2_DIG_VOL, | 821 | SOC_DOUBLE_TLV("DAC2 Playback Volume", RT5677_DAC2_DIG_VOL, |
572 | RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 175, 0, dac_vol_tlv), | 822 | RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv), |
573 | SOC_DOUBLE_TLV("DAC3 Playback Volume", RT5677_DAC3_DIG_VOL, | 823 | SOC_DOUBLE_TLV("DAC3 Playback Volume", RT5677_DAC3_DIG_VOL, |
574 | RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 175, 0, dac_vol_tlv), | 824 | RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv), |
575 | SOC_DOUBLE_TLV("DAC4 Playback Volume", RT5677_DAC4_DIG_VOL, | 825 | SOC_DOUBLE_TLV("DAC4 Playback Volume", RT5677_DAC4_DIG_VOL, |
576 | RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 175, 0, dac_vol_tlv), | 826 | RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv), |
577 | 827 | ||
578 | /* IN1/IN2 Control */ | 828 | /* IN1/IN2 Control */ |
579 | SOC_SINGLE_TLV("IN1 Boost", RT5677_IN1, RT5677_BST_SFT1, 8, 0, bst_tlv), | 829 | SOC_SINGLE_TLV("IN1 Boost", RT5677_IN1, RT5677_BST_SFT1, 8, 0, bst_tlv), |
@@ -592,19 +842,19 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = { | |||
592 | RT5677_L_MUTE_SFT, RT5677_R_MUTE_SFT, 1, 1), | 842 | RT5677_L_MUTE_SFT, RT5677_R_MUTE_SFT, 1, 1), |
593 | 843 | ||
594 | SOC_DOUBLE_TLV("ADC1 Capture Volume", RT5677_STO1_ADC_DIG_VOL, | 844 | SOC_DOUBLE_TLV("ADC1 Capture Volume", RT5677_STO1_ADC_DIG_VOL, |
595 | RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 127, 0, | 845 | RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 63, 0, |
596 | adc_vol_tlv), | 846 | adc_vol_tlv), |
597 | SOC_DOUBLE_TLV("ADC2 Capture Volume", RT5677_STO2_ADC_DIG_VOL, | 847 | SOC_DOUBLE_TLV("ADC2 Capture Volume", RT5677_STO2_ADC_DIG_VOL, |
598 | RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 127, 0, | 848 | RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 63, 0, |
599 | adc_vol_tlv), | 849 | adc_vol_tlv), |
600 | SOC_DOUBLE_TLV("ADC3 Capture Volume", RT5677_STO3_ADC_DIG_VOL, | 850 | SOC_DOUBLE_TLV("ADC3 Capture Volume", RT5677_STO3_ADC_DIG_VOL, |
601 | RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 127, 0, | 851 | RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 63, 0, |
602 | adc_vol_tlv), | 852 | adc_vol_tlv), |
603 | SOC_DOUBLE_TLV("ADC4 Capture Volume", RT5677_STO4_ADC_DIG_VOL, | 853 | SOC_DOUBLE_TLV("ADC4 Capture Volume", RT5677_STO4_ADC_DIG_VOL, |
604 | RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 127, 0, | 854 | RT5677_STO1_ADC_L_VOL_SFT, RT5677_STO1_ADC_R_VOL_SFT, 63, 0, |
605 | adc_vol_tlv), | 855 | adc_vol_tlv), |
606 | SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5677_MONO_ADC_DIG_VOL, | 856 | SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5677_MONO_ADC_DIG_VOL, |
607 | RT5677_MONO_ADC_L_VOL_SFT, RT5677_MONO_ADC_R_VOL_SFT, 127, 0, | 857 | RT5677_MONO_ADC_L_VOL_SFT, RT5677_MONO_ADC_R_VOL_SFT, 63, 0, |
608 | adc_vol_tlv), | 858 | adc_vol_tlv), |
609 | 859 | ||
610 | /* Sidetone Control */ | 860 | /* Sidetone Control */ |
@@ -627,6 +877,9 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = { | |||
627 | SOC_DOUBLE_TLV("Mono ADC Boost Volume", RT5677_ADC_BST_CTRL2, | 877 | SOC_DOUBLE_TLV("Mono ADC Boost Volume", RT5677_ADC_BST_CTRL2, |
628 | RT5677_MONO_ADC_L_BST_SFT, RT5677_MONO_ADC_R_BST_SFT, 3, 0, | 878 | RT5677_MONO_ADC_L_BST_SFT, RT5677_MONO_ADC_R_BST_SFT, 3, 0, |
629 | adc_bst_tlv), | 879 | adc_bst_tlv), |
880 | |||
881 | SOC_SINGLE_EXT("DSP VAD Switch", SND_SOC_NOPM, 0, 1, 0, | ||
882 | rt5677_dsp_vad_get, rt5677_dsp_vad_put), | ||
630 | }; | 883 | }; |
631 | 884 | ||
632 | /** | 885 | /** |
@@ -1086,7 +1339,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1086 | static const struct snd_kcontrol_new rt5677_ib45_bypass_src_mux = | 1339 | static const struct snd_kcontrol_new rt5677_ib45_bypass_src_mux = |
1087 | SOC_DAPM_ENUM("IB45 Bypass Source", rt5677_ib45_bypass_src_enum); | 1340 | SOC_DAPM_ENUM("IB45 Bypass Source", rt5677_ib45_bypass_src_enum); |
1088 | 1341 | ||
1089 | /* Stereo ADC Source 2 */ /* MX-27 MX26 MX25 [11:10] */ | 1342 | /* Stereo ADC Source 2 */ /* MX-27 MX26 MX25 [11:10] */ |
1090 | static const char * const rt5677_stereo_adc2_src[] = { | 1343 | static const char * const rt5677_stereo_adc2_src[] = { |
1091 | "DD MIX1", "DMIC", "Stereo DAC MIX" | 1344 | "DD MIX1", "DMIC", "Stereo DAC MIX" |
1092 | }; | 1345 | }; |
@@ -1171,7 +1424,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1171 | static const struct snd_kcontrol_new rt5677_sto2_adc_lr_mux = | 1424 | static const struct snd_kcontrol_new rt5677_sto2_adc_lr_mux = |
1172 | SOC_DAPM_ENUM("Stereo2 ADC LR Source", rt5677_stereo2_adc_lr_enum); | 1425 | SOC_DAPM_ENUM("Stereo2 ADC LR Source", rt5677_stereo2_adc_lr_enum); |
1173 | 1426 | ||
1174 | /* Stereo1 ADC Source 1 */ /* MX-27 MX26 MX25 [13:12] */ | 1427 | /* Stereo1 ADC Source 1 */ /* MX-27 MX26 MX25 [13:12] */ |
1175 | static const char * const rt5677_stereo_adc1_src[] = { | 1428 | static const char * const rt5677_stereo_adc1_src[] = { |
1176 | "DD MIX1", "ADC1/2", "Stereo DAC MIX" | 1429 | "DD MIX1", "ADC1/2", "Stereo DAC MIX" |
1177 | }; | 1430 | }; |
@@ -1443,7 +1696,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1443 | static const struct snd_kcontrol_new rt5677_pdm2_r_mux = | 1696 | static const struct snd_kcontrol_new rt5677_pdm2_r_mux = |
1444 | SOC_DAPM_ENUM("PDM2 Source", rt5677_pdm2_r_enum); | 1697 | SOC_DAPM_ENUM("PDM2 Source", rt5677_pdm2_r_enum); |
1445 | 1698 | ||
1446 | /* TDM IF1/2 SLB ADC1 Data Selection */ /* MX-3C MX-41 [5:4] MX-08 [1:0]*/ | 1699 | /* TDM IF1/2 SLB ADC1 Data Selection */ /* MX-3C MX-41 [5:4] MX-08 [1:0] */ |
1447 | static const char * const rt5677_if12_adc1_src[] = { | 1700 | static const char * const rt5677_if12_adc1_src[] = { |
1448 | "STO1 ADC MIX", "OB01", "VAD ADC" | 1701 | "STO1 ADC MIX", "OB01", "VAD ADC" |
1449 | }; | 1702 | }; |
@@ -1521,7 +1774,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1521 | static const struct snd_kcontrol_new rt5677_slb_adc3_mux = | 1774 | static const struct snd_kcontrol_new rt5677_slb_adc3_mux = |
1522 | SOC_DAPM_ENUM("SLB ADC3 Source", rt5677_slb_adc3_enum); | 1775 | SOC_DAPM_ENUM("SLB ADC3 Source", rt5677_slb_adc3_enum); |
1523 | 1776 | ||
1524 | /* TDM IF1/2 SLB ADC4 Data Selection */ /* MX-3C MX-41 [11:10] MX-08 [7:6] */ | 1777 | /* TDM IF1/2 SLB ADC4 Data Selection */ /* MX-3C MX-41 [11:10] MX-08 [7:6] */ |
1525 | static const char * const rt5677_if12_adc4_src[] = { | 1778 | static const char * const rt5677_if12_adc4_src[] = { |
1526 | "STO4 ADC MIX", "OB67", "OB01" | 1779 | "STO4 ADC MIX", "OB67", "OB01" |
1527 | }; | 1780 | }; |
@@ -1547,7 +1800,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1547 | static const struct snd_kcontrol_new rt5677_slb_adc4_mux = | 1800 | static const struct snd_kcontrol_new rt5677_slb_adc4_mux = |
1548 | SOC_DAPM_ENUM("SLB ADC4 Source", rt5677_slb_adc4_enum); | 1801 | SOC_DAPM_ENUM("SLB ADC4 Source", rt5677_slb_adc4_enum); |
1549 | 1802 | ||
1550 | /* Interface3/4 ADC Data Input */ /* MX-2F [3:0] MX-30 [7:4]*/ | 1803 | /* Interface3/4 ADC Data Input */ /* MX-2F [3:0] MX-30 [7:4] */ |
1551 | static const char * const rt5677_if34_adc_src[] = { | 1804 | static const char * const rt5677_if34_adc_src[] = { |
1552 | "STO1 ADC MIX", "STO2 ADC MIX", "STO3 ADC MIX", "STO4 ADC MIX", | 1805 | "STO1 ADC MIX", "STO2 ADC MIX", "STO3 ADC MIX", "STO4 ADC MIX", |
1553 | "MONO ADC MIX", "OB01", "OB23", "VAD ADC" | 1806 | "MONO ADC MIX", "OB01", "OB23", "VAD ADC" |
@@ -1567,6 +1820,213 @@ static SOC_ENUM_SINGLE_DECL( | |||
1567 | static const struct snd_kcontrol_new rt5677_if4_adc_mux = | 1820 | static const struct snd_kcontrol_new rt5677_if4_adc_mux = |
1568 | SOC_DAPM_ENUM("IF4 ADC Source", rt5677_if4_adc_enum); | 1821 | SOC_DAPM_ENUM("IF4 ADC Source", rt5677_if4_adc_enum); |
1569 | 1822 | ||
1823 | /* TDM IF1/2 ADC Data Selection */ /* MX-3B MX-40 [7:6][5:4][3:2][1:0] */ | ||
1824 | static const char * const rt5677_if12_adc_swap_src[] = { | ||
1825 | "L/R", "R/L", "L/L", "R/R" | ||
1826 | }; | ||
1827 | |||
1828 | static SOC_ENUM_SINGLE_DECL( | ||
1829 | rt5677_if1_adc1_swap_enum, RT5677_TDM1_CTRL1, | ||
1830 | RT5677_IF1_ADC1_SWAP_SFT, rt5677_if12_adc_swap_src); | ||
1831 | |||
1832 | static const struct snd_kcontrol_new rt5677_if1_adc1_swap_mux = | ||
1833 | SOC_DAPM_ENUM("IF1 ADC1 Swap Source", rt5677_if1_adc1_swap_enum); | ||
1834 | |||
1835 | static SOC_ENUM_SINGLE_DECL( | ||
1836 | rt5677_if1_adc2_swap_enum, RT5677_TDM1_CTRL1, | ||
1837 | RT5677_IF1_ADC2_SWAP_SFT, rt5677_if12_adc_swap_src); | ||
1838 | |||
1839 | static const struct snd_kcontrol_new rt5677_if1_adc2_swap_mux = | ||
1840 | SOC_DAPM_ENUM("IF1 ADC2 Swap Source", rt5677_if1_adc2_swap_enum); | ||
1841 | |||
1842 | static SOC_ENUM_SINGLE_DECL( | ||
1843 | rt5677_if1_adc3_swap_enum, RT5677_TDM1_CTRL1, | ||
1844 | RT5677_IF1_ADC3_SWAP_SFT, rt5677_if12_adc_swap_src); | ||
1845 | |||
1846 | static const struct snd_kcontrol_new rt5677_if1_adc3_swap_mux = | ||
1847 | SOC_DAPM_ENUM("IF1 ADC3 Swap Source", rt5677_if1_adc3_swap_enum); | ||
1848 | |||
1849 | static SOC_ENUM_SINGLE_DECL( | ||
1850 | rt5677_if1_adc4_swap_enum, RT5677_TDM1_CTRL1, | ||
1851 | RT5677_IF1_ADC4_SWAP_SFT, rt5677_if12_adc_swap_src); | ||
1852 | |||
1853 | static const struct snd_kcontrol_new rt5677_if1_adc4_swap_mux = | ||
1854 | SOC_DAPM_ENUM("IF1 ADC4 Swap Source", rt5677_if1_adc4_swap_enum); | ||
1855 | |||
1856 | static SOC_ENUM_SINGLE_DECL( | ||
1857 | rt5677_if2_adc1_swap_enum, RT5677_TDM2_CTRL1, | ||
1858 | RT5677_IF1_ADC2_SWAP_SFT, rt5677_if12_adc_swap_src); | ||
1859 | |||
1860 | static const struct snd_kcontrol_new rt5677_if2_adc1_swap_mux = | ||
1861 | SOC_DAPM_ENUM("IF1 ADC2 Swap Source", rt5677_if2_adc1_swap_enum); | ||
1862 | |||
1863 | static SOC_ENUM_SINGLE_DECL( | ||
1864 | rt5677_if2_adc2_swap_enum, RT5677_TDM2_CTRL1, | ||
1865 | RT5677_IF2_ADC2_SWAP_SFT, rt5677_if12_adc_swap_src); | ||
1866 | |||
1867 | static const struct snd_kcontrol_new rt5677_if2_adc2_swap_mux = | ||
1868 | SOC_DAPM_ENUM("IF2 ADC2 Swap Source", rt5677_if2_adc2_swap_enum); | ||
1869 | |||
1870 | static SOC_ENUM_SINGLE_DECL( | ||
1871 | rt5677_if2_adc3_swap_enum, RT5677_TDM2_CTRL1, | ||
1872 | RT5677_IF2_ADC3_SWAP_SFT, rt5677_if12_adc_swap_src); | ||
1873 | |||
1874 | static const struct snd_kcontrol_new rt5677_if2_adc3_swap_mux = | ||
1875 | SOC_DAPM_ENUM("IF2 ADC3 Swap Source", rt5677_if2_adc3_swap_enum); | ||
1876 | |||
1877 | static SOC_ENUM_SINGLE_DECL( | ||
1878 | rt5677_if2_adc4_swap_enum, RT5677_TDM2_CTRL1, | ||
1879 | RT5677_IF2_ADC4_SWAP_SFT, rt5677_if12_adc_swap_src); | ||
1880 | |||
1881 | static const struct snd_kcontrol_new rt5677_if2_adc4_swap_mux = | ||
1882 | SOC_DAPM_ENUM("IF2 ADC4 Swap Source", rt5677_if2_adc4_swap_enum); | ||
1883 | |||
1884 | /* TDM IF1 ADC Data Selection */ /* MX-3C [2:0] */ | ||
1885 | static const char * const rt5677_if1_adc_tdm_swap_src[] = { | ||
1886 | "1/2/3/4", "2/1/3/4", "2/3/1/4", "4/1/2/3", "1/3/2/4", "1/4/2/3", | ||
1887 | "3/1/2/4", "3/4/1/2" | ||
1888 | }; | ||
1889 | |||
1890 | static SOC_ENUM_SINGLE_DECL( | ||
1891 | rt5677_if1_adc_tdm_swap_enum, RT5677_TDM1_CTRL2, | ||
1892 | RT5677_IF1_ADC_CTRL_SFT, rt5677_if1_adc_tdm_swap_src); | ||
1893 | |||
1894 | static const struct snd_kcontrol_new rt5677_if1_adc_tdm_swap_mux = | ||
1895 | SOC_DAPM_ENUM("IF1 ADC TDM Swap Source", rt5677_if1_adc_tdm_swap_enum); | ||
1896 | |||
1897 | /* TDM IF2 ADC Data Selection */ /* MX-41[2:0] */ | ||
1898 | static const char * const rt5677_if2_adc_tdm_swap_src[] = { | ||
1899 | "1/2/3/4", "2/1/3/4", "3/1/2/4", "4/1/2/3", "1/3/2/4", "1/4/2/3", | ||
1900 | "2/3/1/4", "3/4/1/2" | ||
1901 | }; | ||
1902 | |||
1903 | static SOC_ENUM_SINGLE_DECL( | ||
1904 | rt5677_if2_adc_tdm_swap_enum, RT5677_TDM2_CTRL2, | ||
1905 | RT5677_IF2_ADC_CTRL_SFT, rt5677_if2_adc_tdm_swap_src); | ||
1906 | |||
1907 | static const struct snd_kcontrol_new rt5677_if2_adc_tdm_swap_mux = | ||
1908 | SOC_DAPM_ENUM("IF2 ADC TDM Swap Source", rt5677_if2_adc_tdm_swap_enum); | ||
1909 | |||
1910 | /* TDM IF1/2 DAC Data Selection */ /* MX-3E[14:12][10:8][6:4][2:0] | ||
1911 | MX-3F[14:12][10:8][6:4][2:0] | ||
1912 | MX-43[14:12][10:8][6:4][2:0] | ||
1913 | MX-44[14:12][10:8][6:4][2:0] */ | ||
1914 | static const char * const rt5677_if12_dac_tdm_sel_src[] = { | ||
1915 | "Slot0", "Slot1", "Slot2", "Slot3", "Slot4", "Slot5", "Slot6", "Slot7" | ||
1916 | }; | ||
1917 | |||
1918 | static SOC_ENUM_SINGLE_DECL( | ||
1919 | rt5677_if1_dac0_tdm_sel_enum, RT5677_TDM1_CTRL4, | ||
1920 | RT5677_IF1_DAC0_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1921 | |||
1922 | static const struct snd_kcontrol_new rt5677_if1_dac0_tdm_sel_mux = | ||
1923 | SOC_DAPM_ENUM("IF1 DAC0 TDM Source", rt5677_if1_dac0_tdm_sel_enum); | ||
1924 | |||
1925 | static SOC_ENUM_SINGLE_DECL( | ||
1926 | rt5677_if1_dac1_tdm_sel_enum, RT5677_TDM1_CTRL4, | ||
1927 | RT5677_IF1_DAC1_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1928 | |||
1929 | static const struct snd_kcontrol_new rt5677_if1_dac1_tdm_sel_mux = | ||
1930 | SOC_DAPM_ENUM("IF1 DAC1 TDM Source", rt5677_if1_dac1_tdm_sel_enum); | ||
1931 | |||
1932 | static SOC_ENUM_SINGLE_DECL( | ||
1933 | rt5677_if1_dac2_tdm_sel_enum, RT5677_TDM1_CTRL4, | ||
1934 | RT5677_IF1_DAC2_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1935 | |||
1936 | static const struct snd_kcontrol_new rt5677_if1_dac2_tdm_sel_mux = | ||
1937 | SOC_DAPM_ENUM("IF1 DAC2 TDM Source", rt5677_if1_dac2_tdm_sel_enum); | ||
1938 | |||
1939 | static SOC_ENUM_SINGLE_DECL( | ||
1940 | rt5677_if1_dac3_tdm_sel_enum, RT5677_TDM1_CTRL4, | ||
1941 | RT5677_IF1_DAC3_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1942 | |||
1943 | static const struct snd_kcontrol_new rt5677_if1_dac3_tdm_sel_mux = | ||
1944 | SOC_DAPM_ENUM("IF1 DAC3 TDM Source", rt5677_if1_dac3_tdm_sel_enum); | ||
1945 | |||
1946 | static SOC_ENUM_SINGLE_DECL( | ||
1947 | rt5677_if1_dac4_tdm_sel_enum, RT5677_TDM1_CTRL5, | ||
1948 | RT5677_IF1_DAC4_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1949 | |||
1950 | static const struct snd_kcontrol_new rt5677_if1_dac4_tdm_sel_mux = | ||
1951 | SOC_DAPM_ENUM("IF1 DAC4 TDM Source", rt5677_if1_dac4_tdm_sel_enum); | ||
1952 | |||
1953 | static SOC_ENUM_SINGLE_DECL( | ||
1954 | rt5677_if1_dac5_tdm_sel_enum, RT5677_TDM1_CTRL5, | ||
1955 | RT5677_IF1_DAC5_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1956 | |||
1957 | static const struct snd_kcontrol_new rt5677_if1_dac5_tdm_sel_mux = | ||
1958 | SOC_DAPM_ENUM("IF1 DAC5 TDM Source", rt5677_if1_dac5_tdm_sel_enum); | ||
1959 | |||
1960 | static SOC_ENUM_SINGLE_DECL( | ||
1961 | rt5677_if1_dac6_tdm_sel_enum, RT5677_TDM1_CTRL5, | ||
1962 | RT5677_IF1_DAC6_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1963 | |||
1964 | static const struct snd_kcontrol_new rt5677_if1_dac6_tdm_sel_mux = | ||
1965 | SOC_DAPM_ENUM("IF1 DAC6 TDM Source", rt5677_if1_dac6_tdm_sel_enum); | ||
1966 | |||
1967 | static SOC_ENUM_SINGLE_DECL( | ||
1968 | rt5677_if1_dac7_tdm_sel_enum, RT5677_TDM1_CTRL5, | ||
1969 | RT5677_IF1_DAC7_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1970 | |||
1971 | static const struct snd_kcontrol_new rt5677_if1_dac7_tdm_sel_mux = | ||
1972 | SOC_DAPM_ENUM("IF1 DAC7 TDM Source", rt5677_if1_dac7_tdm_sel_enum); | ||
1973 | |||
1974 | static SOC_ENUM_SINGLE_DECL( | ||
1975 | rt5677_if2_dac0_tdm_sel_enum, RT5677_TDM2_CTRL4, | ||
1976 | RT5677_IF2_DAC0_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1977 | |||
1978 | static const struct snd_kcontrol_new rt5677_if2_dac0_tdm_sel_mux = | ||
1979 | SOC_DAPM_ENUM("IF2 DAC0 TDM Source", rt5677_if2_dac0_tdm_sel_enum); | ||
1980 | |||
1981 | static SOC_ENUM_SINGLE_DECL( | ||
1982 | rt5677_if2_dac1_tdm_sel_enum, RT5677_TDM2_CTRL4, | ||
1983 | RT5677_IF2_DAC1_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1984 | |||
1985 | static const struct snd_kcontrol_new rt5677_if2_dac1_tdm_sel_mux = | ||
1986 | SOC_DAPM_ENUM("IF2 DAC1 TDM Source", rt5677_if2_dac1_tdm_sel_enum); | ||
1987 | |||
1988 | static SOC_ENUM_SINGLE_DECL( | ||
1989 | rt5677_if2_dac2_tdm_sel_enum, RT5677_TDM2_CTRL4, | ||
1990 | RT5677_IF2_DAC2_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1991 | |||
1992 | static const struct snd_kcontrol_new rt5677_if2_dac2_tdm_sel_mux = | ||
1993 | SOC_DAPM_ENUM("IF2 DAC2 TDM Source", rt5677_if2_dac2_tdm_sel_enum); | ||
1994 | |||
1995 | static SOC_ENUM_SINGLE_DECL( | ||
1996 | rt5677_if2_dac3_tdm_sel_enum, RT5677_TDM2_CTRL4, | ||
1997 | RT5677_IF2_DAC3_SFT, rt5677_if12_dac_tdm_sel_src); | ||
1998 | |||
1999 | static const struct snd_kcontrol_new rt5677_if2_dac3_tdm_sel_mux = | ||
2000 | SOC_DAPM_ENUM("IF2 DAC3 TDM Source", rt5677_if2_dac3_tdm_sel_enum); | ||
2001 | |||
2002 | static SOC_ENUM_SINGLE_DECL( | ||
2003 | rt5677_if2_dac4_tdm_sel_enum, RT5677_TDM2_CTRL5, | ||
2004 | RT5677_IF2_DAC4_SFT, rt5677_if12_dac_tdm_sel_src); | ||
2005 | |||
2006 | static const struct snd_kcontrol_new rt5677_if2_dac4_tdm_sel_mux = | ||
2007 | SOC_DAPM_ENUM("IF2 DAC4 TDM Source", rt5677_if2_dac4_tdm_sel_enum); | ||
2008 | |||
2009 | static SOC_ENUM_SINGLE_DECL( | ||
2010 | rt5677_if2_dac5_tdm_sel_enum, RT5677_TDM2_CTRL5, | ||
2011 | RT5677_IF2_DAC5_SFT, rt5677_if12_dac_tdm_sel_src); | ||
2012 | |||
2013 | static const struct snd_kcontrol_new rt5677_if2_dac5_tdm_sel_mux = | ||
2014 | SOC_DAPM_ENUM("IF2 DAC5 TDM Source", rt5677_if2_dac5_tdm_sel_enum); | ||
2015 | |||
2016 | static SOC_ENUM_SINGLE_DECL( | ||
2017 | rt5677_if2_dac6_tdm_sel_enum, RT5677_TDM2_CTRL5, | ||
2018 | RT5677_IF2_DAC6_SFT, rt5677_if12_dac_tdm_sel_src); | ||
2019 | |||
2020 | static const struct snd_kcontrol_new rt5677_if2_dac6_tdm_sel_mux = | ||
2021 | SOC_DAPM_ENUM("IF2 DAC6 TDM Source", rt5677_if2_dac6_tdm_sel_enum); | ||
2022 | |||
2023 | static SOC_ENUM_SINGLE_DECL( | ||
2024 | rt5677_if2_dac7_tdm_sel_enum, RT5677_TDM2_CTRL5, | ||
2025 | RT5677_IF2_DAC7_SFT, rt5677_if12_dac_tdm_sel_src); | ||
2026 | |||
2027 | static const struct snd_kcontrol_new rt5677_if2_dac7_tdm_sel_mux = | ||
2028 | SOC_DAPM_ENUM("IF2 DAC7 TDM Source", rt5677_if2_dac7_tdm_sel_enum); | ||
2029 | |||
1570 | static int rt5677_bst1_event(struct snd_soc_dapm_widget *w, | 2030 | static int rt5677_bst1_event(struct snd_soc_dapm_widget *w, |
1571 | struct snd_kcontrol *kcontrol, int event) | 2031 | struct snd_kcontrol *kcontrol, int event) |
1572 | { | 2032 | { |
@@ -1678,6 +2138,77 @@ static int rt5677_set_micbias1_event(struct snd_soc_dapm_widget *w, | |||
1678 | return 0; | 2138 | return 0; |
1679 | } | 2139 | } |
1680 | 2140 | ||
2141 | static int rt5677_if1_adc_tdm_event(struct snd_soc_dapm_widget *w, | ||
2142 | struct snd_kcontrol *kcontrol, int event) | ||
2143 | { | ||
2144 | struct snd_soc_codec *codec = w->codec; | ||
2145 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
2146 | unsigned int value; | ||
2147 | |||
2148 | switch (event) { | ||
2149 | case SND_SOC_DAPM_PRE_PMU: | ||
2150 | regmap_read(rt5677->regmap, RT5677_TDM1_CTRL2, &value); | ||
2151 | if (value & RT5677_IF1_ADC_CTRL_MASK) | ||
2152 | regmap_update_bits(rt5677->regmap, RT5677_TDM1_CTRL1, | ||
2153 | RT5677_IF1_ADC_MODE_MASK, | ||
2154 | RT5677_IF1_ADC_MODE_TDM); | ||
2155 | break; | ||
2156 | |||
2157 | default: | ||
2158 | return 0; | ||
2159 | } | ||
2160 | |||
2161 | return 0; | ||
2162 | } | ||
2163 | |||
2164 | static int rt5677_if2_adc_tdm_event(struct snd_soc_dapm_widget *w, | ||
2165 | struct snd_kcontrol *kcontrol, int event) | ||
2166 | { | ||
2167 | struct snd_soc_codec *codec = w->codec; | ||
2168 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
2169 | unsigned int value; | ||
2170 | |||
2171 | switch (event) { | ||
2172 | case SND_SOC_DAPM_PRE_PMU: | ||
2173 | regmap_read(rt5677->regmap, RT5677_TDM2_CTRL2, &value); | ||
2174 | if (value & RT5677_IF2_ADC_CTRL_MASK) | ||
2175 | regmap_update_bits(rt5677->regmap, RT5677_TDM2_CTRL1, | ||
2176 | RT5677_IF2_ADC_MODE_MASK, | ||
2177 | RT5677_IF2_ADC_MODE_TDM); | ||
2178 | break; | ||
2179 | |||
2180 | default: | ||
2181 | return 0; | ||
2182 | } | ||
2183 | |||
2184 | return 0; | ||
2185 | } | ||
2186 | |||
2187 | static int rt5677_vref_event(struct snd_soc_dapm_widget *w, | ||
2188 | struct snd_kcontrol *kcontrol, int event) | ||
2189 | { | ||
2190 | struct snd_soc_codec *codec = w->codec; | ||
2191 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
2192 | |||
2193 | switch (event) { | ||
2194 | case SND_SOC_DAPM_POST_PMU: | ||
2195 | if (codec->dapm.bias_level != SND_SOC_BIAS_ON && | ||
2196 | !rt5677->is_vref_slow) { | ||
2197 | mdelay(20); | ||
2198 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, | ||
2199 | RT5677_PWR_FV1 | RT5677_PWR_FV2, | ||
2200 | RT5677_PWR_FV1 | RT5677_PWR_FV2); | ||
2201 | rt5677->is_vref_slow = true; | ||
2202 | } | ||
2203 | break; | ||
2204 | |||
2205 | default: | ||
2206 | return 0; | ||
2207 | } | ||
2208 | |||
2209 | return 0; | ||
2210 | } | ||
2211 | |||
1681 | static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | 2212 | static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { |
1682 | SND_SOC_DAPM_SUPPLY("PLL1", RT5677_PWR_ANLG2, RT5677_PWR_PLL1_BIT, | 2213 | SND_SOC_DAPM_SUPPLY("PLL1", RT5677_PWR_ANLG2, RT5677_PWR_PLL1_BIT, |
1683 | 0, rt5677_set_pll1_event, SND_SOC_DAPM_POST_PMU), | 2214 | 0, rt5677_set_pll1_event, SND_SOC_DAPM_POST_PMU), |
@@ -1837,10 +2368,8 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
1837 | SND_SOC_DAPM_PGA("Stereo4 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | 2368 | SND_SOC_DAPM_PGA("Stereo4 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), |
1838 | SND_SOC_DAPM_PGA("Sto2 ADC LR MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | 2369 | SND_SOC_DAPM_PGA("Sto2 ADC LR MIX", SND_SOC_NOPM, 0, 0, NULL, 0), |
1839 | SND_SOC_DAPM_PGA("Mono ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | 2370 | SND_SOC_DAPM_PGA("Mono ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), |
1840 | SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0), | 2371 | SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), |
1841 | SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0), | 2372 | SND_SOC_DAPM_PGA("IF2 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), |
1842 | SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1843 | SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1844 | 2373 | ||
1845 | /* DSP */ | 2374 | /* DSP */ |
1846 | SND_SOC_DAPM_MUX("IB9 Mux", SND_SOC_NOPM, 0, 0, | 2375 | SND_SOC_DAPM_MUX("IB9 Mux", SND_SOC_NOPM, 0, 0, |
@@ -1963,6 +2492,17 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
1963 | &rt5677_if1_adc3_mux), | 2492 | &rt5677_if1_adc3_mux), |
1964 | SND_SOC_DAPM_MUX("IF1 ADC4 Mux", SND_SOC_NOPM, 0, 0, | 2493 | SND_SOC_DAPM_MUX("IF1 ADC4 Mux", SND_SOC_NOPM, 0, 0, |
1965 | &rt5677_if1_adc4_mux), | 2494 | &rt5677_if1_adc4_mux), |
2495 | SND_SOC_DAPM_MUX("IF1 ADC1 Swap Mux", SND_SOC_NOPM, 0, 0, | ||
2496 | &rt5677_if1_adc1_swap_mux), | ||
2497 | SND_SOC_DAPM_MUX("IF1 ADC2 Swap Mux", SND_SOC_NOPM, 0, 0, | ||
2498 | &rt5677_if1_adc2_swap_mux), | ||
2499 | SND_SOC_DAPM_MUX("IF1 ADC3 Swap Mux", SND_SOC_NOPM, 0, 0, | ||
2500 | &rt5677_if1_adc3_swap_mux), | ||
2501 | SND_SOC_DAPM_MUX("IF1 ADC4 Swap Mux", SND_SOC_NOPM, 0, 0, | ||
2502 | &rt5677_if1_adc4_swap_mux), | ||
2503 | SND_SOC_DAPM_MUX_E("IF1 ADC TDM Swap Mux", SND_SOC_NOPM, 0, 0, | ||
2504 | &rt5677_if1_adc_tdm_swap_mux, rt5677_if1_adc_tdm_event, | ||
2505 | SND_SOC_DAPM_PRE_PMU), | ||
1966 | SND_SOC_DAPM_MUX("IF2 ADC1 Mux", SND_SOC_NOPM, 0, 0, | 2506 | SND_SOC_DAPM_MUX("IF2 ADC1 Mux", SND_SOC_NOPM, 0, 0, |
1967 | &rt5677_if2_adc1_mux), | 2507 | &rt5677_if2_adc1_mux), |
1968 | SND_SOC_DAPM_MUX("IF2 ADC2 Mux", SND_SOC_NOPM, 0, 0, | 2508 | SND_SOC_DAPM_MUX("IF2 ADC2 Mux", SND_SOC_NOPM, 0, 0, |
@@ -1971,6 +2511,17 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
1971 | &rt5677_if2_adc3_mux), | 2511 | &rt5677_if2_adc3_mux), |
1972 | SND_SOC_DAPM_MUX("IF2 ADC4 Mux", SND_SOC_NOPM, 0, 0, | 2512 | SND_SOC_DAPM_MUX("IF2 ADC4 Mux", SND_SOC_NOPM, 0, 0, |
1973 | &rt5677_if2_adc4_mux), | 2513 | &rt5677_if2_adc4_mux), |
2514 | SND_SOC_DAPM_MUX("IF2 ADC1 Swap Mux", SND_SOC_NOPM, 0, 0, | ||
2515 | &rt5677_if2_adc1_swap_mux), | ||
2516 | SND_SOC_DAPM_MUX("IF2 ADC2 Swap Mux", SND_SOC_NOPM, 0, 0, | ||
2517 | &rt5677_if2_adc2_swap_mux), | ||
2518 | SND_SOC_DAPM_MUX("IF2 ADC3 Swap Mux", SND_SOC_NOPM, 0, 0, | ||
2519 | &rt5677_if2_adc3_swap_mux), | ||
2520 | SND_SOC_DAPM_MUX("IF2 ADC4 Swap Mux", SND_SOC_NOPM, 0, 0, | ||
2521 | &rt5677_if2_adc4_swap_mux), | ||
2522 | SND_SOC_DAPM_MUX_E("IF2 ADC TDM Swap Mux", SND_SOC_NOPM, 0, 0, | ||
2523 | &rt5677_if2_adc_tdm_swap_mux, rt5677_if2_adc_tdm_event, | ||
2524 | SND_SOC_DAPM_PRE_PMU), | ||
1974 | SND_SOC_DAPM_MUX("IF3 ADC Mux", SND_SOC_NOPM, 0, 0, | 2525 | SND_SOC_DAPM_MUX("IF3 ADC Mux", SND_SOC_NOPM, 0, 0, |
1975 | &rt5677_if3_adc_mux), | 2526 | &rt5677_if3_adc_mux), |
1976 | SND_SOC_DAPM_MUX("IF4 ADC Mux", SND_SOC_NOPM, 0, 0, | 2527 | SND_SOC_DAPM_MUX("IF4 ADC Mux", SND_SOC_NOPM, 0, 0, |
@@ -1984,6 +2535,40 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
1984 | SND_SOC_DAPM_MUX("SLB ADC4 Mux", SND_SOC_NOPM, 0, 0, | 2535 | SND_SOC_DAPM_MUX("SLB ADC4 Mux", SND_SOC_NOPM, 0, 0, |
1985 | &rt5677_slb_adc4_mux), | 2536 | &rt5677_slb_adc4_mux), |
1986 | 2537 | ||
2538 | SND_SOC_DAPM_MUX("IF1 DAC0 Mux", SND_SOC_NOPM, 0, 0, | ||
2539 | &rt5677_if1_dac0_tdm_sel_mux), | ||
2540 | SND_SOC_DAPM_MUX("IF1 DAC1 Mux", SND_SOC_NOPM, 0, 0, | ||
2541 | &rt5677_if1_dac1_tdm_sel_mux), | ||
2542 | SND_SOC_DAPM_MUX("IF1 DAC2 Mux", SND_SOC_NOPM, 0, 0, | ||
2543 | &rt5677_if1_dac2_tdm_sel_mux), | ||
2544 | SND_SOC_DAPM_MUX("IF1 DAC3 Mux", SND_SOC_NOPM, 0, 0, | ||
2545 | &rt5677_if1_dac3_tdm_sel_mux), | ||
2546 | SND_SOC_DAPM_MUX("IF1 DAC4 Mux", SND_SOC_NOPM, 0, 0, | ||
2547 | &rt5677_if1_dac4_tdm_sel_mux), | ||
2548 | SND_SOC_DAPM_MUX("IF1 DAC5 Mux", SND_SOC_NOPM, 0, 0, | ||
2549 | &rt5677_if1_dac5_tdm_sel_mux), | ||
2550 | SND_SOC_DAPM_MUX("IF1 DAC6 Mux", SND_SOC_NOPM, 0, 0, | ||
2551 | &rt5677_if1_dac6_tdm_sel_mux), | ||
2552 | SND_SOC_DAPM_MUX("IF1 DAC7 Mux", SND_SOC_NOPM, 0, 0, | ||
2553 | &rt5677_if1_dac7_tdm_sel_mux), | ||
2554 | |||
2555 | SND_SOC_DAPM_MUX("IF2 DAC0 Mux", SND_SOC_NOPM, 0, 0, | ||
2556 | &rt5677_if2_dac0_tdm_sel_mux), | ||
2557 | SND_SOC_DAPM_MUX("IF2 DAC1 Mux", SND_SOC_NOPM, 0, 0, | ||
2558 | &rt5677_if2_dac1_tdm_sel_mux), | ||
2559 | SND_SOC_DAPM_MUX("IF2 DAC2 Mux", SND_SOC_NOPM, 0, 0, | ||
2560 | &rt5677_if2_dac2_tdm_sel_mux), | ||
2561 | SND_SOC_DAPM_MUX("IF2 DAC3 Mux", SND_SOC_NOPM, 0, 0, | ||
2562 | &rt5677_if2_dac3_tdm_sel_mux), | ||
2563 | SND_SOC_DAPM_MUX("IF2 DAC4 Mux", SND_SOC_NOPM, 0, 0, | ||
2564 | &rt5677_if2_dac4_tdm_sel_mux), | ||
2565 | SND_SOC_DAPM_MUX("IF2 DAC5 Mux", SND_SOC_NOPM, 0, 0, | ||
2566 | &rt5677_if2_dac5_tdm_sel_mux), | ||
2567 | SND_SOC_DAPM_MUX("IF2 DAC6 Mux", SND_SOC_NOPM, 0, 0, | ||
2568 | &rt5677_if2_dac6_tdm_sel_mux), | ||
2569 | SND_SOC_DAPM_MUX("IF2 DAC7 Mux", SND_SOC_NOPM, 0, 0, | ||
2570 | &rt5677_if2_dac7_tdm_sel_mux), | ||
2571 | |||
1987 | /* Audio Interface */ | 2572 | /* Audio Interface */ |
1988 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | 2573 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), |
1989 | SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), | 2574 | SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), |
@@ -2022,7 +2607,7 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
2022 | rt5677_ob_7_mix, ARRAY_SIZE(rt5677_ob_7_mix)), | 2607 | rt5677_ob_7_mix, ARRAY_SIZE(rt5677_ob_7_mix)), |
2023 | 2608 | ||
2024 | /* Output Side */ | 2609 | /* Output Side */ |
2025 | /* DAC mixer before sound effect */ | 2610 | /* DAC mixer before sound effect */ |
2026 | SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0, | 2611 | SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0, |
2027 | rt5677_dac_l_mix, ARRAY_SIZE(rt5677_dac_l_mix)), | 2612 | rt5677_dac_l_mix, ARRAY_SIZE(rt5677_dac_l_mix)), |
2028 | SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0, | 2613 | SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0, |
@@ -2109,13 +2694,20 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
2109 | SND_SOC_DAPM_MUX("PDM2 R Mux", RT5677_PDM_OUT_CTRL, RT5677_M_PDM2_R_SFT, | 2694 | SND_SOC_DAPM_MUX("PDM2 R Mux", RT5677_PDM_OUT_CTRL, RT5677_M_PDM2_R_SFT, |
2110 | 1, &rt5677_pdm2_r_mux), | 2695 | 1, &rt5677_pdm2_r_mux), |
2111 | 2696 | ||
2112 | SND_SOC_DAPM_PGA_S("LOUT1 amp", 1, RT5677_PWR_ANLG1, RT5677_PWR_LO1_BIT, | 2697 | SND_SOC_DAPM_PGA_S("LOUT1 amp", 0, RT5677_PWR_ANLG1, RT5677_PWR_LO1_BIT, |
2113 | 0, NULL, 0), | 2698 | 0, NULL, 0), |
2114 | SND_SOC_DAPM_PGA_S("LOUT2 amp", 1, RT5677_PWR_ANLG1, RT5677_PWR_LO2_BIT, | 2699 | SND_SOC_DAPM_PGA_S("LOUT2 amp", 0, RT5677_PWR_ANLG1, RT5677_PWR_LO2_BIT, |
2115 | 0, NULL, 0), | 2700 | 0, NULL, 0), |
2116 | SND_SOC_DAPM_PGA_S("LOUT3 amp", 1, RT5677_PWR_ANLG1, RT5677_PWR_LO3_BIT, | 2701 | SND_SOC_DAPM_PGA_S("LOUT3 amp", 0, RT5677_PWR_ANLG1, RT5677_PWR_LO3_BIT, |
2117 | 0, NULL, 0), | 2702 | 0, NULL, 0), |
2118 | 2703 | ||
2704 | SND_SOC_DAPM_PGA_S("LOUT1 vref", 1, SND_SOC_NOPM, 0, 0, | ||
2705 | rt5677_vref_event, SND_SOC_DAPM_POST_PMU), | ||
2706 | SND_SOC_DAPM_PGA_S("LOUT2 vref", 1, SND_SOC_NOPM, 0, 0, | ||
2707 | rt5677_vref_event, SND_SOC_DAPM_POST_PMU), | ||
2708 | SND_SOC_DAPM_PGA_S("LOUT3 vref", 1, SND_SOC_NOPM, 0, 0, | ||
2709 | rt5677_vref_event, SND_SOC_DAPM_POST_PMU), | ||
2710 | |||
2119 | /* Output Lines */ | 2711 | /* Output Lines */ |
2120 | SND_SOC_DAPM_OUTPUT("LOUT1"), | 2712 | SND_SOC_DAPM_OUTPUT("LOUT1"), |
2121 | SND_SOC_DAPM_OUTPUT("LOUT2"), | 2713 | SND_SOC_DAPM_OUTPUT("LOUT2"), |
@@ -2124,6 +2716,8 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
2124 | SND_SOC_DAPM_OUTPUT("PDM1R"), | 2716 | SND_SOC_DAPM_OUTPUT("PDM1R"), |
2125 | SND_SOC_DAPM_OUTPUT("PDM2L"), | 2717 | SND_SOC_DAPM_OUTPUT("PDM2L"), |
2126 | SND_SOC_DAPM_OUTPUT("PDM2R"), | 2718 | SND_SOC_DAPM_OUTPUT("PDM2R"), |
2719 | |||
2720 | SND_SOC_DAPM_POST("vref", rt5677_vref_event), | ||
2127 | }; | 2721 | }; |
2128 | 2722 | ||
2129 | static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | 2723 | static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { |
@@ -2354,11 +2948,42 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2354 | { "IF1 ADC4 Mux", "OB67", "OB67" }, | 2948 | { "IF1 ADC4 Mux", "OB67", "OB67" }, |
2355 | { "IF1 ADC4 Mux", "OB01", "OB01 Bypass Mux" }, | 2949 | { "IF1 ADC4 Mux", "OB01", "OB01 Bypass Mux" }, |
2356 | 2950 | ||
2951 | { "IF1 ADC1 Swap Mux", "L/R", "IF1 ADC1 Mux" }, | ||
2952 | { "IF1 ADC1 Swap Mux", "R/L", "IF1 ADC1 Mux" }, | ||
2953 | { "IF1 ADC1 Swap Mux", "L/L", "IF1 ADC1 Mux" }, | ||
2954 | { "IF1 ADC1 Swap Mux", "R/R", "IF1 ADC1 Mux" }, | ||
2955 | |||
2956 | { "IF1 ADC2 Swap Mux", "L/R", "IF1 ADC2 Mux" }, | ||
2957 | { "IF1 ADC2 Swap Mux", "R/L", "IF1 ADC2 Mux" }, | ||
2958 | { "IF1 ADC2 Swap Mux", "L/L", "IF1 ADC2 Mux" }, | ||
2959 | { "IF1 ADC2 Swap Mux", "R/R", "IF1 ADC2 Mux" }, | ||
2960 | |||
2961 | { "IF1 ADC3 Swap Mux", "L/R", "IF1 ADC3 Mux" }, | ||
2962 | { "IF1 ADC3 Swap Mux", "R/L", "IF1 ADC3 Mux" }, | ||
2963 | { "IF1 ADC3 Swap Mux", "L/L", "IF1 ADC3 Mux" }, | ||
2964 | { "IF1 ADC3 Swap Mux", "R/R", "IF1 ADC3 Mux" }, | ||
2965 | |||
2966 | { "IF1 ADC4 Swap Mux", "L/R", "IF1 ADC4 Mux" }, | ||
2967 | { "IF1 ADC4 Swap Mux", "R/L", "IF1 ADC4 Mux" }, | ||
2968 | { "IF1 ADC4 Swap Mux", "L/L", "IF1 ADC4 Mux" }, | ||
2969 | { "IF1 ADC4 Swap Mux", "R/R", "IF1 ADC4 Mux" }, | ||
2970 | |||
2971 | { "IF1 ADC", NULL, "IF1 ADC1 Swap Mux" }, | ||
2972 | { "IF1 ADC", NULL, "IF1 ADC2 Swap Mux" }, | ||
2973 | { "IF1 ADC", NULL, "IF1 ADC3 Swap Mux" }, | ||
2974 | { "IF1 ADC", NULL, "IF1 ADC4 Swap Mux" }, | ||
2975 | |||
2976 | { "IF1 ADC TDM Swap Mux", "1/2/3/4", "IF1 ADC" }, | ||
2977 | { "IF1 ADC TDM Swap Mux", "2/1/3/4", "IF1 ADC" }, | ||
2978 | { "IF1 ADC TDM Swap Mux", "2/3/1/4", "IF1 ADC" }, | ||
2979 | { "IF1 ADC TDM Swap Mux", "4/1/2/3", "IF1 ADC" }, | ||
2980 | { "IF1 ADC TDM Swap Mux", "1/3/2/4", "IF1 ADC" }, | ||
2981 | { "IF1 ADC TDM Swap Mux", "1/4/2/3", "IF1 ADC" }, | ||
2982 | { "IF1 ADC TDM Swap Mux", "3/1/2/4", "IF1 ADC" }, | ||
2983 | { "IF1 ADC TDM Swap Mux", "3/4/1/2", "IF1 ADC" }, | ||
2984 | |||
2357 | { "AIF1TX", NULL, "I2S1" }, | 2985 | { "AIF1TX", NULL, "I2S1" }, |
2358 | { "AIF1TX", NULL, "IF1 ADC1 Mux" }, | 2986 | { "AIF1TX", NULL, "IF1 ADC TDM Swap Mux" }, |
2359 | { "AIF1TX", NULL, "IF1 ADC2 Mux" }, | ||
2360 | { "AIF1TX", NULL, "IF1 ADC3 Mux" }, | ||
2361 | { "AIF1TX", NULL, "IF1 ADC4 Mux" }, | ||
2362 | 2987 | ||
2363 | { "IF2 ADC1 Mux", "STO1 ADC MIX", "Stereo1 ADC MIX" }, | 2988 | { "IF2 ADC1 Mux", "STO1 ADC MIX", "Stereo1 ADC MIX" }, |
2364 | { "IF2 ADC1 Mux", "OB01", "OB01 Bypass Mux" }, | 2989 | { "IF2 ADC1 Mux", "OB01", "OB01 Bypass Mux" }, |
@@ -2375,11 +3000,42 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2375 | { "IF2 ADC4 Mux", "OB67", "OB67" }, | 3000 | { "IF2 ADC4 Mux", "OB67", "OB67" }, |
2376 | { "IF2 ADC4 Mux", "OB01", "OB01 Bypass Mux" }, | 3001 | { "IF2 ADC4 Mux", "OB01", "OB01 Bypass Mux" }, |
2377 | 3002 | ||
3003 | { "IF2 ADC1 Swap Mux", "L/R", "IF2 ADC1 Mux" }, | ||
3004 | { "IF2 ADC1 Swap Mux", "R/L", "IF2 ADC1 Mux" }, | ||
3005 | { "IF2 ADC1 Swap Mux", "L/L", "IF2 ADC1 Mux" }, | ||
3006 | { "IF2 ADC1 Swap Mux", "R/R", "IF2 ADC1 Mux" }, | ||
3007 | |||
3008 | { "IF2 ADC2 Swap Mux", "L/R", "IF2 ADC2 Mux" }, | ||
3009 | { "IF2 ADC2 Swap Mux", "R/L", "IF2 ADC2 Mux" }, | ||
3010 | { "IF2 ADC2 Swap Mux", "L/L", "IF2 ADC2 Mux" }, | ||
3011 | { "IF2 ADC2 Swap Mux", "R/R", "IF2 ADC2 Mux" }, | ||
3012 | |||
3013 | { "IF2 ADC3 Swap Mux", "L/R", "IF2 ADC3 Mux" }, | ||
3014 | { "IF2 ADC3 Swap Mux", "R/L", "IF2 ADC3 Mux" }, | ||
3015 | { "IF2 ADC3 Swap Mux", "L/L", "IF2 ADC3 Mux" }, | ||
3016 | { "IF2 ADC3 Swap Mux", "R/R", "IF2 ADC3 Mux" }, | ||
3017 | |||
3018 | { "IF2 ADC4 Swap Mux", "L/R", "IF2 ADC4 Mux" }, | ||
3019 | { "IF2 ADC4 Swap Mux", "R/L", "IF2 ADC4 Mux" }, | ||
3020 | { "IF2 ADC4 Swap Mux", "L/L", "IF2 ADC4 Mux" }, | ||
3021 | { "IF2 ADC4 Swap Mux", "R/R", "IF2 ADC4 Mux" }, | ||
3022 | |||
3023 | { "IF2 ADC", NULL, "IF2 ADC1 Swap Mux" }, | ||
3024 | { "IF2 ADC", NULL, "IF2 ADC2 Swap Mux" }, | ||
3025 | { "IF2 ADC", NULL, "IF2 ADC3 Swap Mux" }, | ||
3026 | { "IF2 ADC", NULL, "IF2 ADC4 Swap Mux" }, | ||
3027 | |||
3028 | { "IF2 ADC TDM Swap Mux", "1/2/3/4", "IF2 ADC" }, | ||
3029 | { "IF2 ADC TDM Swap Mux", "2/1/3/4", "IF2 ADC" }, | ||
3030 | { "IF2 ADC TDM Swap Mux", "3/1/2/4", "IF2 ADC" }, | ||
3031 | { "IF2 ADC TDM Swap Mux", "4/1/2/3", "IF2 ADC" }, | ||
3032 | { "IF2 ADC TDM Swap Mux", "1/3/2/4", "IF2 ADC" }, | ||
3033 | { "IF2 ADC TDM Swap Mux", "1/4/2/3", "IF2 ADC" }, | ||
3034 | { "IF2 ADC TDM Swap Mux", "2/3/1/4", "IF2 ADC" }, | ||
3035 | { "IF2 ADC TDM Swap Mux", "3/4/1/2", "IF2 ADC" }, | ||
3036 | |||
2378 | { "AIF2TX", NULL, "I2S2" }, | 3037 | { "AIF2TX", NULL, "I2S2" }, |
2379 | { "AIF2TX", NULL, "IF2 ADC1 Mux" }, | 3038 | { "AIF2TX", NULL, "IF2 ADC TDM Swap Mux" }, |
2380 | { "AIF2TX", NULL, "IF2 ADC2 Mux" }, | ||
2381 | { "AIF2TX", NULL, "IF2 ADC3 Mux" }, | ||
2382 | { "AIF2TX", NULL, "IF2 ADC4 Mux" }, | ||
2383 | 3039 | ||
2384 | { "IF3 ADC Mux", "STO1 ADC MIX", "Stereo1 ADC MIX" }, | 3040 | { "IF3 ADC Mux", "STO1 ADC MIX", "Stereo1 ADC MIX" }, |
2385 | { "IF3 ADC Mux", "STO2 ADC MIX", "Stereo2 ADC MIX" }, | 3041 | { "IF3 ADC Mux", "STO2 ADC MIX", "Stereo2 ADC MIX" }, |
@@ -2569,14 +3225,86 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2569 | { "IF1 DAC6", NULL, "I2S1" }, | 3225 | { "IF1 DAC6", NULL, "I2S1" }, |
2570 | { "IF1 DAC7", NULL, "I2S1" }, | 3226 | { "IF1 DAC7", NULL, "I2S1" }, |
2571 | 3227 | ||
2572 | { "IF1 DAC01", NULL, "IF1 DAC0" }, | 3228 | { "IF1 DAC0 Mux", "Slot0", "IF1 DAC0" }, |
2573 | { "IF1 DAC01", NULL, "IF1 DAC1" }, | 3229 | { "IF1 DAC0 Mux", "Slot1", "IF1 DAC1" }, |
2574 | { "IF1 DAC23", NULL, "IF1 DAC2" }, | 3230 | { "IF1 DAC0 Mux", "Slot2", "IF1 DAC2" }, |
2575 | { "IF1 DAC23", NULL, "IF1 DAC3" }, | 3231 | { "IF1 DAC0 Mux", "Slot3", "IF1 DAC3" }, |
2576 | { "IF1 DAC45", NULL, "IF1 DAC4" }, | 3232 | { "IF1 DAC0 Mux", "Slot4", "IF1 DAC4" }, |
2577 | { "IF1 DAC45", NULL, "IF1 DAC5" }, | 3233 | { "IF1 DAC0 Mux", "Slot5", "IF1 DAC5" }, |
2578 | { "IF1 DAC67", NULL, "IF1 DAC6" }, | 3234 | { "IF1 DAC0 Mux", "Slot6", "IF1 DAC6" }, |
2579 | { "IF1 DAC67", NULL, "IF1 DAC7" }, | 3235 | { "IF1 DAC0 Mux", "Slot7", "IF1 DAC7" }, |
3236 | |||
3237 | { "IF1 DAC1 Mux", "Slot0", "IF1 DAC0" }, | ||
3238 | { "IF1 DAC1 Mux", "Slot1", "IF1 DAC1" }, | ||
3239 | { "IF1 DAC1 Mux", "Slot2", "IF1 DAC2" }, | ||
3240 | { "IF1 DAC1 Mux", "Slot3", "IF1 DAC3" }, | ||
3241 | { "IF1 DAC1 Mux", "Slot4", "IF1 DAC4" }, | ||
3242 | { "IF1 DAC1 Mux", "Slot5", "IF1 DAC5" }, | ||
3243 | { "IF1 DAC1 Mux", "Slot6", "IF1 DAC6" }, | ||
3244 | { "IF1 DAC1 Mux", "Slot7", "IF1 DAC7" }, | ||
3245 | |||
3246 | { "IF1 DAC2 Mux", "Slot0", "IF1 DAC0" }, | ||
3247 | { "IF1 DAC2 Mux", "Slot1", "IF1 DAC1" }, | ||
3248 | { "IF1 DAC2 Mux", "Slot2", "IF1 DAC2" }, | ||
3249 | { "IF1 DAC2 Mux", "Slot3", "IF1 DAC3" }, | ||
3250 | { "IF1 DAC2 Mux", "Slot4", "IF1 DAC4" }, | ||
3251 | { "IF1 DAC2 Mux", "Slot5", "IF1 DAC5" }, | ||
3252 | { "IF1 DAC2 Mux", "Slot6", "IF1 DAC6" }, | ||
3253 | { "IF1 DAC2 Mux", "Slot7", "IF1 DAC7" }, | ||
3254 | |||
3255 | { "IF1 DAC3 Mux", "Slot0", "IF1 DAC0" }, | ||
3256 | { "IF1 DAC3 Mux", "Slot1", "IF1 DAC1" }, | ||
3257 | { "IF1 DAC3 Mux", "Slot2", "IF1 DAC2" }, | ||
3258 | { "IF1 DAC3 Mux", "Slot3", "IF1 DAC3" }, | ||
3259 | { "IF1 DAC3 Mux", "Slot4", "IF1 DAC4" }, | ||
3260 | { "IF1 DAC3 Mux", "Slot5", "IF1 DAC5" }, | ||
3261 | { "IF1 DAC3 Mux", "Slot6", "IF1 DAC6" }, | ||
3262 | { "IF1 DAC3 Mux", "Slot7", "IF1 DAC7" }, | ||
3263 | |||
3264 | { "IF1 DAC4 Mux", "Slot0", "IF1 DAC0" }, | ||
3265 | { "IF1 DAC4 Mux", "Slot1", "IF1 DAC1" }, | ||
3266 | { "IF1 DAC4 Mux", "Slot2", "IF1 DAC2" }, | ||
3267 | { "IF1 DAC4 Mux", "Slot3", "IF1 DAC3" }, | ||
3268 | { "IF1 DAC4 Mux", "Slot4", "IF1 DAC4" }, | ||
3269 | { "IF1 DAC4 Mux", "Slot5", "IF1 DAC5" }, | ||
3270 | { "IF1 DAC4 Mux", "Slot6", "IF1 DAC6" }, | ||
3271 | { "IF1 DAC4 Mux", "Slot7", "IF1 DAC7" }, | ||
3272 | |||
3273 | { "IF1 DAC5 Mux", "Slot0", "IF1 DAC0" }, | ||
3274 | { "IF1 DAC5 Mux", "Slot1", "IF1 DAC1" }, | ||
3275 | { "IF1 DAC5 Mux", "Slot2", "IF1 DAC2" }, | ||
3276 | { "IF1 DAC5 Mux", "Slot3", "IF1 DAC3" }, | ||
3277 | { "IF1 DAC5 Mux", "Slot4", "IF1 DAC4" }, | ||
3278 | { "IF1 DAC5 Mux", "Slot5", "IF1 DAC5" }, | ||
3279 | { "IF1 DAC5 Mux", "Slot6", "IF1 DAC6" }, | ||
3280 | { "IF1 DAC5 Mux", "Slot7", "IF1 DAC7" }, | ||
3281 | |||
3282 | { "IF1 DAC6 Mux", "Slot0", "IF1 DAC0" }, | ||
3283 | { "IF1 DAC6 Mux", "Slot1", "IF1 DAC1" }, | ||
3284 | { "IF1 DAC6 Mux", "Slot2", "IF1 DAC2" }, | ||
3285 | { "IF1 DAC6 Mux", "Slot3", "IF1 DAC3" }, | ||
3286 | { "IF1 DAC6 Mux", "Slot4", "IF1 DAC4" }, | ||
3287 | { "IF1 DAC6 Mux", "Slot5", "IF1 DAC5" }, | ||
3288 | { "IF1 DAC6 Mux", "Slot6", "IF1 DAC6" }, | ||
3289 | { "IF1 DAC6 Mux", "Slot7", "IF1 DAC7" }, | ||
3290 | |||
3291 | { "IF1 DAC7 Mux", "Slot0", "IF1 DAC0" }, | ||
3292 | { "IF1 DAC7 Mux", "Slot1", "IF1 DAC1" }, | ||
3293 | { "IF1 DAC7 Mux", "Slot2", "IF1 DAC2" }, | ||
3294 | { "IF1 DAC7 Mux", "Slot3", "IF1 DAC3" }, | ||
3295 | { "IF1 DAC7 Mux", "Slot4", "IF1 DAC4" }, | ||
3296 | { "IF1 DAC7 Mux", "Slot5", "IF1 DAC5" }, | ||
3297 | { "IF1 DAC7 Mux", "Slot6", "IF1 DAC6" }, | ||
3298 | { "IF1 DAC7 Mux", "Slot7", "IF1 DAC7" }, | ||
3299 | |||
3300 | { "IF1 DAC01", NULL, "IF1 DAC0 Mux" }, | ||
3301 | { "IF1 DAC01", NULL, "IF1 DAC1 Mux" }, | ||
3302 | { "IF1 DAC23", NULL, "IF1 DAC2 Mux" }, | ||
3303 | { "IF1 DAC23", NULL, "IF1 DAC3 Mux" }, | ||
3304 | { "IF1 DAC45", NULL, "IF1 DAC4 Mux" }, | ||
3305 | { "IF1 DAC45", NULL, "IF1 DAC5 Mux" }, | ||
3306 | { "IF1 DAC67", NULL, "IF1 DAC6 Mux" }, | ||
3307 | { "IF1 DAC67", NULL, "IF1 DAC7 Mux" }, | ||
2580 | 3308 | ||
2581 | { "IF2 DAC0", NULL, "AIF2RX" }, | 3309 | { "IF2 DAC0", NULL, "AIF2RX" }, |
2582 | { "IF2 DAC1", NULL, "AIF2RX" }, | 3310 | { "IF2 DAC1", NULL, "AIF2RX" }, |
@@ -2595,14 +3323,86 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2595 | { "IF2 DAC6", NULL, "I2S2" }, | 3323 | { "IF2 DAC6", NULL, "I2S2" }, |
2596 | { "IF2 DAC7", NULL, "I2S2" }, | 3324 | { "IF2 DAC7", NULL, "I2S2" }, |
2597 | 3325 | ||
2598 | { "IF2 DAC01", NULL, "IF2 DAC0" }, | 3326 | { "IF2 DAC0 Mux", "Slot0", "IF2 DAC0" }, |
2599 | { "IF2 DAC01", NULL, "IF2 DAC1" }, | 3327 | { "IF2 DAC0 Mux", "Slot1", "IF2 DAC1" }, |
2600 | { "IF2 DAC23", NULL, "IF2 DAC2" }, | 3328 | { "IF2 DAC0 Mux", "Slot2", "IF2 DAC2" }, |
2601 | { "IF2 DAC23", NULL, "IF2 DAC3" }, | 3329 | { "IF2 DAC0 Mux", "Slot3", "IF2 DAC3" }, |
2602 | { "IF2 DAC45", NULL, "IF2 DAC4" }, | 3330 | { "IF2 DAC0 Mux", "Slot4", "IF2 DAC4" }, |
2603 | { "IF2 DAC45", NULL, "IF2 DAC5" }, | 3331 | { "IF2 DAC0 Mux", "Slot5", "IF2 DAC5" }, |
2604 | { "IF2 DAC67", NULL, "IF2 DAC6" }, | 3332 | { "IF2 DAC0 Mux", "Slot6", "IF2 DAC6" }, |
2605 | { "IF2 DAC67", NULL, "IF2 DAC7" }, | 3333 | { "IF2 DAC0 Mux", "Slot7", "IF2 DAC7" }, |
3334 | |||
3335 | { "IF2 DAC1 Mux", "Slot0", "IF2 DAC0" }, | ||
3336 | { "IF2 DAC1 Mux", "Slot1", "IF2 DAC1" }, | ||
3337 | { "IF2 DAC1 Mux", "Slot2", "IF2 DAC2" }, | ||
3338 | { "IF2 DAC1 Mux", "Slot3", "IF2 DAC3" }, | ||
3339 | { "IF2 DAC1 Mux", "Slot4", "IF2 DAC4" }, | ||
3340 | { "IF2 DAC1 Mux", "Slot5", "IF2 DAC5" }, | ||
3341 | { "IF2 DAC1 Mux", "Slot6", "IF2 DAC6" }, | ||
3342 | { "IF2 DAC1 Mux", "Slot7", "IF2 DAC7" }, | ||
3343 | |||
3344 | { "IF2 DAC2 Mux", "Slot0", "IF2 DAC0" }, | ||
3345 | { "IF2 DAC2 Mux", "Slot1", "IF2 DAC1" }, | ||
3346 | { "IF2 DAC2 Mux", "Slot2", "IF2 DAC2" }, | ||
3347 | { "IF2 DAC2 Mux", "Slot3", "IF2 DAC3" }, | ||
3348 | { "IF2 DAC2 Mux", "Slot4", "IF2 DAC4" }, | ||
3349 | { "IF2 DAC2 Mux", "Slot5", "IF2 DAC5" }, | ||
3350 | { "IF2 DAC2 Mux", "Slot6", "IF2 DAC6" }, | ||
3351 | { "IF2 DAC2 Mux", "Slot7", "IF2 DAC7" }, | ||
3352 | |||
3353 | { "IF2 DAC3 Mux", "Slot0", "IF2 DAC0" }, | ||
3354 | { "IF2 DAC3 Mux", "Slot1", "IF2 DAC1" }, | ||
3355 | { "IF2 DAC3 Mux", "Slot2", "IF2 DAC2" }, | ||
3356 | { "IF2 DAC3 Mux", "Slot3", "IF2 DAC3" }, | ||
3357 | { "IF2 DAC3 Mux", "Slot4", "IF2 DAC4" }, | ||
3358 | { "IF2 DAC3 Mux", "Slot5", "IF2 DAC5" }, | ||
3359 | { "IF2 DAC3 Mux", "Slot6", "IF2 DAC6" }, | ||
3360 | { "IF2 DAC3 Mux", "Slot7", "IF2 DAC7" }, | ||
3361 | |||
3362 | { "IF2 DAC4 Mux", "Slot0", "IF2 DAC0" }, | ||
3363 | { "IF2 DAC4 Mux", "Slot1", "IF2 DAC1" }, | ||
3364 | { "IF2 DAC4 Mux", "Slot2", "IF2 DAC2" }, | ||
3365 | { "IF2 DAC4 Mux", "Slot3", "IF2 DAC3" }, | ||
3366 | { "IF2 DAC4 Mux", "Slot4", "IF2 DAC4" }, | ||
3367 | { "IF2 DAC4 Mux", "Slot5", "IF2 DAC5" }, | ||
3368 | { "IF2 DAC4 Mux", "Slot6", "IF2 DAC6" }, | ||
3369 | { "IF2 DAC4 Mux", "Slot7", "IF2 DAC7" }, | ||
3370 | |||
3371 | { "IF2 DAC5 Mux", "Slot0", "IF2 DAC0" }, | ||
3372 | { "IF2 DAC5 Mux", "Slot1", "IF2 DAC1" }, | ||
3373 | { "IF2 DAC5 Mux", "Slot2", "IF2 DAC2" }, | ||
3374 | { "IF2 DAC5 Mux", "Slot3", "IF2 DAC3" }, | ||
3375 | { "IF2 DAC5 Mux", "Slot4", "IF2 DAC4" }, | ||
3376 | { "IF2 DAC5 Mux", "Slot5", "IF2 DAC5" }, | ||
3377 | { "IF2 DAC5 Mux", "Slot6", "IF2 DAC6" }, | ||
3378 | { "IF2 DAC5 Mux", "Slot7", "IF2 DAC7" }, | ||
3379 | |||
3380 | { "IF2 DAC6 Mux", "Slot0", "IF2 DAC0" }, | ||
3381 | { "IF2 DAC6 Mux", "Slot1", "IF2 DAC1" }, | ||
3382 | { "IF2 DAC6 Mux", "Slot2", "IF2 DAC2" }, | ||
3383 | { "IF2 DAC6 Mux", "Slot3", "IF2 DAC3" }, | ||
3384 | { "IF2 DAC6 Mux", "Slot4", "IF2 DAC4" }, | ||
3385 | { "IF2 DAC6 Mux", "Slot5", "IF2 DAC5" }, | ||
3386 | { "IF2 DAC6 Mux", "Slot6", "IF2 DAC6" }, | ||
3387 | { "IF2 DAC6 Mux", "Slot7", "IF2 DAC7" }, | ||
3388 | |||
3389 | { "IF2 DAC7 Mux", "Slot0", "IF2 DAC0" }, | ||
3390 | { "IF2 DAC7 Mux", "Slot1", "IF2 DAC1" }, | ||
3391 | { "IF2 DAC7 Mux", "Slot2", "IF2 DAC2" }, | ||
3392 | { "IF2 DAC7 Mux", "Slot3", "IF2 DAC3" }, | ||
3393 | { "IF2 DAC7 Mux", "Slot4", "IF2 DAC4" }, | ||
3394 | { "IF2 DAC7 Mux", "Slot5", "IF2 DAC5" }, | ||
3395 | { "IF2 DAC7 Mux", "Slot6", "IF2 DAC6" }, | ||
3396 | { "IF2 DAC7 Mux", "Slot7", "IF2 DAC7" }, | ||
3397 | |||
3398 | { "IF2 DAC01", NULL, "IF2 DAC0 Mux" }, | ||
3399 | { "IF2 DAC01", NULL, "IF2 DAC1 Mux" }, | ||
3400 | { "IF2 DAC23", NULL, "IF2 DAC2 Mux" }, | ||
3401 | { "IF2 DAC23", NULL, "IF2 DAC3 Mux" }, | ||
3402 | { "IF2 DAC45", NULL, "IF2 DAC4 Mux" }, | ||
3403 | { "IF2 DAC45", NULL, "IF2 DAC5 Mux" }, | ||
3404 | { "IF2 DAC67", NULL, "IF2 DAC6 Mux" }, | ||
3405 | { "IF2 DAC67", NULL, "IF2 DAC7 Mux" }, | ||
2606 | 3406 | ||
2607 | { "IF3 DAC", NULL, "AIF3RX" }, | 3407 | { "IF3 DAC", NULL, "AIF3RX" }, |
2608 | { "IF3 DAC", NULL, "I2S3" }, | 3408 | { "IF3 DAC", NULL, "I2S3" }, |
@@ -2806,9 +3606,13 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2806 | { "LOUT2 amp", NULL, "DAC 2" }, | 3606 | { "LOUT2 amp", NULL, "DAC 2" }, |
2807 | { "LOUT3 amp", NULL, "DAC 3" }, | 3607 | { "LOUT3 amp", NULL, "DAC 3" }, |
2808 | 3608 | ||
2809 | { "LOUT1", NULL, "LOUT1 amp" }, | 3609 | { "LOUT1 vref", NULL, "LOUT1 amp" }, |
2810 | { "LOUT2", NULL, "LOUT2 amp" }, | 3610 | { "LOUT2 vref", NULL, "LOUT2 amp" }, |
2811 | { "LOUT3", NULL, "LOUT3 amp" }, | 3611 | { "LOUT3 vref", NULL, "LOUT3 amp" }, |
3612 | |||
3613 | { "LOUT1", NULL, "LOUT1 vref" }, | ||
3614 | { "LOUT2", NULL, "LOUT2 vref" }, | ||
3615 | { "LOUT3", NULL, "LOUT3 vref" }, | ||
2812 | 3616 | ||
2813 | { "PDM1L", NULL, "PDM1 L Mux" }, | 3617 | { "PDM1L", NULL, "PDM1 L Mux" }, |
2814 | { "PDM1R", NULL, "PDM1 R Mux" }, | 3618 | { "PDM1R", NULL, "PDM1 R Mux" }, |
@@ -2837,7 +3641,8 @@ static int rt5677_hw_params(struct snd_pcm_substream *substream, | |||
2837 | rt5677->lrck[dai->id] = params_rate(params); | 3641 | rt5677->lrck[dai->id] = params_rate(params); |
2838 | pre_div = rl6231_get_clk_info(rt5677->sysclk, rt5677->lrck[dai->id]); | 3642 | pre_div = rl6231_get_clk_info(rt5677->sysclk, rt5677->lrck[dai->id]); |
2839 | if (pre_div < 0) { | 3643 | if (pre_div < 0) { |
2840 | dev_err(codec->dev, "Unsupported clock setting\n"); | 3644 | dev_err(codec->dev, "Unsupported clock setting: sysclk=%dHz lrck=%dHz\n", |
3645 | rt5677->sysclk, rt5677->lrck[dai->id]); | ||
2841 | return -EINVAL; | 3646 | return -EINVAL; |
2842 | } | 3647 | } |
2843 | frame_size = snd_soc_params_to_frame_size(params); | 3648 | frame_size = snd_soc_params_to_frame_size(params); |
@@ -3181,6 +3986,8 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec, | |||
3181 | 3986 | ||
3182 | case SND_SOC_BIAS_PREPARE: | 3987 | case SND_SOC_BIAS_PREPARE: |
3183 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { | 3988 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { |
3989 | rt5677_set_dsp_vad(codec, false); | ||
3990 | |||
3184 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, | 3991 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, |
3185 | RT5677_LDO1_SEL_MASK | RT5677_LDO2_SEL_MASK, | 3992 | RT5677_LDO1_SEL_MASK | RT5677_LDO2_SEL_MASK, |
3186 | 0x0055); | 3993 | 0x0055); |
@@ -3188,14 +3995,12 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec, | |||
3188 | RT5677_PR_BASE + RT5677_BIAS_CUR4, | 3995 | RT5677_PR_BASE + RT5677_BIAS_CUR4, |
3189 | 0x0f00, 0x0f00); | 3996 | 0x0f00, 0x0f00); |
3190 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, | 3997 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, |
3998 | RT5677_PWR_FV1 | RT5677_PWR_FV2 | | ||
3191 | RT5677_PWR_VREF1 | RT5677_PWR_MB | | 3999 | RT5677_PWR_VREF1 | RT5677_PWR_MB | |
3192 | RT5677_PWR_BG | RT5677_PWR_VREF2, | 4000 | RT5677_PWR_BG | RT5677_PWR_VREF2, |
3193 | RT5677_PWR_VREF1 | RT5677_PWR_MB | | 4001 | RT5677_PWR_VREF1 | RT5677_PWR_MB | |
3194 | RT5677_PWR_BG | RT5677_PWR_VREF2); | 4002 | RT5677_PWR_BG | RT5677_PWR_VREF2); |
3195 | mdelay(20); | 4003 | rt5677->is_vref_slow = false; |
3196 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, | ||
3197 | RT5677_PWR_FV1 | RT5677_PWR_FV2, | ||
3198 | RT5677_PWR_FV1 | RT5677_PWR_FV2); | ||
3199 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2, | 4004 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2, |
3200 | RT5677_PWR_CORE, RT5677_PWR_CORE); | 4005 | RT5677_PWR_CORE, RT5677_PWR_CORE); |
3201 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, | 4006 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, |
@@ -3214,6 +4019,9 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec, | |||
3214 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000); | 4019 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000); |
3215 | regmap_update_bits(rt5677->regmap, | 4020 | regmap_update_bits(rt5677->regmap, |
3216 | RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000); | 4021 | RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000); |
4022 | |||
4023 | if (rt5677->dsp_vad_en) | ||
4024 | rt5677_set_dsp_vad(codec, true); | ||
3217 | break; | 4025 | break; |
3218 | 4026 | ||
3219 | default: | 4027 | default: |
@@ -3309,6 +4117,78 @@ static int rt5677_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | |||
3309 | return 0; | 4117 | return 0; |
3310 | } | 4118 | } |
3311 | 4119 | ||
4120 | /** Configures the gpio as | ||
4121 | * 0 - floating | ||
4122 | * 1 - pull down | ||
4123 | * 2 - pull up | ||
4124 | */ | ||
4125 | static void rt5677_gpio_config(struct rt5677_priv *rt5677, unsigned offset, | ||
4126 | int value) | ||
4127 | { | ||
4128 | int shift; | ||
4129 | |||
4130 | switch (offset) { | ||
4131 | case RT5677_GPIO1 ... RT5677_GPIO2: | ||
4132 | shift = 2 * (1 - offset); | ||
4133 | regmap_update_bits(rt5677->regmap, | ||
4134 | RT5677_PR_BASE + RT5677_DIG_IN_PIN_ST_CTRL2, | ||
4135 | 0x3 << shift, | ||
4136 | (value & 0x3) << shift); | ||
4137 | break; | ||
4138 | |||
4139 | case RT5677_GPIO3 ... RT5677_GPIO6: | ||
4140 | shift = 2 * (9 - offset); | ||
4141 | regmap_update_bits(rt5677->regmap, | ||
4142 | RT5677_PR_BASE + RT5677_DIG_IN_PIN_ST_CTRL3, | ||
4143 | 0x3 << shift, | ||
4144 | (value & 0x3) << shift); | ||
4145 | break; | ||
4146 | |||
4147 | default: | ||
4148 | break; | ||
4149 | } | ||
4150 | } | ||
4151 | |||
4152 | static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset) | ||
4153 | { | ||
4154 | struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); | ||
4155 | struct regmap_irq_chip_data *data = rt5677->irq_data; | ||
4156 | int irq; | ||
4157 | |||
4158 | if (offset >= RT5677_GPIO1 && offset <= RT5677_GPIO3) { | ||
4159 | if ((rt5677->pdata.jd1_gpio == 1 && offset == RT5677_GPIO1) || | ||
4160 | (rt5677->pdata.jd1_gpio == 2 && | ||
4161 | offset == RT5677_GPIO2) || | ||
4162 | (rt5677->pdata.jd1_gpio == 3 && | ||
4163 | offset == RT5677_GPIO3)) { | ||
4164 | irq = RT5677_IRQ_JD1; | ||
4165 | } else { | ||
4166 | return -ENXIO; | ||
4167 | } | ||
4168 | } | ||
4169 | |||
4170 | if (offset >= RT5677_GPIO4 && offset <= RT5677_GPIO6) { | ||
4171 | if ((rt5677->pdata.jd2_gpio == 1 && offset == RT5677_GPIO4) || | ||
4172 | (rt5677->pdata.jd2_gpio == 2 && | ||
4173 | offset == RT5677_GPIO5) || | ||
4174 | (rt5677->pdata.jd2_gpio == 3 && | ||
4175 | offset == RT5677_GPIO6)) { | ||
4176 | irq = RT5677_IRQ_JD2; | ||
4177 | } else if ((rt5677->pdata.jd3_gpio == 1 && | ||
4178 | offset == RT5677_GPIO4) || | ||
4179 | (rt5677->pdata.jd3_gpio == 2 && | ||
4180 | offset == RT5677_GPIO5) || | ||
4181 | (rt5677->pdata.jd3_gpio == 3 && | ||
4182 | offset == RT5677_GPIO6)) { | ||
4183 | irq = RT5677_IRQ_JD3; | ||
4184 | } else { | ||
4185 | return -ENXIO; | ||
4186 | } | ||
4187 | } | ||
4188 | |||
4189 | return regmap_irq_get_virq(data, irq); | ||
4190 | } | ||
4191 | |||
3312 | static struct gpio_chip rt5677_template_chip = { | 4192 | static struct gpio_chip rt5677_template_chip = { |
3313 | .label = "rt5677", | 4193 | .label = "rt5677", |
3314 | .owner = THIS_MODULE, | 4194 | .owner = THIS_MODULE, |
@@ -3316,6 +4196,7 @@ static struct gpio_chip rt5677_template_chip = { | |||
3316 | .set = rt5677_gpio_set, | 4196 | .set = rt5677_gpio_set, |
3317 | .direction_input = rt5677_gpio_direction_in, | 4197 | .direction_input = rt5677_gpio_direction_in, |
3318 | .get = rt5677_gpio_get, | 4198 | .get = rt5677_gpio_get, |
4199 | .to_irq = rt5677_to_irq, | ||
3319 | .can_sleep = 1, | 4200 | .can_sleep = 1, |
3320 | }; | 4201 | }; |
3321 | 4202 | ||
@@ -3341,6 +4222,11 @@ static void rt5677_free_gpio(struct i2c_client *i2c) | |||
3341 | gpiochip_remove(&rt5677->gpio_chip); | 4222 | gpiochip_remove(&rt5677->gpio_chip); |
3342 | } | 4223 | } |
3343 | #else | 4224 | #else |
4225 | static void rt5677_gpio_config(struct rt5677_priv *rt5677, unsigned offset, | ||
4226 | int value) | ||
4227 | { | ||
4228 | } | ||
4229 | |||
3344 | static void rt5677_init_gpio(struct i2c_client *i2c) | 4230 | static void rt5677_init_gpio(struct i2c_client *i2c) |
3345 | { | 4231 | { |
3346 | } | 4232 | } |
@@ -3353,6 +4239,7 @@ static void rt5677_free_gpio(struct i2c_client *i2c) | |||
3353 | static int rt5677_probe(struct snd_soc_codec *codec) | 4239 | static int rt5677_probe(struct snd_soc_codec *codec) |
3354 | { | 4240 | { |
3355 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 4241 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
4242 | int i; | ||
3356 | 4243 | ||
3357 | rt5677->codec = codec; | 4244 | rt5677->codec = codec; |
3358 | 4245 | ||
@@ -3371,6 +4258,37 @@ static int rt5677_probe(struct snd_soc_codec *codec) | |||
3371 | regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020); | 4258 | regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020); |
3372 | regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x0c00); | 4259 | regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x0c00); |
3373 | 4260 | ||
4261 | for (i = 0; i < RT5677_GPIO_NUM; i++) | ||
4262 | rt5677_gpio_config(rt5677, i, rt5677->pdata.gpio_config[i]); | ||
4263 | |||
4264 | if (rt5677->irq_data) { | ||
4265 | regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL1, 0x8000, | ||
4266 | 0x8000); | ||
4267 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x0018, | ||
4268 | 0x0008); | ||
4269 | |||
4270 | if (rt5677->pdata.jd1_gpio) | ||
4271 | regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1, | ||
4272 | RT5677_SEL_GPIO_JD1_MASK, | ||
4273 | rt5677->pdata.jd1_gpio << | ||
4274 | RT5677_SEL_GPIO_JD1_SFT); | ||
4275 | |||
4276 | if (rt5677->pdata.jd2_gpio) | ||
4277 | regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1, | ||
4278 | RT5677_SEL_GPIO_JD2_MASK, | ||
4279 | rt5677->pdata.jd2_gpio << | ||
4280 | RT5677_SEL_GPIO_JD2_SFT); | ||
4281 | |||
4282 | if (rt5677->pdata.jd3_gpio) | ||
4283 | regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1, | ||
4284 | RT5677_SEL_GPIO_JD3_MASK, | ||
4285 | rt5677->pdata.jd3_gpio << | ||
4286 | RT5677_SEL_GPIO_JD3_SFT); | ||
4287 | } | ||
4288 | |||
4289 | mutex_init(&rt5677->dsp_cmd_lock); | ||
4290 | mutex_init(&rt5677->dsp_pri_lock); | ||
4291 | |||
3374 | return 0; | 4292 | return 0; |
3375 | } | 4293 | } |
3376 | 4294 | ||
@@ -3390,8 +4308,11 @@ static int rt5677_suspend(struct snd_soc_codec *codec) | |||
3390 | { | 4308 | { |
3391 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 4309 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
3392 | 4310 | ||
3393 | regcache_cache_only(rt5677->regmap, true); | 4311 | if (!rt5677->dsp_vad_en) { |
3394 | regcache_mark_dirty(rt5677->regmap); | 4312 | regcache_cache_only(rt5677->regmap, true); |
4313 | regcache_mark_dirty(rt5677->regmap); | ||
4314 | } | ||
4315 | |||
3395 | if (gpio_is_valid(rt5677->pow_ldo2)) | 4316 | if (gpio_is_valid(rt5677->pow_ldo2)) |
3396 | gpio_set_value_cansleep(rt5677->pow_ldo2, 0); | 4317 | gpio_set_value_cansleep(rt5677->pow_ldo2, 0); |
3397 | 4318 | ||
@@ -3406,8 +4327,11 @@ static int rt5677_resume(struct snd_soc_codec *codec) | |||
3406 | gpio_set_value_cansleep(rt5677->pow_ldo2, 1); | 4327 | gpio_set_value_cansleep(rt5677->pow_ldo2, 1); |
3407 | msleep(10); | 4328 | msleep(10); |
3408 | } | 4329 | } |
3409 | regcache_cache_only(rt5677->regmap, false); | 4330 | |
3410 | regcache_sync(rt5677->regmap); | 4331 | if (!rt5677->dsp_vad_en) { |
4332 | regcache_cache_only(rt5677->regmap, false); | ||
4333 | regcache_sync(rt5677->regmap); | ||
4334 | } | ||
3411 | 4335 | ||
3412 | return 0; | 4336 | return 0; |
3413 | } | 4337 | } |
@@ -3416,6 +4340,51 @@ static int rt5677_resume(struct snd_soc_codec *codec) | |||
3416 | #define rt5677_resume NULL | 4340 | #define rt5677_resume NULL |
3417 | #endif | 4341 | #endif |
3418 | 4342 | ||
4343 | static int rt5677_read(void *context, unsigned int reg, unsigned int *val) | ||
4344 | { | ||
4345 | struct i2c_client *client = context; | ||
4346 | struct rt5677_priv *rt5677 = i2c_get_clientdata(client); | ||
4347 | |||
4348 | if (rt5677->is_dsp_mode) { | ||
4349 | if (reg > 0xff) { | ||
4350 | mutex_lock(&rt5677->dsp_pri_lock); | ||
4351 | rt5677_dsp_mode_i2c_write(rt5677, RT5677_PRIV_INDEX, | ||
4352 | reg & 0xff); | ||
4353 | rt5677_dsp_mode_i2c_read(rt5677, RT5677_PRIV_DATA, val); | ||
4354 | mutex_unlock(&rt5677->dsp_pri_lock); | ||
4355 | } else { | ||
4356 | rt5677_dsp_mode_i2c_read(rt5677, reg, val); | ||
4357 | } | ||
4358 | } else { | ||
4359 | regmap_read(rt5677->regmap_physical, reg, val); | ||
4360 | } | ||
4361 | |||
4362 | return 0; | ||
4363 | } | ||
4364 | |||
4365 | static int rt5677_write(void *context, unsigned int reg, unsigned int val) | ||
4366 | { | ||
4367 | struct i2c_client *client = context; | ||
4368 | struct rt5677_priv *rt5677 = i2c_get_clientdata(client); | ||
4369 | |||
4370 | if (rt5677->is_dsp_mode) { | ||
4371 | if (reg > 0xff) { | ||
4372 | mutex_lock(&rt5677->dsp_pri_lock); | ||
4373 | rt5677_dsp_mode_i2c_write(rt5677, RT5677_PRIV_INDEX, | ||
4374 | reg & 0xff); | ||
4375 | rt5677_dsp_mode_i2c_write(rt5677, RT5677_PRIV_DATA, | ||
4376 | val); | ||
4377 | mutex_unlock(&rt5677->dsp_pri_lock); | ||
4378 | } else { | ||
4379 | rt5677_dsp_mode_i2c_write(rt5677, reg, val); | ||
4380 | } | ||
4381 | } else { | ||
4382 | regmap_write(rt5677->regmap_physical, reg, val); | ||
4383 | } | ||
4384 | |||
4385 | return 0; | ||
4386 | } | ||
4387 | |||
3419 | #define RT5677_STEREO_RATES SNDRV_PCM_RATE_8000_96000 | 4388 | #define RT5677_STEREO_RATES SNDRV_PCM_RATE_8000_96000 |
3420 | #define RT5677_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | 4389 | #define RT5677_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
3421 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | 4390 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) |
@@ -3541,6 +4510,20 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5677 = { | |||
3541 | .num_dapm_routes = ARRAY_SIZE(rt5677_dapm_routes), | 4510 | .num_dapm_routes = ARRAY_SIZE(rt5677_dapm_routes), |
3542 | }; | 4511 | }; |
3543 | 4512 | ||
4513 | static const struct regmap_config rt5677_regmap_physical = { | ||
4514 | .name = "physical", | ||
4515 | .reg_bits = 8, | ||
4516 | .val_bits = 16, | ||
4517 | |||
4518 | .max_register = RT5677_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5677_ranges) * | ||
4519 | RT5677_PR_SPACING), | ||
4520 | .readable_reg = rt5677_readable_register, | ||
4521 | |||
4522 | .cache_type = REGCACHE_NONE, | ||
4523 | .ranges = rt5677_ranges, | ||
4524 | .num_ranges = ARRAY_SIZE(rt5677_ranges), | ||
4525 | }; | ||
4526 | |||
3544 | static const struct regmap_config rt5677_regmap = { | 4527 | static const struct regmap_config rt5677_regmap = { |
3545 | .reg_bits = 8, | 4528 | .reg_bits = 8, |
3546 | .val_bits = 16, | 4529 | .val_bits = 16, |
@@ -3550,6 +4533,8 @@ static const struct regmap_config rt5677_regmap = { | |||
3550 | 4533 | ||
3551 | .volatile_reg = rt5677_volatile_register, | 4534 | .volatile_reg = rt5677_volatile_register, |
3552 | .readable_reg = rt5677_readable_register, | 4535 | .readable_reg = rt5677_readable_register, |
4536 | .reg_read = rt5677_read, | ||
4537 | .reg_write = rt5677_write, | ||
3553 | 4538 | ||
3554 | .cache_type = REGCACHE_RBTREE, | 4539 | .cache_type = REGCACHE_RBTREE, |
3555 | .reg_defaults = rt5677_reg, | 4540 | .reg_defaults = rt5677_reg, |
@@ -3590,9 +4575,77 @@ static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np) | |||
3590 | (rt5677->pow_ldo2 != -ENOENT)) | 4575 | (rt5677->pow_ldo2 != -ENOENT)) |
3591 | return rt5677->pow_ldo2; | 4576 | return rt5677->pow_ldo2; |
3592 | 4577 | ||
4578 | of_property_read_u8_array(np, "realtek,gpio-config", | ||
4579 | rt5677->pdata.gpio_config, RT5677_GPIO_NUM); | ||
4580 | |||
4581 | of_property_read_u32(np, "realtek,jd1-gpio", &rt5677->pdata.jd1_gpio); | ||
4582 | of_property_read_u32(np, "realtek,jd2-gpio", &rt5677->pdata.jd2_gpio); | ||
4583 | of_property_read_u32(np, "realtek,jd3-gpio", &rt5677->pdata.jd3_gpio); | ||
4584 | |||
4585 | return 0; | ||
4586 | } | ||
4587 | |||
4588 | static struct regmap_irq rt5677_irqs[] = { | ||
4589 | [RT5677_IRQ_JD1] = { | ||
4590 | .reg_offset = 0, | ||
4591 | .mask = RT5677_EN_IRQ_GPIO_JD1, | ||
4592 | }, | ||
4593 | [RT5677_IRQ_JD2] = { | ||
4594 | .reg_offset = 0, | ||
4595 | .mask = RT5677_EN_IRQ_GPIO_JD2, | ||
4596 | }, | ||
4597 | [RT5677_IRQ_JD3] = { | ||
4598 | .reg_offset = 0, | ||
4599 | .mask = RT5677_EN_IRQ_GPIO_JD3, | ||
4600 | }, | ||
4601 | }; | ||
4602 | |||
4603 | static struct regmap_irq_chip rt5677_irq_chip = { | ||
4604 | .name = "rt5677", | ||
4605 | .irqs = rt5677_irqs, | ||
4606 | .num_irqs = ARRAY_SIZE(rt5677_irqs), | ||
4607 | |||
4608 | .num_regs = 1, | ||
4609 | .status_base = RT5677_IRQ_CTRL1, | ||
4610 | .mask_base = RT5677_IRQ_CTRL1, | ||
4611 | .mask_invert = 1, | ||
4612 | }; | ||
4613 | |||
4614 | static int rt5677_init_irq(struct i2c_client *i2c) | ||
4615 | { | ||
4616 | int ret; | ||
4617 | struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c); | ||
4618 | |||
4619 | if (!rt5677->pdata.jd1_gpio && | ||
4620 | !rt5677->pdata.jd2_gpio && | ||
4621 | !rt5677->pdata.jd3_gpio) | ||
4622 | return 0; | ||
4623 | |||
4624 | if (!i2c->irq) { | ||
4625 | dev_err(&i2c->dev, "No interrupt specified\n"); | ||
4626 | return -EINVAL; | ||
4627 | } | ||
4628 | |||
4629 | ret = regmap_add_irq_chip(rt5677->regmap, i2c->irq, | ||
4630 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0, | ||
4631 | &rt5677_irq_chip, &rt5677->irq_data); | ||
4632 | |||
4633 | if (ret != 0) { | ||
4634 | dev_err(&i2c->dev, "Failed to register IRQ chip: %d\n", ret); | ||
4635 | return ret; | ||
4636 | } | ||
4637 | |||
3593 | return 0; | 4638 | return 0; |
3594 | } | 4639 | } |
3595 | 4640 | ||
4641 | static void rt5677_free_irq(struct i2c_client *i2c) | ||
4642 | { | ||
4643 | struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c); | ||
4644 | |||
4645 | if (rt5677->irq_data) | ||
4646 | regmap_del_irq_chip(i2c->irq, rt5677->irq_data); | ||
4647 | } | ||
4648 | |||
3596 | static int rt5677_i2c_probe(struct i2c_client *i2c, | 4649 | static int rt5677_i2c_probe(struct i2c_client *i2c, |
3597 | const struct i2c_device_id *id) | 4650 | const struct i2c_device_id *id) |
3598 | { | 4651 | { |
@@ -3638,7 +4691,16 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
3638 | msleep(10); | 4691 | msleep(10); |
3639 | } | 4692 | } |
3640 | 4693 | ||
3641 | rt5677->regmap = devm_regmap_init_i2c(i2c, &rt5677_regmap); | 4694 | rt5677->regmap_physical = devm_regmap_init_i2c(i2c, |
4695 | &rt5677_regmap_physical); | ||
4696 | if (IS_ERR(rt5677->regmap_physical)) { | ||
4697 | ret = PTR_ERR(rt5677->regmap_physical); | ||
4698 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
4699 | ret); | ||
4700 | return ret; | ||
4701 | } | ||
4702 | |||
4703 | rt5677->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt5677_regmap); | ||
3642 | if (IS_ERR(rt5677->regmap)) { | 4704 | if (IS_ERR(rt5677->regmap)) { |
3643 | ret = PTR_ERR(rt5677->regmap); | 4705 | ret = PTR_ERR(rt5677->regmap); |
3644 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 4706 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
@@ -3690,6 +4752,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
3690 | } | 4752 | } |
3691 | 4753 | ||
3692 | rt5677_init_gpio(i2c); | 4754 | rt5677_init_gpio(i2c); |
4755 | rt5677_init_irq(i2c); | ||
3693 | 4756 | ||
3694 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, | 4757 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, |
3695 | rt5677_dai, ARRAY_SIZE(rt5677_dai)); | 4758 | rt5677_dai, ARRAY_SIZE(rt5677_dai)); |
@@ -3698,6 +4761,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
3698 | static int rt5677_i2c_remove(struct i2c_client *i2c) | 4761 | static int rt5677_i2c_remove(struct i2c_client *i2c) |
3699 | { | 4762 | { |
3700 | snd_soc_unregister_codec(&i2c->dev); | 4763 | snd_soc_unregister_codec(&i2c->dev); |
4764 | rt5677_free_irq(i2c); | ||
3701 | rt5677_free_gpio(i2c); | 4765 | rt5677_free_gpio(i2c); |
3702 | 4766 | ||
3703 | return 0; | 4767 | return 0; |
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index d4eb6d5e6746..c0a625f290cc 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #define __RT5677_H__ | 13 | #define __RT5677_H__ |
14 | 14 | ||
15 | #include <sound/rt5677.h> | 15 | #include <sound/rt5677.h> |
16 | #include <linux/gpio/driver.h> | ||
16 | 17 | ||
17 | /* Info */ | 18 | /* Info */ |
18 | #define RT5677_RESET 0x00 | 19 | #define RT5677_RESET 0x00 |
@@ -305,10 +306,10 @@ | |||
305 | #define RT5677_R_MUTE_SFT 7 | 306 | #define RT5677_R_MUTE_SFT 7 |
306 | #define RT5677_VOL_R_MUTE (0x1 << 6) | 307 | #define RT5677_VOL_R_MUTE (0x1 << 6) |
307 | #define RT5677_VOL_R_SFT 6 | 308 | #define RT5677_VOL_R_SFT 6 |
308 | #define RT5677_L_VOL_MASK (0x3f << 8) | 309 | #define RT5677_L_VOL_MASK (0x7f << 9) |
309 | #define RT5677_L_VOL_SFT 8 | 310 | #define RT5677_L_VOL_SFT 9 |
310 | #define RT5677_R_VOL_MASK (0x3f) | 311 | #define RT5677_R_VOL_MASK (0x7f << 1) |
311 | #define RT5677_R_VOL_SFT 0 | 312 | #define RT5677_R_VOL_SFT 1 |
312 | 313 | ||
313 | /* LOUT1 Control (0x01) */ | 314 | /* LOUT1 Control (0x01) */ |
314 | #define RT5677_LOUT1_L_MUTE (0x1 << 15) | 315 | #define RT5677_LOUT1_L_MUTE (0x1 << 15) |
@@ -446,16 +447,16 @@ | |||
446 | #define RT5677_SEL_DAC2_R_SRC_SFT 0 | 447 | #define RT5677_SEL_DAC2_R_SRC_SFT 0 |
447 | 448 | ||
448 | /* Stereo1 ADC Digital Volume Control (0x1c) */ | 449 | /* Stereo1 ADC Digital Volume Control (0x1c) */ |
449 | #define RT5677_STO1_ADC_L_VOL_MASK (0x7f << 8) | 450 | #define RT5677_STO1_ADC_L_VOL_MASK (0x3f << 9) |
450 | #define RT5677_STO1_ADC_L_VOL_SFT 8 | 451 | #define RT5677_STO1_ADC_L_VOL_SFT 9 |
451 | #define RT5677_STO1_ADC_R_VOL_MASK (0x7f) | 452 | #define RT5677_STO1_ADC_R_VOL_MASK (0x3f << 1) |
452 | #define RT5677_STO1_ADC_R_VOL_SFT 0 | 453 | #define RT5677_STO1_ADC_R_VOL_SFT 1 |
453 | 454 | ||
454 | /* Mono ADC Digital Volume Control (0x1d) */ | 455 | /* Mono ADC Digital Volume Control (0x1d) */ |
455 | #define RT5677_MONO_ADC_L_VOL_MASK (0x7f << 8) | 456 | #define RT5677_MONO_ADC_L_VOL_MASK (0x3f << 9) |
456 | #define RT5677_MONO_ADC_L_VOL_SFT 8 | 457 | #define RT5677_MONO_ADC_L_VOL_SFT 9 |
457 | #define RT5677_MONO_ADC_R_VOL_MASK (0x7f) | 458 | #define RT5677_MONO_ADC_R_VOL_MASK (0x3f << 1) |
458 | #define RT5677_MONO_ADC_R_VOL_SFT 0 | 459 | #define RT5677_MONO_ADC_R_VOL_SFT 1 |
459 | 460 | ||
460 | /* Stereo 1/2 ADC Boost Gain Control (0x1e) */ | 461 | /* Stereo 1/2 ADC Boost Gain Control (0x1e) */ |
461 | #define RT5677_STO1_ADC_L_BST_MASK (0x3 << 14) | 462 | #define RT5677_STO1_ADC_L_BST_MASK (0x3 << 14) |
@@ -798,7 +799,21 @@ | |||
798 | #define RT5677_PDM2_I2C_EXE (0x1 << 1) | 799 | #define RT5677_PDM2_I2C_EXE (0x1 << 1) |
799 | #define RT5677_PDM2_I2C_BUSY (0x1 << 0) | 800 | #define RT5677_PDM2_I2C_BUSY (0x1 << 0) |
800 | 801 | ||
801 | /* MX3C TDM1 control 1 (0x3c) */ | 802 | /* TDM1 control 1 (0x3b) */ |
803 | #define RT5677_IF1_ADC_MODE_MASK (0x1 << 12) | ||
804 | #define RT5677_IF1_ADC_MODE_SFT 12 | ||
805 | #define RT5677_IF1_ADC_MODE_I2S (0x0 << 12) | ||
806 | #define RT5677_IF1_ADC_MODE_TDM (0x1 << 12) | ||
807 | #define RT5677_IF1_ADC1_SWAP_MASK (0x3 << 6) | ||
808 | #define RT5677_IF1_ADC1_SWAP_SFT 6 | ||
809 | #define RT5677_IF1_ADC2_SWAP_MASK (0x3 << 4) | ||
810 | #define RT5677_IF1_ADC2_SWAP_SFT 4 | ||
811 | #define RT5677_IF1_ADC3_SWAP_MASK (0x3 << 2) | ||
812 | #define RT5677_IF1_ADC3_SWAP_SFT 2 | ||
813 | #define RT5677_IF1_ADC4_SWAP_MASK (0x3 << 0) | ||
814 | #define RT5677_IF1_ADC4_SWAP_SFT 0 | ||
815 | |||
816 | /* TDM1 control 2 (0x3c) */ | ||
802 | #define RT5677_IF1_ADC4_MASK (0x3 << 10) | 817 | #define RT5677_IF1_ADC4_MASK (0x3 << 10) |
803 | #define RT5677_IF1_ADC4_SFT 10 | 818 | #define RT5677_IF1_ADC4_SFT 10 |
804 | #define RT5677_IF1_ADC3_MASK (0x3 << 8) | 819 | #define RT5677_IF1_ADC3_MASK (0x3 << 8) |
@@ -807,8 +822,44 @@ | |||
807 | #define RT5677_IF1_ADC2_SFT 6 | 822 | #define RT5677_IF1_ADC2_SFT 6 |
808 | #define RT5677_IF1_ADC1_MASK (0x3 << 4) | 823 | #define RT5677_IF1_ADC1_MASK (0x3 << 4) |
809 | #define RT5677_IF1_ADC1_SFT 4 | 824 | #define RT5677_IF1_ADC1_SFT 4 |
810 | 825 | #define RT5677_IF1_ADC_CTRL_MASK (0x7 << 0) | |
811 | /* MX41 TDM2 control 1 (0x41) */ | 826 | #define RT5677_IF1_ADC_CTRL_SFT 0 |
827 | |||
828 | /* TDM1 control 4 (0x3e) */ | ||
829 | #define RT5677_IF1_DAC0_MASK (0x7 << 12) | ||
830 | #define RT5677_IF1_DAC0_SFT 12 | ||
831 | #define RT5677_IF1_DAC1_MASK (0x7 << 8) | ||
832 | #define RT5677_IF1_DAC1_SFT 8 | ||
833 | #define RT5677_IF1_DAC2_MASK (0x7 << 4) | ||
834 | #define RT5677_IF1_DAC2_SFT 4 | ||
835 | #define RT5677_IF1_DAC3_MASK (0x7 << 0) | ||
836 | #define RT5677_IF1_DAC3_SFT 0 | ||
837 | |||
838 | /* TDM1 control 5 (0x3f) */ | ||
839 | #define RT5677_IF1_DAC4_MASK (0x7 << 12) | ||
840 | #define RT5677_IF1_DAC4_SFT 12 | ||
841 | #define RT5677_IF1_DAC5_MASK (0x7 << 8) | ||
842 | #define RT5677_IF1_DAC5_SFT 8 | ||
843 | #define RT5677_IF1_DAC6_MASK (0x7 << 4) | ||
844 | #define RT5677_IF1_DAC6_SFT 4 | ||
845 | #define RT5677_IF1_DAC7_MASK (0x7 << 0) | ||
846 | #define RT5677_IF1_DAC7_SFT 0 | ||
847 | |||
848 | /* TDM2 control 1 (0x40) */ | ||
849 | #define RT5677_IF2_ADC_MODE_MASK (0x1 << 12) | ||
850 | #define RT5677_IF2_ADC_MODE_SFT 12 | ||
851 | #define RT5677_IF2_ADC_MODE_I2S (0x0 << 12) | ||
852 | #define RT5677_IF2_ADC_MODE_TDM (0x1 << 12) | ||
853 | #define RT5677_IF2_ADC1_SWAP_MASK (0x3 << 6) | ||
854 | #define RT5677_IF2_ADC1_SWAP_SFT 6 | ||
855 | #define RT5677_IF2_ADC2_SWAP_MASK (0x3 << 4) | ||
856 | #define RT5677_IF2_ADC2_SWAP_SFT 4 | ||
857 | #define RT5677_IF2_ADC3_SWAP_MASK (0x3 << 2) | ||
858 | #define RT5677_IF2_ADC3_SWAP_SFT 2 | ||
859 | #define RT5677_IF2_ADC4_SWAP_MASK (0x3 << 0) | ||
860 | #define RT5677_IF2_ADC4_SWAP_SFT 0 | ||
861 | |||
862 | /* TDM2 control 2 (0x41) */ | ||
812 | #define RT5677_IF2_ADC4_MASK (0x3 << 10) | 863 | #define RT5677_IF2_ADC4_MASK (0x3 << 10) |
813 | #define RT5677_IF2_ADC4_SFT 10 | 864 | #define RT5677_IF2_ADC4_SFT 10 |
814 | #define RT5677_IF2_ADC3_MASK (0x3 << 8) | 865 | #define RT5677_IF2_ADC3_MASK (0x3 << 8) |
@@ -817,6 +868,28 @@ | |||
817 | #define RT5677_IF2_ADC2_SFT 6 | 868 | #define RT5677_IF2_ADC2_SFT 6 |
818 | #define RT5677_IF2_ADC1_MASK (0x3 << 4) | 869 | #define RT5677_IF2_ADC1_MASK (0x3 << 4) |
819 | #define RT5677_IF2_ADC1_SFT 4 | 870 | #define RT5677_IF2_ADC1_SFT 4 |
871 | #define RT5677_IF2_ADC_CTRL_MASK (0x7 << 0) | ||
872 | #define RT5677_IF2_ADC_CTRL_SFT 0 | ||
873 | |||
874 | /* TDM2 control 4 (0x43) */ | ||
875 | #define RT5677_IF2_DAC0_MASK (0x7 << 12) | ||
876 | #define RT5677_IF2_DAC0_SFT 12 | ||
877 | #define RT5677_IF2_DAC1_MASK (0x7 << 8) | ||
878 | #define RT5677_IF2_DAC1_SFT 8 | ||
879 | #define RT5677_IF2_DAC2_MASK (0x7 << 4) | ||
880 | #define RT5677_IF2_DAC2_SFT 4 | ||
881 | #define RT5677_IF2_DAC3_MASK (0x7 << 0) | ||
882 | #define RT5677_IF2_DAC3_SFT 0 | ||
883 | |||
884 | /* TDM2 control 5 (0x44) */ | ||
885 | #define RT5677_IF2_DAC4_MASK (0x7 << 12) | ||
886 | #define RT5677_IF2_DAC4_SFT 12 | ||
887 | #define RT5677_IF2_DAC5_MASK (0x7 << 8) | ||
888 | #define RT5677_IF2_DAC5_SFT 8 | ||
889 | #define RT5677_IF2_DAC6_MASK (0x7 << 4) | ||
890 | #define RT5677_IF2_DAC6_SFT 4 | ||
891 | #define RT5677_IF2_DAC7_MASK (0x7 << 0) | ||
892 | #define RT5677_IF2_DAC7_SFT 0 | ||
820 | 893 | ||
821 | /* Digital Microphone Control 1 (0x50) */ | 894 | /* Digital Microphone Control 1 (0x50) */ |
822 | #define RT5677_DMIC_1_EN_MASK (0x1 << 15) | 895 | #define RT5677_DMIC_1_EN_MASK (0x1 << 15) |
@@ -1367,6 +1440,48 @@ | |||
1367 | #define RT5677_SEL_SRC_IB01 (0x1 << 0) | 1440 | #define RT5677_SEL_SRC_IB01 (0x1 << 0) |
1368 | #define RT5677_SEL_SRC_IB01_SFT 0 | 1441 | #define RT5677_SEL_SRC_IB01_SFT 0 |
1369 | 1442 | ||
1443 | /* Jack Detect Control 1 (0xb5) */ | ||
1444 | #define RT5677_SEL_GPIO_JD1_MASK (0x3 << 14) | ||
1445 | #define RT5677_SEL_GPIO_JD1_SFT 14 | ||
1446 | #define RT5677_SEL_GPIO_JD2_MASK (0x3 << 12) | ||
1447 | #define RT5677_SEL_GPIO_JD2_SFT 12 | ||
1448 | #define RT5677_SEL_GPIO_JD3_MASK (0x3 << 10) | ||
1449 | #define RT5677_SEL_GPIO_JD3_SFT 10 | ||
1450 | |||
1451 | /* IRQ Control 1 (0xbd) */ | ||
1452 | #define RT5677_STA_GPIO_JD1 (0x1 << 15) | ||
1453 | #define RT5677_STA_GPIO_JD1_SFT 15 | ||
1454 | #define RT5677_EN_IRQ_GPIO_JD1 (0x1 << 14) | ||
1455 | #define RT5677_EN_IRQ_GPIO_JD1_SFT 14 | ||
1456 | #define RT5677_EN_GPIO_JD1_STICKY (0x1 << 13) | ||
1457 | #define RT5677_EN_GPIO_JD1_STICKY_SFT 13 | ||
1458 | #define RT5677_INV_GPIO_JD1 (0x1 << 12) | ||
1459 | #define RT5677_INV_GPIO_JD1_SFT 12 | ||
1460 | #define RT5677_STA_GPIO_JD2 (0x1 << 11) | ||
1461 | #define RT5677_STA_GPIO_JD2_SFT 11 | ||
1462 | #define RT5677_EN_IRQ_GPIO_JD2 (0x1 << 10) | ||
1463 | #define RT5677_EN_IRQ_GPIO_JD2_SFT 10 | ||
1464 | #define RT5677_EN_GPIO_JD2_STICKY (0x1 << 9) | ||
1465 | #define RT5677_EN_GPIO_JD2_STICKY_SFT 9 | ||
1466 | #define RT5677_INV_GPIO_JD2 (0x1 << 8) | ||
1467 | #define RT5677_INV_GPIO_JD2_SFT 8 | ||
1468 | #define RT5677_STA_MICBIAS1_OVCD (0x1 << 7) | ||
1469 | #define RT5677_STA_MICBIAS1_OVCD_SFT 7 | ||
1470 | #define RT5677_EN_IRQ_MICBIAS1_OVCD (0x1 << 6) | ||
1471 | #define RT5677_EN_IRQ_MICBIAS1_OVCD_SFT 6 | ||
1472 | #define RT5677_EN_MICBIAS1_OVCD_STICKY (0x1 << 5) | ||
1473 | #define RT5677_EN_MICBIAS1_OVCD_STICKY_SFT 5 | ||
1474 | #define RT5677_INV_MICBIAS1_OVCD (0x1 << 4) | ||
1475 | #define RT5677_INV_MICBIAS1_OVCD_SFT 4 | ||
1476 | #define RT5677_STA_GPIO_JD3 (0x1 << 3) | ||
1477 | #define RT5677_STA_GPIO_JD3_SFT 3 | ||
1478 | #define RT5677_EN_IRQ_GPIO_JD3 (0x1 << 2) | ||
1479 | #define RT5677_EN_IRQ_GPIO_JD3_SFT 2 | ||
1480 | #define RT5677_EN_GPIO_JD3_STICKY (0x1 << 1) | ||
1481 | #define RT5677_EN_GPIO_JD3_STICKY_SFT 1 | ||
1482 | #define RT5677_INV_GPIO_JD3 (0x1 << 0) | ||
1483 | #define RT5677_INV_GPIO_JD3_SFT 0 | ||
1484 | |||
1370 | /* GPIO status (0xbf) */ | 1485 | /* GPIO status (0xbf) */ |
1371 | #define RT5677_GPIO6_STATUS_MASK (0x1 << 5) | 1486 | #define RT5677_GPIO6_STATUS_MASK (0x1 << 5) |
1372 | #define RT5677_GPIO6_STATUS_SFT 5 | 1487 | #define RT5677_GPIO6_STATUS_SFT 5 |
@@ -1506,6 +1621,9 @@ | |||
1506 | #define RT5677_GPIO5_FUNC_GPIO (0x0 << 9) | 1621 | #define RT5677_GPIO5_FUNC_GPIO (0x0 << 9) |
1507 | #define RT5677_GPIO5_FUNC_DMIC (0x1 << 9) | 1622 | #define RT5677_GPIO5_FUNC_DMIC (0x1 << 9) |
1508 | 1623 | ||
1624 | #define RT5677_FIRMWARE1 "rt5677_dsp_fw1.bin" | ||
1625 | #define RT5677_FIRMWARE2 "rt5677_dsp_fw2.bin" | ||
1626 | |||
1509 | /* System Clock Source */ | 1627 | /* System Clock Source */ |
1510 | enum { | 1628 | enum { |
1511 | RT5677_SCLK_S_MCLK, | 1629 | RT5677_SCLK_S_MCLK, |
@@ -1541,10 +1659,18 @@ enum { | |||
1541 | RT5677_GPIO_NUM, | 1659 | RT5677_GPIO_NUM, |
1542 | }; | 1660 | }; |
1543 | 1661 | ||
1662 | enum { | ||
1663 | RT5677_IRQ_JD1, | ||
1664 | RT5677_IRQ_JD2, | ||
1665 | RT5677_IRQ_JD3, | ||
1666 | }; | ||
1667 | |||
1544 | struct rt5677_priv { | 1668 | struct rt5677_priv { |
1545 | struct snd_soc_codec *codec; | 1669 | struct snd_soc_codec *codec; |
1546 | struct rt5677_platform_data pdata; | 1670 | struct rt5677_platform_data pdata; |
1547 | struct regmap *regmap; | 1671 | struct regmap *regmap, *regmap_physical; |
1672 | const struct firmware *fw1, *fw2; | ||
1673 | struct mutex dsp_cmd_lock, dsp_pri_lock; | ||
1548 | 1674 | ||
1549 | int sysclk; | 1675 | int sysclk; |
1550 | int sysclk_src; | 1676 | int sysclk_src; |
@@ -1558,6 +1684,10 @@ struct rt5677_priv { | |||
1558 | #ifdef CONFIG_GPIOLIB | 1684 | #ifdef CONFIG_GPIOLIB |
1559 | struct gpio_chip gpio_chip; | 1685 | struct gpio_chip gpio_chip; |
1560 | #endif | 1686 | #endif |
1687 | bool dsp_vad_en; | ||
1688 | struct regmap_irq_chip_data *irq_data; | ||
1689 | bool is_dsp_mode; | ||
1690 | bool is_vref_slow; | ||
1561 | }; | 1691 | }; |
1562 | 1692 | ||
1563 | #endif /* __RT5677_H__ */ | 1693 | #endif /* __RT5677_H__ */ |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index dab9b15304af..29cf7ce610f4 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/log2.h> | ||
19 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
20 | #include <linux/regulator/driver.h> | 21 | #include <linux/regulator/driver.h> |
21 | #include <linux/regulator/machine.h> | 22 | #include <linux/regulator/machine.h> |
@@ -121,6 +122,13 @@ struct ldo_regulator { | |||
121 | bool enabled; | 122 | bool enabled; |
122 | }; | 123 | }; |
123 | 124 | ||
125 | enum sgtl5000_micbias_resistor { | ||
126 | SGTL5000_MICBIAS_OFF = 0, | ||
127 | SGTL5000_MICBIAS_2K = 2, | ||
128 | SGTL5000_MICBIAS_4K = 4, | ||
129 | SGTL5000_MICBIAS_8K = 8, | ||
130 | }; | ||
131 | |||
124 | /* sgtl5000 private structure in codec */ | 132 | /* sgtl5000 private structure in codec */ |
125 | struct sgtl5000_priv { | 133 | struct sgtl5000_priv { |
126 | int sysclk; /* sysclk rate */ | 134 | int sysclk; /* sysclk rate */ |
@@ -131,6 +139,8 @@ struct sgtl5000_priv { | |||
131 | struct regmap *regmap; | 139 | struct regmap *regmap; |
132 | struct clk *mclk; | 140 | struct clk *mclk; |
133 | int revision; | 141 | int revision; |
142 | u8 micbias_resistor; | ||
143 | u8 micbias_voltage; | ||
134 | }; | 144 | }; |
135 | 145 | ||
136 | /* | 146 | /* |
@@ -145,12 +155,14 @@ struct sgtl5000_priv { | |||
145 | static int mic_bias_event(struct snd_soc_dapm_widget *w, | 155 | static int mic_bias_event(struct snd_soc_dapm_widget *w, |
146 | struct snd_kcontrol *kcontrol, int event) | 156 | struct snd_kcontrol *kcontrol, int event) |
147 | { | 157 | { |
158 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(w->codec); | ||
159 | |||
148 | switch (event) { | 160 | switch (event) { |
149 | case SND_SOC_DAPM_POST_PMU: | 161 | case SND_SOC_DAPM_POST_PMU: |
150 | /* change mic bias resistor to 4Kohm */ | 162 | /* change mic bias resistor */ |
151 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL, | 163 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL, |
152 | SGTL5000_BIAS_R_MASK, | 164 | SGTL5000_BIAS_R_MASK, |
153 | SGTL5000_BIAS_R_4k << SGTL5000_BIAS_R_SHIFT); | 165 | sgtl5000->micbias_resistor << SGTL5000_BIAS_R_SHIFT); |
154 | break; | 166 | break; |
155 | 167 | ||
156 | case SND_SOC_DAPM_PRE_PMD: | 168 | case SND_SOC_DAPM_PRE_PMD: |
@@ -530,16 +542,16 @@ static int sgtl5000_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
530 | 542 | ||
531 | /* | 543 | /* |
532 | * set clock according to i2s frame clock, | 544 | * set clock according to i2s frame clock, |
533 | * sgtl5000 provide 2 clock sources. | 545 | * sgtl5000 provides 2 clock sources: |
534 | * 1. sys_mclk. sample freq can only configure to | 546 | * 1. sys_mclk: sample freq can only be configured to |
535 | * 1/256, 1/384, 1/512 of sys_mclk. | 547 | * 1/256, 1/384, 1/512 of sys_mclk. |
536 | * 2. pll. can derive any audio clocks. | 548 | * 2. pll: can derive any audio clocks. |
537 | * | 549 | * |
538 | * clock setting rules: | 550 | * clock setting rules: |
539 | * 1. in slave mode, only sys_mclk can use. | 551 | * 1. in slave mode, only sys_mclk can be used |
540 | * 2. as constraint by sys_mclk, sample freq should | 552 | * 2. as constraint by sys_mclk, sample freq should be set to 32 kHz, 44.1 kHz |
541 | * set to 32k, 44.1k and above. | 553 | * and above. |
542 | * 3. using sys_mclk prefer to pll to save power. | 554 | * 3. usage of sys_mclk is preferred over pll to save power. |
543 | */ | 555 | */ |
544 | static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate) | 556 | static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate) |
545 | { | 557 | { |
@@ -549,8 +561,8 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate) | |||
549 | 561 | ||
550 | /* | 562 | /* |
551 | * sample freq should be divided by frame clock, | 563 | * sample freq should be divided by frame clock, |
552 | * if frame clock lower than 44.1khz, sample feq should set to | 564 | * if frame clock is lower than 44.1 kHz, sample freq should be set to |
553 | * 32khz or 44.1khz. | 565 | * 32 kHz or 44.1 kHz. |
554 | */ | 566 | */ |
555 | switch (frame_rate) { | 567 | switch (frame_rate) { |
556 | case 8000: | 568 | case 8000: |
@@ -603,9 +615,10 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate) | |||
603 | 615 | ||
604 | /* | 616 | /* |
605 | * calculate the divider of mclk/sample_freq, | 617 | * calculate the divider of mclk/sample_freq, |
606 | * factor of freq =96k can only be 256, since mclk in range (12m,27m) | 618 | * factor of freq = 96 kHz can only be 256, since mclk is in the range |
619 | * of 8 MHz - 27 MHz | ||
607 | */ | 620 | */ |
608 | switch (sgtl5000->sysclk / sys_fs) { | 621 | switch (sgtl5000->sysclk / frame_rate) { |
609 | case 256: | 622 | case 256: |
610 | clk_ctl |= SGTL5000_MCLK_FREQ_256FS << | 623 | clk_ctl |= SGTL5000_MCLK_FREQ_256FS << |
611 | SGTL5000_MCLK_FREQ_SHIFT; | 624 | SGTL5000_MCLK_FREQ_SHIFT; |
@@ -619,7 +632,7 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate) | |||
619 | SGTL5000_MCLK_FREQ_SHIFT; | 632 | SGTL5000_MCLK_FREQ_SHIFT; |
620 | break; | 633 | break; |
621 | default: | 634 | default: |
622 | /* if mclk not satisify the divider, use pll */ | 635 | /* if mclk does not satisfy the divider, use pll */ |
623 | if (sgtl5000->master) { | 636 | if (sgtl5000->master) { |
624 | clk_ctl |= SGTL5000_MCLK_FREQ_PLL << | 637 | clk_ctl |= SGTL5000_MCLK_FREQ_PLL << |
625 | SGTL5000_MCLK_FREQ_SHIFT; | 638 | SGTL5000_MCLK_FREQ_SHIFT; |
@@ -628,7 +641,7 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate) | |||
628 | "PLL not supported in slave mode\n"); | 641 | "PLL not supported in slave mode\n"); |
629 | dev_err(codec->dev, "%d ratio is not supported. " | 642 | dev_err(codec->dev, "%d ratio is not supported. " |
630 | "SYS_MCLK needs to be 256, 384 or 512 * fs\n", | 643 | "SYS_MCLK needs to be 256, 384 or 512 * fs\n", |
631 | sgtl5000->sysclk / sys_fs); | 644 | sgtl5000->sysclk / frame_rate); |
632 | return -EINVAL; | 645 | return -EINVAL; |
633 | } | 646 | } |
634 | } | 647 | } |
@@ -795,7 +808,7 @@ static int ldo_regulator_enable(struct regulator_dev *dev) | |||
795 | SGTL5000_LINEREG_D_POWERUP, | 808 | SGTL5000_LINEREG_D_POWERUP, |
796 | SGTL5000_LINEREG_D_POWERUP); | 809 | SGTL5000_LINEREG_D_POWERUP); |
797 | 810 | ||
798 | /* when internal ldo enabled, simple digital power can be disabled */ | 811 | /* when internal ldo is enabled, simple digital power can be disabled */ |
799 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, | 812 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, |
800 | SGTL5000_LINREG_SIMPLE_POWERUP, | 813 | SGTL5000_LINREG_SIMPLE_POWERUP, |
801 | 0); | 814 | 0); |
@@ -1079,7 +1092,7 @@ static bool sgtl5000_readable(struct device *dev, unsigned int reg) | |||
1079 | /* | 1092 | /* |
1080 | * sgtl5000 has 3 internal power supplies: | 1093 | * sgtl5000 has 3 internal power supplies: |
1081 | * 1. VAG, normally set to vdda/2 | 1094 | * 1. VAG, normally set to vdda/2 |
1082 | * 2. chargepump, set to different value | 1095 | * 2. charge pump, set to different value |
1083 | * according to voltage of vdda and vddio | 1096 | * according to voltage of vdda and vddio |
1084 | * 3. line out VAG, normally set to vddio/2 | 1097 | * 3. line out VAG, normally set to vddio/2 |
1085 | * | 1098 | * |
@@ -1325,8 +1338,13 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) | |||
1325 | SGTL5000_HP_ZCD_EN | | 1338 | SGTL5000_HP_ZCD_EN | |
1326 | SGTL5000_ADC_ZCD_EN); | 1339 | SGTL5000_ADC_ZCD_EN); |
1327 | 1340 | ||
1328 | snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 2); | 1341 | snd_soc_update_bits(codec, SGTL5000_CHIP_MIC_CTRL, |
1342 | SGTL5000_BIAS_R_MASK, | ||
1343 | sgtl5000->micbias_resistor << SGTL5000_BIAS_R_SHIFT); | ||
1329 | 1344 | ||
1345 | snd_soc_update_bits(codec, SGTL5000_CHIP_MIC_CTRL, | ||
1346 | SGTL5000_BIAS_R_MASK, | ||
1347 | sgtl5000->micbias_voltage << SGTL5000_BIAS_R_SHIFT); | ||
1330 | /* | 1348 | /* |
1331 | * disable DAP | 1349 | * disable DAP |
1332 | * TODO: | 1350 | * TODO: |
@@ -1416,10 +1434,10 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, | |||
1416 | { | 1434 | { |
1417 | struct sgtl5000_priv *sgtl5000; | 1435 | struct sgtl5000_priv *sgtl5000; |
1418 | int ret, reg, rev; | 1436 | int ret, reg, rev; |
1419 | unsigned int mclk; | 1437 | struct device_node *np = client->dev.of_node; |
1438 | u32 value; | ||
1420 | 1439 | ||
1421 | sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv), | 1440 | sgtl5000 = devm_kzalloc(&client->dev, sizeof(*sgtl5000), GFP_KERNEL); |
1422 | GFP_KERNEL); | ||
1423 | if (!sgtl5000) | 1441 | if (!sgtl5000) |
1424 | return -ENOMEM; | 1442 | return -ENOMEM; |
1425 | 1443 | ||
@@ -1440,14 +1458,6 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, | |||
1440 | return ret; | 1458 | return ret; |
1441 | } | 1459 | } |
1442 | 1460 | ||
1443 | /* SGTL5000 SYS_MCLK should be between 8 and 27 MHz */ | ||
1444 | mclk = clk_get_rate(sgtl5000->mclk); | ||
1445 | if (mclk < 8000000 || mclk > 27000000) { | ||
1446 | dev_err(&client->dev, "Invalid SYS_CLK frequency: %u.%03uMHz\n", | ||
1447 | mclk / 1000000, mclk / 1000 % 1000); | ||
1448 | return -EINVAL; | ||
1449 | } | ||
1450 | |||
1451 | ret = clk_prepare_enable(sgtl5000->mclk); | 1461 | ret = clk_prepare_enable(sgtl5000->mclk); |
1452 | if (ret) | 1462 | if (ret) |
1453 | return ret; | 1463 | return ret; |
@@ -1469,6 +1479,47 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, | |||
1469 | dev_info(&client->dev, "sgtl5000 revision 0x%x\n", rev); | 1479 | dev_info(&client->dev, "sgtl5000 revision 0x%x\n", rev); |
1470 | sgtl5000->revision = rev; | 1480 | sgtl5000->revision = rev; |
1471 | 1481 | ||
1482 | if (np) { | ||
1483 | if (!of_property_read_u32(np, | ||
1484 | "micbias-resistor-k-ohms", &value)) { | ||
1485 | switch (value) { | ||
1486 | case SGTL5000_MICBIAS_OFF: | ||
1487 | sgtl5000->micbias_resistor = 0; | ||
1488 | break; | ||
1489 | case SGTL5000_MICBIAS_2K: | ||
1490 | sgtl5000->micbias_resistor = 1; | ||
1491 | break; | ||
1492 | case SGTL5000_MICBIAS_4K: | ||
1493 | sgtl5000->micbias_resistor = 2; | ||
1494 | break; | ||
1495 | case SGTL5000_MICBIAS_8K: | ||
1496 | sgtl5000->micbias_resistor = 3; | ||
1497 | break; | ||
1498 | default: | ||
1499 | sgtl5000->micbias_resistor = 2; | ||
1500 | dev_err(&client->dev, | ||
1501 | "Unsuitable MicBias resistor\n"); | ||
1502 | } | ||
1503 | } else { | ||
1504 | /* default is 4Kohms */ | ||
1505 | sgtl5000->micbias_resistor = 2; | ||
1506 | } | ||
1507 | if (!of_property_read_u32(np, | ||
1508 | "micbias-voltage-m-volts", &value)) { | ||
1509 | /* 1250mV => 0 */ | ||
1510 | /* steps of 250mV */ | ||
1511 | if ((value >= 1250) && (value <= 3000)) | ||
1512 | sgtl5000->micbias_voltage = (value / 250) - 5; | ||
1513 | else { | ||
1514 | sgtl5000->micbias_voltage = 0; | ||
1515 | dev_err(&client->dev, | ||
1516 | "Unsuitable MicBias resistor\n"); | ||
1517 | } | ||
1518 | } else { | ||
1519 | sgtl5000->micbias_voltage = 0; | ||
1520 | } | ||
1521 | } | ||
1522 | |||
1472 | i2c_set_clientdata(client, sgtl5000); | 1523 | i2c_set_clientdata(client, sgtl5000); |
1473 | 1524 | ||
1474 | /* Ensure sgtl5000 will start with sane register values */ | 1525 | /* Ensure sgtl5000 will start with sane register values */ |
diff --git a/sound/soc/codecs/sigmadsp-i2c.c b/sound/soc/codecs/sigmadsp-i2c.c index 246081aae8ca..21ca3a5e9f66 100644 --- a/sound/soc/codecs/sigmadsp-i2c.c +++ b/sound/soc/codecs/sigmadsp-i2c.c | |||
@@ -6,29 +6,88 @@ | |||
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/i2c.h> | ||
10 | #include <linux/export.h> | 9 | #include <linux/export.h> |
10 | #include <linux/i2c.h> | ||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/slab.h> | ||
13 | #include <asm/unaligned.h> | ||
12 | 14 | ||
13 | #include "sigmadsp.h" | 15 | #include "sigmadsp.h" |
14 | 16 | ||
15 | static int sigma_action_write_i2c(void *control_data, | 17 | static int sigmadsp_write_i2c(void *control_data, |
16 | const struct sigma_action *sa, size_t len) | 18 | unsigned int addr, const uint8_t data[], size_t len) |
19 | { | ||
20 | uint8_t *buf; | ||
21 | int ret; | ||
22 | |||
23 | buf = kzalloc(2 + len, GFP_KERNEL | GFP_DMA); | ||
24 | if (!buf) | ||
25 | return -ENOMEM; | ||
26 | |||
27 | put_unaligned_be16(addr, buf); | ||
28 | memcpy(buf + 2, data, len); | ||
29 | |||
30 | ret = i2c_master_send(control_data, buf, len + 2); | ||
31 | |||
32 | kfree(buf); | ||
33 | |||
34 | return ret; | ||
35 | } | ||
36 | |||
37 | static int sigmadsp_read_i2c(void *control_data, | ||
38 | unsigned int addr, uint8_t data[], size_t len) | ||
17 | { | 39 | { |
18 | return i2c_master_send(control_data, (const unsigned char *)&sa->addr, | 40 | struct i2c_client *client = control_data; |
19 | len); | 41 | struct i2c_msg msgs[2]; |
42 | uint8_t buf[2]; | ||
43 | int ret; | ||
44 | |||
45 | put_unaligned_be16(addr, buf); | ||
46 | |||
47 | msgs[0].addr = client->addr; | ||
48 | msgs[0].len = sizeof(buf); | ||
49 | msgs[0].buf = buf; | ||
50 | msgs[0].flags = 0; | ||
51 | |||
52 | msgs[1].addr = client->addr; | ||
53 | msgs[1].len = len; | ||
54 | msgs[1].buf = data; | ||
55 | msgs[1].flags = I2C_M_RD; | ||
56 | |||
57 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
58 | if (ret < 0) | ||
59 | return ret; | ||
60 | else if (ret != ARRAY_SIZE(msgs)) | ||
61 | return -EIO; | ||
62 | return 0; | ||
20 | } | 63 | } |
21 | 64 | ||
22 | int process_sigma_firmware(struct i2c_client *client, const char *name) | 65 | /** |
66 | * devm_sigmadsp_init_i2c() - Initialize SigmaDSP instance | ||
67 | * @client: The parent I2C device | ||
68 | * @ops: The sigmadsp_ops to use for this instance | ||
69 | * @firmware_name: Name of the firmware file to load | ||
70 | * | ||
71 | * Allocates a SigmaDSP instance and loads the specified firmware file. | ||
72 | * | ||
73 | * Returns a pointer to a struct sigmadsp on success, or a PTR_ERR() on error. | ||
74 | */ | ||
75 | struct sigmadsp *devm_sigmadsp_init_i2c(struct i2c_client *client, | ||
76 | const struct sigmadsp_ops *ops, const char *firmware_name) | ||
23 | { | 77 | { |
24 | struct sigma_firmware ssfw; | 78 | struct sigmadsp *sigmadsp; |
79 | |||
80 | sigmadsp = devm_sigmadsp_init(&client->dev, ops, firmware_name); | ||
81 | if (IS_ERR(sigmadsp)) | ||
82 | return sigmadsp; | ||
25 | 83 | ||
26 | ssfw.control_data = client; | 84 | sigmadsp->control_data = client; |
27 | ssfw.write = sigma_action_write_i2c; | 85 | sigmadsp->write = sigmadsp_write_i2c; |
86 | sigmadsp->read = sigmadsp_read_i2c; | ||
28 | 87 | ||
29 | return _process_sigma_firmware(&client->dev, &ssfw, name); | 88 | return sigmadsp; |
30 | } | 89 | } |
31 | EXPORT_SYMBOL(process_sigma_firmware); | 90 | EXPORT_SYMBOL_GPL(devm_sigmadsp_init_i2c); |
32 | 91 | ||
33 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 92 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
34 | MODULE_DESCRIPTION("SigmaDSP I2C firmware loader"); | 93 | MODULE_DESCRIPTION("SigmaDSP I2C firmware loader"); |
diff --git a/sound/soc/codecs/sigmadsp-regmap.c b/sound/soc/codecs/sigmadsp-regmap.c index f78ed8d2cfb2..912861be5b87 100644 --- a/sound/soc/codecs/sigmadsp-regmap.c +++ b/sound/soc/codecs/sigmadsp-regmap.c | |||
@@ -12,24 +12,48 @@ | |||
12 | 12 | ||
13 | #include "sigmadsp.h" | 13 | #include "sigmadsp.h" |
14 | 14 | ||
15 | static int sigma_action_write_regmap(void *control_data, | 15 | static int sigmadsp_write_regmap(void *control_data, |
16 | const struct sigma_action *sa, size_t len) | 16 | unsigned int addr, const uint8_t data[], size_t len) |
17 | { | 17 | { |
18 | return regmap_raw_write(control_data, be16_to_cpu(sa->addr), | 18 | return regmap_raw_write(control_data, addr, |
19 | sa->payload, len - 2); | 19 | data, len); |
20 | } | 20 | } |
21 | 21 | ||
22 | int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap, | 22 | static int sigmadsp_read_regmap(void *control_data, |
23 | const char *name) | 23 | unsigned int addr, uint8_t data[], size_t len) |
24 | { | 24 | { |
25 | struct sigma_firmware ssfw; | 25 | return regmap_raw_read(control_data, addr, |
26 | data, len); | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * devm_sigmadsp_init_i2c() - Initialize SigmaDSP instance | ||
31 | * @dev: The parent device | ||
32 | * @regmap: Regmap instance to use | ||
33 | * @ops: The sigmadsp_ops to use for this instance | ||
34 | * @firmware_name: Name of the firmware file to load | ||
35 | * | ||
36 | * Allocates a SigmaDSP instance and loads the specified firmware file. | ||
37 | * | ||
38 | * Returns a pointer to a struct sigmadsp on success, or a PTR_ERR() on error. | ||
39 | */ | ||
40 | struct sigmadsp *devm_sigmadsp_init_regmap(struct device *dev, | ||
41 | struct regmap *regmap, const struct sigmadsp_ops *ops, | ||
42 | const char *firmware_name) | ||
43 | { | ||
44 | struct sigmadsp *sigmadsp; | ||
45 | |||
46 | sigmadsp = devm_sigmadsp_init(dev, ops, firmware_name); | ||
47 | if (IS_ERR(sigmadsp)) | ||
48 | return sigmadsp; | ||
26 | 49 | ||
27 | ssfw.control_data = regmap; | 50 | sigmadsp->control_data = regmap; |
28 | ssfw.write = sigma_action_write_regmap; | 51 | sigmadsp->write = sigmadsp_write_regmap; |
52 | sigmadsp->read = sigmadsp_read_regmap; | ||
29 | 53 | ||
30 | return _process_sigma_firmware(dev, &ssfw, name); | 54 | return sigmadsp; |
31 | } | 55 | } |
32 | EXPORT_SYMBOL(process_sigma_firmware_regmap); | 56 | EXPORT_SYMBOL_GPL(devm_sigmadsp_init_regmap); |
33 | 57 | ||
34 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 58 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
35 | MODULE_DESCRIPTION("SigmaDSP regmap firmware loader"); | 59 | MODULE_DESCRIPTION("SigmaDSP regmap firmware loader"); |
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c index f2de7e049bc6..d53680ac78e4 100644 --- a/sound/soc/codecs/sigmadsp.c +++ b/sound/soc/codecs/sigmadsp.c | |||
@@ -1,23 +1,74 @@ | |||
1 | /* | 1 | /* |
2 | * Load Analog Devices SigmaStudio firmware files | 2 | * Load Analog Devices SigmaStudio firmware files |
3 | * | 3 | * |
4 | * Copyright 2009-2011 Analog Devices Inc. | 4 | * Copyright 2009-2014 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/crc32.h> | 9 | #include <linux/crc32.h> |
10 | #include <linux/delay.h> | ||
11 | #include <linux/firmware.h> | 10 | #include <linux/firmware.h> |
12 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
13 | #include <linux/i2c.h> | 12 | #include <linux/i2c.h> |
14 | #include <linux/regmap.h> | 13 | #include <linux/regmap.h> |
15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/slab.h> | ||
16 | |||
17 | #include <sound/control.h> | ||
18 | #include <sound/soc.h> | ||
16 | 19 | ||
17 | #include "sigmadsp.h" | 20 | #include "sigmadsp.h" |
18 | 21 | ||
19 | #define SIGMA_MAGIC "ADISIGM" | 22 | #define SIGMA_MAGIC "ADISIGM" |
20 | 23 | ||
24 | #define SIGMA_FW_CHUNK_TYPE_DATA 0 | ||
25 | #define SIGMA_FW_CHUNK_TYPE_CONTROL 1 | ||
26 | #define SIGMA_FW_CHUNK_TYPE_SAMPLERATES 2 | ||
27 | |||
28 | struct sigmadsp_control { | ||
29 | struct list_head head; | ||
30 | uint32_t samplerates; | ||
31 | unsigned int addr; | ||
32 | unsigned int num_bytes; | ||
33 | const char *name; | ||
34 | struct snd_kcontrol *kcontrol; | ||
35 | bool cached; | ||
36 | uint8_t cache[]; | ||
37 | }; | ||
38 | |||
39 | struct sigmadsp_data { | ||
40 | struct list_head head; | ||
41 | uint32_t samplerates; | ||
42 | unsigned int addr; | ||
43 | unsigned int length; | ||
44 | uint8_t data[]; | ||
45 | }; | ||
46 | |||
47 | struct sigma_fw_chunk { | ||
48 | __le32 length; | ||
49 | __le32 tag; | ||
50 | __le32 samplerates; | ||
51 | } __packed; | ||
52 | |||
53 | struct sigma_fw_chunk_data { | ||
54 | struct sigma_fw_chunk chunk; | ||
55 | __le16 addr; | ||
56 | uint8_t data[]; | ||
57 | } __packed; | ||
58 | |||
59 | struct sigma_fw_chunk_control { | ||
60 | struct sigma_fw_chunk chunk; | ||
61 | __le16 type; | ||
62 | __le16 addr; | ||
63 | __le16 num_bytes; | ||
64 | const char name[]; | ||
65 | } __packed; | ||
66 | |||
67 | struct sigma_fw_chunk_samplerate { | ||
68 | struct sigma_fw_chunk chunk; | ||
69 | __le32 samplerates[]; | ||
70 | } __packed; | ||
71 | |||
21 | struct sigma_firmware_header { | 72 | struct sigma_firmware_header { |
22 | unsigned char magic[7]; | 73 | unsigned char magic[7]; |
23 | u8 version; | 74 | u8 version; |
@@ -28,12 +79,286 @@ enum { | |||
28 | SIGMA_ACTION_WRITEXBYTES = 0, | 79 | SIGMA_ACTION_WRITEXBYTES = 0, |
29 | SIGMA_ACTION_WRITESINGLE, | 80 | SIGMA_ACTION_WRITESINGLE, |
30 | SIGMA_ACTION_WRITESAFELOAD, | 81 | SIGMA_ACTION_WRITESAFELOAD, |
31 | SIGMA_ACTION_DELAY, | ||
32 | SIGMA_ACTION_PLLWAIT, | ||
33 | SIGMA_ACTION_NOOP, | ||
34 | SIGMA_ACTION_END, | 82 | SIGMA_ACTION_END, |
35 | }; | 83 | }; |
36 | 84 | ||
85 | struct sigma_action { | ||
86 | u8 instr; | ||
87 | u8 len_hi; | ||
88 | __le16 len; | ||
89 | __be16 addr; | ||
90 | unsigned char payload[]; | ||
91 | } __packed; | ||
92 | |||
93 | static int sigmadsp_write(struct sigmadsp *sigmadsp, unsigned int addr, | ||
94 | const uint8_t data[], size_t len) | ||
95 | { | ||
96 | return sigmadsp->write(sigmadsp->control_data, addr, data, len); | ||
97 | } | ||
98 | |||
99 | static int sigmadsp_read(struct sigmadsp *sigmadsp, unsigned int addr, | ||
100 | uint8_t data[], size_t len) | ||
101 | { | ||
102 | return sigmadsp->read(sigmadsp->control_data, addr, data, len); | ||
103 | } | ||
104 | |||
105 | static int sigmadsp_ctrl_info(struct snd_kcontrol *kcontrol, | ||
106 | struct snd_ctl_elem_info *info) | ||
107 | { | ||
108 | struct sigmadsp_control *ctrl = (void *)kcontrol->private_value; | ||
109 | |||
110 | info->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
111 | info->count = ctrl->num_bytes; | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int sigmadsp_ctrl_write(struct sigmadsp *sigmadsp, | ||
117 | struct sigmadsp_control *ctrl, void *data) | ||
118 | { | ||
119 | /* safeload loads up to 20 bytes in a atomic operation */ | ||
120 | if (ctrl->num_bytes > 4 && ctrl->num_bytes <= 20 && sigmadsp->ops && | ||
121 | sigmadsp->ops->safeload) | ||
122 | return sigmadsp->ops->safeload(sigmadsp, ctrl->addr, data, | ||
123 | ctrl->num_bytes); | ||
124 | else | ||
125 | return sigmadsp_write(sigmadsp, ctrl->addr, data, | ||
126 | ctrl->num_bytes); | ||
127 | } | ||
128 | |||
129 | static int sigmadsp_ctrl_put(struct snd_kcontrol *kcontrol, | ||
130 | struct snd_ctl_elem_value *ucontrol) | ||
131 | { | ||
132 | struct sigmadsp_control *ctrl = (void *)kcontrol->private_value; | ||
133 | struct sigmadsp *sigmadsp = snd_kcontrol_chip(kcontrol); | ||
134 | uint8_t *data; | ||
135 | int ret = 0; | ||
136 | |||
137 | mutex_lock(&sigmadsp->lock); | ||
138 | |||
139 | data = ucontrol->value.bytes.data; | ||
140 | |||
141 | if (!(kcontrol->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)) | ||
142 | ret = sigmadsp_ctrl_write(sigmadsp, ctrl, data); | ||
143 | |||
144 | if (ret == 0) { | ||
145 | memcpy(ctrl->cache, data, ctrl->num_bytes); | ||
146 | ctrl->cached = true; | ||
147 | } | ||
148 | |||
149 | mutex_unlock(&sigmadsp->lock); | ||
150 | |||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static int sigmadsp_ctrl_get(struct snd_kcontrol *kcontrol, | ||
155 | struct snd_ctl_elem_value *ucontrol) | ||
156 | { | ||
157 | struct sigmadsp_control *ctrl = (void *)kcontrol->private_value; | ||
158 | struct sigmadsp *sigmadsp = snd_kcontrol_chip(kcontrol); | ||
159 | int ret = 0; | ||
160 | |||
161 | mutex_lock(&sigmadsp->lock); | ||
162 | |||
163 | if (!ctrl->cached) { | ||
164 | ret = sigmadsp_read(sigmadsp, ctrl->addr, ctrl->cache, | ||
165 | ctrl->num_bytes); | ||
166 | } | ||
167 | |||
168 | if (ret == 0) { | ||
169 | ctrl->cached = true; | ||
170 | memcpy(ucontrol->value.bytes.data, ctrl->cache, | ||
171 | ctrl->num_bytes); | ||
172 | } | ||
173 | |||
174 | mutex_unlock(&sigmadsp->lock); | ||
175 | |||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static void sigmadsp_control_free(struct snd_kcontrol *kcontrol) | ||
180 | { | ||
181 | struct sigmadsp_control *ctrl = (void *)kcontrol->private_value; | ||
182 | |||
183 | ctrl->kcontrol = NULL; | ||
184 | } | ||
185 | |||
186 | static bool sigma_fw_validate_control_name(const char *name, unsigned int len) | ||
187 | { | ||
188 | unsigned int i; | ||
189 | |||
190 | for (i = 0; i < len; i++) { | ||
191 | /* Normal ASCII characters are valid */ | ||
192 | if (name[i] < ' ' || name[i] > '~') | ||
193 | return false; | ||
194 | } | ||
195 | |||
196 | return true; | ||
197 | } | ||
198 | |||
199 | static int sigma_fw_load_control(struct sigmadsp *sigmadsp, | ||
200 | const struct sigma_fw_chunk *chunk, unsigned int length) | ||
201 | { | ||
202 | const struct sigma_fw_chunk_control *ctrl_chunk; | ||
203 | struct sigmadsp_control *ctrl; | ||
204 | unsigned int num_bytes; | ||
205 | size_t name_len; | ||
206 | char *name; | ||
207 | int ret; | ||
208 | |||
209 | if (length <= sizeof(*ctrl_chunk)) | ||
210 | return -EINVAL; | ||
211 | |||
212 | ctrl_chunk = (const struct sigma_fw_chunk_control *)chunk; | ||
213 | |||
214 | name_len = length - sizeof(*ctrl_chunk); | ||
215 | if (name_len >= SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
216 | name_len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - 1; | ||
217 | |||
218 | /* Make sure there are no non-displayable characaters in the string */ | ||
219 | if (!sigma_fw_validate_control_name(ctrl_chunk->name, name_len)) | ||
220 | return -EINVAL; | ||
221 | |||
222 | num_bytes = le16_to_cpu(ctrl_chunk->num_bytes); | ||
223 | ctrl = kzalloc(sizeof(*ctrl) + num_bytes, GFP_KERNEL); | ||
224 | if (!ctrl) | ||
225 | return -ENOMEM; | ||
226 | |||
227 | name = kzalloc(name_len + 1, GFP_KERNEL); | ||
228 | if (!name) { | ||
229 | ret = -ENOMEM; | ||
230 | goto err_free_ctrl; | ||
231 | } | ||
232 | memcpy(name, ctrl_chunk->name, name_len); | ||
233 | name[name_len] = '\0'; | ||
234 | ctrl->name = name; | ||
235 | |||
236 | ctrl->addr = le16_to_cpu(ctrl_chunk->addr); | ||
237 | ctrl->num_bytes = num_bytes; | ||
238 | ctrl->samplerates = le32_to_cpu(chunk->samplerates); | ||
239 | |||
240 | list_add_tail(&ctrl->head, &sigmadsp->ctrl_list); | ||
241 | |||
242 | return 0; | ||
243 | |||
244 | err_free_ctrl: | ||
245 | kfree(ctrl); | ||
246 | |||
247 | return ret; | ||
248 | } | ||
249 | |||
250 | static int sigma_fw_load_data(struct sigmadsp *sigmadsp, | ||
251 | const struct sigma_fw_chunk *chunk, unsigned int length) | ||
252 | { | ||
253 | const struct sigma_fw_chunk_data *data_chunk; | ||
254 | struct sigmadsp_data *data; | ||
255 | |||
256 | if (length <= sizeof(*data_chunk)) | ||
257 | return -EINVAL; | ||
258 | |||
259 | data_chunk = (struct sigma_fw_chunk_data *)chunk; | ||
260 | |||
261 | length -= sizeof(*data_chunk); | ||
262 | |||
263 | data = kzalloc(sizeof(*data) + length, GFP_KERNEL); | ||
264 | if (!data) | ||
265 | return -ENOMEM; | ||
266 | |||
267 | data->addr = le16_to_cpu(data_chunk->addr); | ||
268 | data->length = length; | ||
269 | data->samplerates = le32_to_cpu(chunk->samplerates); | ||
270 | memcpy(data->data, data_chunk->data, length); | ||
271 | list_add_tail(&data->head, &sigmadsp->data_list); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int sigma_fw_load_samplerates(struct sigmadsp *sigmadsp, | ||
277 | const struct sigma_fw_chunk *chunk, unsigned int length) | ||
278 | { | ||
279 | const struct sigma_fw_chunk_samplerate *rate_chunk; | ||
280 | unsigned int num_rates; | ||
281 | unsigned int *rates; | ||
282 | unsigned int i; | ||
283 | |||
284 | rate_chunk = (const struct sigma_fw_chunk_samplerate *)chunk; | ||
285 | |||
286 | num_rates = (length - sizeof(*rate_chunk)) / sizeof(__le32); | ||
287 | |||
288 | if (num_rates > 32 || num_rates == 0) | ||
289 | return -EINVAL; | ||
290 | |||
291 | /* We only allow one samplerates block per file */ | ||
292 | if (sigmadsp->rate_constraints.count) | ||
293 | return -EINVAL; | ||
294 | |||
295 | rates = kcalloc(num_rates, sizeof(*rates), GFP_KERNEL); | ||
296 | if (!rates) | ||
297 | return -ENOMEM; | ||
298 | |||
299 | for (i = 0; i < num_rates; i++) | ||
300 | rates[i] = le32_to_cpu(rate_chunk->samplerates[i]); | ||
301 | |||
302 | sigmadsp->rate_constraints.count = num_rates; | ||
303 | sigmadsp->rate_constraints.list = rates; | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int sigmadsp_fw_load_v2(struct sigmadsp *sigmadsp, | ||
309 | const struct firmware *fw) | ||
310 | { | ||
311 | struct sigma_fw_chunk *chunk; | ||
312 | unsigned int length, pos; | ||
313 | int ret; | ||
314 | |||
315 | /* | ||
316 | * Make sure that there is at least one chunk to avoid integer | ||
317 | * underflows later on. Empty firmware is still valid though. | ||
318 | */ | ||
319 | if (fw->size < sizeof(*chunk) + sizeof(struct sigma_firmware_header)) | ||
320 | return 0; | ||
321 | |||
322 | pos = sizeof(struct sigma_firmware_header); | ||
323 | |||
324 | while (pos < fw->size - sizeof(*chunk)) { | ||
325 | chunk = (struct sigma_fw_chunk *)(fw->data + pos); | ||
326 | |||
327 | length = le32_to_cpu(chunk->length); | ||
328 | |||
329 | if (length > fw->size - pos || length < sizeof(*chunk)) | ||
330 | return -EINVAL; | ||
331 | |||
332 | switch (le32_to_cpu(chunk->tag)) { | ||
333 | case SIGMA_FW_CHUNK_TYPE_DATA: | ||
334 | ret = sigma_fw_load_data(sigmadsp, chunk, length); | ||
335 | break; | ||
336 | case SIGMA_FW_CHUNK_TYPE_CONTROL: | ||
337 | ret = sigma_fw_load_control(sigmadsp, chunk, length); | ||
338 | break; | ||
339 | case SIGMA_FW_CHUNK_TYPE_SAMPLERATES: | ||
340 | ret = sigma_fw_load_samplerates(sigmadsp, chunk, length); | ||
341 | break; | ||
342 | default: | ||
343 | dev_warn(sigmadsp->dev, "Unknown chunk type: %d\n", | ||
344 | chunk->tag); | ||
345 | ret = 0; | ||
346 | break; | ||
347 | } | ||
348 | |||
349 | if (ret) | ||
350 | return ret; | ||
351 | |||
352 | /* | ||
353 | * This can not overflow since if length is larger than the | ||
354 | * maximum firmware size (0x4000000) we'll error out earilier. | ||
355 | */ | ||
356 | pos += ALIGN(length, sizeof(__le32)); | ||
357 | } | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
37 | static inline u32 sigma_action_len(struct sigma_action *sa) | 362 | static inline u32 sigma_action_len(struct sigma_action *sa) |
38 | { | 363 | { |
39 | return (sa->len_hi << 16) | le16_to_cpu(sa->len); | 364 | return (sa->len_hi << 16) | le16_to_cpu(sa->len); |
@@ -62,11 +387,11 @@ static size_t sigma_action_size(struct sigma_action *sa) | |||
62 | * Returns a negative error value in case of an error, 0 if processing of | 387 | * Returns a negative error value in case of an error, 0 if processing of |
63 | * the firmware should be stopped after this action, 1 otherwise. | 388 | * the firmware should be stopped after this action, 1 otherwise. |
64 | */ | 389 | */ |
65 | static int | 390 | static int process_sigma_action(struct sigmadsp *sigmadsp, |
66 | process_sigma_action(struct sigma_firmware *ssfw, struct sigma_action *sa) | 391 | struct sigma_action *sa) |
67 | { | 392 | { |
68 | size_t len = sigma_action_len(sa); | 393 | size_t len = sigma_action_len(sa); |
69 | int ret; | 394 | struct sigmadsp_data *data; |
70 | 395 | ||
71 | pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__, | 396 | pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__, |
72 | sa->instr, sa->addr, len); | 397 | sa->instr, sa->addr, len); |
@@ -75,13 +400,17 @@ process_sigma_action(struct sigma_firmware *ssfw, struct sigma_action *sa) | |||
75 | case SIGMA_ACTION_WRITEXBYTES: | 400 | case SIGMA_ACTION_WRITEXBYTES: |
76 | case SIGMA_ACTION_WRITESINGLE: | 401 | case SIGMA_ACTION_WRITESINGLE: |
77 | case SIGMA_ACTION_WRITESAFELOAD: | 402 | case SIGMA_ACTION_WRITESAFELOAD: |
78 | ret = ssfw->write(ssfw->control_data, sa, len); | 403 | if (len < 3) |
79 | if (ret < 0) | ||
80 | return -EINVAL; | 404 | return -EINVAL; |
81 | break; | 405 | |
82 | case SIGMA_ACTION_DELAY: | 406 | data = kzalloc(sizeof(*data) + len - 2, GFP_KERNEL); |
83 | udelay(len); | 407 | if (!data) |
84 | len = 0; | 408 | return -ENOMEM; |
409 | |||
410 | data->addr = be16_to_cpu(sa->addr); | ||
411 | data->length = len - 2; | ||
412 | memcpy(data->data, sa->payload, data->length); | ||
413 | list_add_tail(&data->head, &sigmadsp->data_list); | ||
85 | break; | 414 | break; |
86 | case SIGMA_ACTION_END: | 415 | case SIGMA_ACTION_END: |
87 | return 0; | 416 | return 0; |
@@ -92,22 +421,24 @@ process_sigma_action(struct sigma_firmware *ssfw, struct sigma_action *sa) | |||
92 | return 1; | 421 | return 1; |
93 | } | 422 | } |
94 | 423 | ||
95 | static int | 424 | static int sigmadsp_fw_load_v1(struct sigmadsp *sigmadsp, |
96 | process_sigma_actions(struct sigma_firmware *ssfw) | 425 | const struct firmware *fw) |
97 | { | 426 | { |
98 | struct sigma_action *sa; | 427 | struct sigma_action *sa; |
99 | size_t size; | 428 | size_t size, pos; |
100 | int ret; | 429 | int ret; |
101 | 430 | ||
102 | while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) { | 431 | pos = sizeof(struct sigma_firmware_header); |
103 | sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos); | 432 | |
433 | while (pos + sizeof(*sa) <= fw->size) { | ||
434 | sa = (struct sigma_action *)(fw->data + pos); | ||
104 | 435 | ||
105 | size = sigma_action_size(sa); | 436 | size = sigma_action_size(sa); |
106 | ssfw->pos += size; | 437 | pos += size; |
107 | if (ssfw->pos > ssfw->fw->size || size == 0) | 438 | if (pos > fw->size || size == 0) |
108 | break; | 439 | break; |
109 | 440 | ||
110 | ret = process_sigma_action(ssfw, sa); | 441 | ret = process_sigma_action(sigmadsp, sa); |
111 | 442 | ||
112 | pr_debug("%s: action returned %i\n", __func__, ret); | 443 | pr_debug("%s: action returned %i\n", __func__, ret); |
113 | 444 | ||
@@ -115,29 +446,47 @@ process_sigma_actions(struct sigma_firmware *ssfw) | |||
115 | return ret; | 446 | return ret; |
116 | } | 447 | } |
117 | 448 | ||
118 | if (ssfw->pos != ssfw->fw->size) | 449 | if (pos != fw->size) |
119 | return -EINVAL; | 450 | return -EINVAL; |
120 | 451 | ||
121 | return 0; | 452 | return 0; |
122 | } | 453 | } |
123 | 454 | ||
124 | int _process_sigma_firmware(struct device *dev, | 455 | static void sigmadsp_firmware_release(struct sigmadsp *sigmadsp) |
125 | struct sigma_firmware *ssfw, const char *name) | ||
126 | { | 456 | { |
127 | int ret; | 457 | struct sigmadsp_control *ctrl, *_ctrl; |
128 | struct sigma_firmware_header *ssfw_head; | 458 | struct sigmadsp_data *data, *_data; |
459 | |||
460 | list_for_each_entry_safe(ctrl, _ctrl, &sigmadsp->ctrl_list, head) { | ||
461 | kfree(ctrl->name); | ||
462 | kfree(ctrl); | ||
463 | } | ||
464 | |||
465 | list_for_each_entry_safe(data, _data, &sigmadsp->data_list, head) | ||
466 | kfree(data); | ||
467 | |||
468 | INIT_LIST_HEAD(&sigmadsp->ctrl_list); | ||
469 | INIT_LIST_HEAD(&sigmadsp->data_list); | ||
470 | } | ||
471 | |||
472 | static void devm_sigmadsp_release(struct device *dev, void *res) | ||
473 | { | ||
474 | sigmadsp_firmware_release((struct sigmadsp *)res); | ||
475 | } | ||
476 | |||
477 | static int sigmadsp_firmware_load(struct sigmadsp *sigmadsp, const char *name) | ||
478 | { | ||
479 | const struct sigma_firmware_header *ssfw_head; | ||
129 | const struct firmware *fw; | 480 | const struct firmware *fw; |
481 | int ret; | ||
130 | u32 crc; | 482 | u32 crc; |
131 | 483 | ||
132 | pr_debug("%s: loading firmware %s\n", __func__, name); | ||
133 | |||
134 | /* first load the blob */ | 484 | /* first load the blob */ |
135 | ret = request_firmware(&fw, name, dev); | 485 | ret = request_firmware(&fw, name, sigmadsp->dev); |
136 | if (ret) { | 486 | if (ret) { |
137 | pr_debug("%s: request_firmware() failed with %i\n", __func__, ret); | 487 | pr_debug("%s: request_firmware() failed with %i\n", __func__, ret); |
138 | return ret; | 488 | goto done; |
139 | } | 489 | } |
140 | ssfw->fw = fw; | ||
141 | 490 | ||
142 | /* then verify the header */ | 491 | /* then verify the header */ |
143 | ret = -EINVAL; | 492 | ret = -EINVAL; |
@@ -149,13 +498,13 @@ int _process_sigma_firmware(struct device *dev, | |||
149 | * overflows later in the loading process. | 498 | * overflows later in the loading process. |
150 | */ | 499 | */ |
151 | if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) { | 500 | if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) { |
152 | dev_err(dev, "Failed to load firmware: Invalid size\n"); | 501 | dev_err(sigmadsp->dev, "Failed to load firmware: Invalid size\n"); |
153 | goto done; | 502 | goto done; |
154 | } | 503 | } |
155 | 504 | ||
156 | ssfw_head = (void *)fw->data; | 505 | ssfw_head = (void *)fw->data; |
157 | if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) { | 506 | if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) { |
158 | dev_err(dev, "Failed to load firmware: Invalid magic\n"); | 507 | dev_err(sigmadsp->dev, "Failed to load firmware: Invalid magic\n"); |
159 | goto done; | 508 | goto done; |
160 | } | 509 | } |
161 | 510 | ||
@@ -163,23 +512,303 @@ int _process_sigma_firmware(struct device *dev, | |||
163 | fw->size - sizeof(*ssfw_head)); | 512 | fw->size - sizeof(*ssfw_head)); |
164 | pr_debug("%s: crc=%x\n", __func__, crc); | 513 | pr_debug("%s: crc=%x\n", __func__, crc); |
165 | if (crc != le32_to_cpu(ssfw_head->crc)) { | 514 | if (crc != le32_to_cpu(ssfw_head->crc)) { |
166 | dev_err(dev, "Failed to load firmware: Wrong crc checksum: expected %x got %x\n", | 515 | dev_err(sigmadsp->dev, "Failed to load firmware: Wrong crc checksum: expected %x got %x\n", |
167 | le32_to_cpu(ssfw_head->crc), crc); | 516 | le32_to_cpu(ssfw_head->crc), crc); |
168 | goto done; | 517 | goto done; |
169 | } | 518 | } |
170 | 519 | ||
171 | ssfw->pos = sizeof(*ssfw_head); | 520 | switch (ssfw_head->version) { |
521 | case 1: | ||
522 | ret = sigmadsp_fw_load_v1(sigmadsp, fw); | ||
523 | break; | ||
524 | case 2: | ||
525 | ret = sigmadsp_fw_load_v2(sigmadsp, fw); | ||
526 | break; | ||
527 | default: | ||
528 | dev_err(sigmadsp->dev, | ||
529 | "Failed to load firmware: Invalid version %d. Supported firmware versions: 1, 2\n", | ||
530 | ssfw_head->version); | ||
531 | ret = -EINVAL; | ||
532 | break; | ||
533 | } | ||
172 | 534 | ||
173 | /* finally process all of the actions */ | 535 | if (ret) |
174 | ret = process_sigma_actions(ssfw); | 536 | sigmadsp_firmware_release(sigmadsp); |
175 | 537 | ||
176 | done: | 538 | done: |
177 | release_firmware(fw); | 539 | release_firmware(fw); |
178 | 540 | ||
179 | pr_debug("%s: loaded %s\n", __func__, name); | 541 | return ret; |
542 | } | ||
543 | |||
544 | static int sigmadsp_init(struct sigmadsp *sigmadsp, struct device *dev, | ||
545 | const struct sigmadsp_ops *ops, const char *firmware_name) | ||
546 | { | ||
547 | sigmadsp->ops = ops; | ||
548 | sigmadsp->dev = dev; | ||
549 | |||
550 | INIT_LIST_HEAD(&sigmadsp->ctrl_list); | ||
551 | INIT_LIST_HEAD(&sigmadsp->data_list); | ||
552 | mutex_init(&sigmadsp->lock); | ||
553 | |||
554 | return sigmadsp_firmware_load(sigmadsp, firmware_name); | ||
555 | } | ||
556 | |||
557 | /** | ||
558 | * devm_sigmadsp_init() - Initialize SigmaDSP instance | ||
559 | * @dev: The parent device | ||
560 | * @ops: The sigmadsp_ops to use for this instance | ||
561 | * @firmware_name: Name of the firmware file to load | ||
562 | * | ||
563 | * Allocates a SigmaDSP instance and loads the specified firmware file. | ||
564 | * | ||
565 | * Returns a pointer to a struct sigmadsp on success, or a PTR_ERR() on error. | ||
566 | */ | ||
567 | struct sigmadsp *devm_sigmadsp_init(struct device *dev, | ||
568 | const struct sigmadsp_ops *ops, const char *firmware_name) | ||
569 | { | ||
570 | struct sigmadsp *sigmadsp; | ||
571 | int ret; | ||
572 | |||
573 | sigmadsp = devres_alloc(devm_sigmadsp_release, sizeof(*sigmadsp), | ||
574 | GFP_KERNEL); | ||
575 | if (!sigmadsp) | ||
576 | return ERR_PTR(-ENOMEM); | ||
577 | |||
578 | ret = sigmadsp_init(sigmadsp, dev, ops, firmware_name); | ||
579 | if (ret) { | ||
580 | devres_free(sigmadsp); | ||
581 | return ERR_PTR(ret); | ||
582 | } | ||
583 | |||
584 | devres_add(dev, sigmadsp); | ||
585 | |||
586 | return sigmadsp; | ||
587 | } | ||
588 | EXPORT_SYMBOL_GPL(devm_sigmadsp_init); | ||
589 | |||
590 | static int sigmadsp_rate_to_index(struct sigmadsp *sigmadsp, unsigned int rate) | ||
591 | { | ||
592 | unsigned int i; | ||
593 | |||
594 | for (i = 0; i < sigmadsp->rate_constraints.count; i++) { | ||
595 | if (sigmadsp->rate_constraints.list[i] == rate) | ||
596 | return i; | ||
597 | } | ||
598 | |||
599 | return -EINVAL; | ||
600 | } | ||
601 | |||
602 | static unsigned int sigmadsp_get_samplerate_mask(struct sigmadsp *sigmadsp, | ||
603 | unsigned int samplerate) | ||
604 | { | ||
605 | int samplerate_index; | ||
606 | |||
607 | if (samplerate == 0) | ||
608 | return 0; | ||
609 | |||
610 | if (sigmadsp->rate_constraints.count) { | ||
611 | samplerate_index = sigmadsp_rate_to_index(sigmadsp, samplerate); | ||
612 | if (samplerate_index < 0) | ||
613 | return 0; | ||
614 | |||
615 | return BIT(samplerate_index); | ||
616 | } else { | ||
617 | return ~0; | ||
618 | } | ||
619 | } | ||
620 | |||
621 | static bool sigmadsp_samplerate_valid(unsigned int supported, | ||
622 | unsigned int requested) | ||
623 | { | ||
624 | /* All samplerates are supported */ | ||
625 | if (!supported) | ||
626 | return true; | ||
627 | |||
628 | return supported & requested; | ||
629 | } | ||
630 | |||
631 | static int sigmadsp_alloc_control(struct sigmadsp *sigmadsp, | ||
632 | struct sigmadsp_control *ctrl, unsigned int samplerate_mask) | ||
633 | { | ||
634 | struct snd_kcontrol_new template; | ||
635 | struct snd_kcontrol *kcontrol; | ||
636 | |||
637 | memset(&template, 0, sizeof(template)); | ||
638 | template.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
639 | template.name = ctrl->name; | ||
640 | template.info = sigmadsp_ctrl_info; | ||
641 | template.get = sigmadsp_ctrl_get; | ||
642 | template.put = sigmadsp_ctrl_put; | ||
643 | template.private_value = (unsigned long)ctrl; | ||
644 | template.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | ||
645 | if (!sigmadsp_samplerate_valid(ctrl->samplerates, samplerate_mask)) | ||
646 | template.access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
647 | |||
648 | kcontrol = snd_ctl_new1(&template, sigmadsp); | ||
649 | if (!kcontrol) | ||
650 | return -ENOMEM; | ||
651 | |||
652 | kcontrol->private_free = sigmadsp_control_free; | ||
653 | ctrl->kcontrol = kcontrol; | ||
654 | |||
655 | return snd_ctl_add(sigmadsp->component->card->snd_card, kcontrol); | ||
656 | } | ||
657 | |||
658 | static void sigmadsp_activate_ctrl(struct sigmadsp *sigmadsp, | ||
659 | struct sigmadsp_control *ctrl, unsigned int samplerate_mask) | ||
660 | { | ||
661 | struct snd_card *card = sigmadsp->component->card->snd_card; | ||
662 | struct snd_kcontrol_volatile *vd; | ||
663 | struct snd_ctl_elem_id id; | ||
664 | bool active; | ||
665 | bool changed = false; | ||
666 | |||
667 | active = sigmadsp_samplerate_valid(ctrl->samplerates, samplerate_mask); | ||
668 | |||
669 | down_write(&card->controls_rwsem); | ||
670 | if (!ctrl->kcontrol) { | ||
671 | up_write(&card->controls_rwsem); | ||
672 | return; | ||
673 | } | ||
674 | |||
675 | id = ctrl->kcontrol->id; | ||
676 | vd = &ctrl->kcontrol->vd[0]; | ||
677 | if (active == (bool)(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)) { | ||
678 | vd->access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
679 | changed = true; | ||
680 | } | ||
681 | up_write(&card->controls_rwsem); | ||
682 | |||
683 | if (active && changed) { | ||
684 | mutex_lock(&sigmadsp->lock); | ||
685 | if (ctrl->cached) | ||
686 | sigmadsp_ctrl_write(sigmadsp, ctrl, ctrl->cache); | ||
687 | mutex_unlock(&sigmadsp->lock); | ||
688 | } | ||
689 | |||
690 | if (changed) | ||
691 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, &id); | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * sigmadsp_attach() - Attach a sigmadsp instance to a ASoC component | ||
696 | * @sigmadsp: The sigmadsp instance to attach | ||
697 | * @component: The component to attach to | ||
698 | * | ||
699 | * Typically called in the components probe callback. | ||
700 | * | ||
701 | * Note, once this function has been called the firmware must not be released | ||
702 | * until after the ALSA snd_card that the component belongs to has been | ||
703 | * disconnected, even if sigmadsp_attach() returns an error. | ||
704 | */ | ||
705 | int sigmadsp_attach(struct sigmadsp *sigmadsp, | ||
706 | struct snd_soc_component *component) | ||
707 | { | ||
708 | struct sigmadsp_control *ctrl; | ||
709 | unsigned int samplerate_mask; | ||
710 | int ret; | ||
711 | |||
712 | sigmadsp->component = component; | ||
713 | |||
714 | samplerate_mask = sigmadsp_get_samplerate_mask(sigmadsp, | ||
715 | sigmadsp->current_samplerate); | ||
716 | |||
717 | list_for_each_entry(ctrl, &sigmadsp->ctrl_list, head) { | ||
718 | ret = sigmadsp_alloc_control(sigmadsp, ctrl, samplerate_mask); | ||
719 | if (ret) | ||
720 | return ret; | ||
721 | } | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | EXPORT_SYMBOL_GPL(sigmadsp_attach); | ||
726 | |||
727 | /** | ||
728 | * sigmadsp_setup() - Setup the DSP for the specified samplerate | ||
729 | * @sigmadsp: The sigmadsp instance to configure | ||
730 | * @samplerate: The samplerate the DSP should be configured for | ||
731 | * | ||
732 | * Loads the appropriate firmware program and parameter memory (if not already | ||
733 | * loaded) and enables the controls for the specified samplerate. Any control | ||
734 | * parameter changes that have been made previously will be restored. | ||
735 | * | ||
736 | * Returns 0 on success, a negative error code otherwise. | ||
737 | */ | ||
738 | int sigmadsp_setup(struct sigmadsp *sigmadsp, unsigned int samplerate) | ||
739 | { | ||
740 | struct sigmadsp_control *ctrl; | ||
741 | unsigned int samplerate_mask; | ||
742 | struct sigmadsp_data *data; | ||
743 | int ret; | ||
744 | |||
745 | if (sigmadsp->current_samplerate == samplerate) | ||
746 | return 0; | ||
747 | |||
748 | samplerate_mask = sigmadsp_get_samplerate_mask(sigmadsp, samplerate); | ||
749 | if (samplerate_mask == 0) | ||
750 | return -EINVAL; | ||
751 | |||
752 | list_for_each_entry(data, &sigmadsp->data_list, head) { | ||
753 | if (!sigmadsp_samplerate_valid(data->samplerates, | ||
754 | samplerate_mask)) | ||
755 | continue; | ||
756 | ret = sigmadsp_write(sigmadsp, data->addr, data->data, | ||
757 | data->length); | ||
758 | if (ret) | ||
759 | goto err; | ||
760 | } | ||
761 | |||
762 | list_for_each_entry(ctrl, &sigmadsp->ctrl_list, head) | ||
763 | sigmadsp_activate_ctrl(sigmadsp, ctrl, samplerate_mask); | ||
764 | |||
765 | sigmadsp->current_samplerate = samplerate; | ||
766 | |||
767 | return 0; | ||
768 | err: | ||
769 | sigmadsp_reset(sigmadsp); | ||
180 | 770 | ||
181 | return ret; | 771 | return ret; |
182 | } | 772 | } |
183 | EXPORT_SYMBOL_GPL(_process_sigma_firmware); | 773 | EXPORT_SYMBOL_GPL(sigmadsp_setup); |
774 | |||
775 | /** | ||
776 | * sigmadsp_reset() - Notify the sigmadsp instance that the DSP has been reset | ||
777 | * @sigmadsp: The sigmadsp instance to reset | ||
778 | * | ||
779 | * Should be called whenever the DSP has been reset and parameter and program | ||
780 | * memory need to be re-loaded. | ||
781 | */ | ||
782 | void sigmadsp_reset(struct sigmadsp *sigmadsp) | ||
783 | { | ||
784 | struct sigmadsp_control *ctrl; | ||
785 | |||
786 | list_for_each_entry(ctrl, &sigmadsp->ctrl_list, head) | ||
787 | sigmadsp_activate_ctrl(sigmadsp, ctrl, false); | ||
788 | |||
789 | sigmadsp->current_samplerate = 0; | ||
790 | } | ||
791 | EXPORT_SYMBOL_GPL(sigmadsp_reset); | ||
792 | |||
793 | /** | ||
794 | * sigmadsp_restrict_params() - Applies DSP firmware specific constraints | ||
795 | * @sigmadsp: The sigmadsp instance | ||
796 | * @substream: The substream to restrict | ||
797 | * | ||
798 | * Applies samplerate constraints that may be required by the firmware Should | ||
799 | * typically be called from the CODEC/component drivers startup callback. | ||
800 | * | ||
801 | * Returns 0 on success, a negative error code otherwise. | ||
802 | */ | ||
803 | int sigmadsp_restrict_params(struct sigmadsp *sigmadsp, | ||
804 | struct snd_pcm_substream *substream) | ||
805 | { | ||
806 | if (sigmadsp->rate_constraints.count == 0) | ||
807 | return 0; | ||
808 | |||
809 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
810 | SNDRV_PCM_HW_PARAM_RATE, &sigmadsp->rate_constraints); | ||
811 | } | ||
812 | EXPORT_SYMBOL_GPL(sigmadsp_restrict_params); | ||
184 | 813 | ||
185 | MODULE_LICENSE("GPL"); | 814 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/sigmadsp.h b/sound/soc/codecs/sigmadsp.h index c47cd23e9827..614475cbb823 100644 --- a/sound/soc/codecs/sigmadsp.h +++ b/sound/soc/codecs/sigmadsp.h | |||
@@ -11,31 +11,56 @@ | |||
11 | 11 | ||
12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
13 | #include <linux/regmap.h> | 13 | #include <linux/regmap.h> |
14 | #include <linux/list.h> | ||
14 | 15 | ||
15 | struct sigma_action { | 16 | #include <sound/pcm.h> |
16 | u8 instr; | ||
17 | u8 len_hi; | ||
18 | __le16 len; | ||
19 | __be16 addr; | ||
20 | unsigned char payload[]; | ||
21 | } __packed; | ||
22 | 17 | ||
23 | struct sigma_firmware { | 18 | struct sigmadsp; |
24 | const struct firmware *fw; | 19 | struct snd_soc_component; |
25 | size_t pos; | 20 | struct snd_pcm_substream; |
21 | |||
22 | struct sigmadsp_ops { | ||
23 | int (*safeload)(struct sigmadsp *sigmadsp, unsigned int addr, | ||
24 | const uint8_t *data, size_t len); | ||
25 | }; | ||
26 | |||
27 | struct sigmadsp { | ||
28 | const struct sigmadsp_ops *ops; | ||
29 | |||
30 | struct list_head ctrl_list; | ||
31 | struct list_head data_list; | ||
32 | |||
33 | struct snd_pcm_hw_constraint_list rate_constraints; | ||
34 | |||
35 | unsigned int current_samplerate; | ||
36 | struct snd_soc_component *component; | ||
37 | struct device *dev; | ||
38 | |||
39 | struct mutex lock; | ||
26 | 40 | ||
27 | void *control_data; | 41 | void *control_data; |
28 | int (*write)(void *control_data, const struct sigma_action *sa, | 42 | int (*write)(void *, unsigned int, const uint8_t *, size_t); |
29 | size_t len); | 43 | int (*read)(void *, unsigned int, uint8_t *, size_t); |
30 | }; | 44 | }; |
31 | 45 | ||
32 | int _process_sigma_firmware(struct device *dev, | 46 | struct sigmadsp *devm_sigmadsp_init(struct device *dev, |
33 | struct sigma_firmware *ssfw, const char *name); | 47 | const struct sigmadsp_ops *ops, const char *firmware_name); |
48 | void sigmadsp_reset(struct sigmadsp *sigmadsp); | ||
49 | |||
50 | int sigmadsp_restrict_params(struct sigmadsp *sigmadsp, | ||
51 | struct snd_pcm_substream *substream); | ||
34 | 52 | ||
35 | struct i2c_client; | 53 | struct i2c_client; |
36 | 54 | ||
37 | extern int process_sigma_firmware(struct i2c_client *client, const char *name); | 55 | struct sigmadsp *devm_sigmadsp_init_regmap(struct device *dev, |
38 | extern int process_sigma_firmware_regmap(struct device *dev, | 56 | struct regmap *regmap, const struct sigmadsp_ops *ops, |
39 | struct regmap *regmap, const char *name); | 57 | const char *firmware_name); |
58 | struct sigmadsp *devm_sigmadsp_init_i2c(struct i2c_client *client, | ||
59 | const struct sigmadsp_ops *ops, const char *firmware_name); | ||
60 | |||
61 | int sigmadsp_attach(struct sigmadsp *sigmadsp, | ||
62 | struct snd_soc_component *component); | ||
63 | int sigmadsp_setup(struct sigmadsp *sigmadsp, unsigned int rate); | ||
64 | void sigmadsp_reset(struct sigmadsp *sigmadsp); | ||
40 | 65 | ||
41 | #endif | 66 | #endif |
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c index 06ba4923fd5a..07eea20e6645 100644 --- a/sound/soc/codecs/sirf-audio-codec.c +++ b/sound/soc/codecs/sirf-audio-codec.c | |||
@@ -120,7 +120,8 @@ static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, | |||
120 | { | 120 | { |
121 | #define ATLAS6_CODEC_ENABLE_BITS (1 << 29) | 121 | #define ATLAS6_CODEC_ENABLE_BITS (1 << 29) |
122 | #define ATLAS6_CODEC_RESET_BITS (1 << 28) | 122 | #define ATLAS6_CODEC_RESET_BITS (1 << 28) |
123 | struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev); | 123 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
124 | struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); | ||
124 | switch (event) { | 125 | switch (event) { |
125 | case SND_SOC_DAPM_PRE_PMU: | 126 | case SND_SOC_DAPM_PRE_PMU: |
126 | enable_and_reset_codec(sirf_audio_codec->regmap, | 127 | enable_and_reset_codec(sirf_audio_codec->regmap, |
@@ -142,7 +143,8 @@ static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, | |||
142 | { | 143 | { |
143 | #define PRIMA2_CODEC_ENABLE_BITS (1 << 27) | 144 | #define PRIMA2_CODEC_ENABLE_BITS (1 << 27) |
144 | #define PRIMA2_CODEC_RESET_BITS (1 << 26) | 145 | #define PRIMA2_CODEC_RESET_BITS (1 << 26) |
145 | struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev); | 146 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
147 | struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); | ||
146 | switch (event) { | 148 | switch (event) { |
147 | case SND_SOC_DAPM_POST_PMU: | 149 | case SND_SOC_DAPM_POST_PMU: |
148 | enable_and_reset_codec(sirf_audio_codec->regmap, | 150 | enable_and_reset_codec(sirf_audio_codec->regmap, |
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index cf8fa40662f0..31d97cd5e59b 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c | |||
@@ -867,25 +867,16 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec) | |||
867 | snd_soc_write(codec, SN95031_SSR2, 0x10); | 867 | snd_soc_write(codec, SN95031_SSR2, 0x10); |
868 | snd_soc_write(codec, SN95031_SSR3, 0x40); | 868 | snd_soc_write(codec, SN95031_SSR3, 0x40); |
869 | 869 | ||
870 | snd_soc_add_codec_controls(codec, sn95031_snd_controls, | ||
871 | ARRAY_SIZE(sn95031_snd_controls)); | ||
872 | |||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | static int sn95031_codec_remove(struct snd_soc_codec *codec) | ||
877 | { | ||
878 | pr_debug("codec_remove called\n"); | ||
879 | sn95031_set_vaud_bias(codec, SND_SOC_BIAS_OFF); | ||
880 | |||
881 | return 0; | 870 | return 0; |
882 | } | 871 | } |
883 | 872 | ||
884 | static struct snd_soc_codec_driver sn95031_codec = { | 873 | static struct snd_soc_codec_driver sn95031_codec = { |
885 | .probe = sn95031_codec_probe, | 874 | .probe = sn95031_codec_probe, |
886 | .remove = sn95031_codec_remove, | ||
887 | .set_bias_level = sn95031_set_vaud_bias, | 875 | .set_bias_level = sn95031_set_vaud_bias, |
888 | .idle_bias_off = true, | 876 | .idle_bias_off = true, |
877 | |||
878 | .controls = sn95031_snd_controls, | ||
879 | .num_controls = ARRAY_SIZE(sn95031_snd_controls), | ||
889 | .dapm_widgets = sn95031_dapm_widgets, | 880 | .dapm_widgets = sn95031_dapm_widgets, |
890 | .num_dapm_widgets = ARRAY_SIZE(sn95031_dapm_widgets), | 881 | .num_dapm_widgets = ARRAY_SIZE(sn95031_dapm_widgets), |
891 | .dapm_routes = sn95031_audio_map, | 882 | .dapm_routes = sn95031_audio_map, |
diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index 4b5c17f8507e..a984485108cd 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c | |||
@@ -69,6 +69,22 @@ | |||
69 | #define SSM4567_DAC_FS_64000_96000 0x3 | 69 | #define SSM4567_DAC_FS_64000_96000 0x3 |
70 | #define SSM4567_DAC_FS_128000_192000 0x4 | 70 | #define SSM4567_DAC_FS_128000_192000 0x4 |
71 | 71 | ||
72 | /* SAI_CTRL_1 */ | ||
73 | #define SSM4567_SAI_CTRL_1_BCLK BIT(6) | ||
74 | #define SSM4567_SAI_CTRL_1_TDM_BLCKS_MASK (0x3 << 4) | ||
75 | #define SSM4567_SAI_CTRL_1_TDM_BLCKS_32 (0x0 << 4) | ||
76 | #define SSM4567_SAI_CTRL_1_TDM_BLCKS_48 (0x1 << 4) | ||
77 | #define SSM4567_SAI_CTRL_1_TDM_BLCKS_64 (0x2 << 4) | ||
78 | #define SSM4567_SAI_CTRL_1_FSYNC BIT(3) | ||
79 | #define SSM4567_SAI_CTRL_1_LJ BIT(2) | ||
80 | #define SSM4567_SAI_CTRL_1_TDM BIT(1) | ||
81 | #define SSM4567_SAI_CTRL_1_PDM BIT(0) | ||
82 | |||
83 | /* SAI_CTRL_2 */ | ||
84 | #define SSM4567_SAI_CTRL_2_AUTO_SLOT BIT(3) | ||
85 | #define SSM4567_SAI_CTRL_2_TDM_SLOT_MASK 0x7 | ||
86 | #define SSM4567_SAI_CTRL_2_TDM_SLOT(x) (x) | ||
87 | |||
72 | struct ssm4567 { | 88 | struct ssm4567 { |
73 | struct regmap *regmap; | 89 | struct regmap *regmap; |
74 | }; | 90 | }; |
@@ -145,15 +161,24 @@ static const struct snd_kcontrol_new ssm4567_snd_controls[] = { | |||
145 | SOC_SINGLE_TLV("Master Playback Volume", SSM4567_REG_DAC_VOLUME, 0, | 161 | SOC_SINGLE_TLV("Master Playback Volume", SSM4567_REG_DAC_VOLUME, 0, |
146 | 0xff, 1, ssm4567_vol_tlv), | 162 | 0xff, 1, ssm4567_vol_tlv), |
147 | SOC_SINGLE("DAC Low Power Mode Switch", SSM4567_REG_DAC_CTRL, 4, 1, 0), | 163 | SOC_SINGLE("DAC Low Power Mode Switch", SSM4567_REG_DAC_CTRL, 4, 1, 0), |
164 | SOC_SINGLE("DAC High Pass Filter Switch", SSM4567_REG_DAC_CTRL, | ||
165 | 5, 1, 0), | ||
148 | }; | 166 | }; |
149 | 167 | ||
168 | static const struct snd_kcontrol_new ssm4567_amplifier_boost_control = | ||
169 | SOC_DAPM_SINGLE("Switch", SSM4567_REG_POWER_CTRL, 1, 1, 1); | ||
170 | |||
150 | static const struct snd_soc_dapm_widget ssm4567_dapm_widgets[] = { | 171 | static const struct snd_soc_dapm_widget ssm4567_dapm_widgets[] = { |
151 | SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM4567_REG_POWER_CTRL, 2, 1), | 172 | SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM4567_REG_POWER_CTRL, 2, 1), |
173 | SND_SOC_DAPM_SWITCH("Amplifier Boost", SSM4567_REG_POWER_CTRL, 3, 1, | ||
174 | &ssm4567_amplifier_boost_control), | ||
152 | 175 | ||
153 | SND_SOC_DAPM_OUTPUT("OUT"), | 176 | SND_SOC_DAPM_OUTPUT("OUT"), |
154 | }; | 177 | }; |
155 | 178 | ||
156 | static const struct snd_soc_dapm_route ssm4567_routes[] = { | 179 | static const struct snd_soc_dapm_route ssm4567_routes[] = { |
180 | { "OUT", NULL, "Amplifier Boost" }, | ||
181 | { "Amplifier Boost", "Switch", "DAC" }, | ||
157 | { "OUT", NULL, "DAC" }, | 182 | { "OUT", NULL, "DAC" }, |
158 | }; | 183 | }; |
159 | 184 | ||
@@ -192,6 +217,107 @@ static int ssm4567_mute(struct snd_soc_dai *dai, int mute) | |||
192 | SSM4567_DAC_MUTE, val); | 217 | SSM4567_DAC_MUTE, val); |
193 | } | 218 | } |
194 | 219 | ||
220 | static int ssm4567_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
221 | unsigned int rx_mask, int slots, int width) | ||
222 | { | ||
223 | struct ssm4567 *ssm4567 = snd_soc_dai_get_drvdata(dai); | ||
224 | unsigned int blcks; | ||
225 | int slot; | ||
226 | int ret; | ||
227 | |||
228 | if (tx_mask == 0) | ||
229 | return -EINVAL; | ||
230 | |||
231 | if (rx_mask && rx_mask != tx_mask) | ||
232 | return -EINVAL; | ||
233 | |||
234 | slot = __ffs(tx_mask); | ||
235 | if (tx_mask != BIT(slot)) | ||
236 | return -EINVAL; | ||
237 | |||
238 | switch (width) { | ||
239 | case 32: | ||
240 | blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_32; | ||
241 | break; | ||
242 | case 48: | ||
243 | blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_48; | ||
244 | break; | ||
245 | case 64: | ||
246 | blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_64; | ||
247 | break; | ||
248 | default: | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | ret = regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_2, | ||
253 | SSM4567_SAI_CTRL_2_AUTO_SLOT | SSM4567_SAI_CTRL_2_TDM_SLOT_MASK, | ||
254 | SSM4567_SAI_CTRL_2_TDM_SLOT(slot)); | ||
255 | if (ret) | ||
256 | return ret; | ||
257 | |||
258 | return regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1, | ||
259 | SSM4567_SAI_CTRL_1_TDM_BLCKS_MASK, blcks); | ||
260 | } | ||
261 | |||
262 | static int ssm4567_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
263 | { | ||
264 | struct ssm4567 *ssm4567 = snd_soc_dai_get_drvdata(dai); | ||
265 | unsigned int ctrl1 = 0; | ||
266 | bool invert_fclk; | ||
267 | |||
268 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
269 | case SND_SOC_DAIFMT_CBS_CFS: | ||
270 | break; | ||
271 | default: | ||
272 | return -EINVAL; | ||
273 | } | ||
274 | |||
275 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
276 | case SND_SOC_DAIFMT_NB_NF: | ||
277 | invert_fclk = false; | ||
278 | break; | ||
279 | case SND_SOC_DAIFMT_IB_NF: | ||
280 | ctrl1 |= SSM4567_SAI_CTRL_1_BCLK; | ||
281 | invert_fclk = false; | ||
282 | break; | ||
283 | case SND_SOC_DAIFMT_NB_IF: | ||
284 | ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC; | ||
285 | invert_fclk = true; | ||
286 | break; | ||
287 | case SND_SOC_DAIFMT_IB_IF: | ||
288 | ctrl1 |= SSM4567_SAI_CTRL_1_BCLK; | ||
289 | invert_fclk = true; | ||
290 | break; | ||
291 | default: | ||
292 | return -EINVAL; | ||
293 | } | ||
294 | |||
295 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
296 | case SND_SOC_DAIFMT_I2S: | ||
297 | break; | ||
298 | case SND_SOC_DAIFMT_LEFT_J: | ||
299 | ctrl1 |= SSM4567_SAI_CTRL_1_LJ; | ||
300 | invert_fclk = !invert_fclk; | ||
301 | break; | ||
302 | case SND_SOC_DAIFMT_DSP_A: | ||
303 | ctrl1 |= SSM4567_SAI_CTRL_1_TDM; | ||
304 | break; | ||
305 | case SND_SOC_DAIFMT_DSP_B: | ||
306 | ctrl1 |= SSM4567_SAI_CTRL_1_TDM | SSM4567_SAI_CTRL_1_LJ; | ||
307 | break; | ||
308 | case SND_SOC_DAIFMT_PDM: | ||
309 | ctrl1 |= SSM4567_SAI_CTRL_1_PDM; | ||
310 | break; | ||
311 | default: | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | if (invert_fclk) | ||
316 | ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC; | ||
317 | |||
318 | return regmap_write(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1, ctrl1); | ||
319 | } | ||
320 | |||
195 | static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable) | 321 | static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable) |
196 | { | 322 | { |
197 | int ret = 0; | 323 | int ret = 0; |
@@ -246,6 +372,8 @@ static int ssm4567_set_bias_level(struct snd_soc_codec *codec, | |||
246 | static const struct snd_soc_dai_ops ssm4567_dai_ops = { | 372 | static const struct snd_soc_dai_ops ssm4567_dai_ops = { |
247 | .hw_params = ssm4567_hw_params, | 373 | .hw_params = ssm4567_hw_params, |
248 | .digital_mute = ssm4567_mute, | 374 | .digital_mute = ssm4567_mute, |
375 | .set_fmt = ssm4567_set_dai_fmt, | ||
376 | .set_tdm_slot = ssm4567_set_tdm_slot, | ||
249 | }; | 377 | }; |
250 | 378 | ||
251 | static struct snd_soc_dai_driver ssm4567_dai = { | 379 | static struct snd_soc_dai_driver ssm4567_dai = { |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 48740855566d..7e18200dd6a9 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -833,23 +833,6 @@ static struct snd_soc_dai_driver sta32x_dai = { | |||
833 | .ops = &sta32x_dai_ops, | 833 | .ops = &sta32x_dai_ops, |
834 | }; | 834 | }; |
835 | 835 | ||
836 | #ifdef CONFIG_PM | ||
837 | static int sta32x_suspend(struct snd_soc_codec *codec) | ||
838 | { | ||
839 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
840 | return 0; | ||
841 | } | ||
842 | |||
843 | static int sta32x_resume(struct snd_soc_codec *codec) | ||
844 | { | ||
845 | sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
846 | return 0; | ||
847 | } | ||
848 | #else | ||
849 | #define sta32x_suspend NULL | ||
850 | #define sta32x_resume NULL | ||
851 | #endif | ||
852 | |||
853 | static int sta32x_probe(struct snd_soc_codec *codec) | 836 | static int sta32x_probe(struct snd_soc_codec *codec) |
854 | { | 837 | { |
855 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | 838 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); |
@@ -936,7 +919,6 @@ static int sta32x_remove(struct snd_soc_codec *codec) | |||
936 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | 919 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); |
937 | 920 | ||
938 | sta32x_watchdog_stop(sta32x); | 921 | sta32x_watchdog_stop(sta32x); |
939 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
940 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | 922 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); |
941 | 923 | ||
942 | return 0; | 924 | return 0; |
@@ -955,9 +937,8 @@ static bool sta32x_reg_is_volatile(struct device *dev, unsigned int reg) | |||
955 | static const struct snd_soc_codec_driver sta32x_codec = { | 937 | static const struct snd_soc_codec_driver sta32x_codec = { |
956 | .probe = sta32x_probe, | 938 | .probe = sta32x_probe, |
957 | .remove = sta32x_remove, | 939 | .remove = sta32x_remove, |
958 | .suspend = sta32x_suspend, | ||
959 | .resume = sta32x_resume, | ||
960 | .set_bias_level = sta32x_set_bias_level, | 940 | .set_bias_level = sta32x_set_bias_level, |
941 | .suspend_bias_off = true, | ||
961 | .controls = sta32x_snd_controls, | 942 | .controls = sta32x_snd_controls, |
962 | .num_controls = ARRAY_SIZE(sta32x_snd_controls), | 943 | .num_controls = ARRAY_SIZE(sta32x_snd_controls), |
963 | .dapm_widgets = sta32x_dapm_widgets, | 944 | .dapm_widgets = sta32x_dapm_widgets, |
diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index cc97dd52aa9c..bda2ee18769e 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c | |||
@@ -912,23 +912,6 @@ static struct snd_soc_dai_driver sta350_dai = { | |||
912 | .ops = &sta350_dai_ops, | 912 | .ops = &sta350_dai_ops, |
913 | }; | 913 | }; |
914 | 914 | ||
915 | #ifdef CONFIG_PM | ||
916 | static int sta350_suspend(struct snd_soc_codec *codec) | ||
917 | { | ||
918 | sta350_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | static int sta350_resume(struct snd_soc_codec *codec) | ||
923 | { | ||
924 | sta350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
925 | return 0; | ||
926 | } | ||
927 | #else | ||
928 | #define sta350_suspend NULL | ||
929 | #define sta350_resume NULL | ||
930 | #endif | ||
931 | |||
932 | static int sta350_probe(struct snd_soc_codec *codec) | 915 | static int sta350_probe(struct snd_soc_codec *codec) |
933 | { | 916 | { |
934 | struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec); | 917 | struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec); |
@@ -1065,7 +1048,6 @@ static int sta350_remove(struct snd_soc_codec *codec) | |||
1065 | { | 1048 | { |
1066 | struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec); | 1049 | struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec); |
1067 | 1050 | ||
1068 | sta350_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1069 | regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies); | 1051 | regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies); |
1070 | 1052 | ||
1071 | return 0; | 1053 | return 0; |
@@ -1074,9 +1056,8 @@ static int sta350_remove(struct snd_soc_codec *codec) | |||
1074 | static const struct snd_soc_codec_driver sta350_codec = { | 1056 | static const struct snd_soc_codec_driver sta350_codec = { |
1075 | .probe = sta350_probe, | 1057 | .probe = sta350_probe, |
1076 | .remove = sta350_remove, | 1058 | .remove = sta350_remove, |
1077 | .suspend = sta350_suspend, | ||
1078 | .resume = sta350_resume, | ||
1079 | .set_bias_level = sta350_set_bias_level, | 1059 | .set_bias_level = sta350_set_bias_level, |
1060 | .suspend_bias_off = true, | ||
1080 | .controls = sta350_snd_controls, | 1061 | .controls = sta350_snd_controls, |
1081 | .num_controls = ARRAY_SIZE(sta350_snd_controls), | 1062 | .num_controls = ARRAY_SIZE(sta350_snd_controls), |
1082 | .dapm_widgets = sta350_dapm_widgets, | 1063 | .dapm_widgets = sta350_dapm_widgets, |
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 89c748dd3d6e..b0f436d10125 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c | |||
@@ -319,41 +319,10 @@ static struct snd_soc_dai_driver sta529_dai = { | |||
319 | .ops = &sta529_dai_ops, | 319 | .ops = &sta529_dai_ops, |
320 | }; | 320 | }; |
321 | 321 | ||
322 | static int sta529_probe(struct snd_soc_codec *codec) | ||
323 | { | ||
324 | sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | /* power down chip */ | ||
330 | static int sta529_remove(struct snd_soc_codec *codec) | ||
331 | { | ||
332 | sta529_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static int sta529_suspend(struct snd_soc_codec *codec) | ||
338 | { | ||
339 | sta529_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static int sta529_resume(struct snd_soc_codec *codec) | ||
345 | { | ||
346 | sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static const struct snd_soc_codec_driver sta529_codec_driver = { | 322 | static const struct snd_soc_codec_driver sta529_codec_driver = { |
352 | .probe = sta529_probe, | ||
353 | .remove = sta529_remove, | ||
354 | .set_bias_level = sta529_set_bias_level, | 323 | .set_bias_level = sta529_set_bias_level, |
355 | .suspend = sta529_suspend, | 324 | .suspend_bias_off = true, |
356 | .resume = sta529_resume, | 325 | |
357 | .controls = sta529_snd_controls, | 326 | .controls = sta529_snd_controls, |
358 | .num_controls = ARRAY_SIZE(sta529_snd_controls), | 327 | .num_controls = ARRAY_SIZE(sta529_snd_controls), |
359 | }; | 328 | }; |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 53b810d23fea..dbff0c89be48 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -139,18 +139,19 @@ static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = { | |||
139 | static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 139 | static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
140 | unsigned int val) | 140 | unsigned int val) |
141 | { | 141 | { |
142 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
142 | u16 *cache = codec->reg_cache; | 143 | u16 *cache = codec->reg_cache; |
143 | 144 | ||
144 | if (reg > AC97_STAC_PAGE0) { | 145 | if (reg > AC97_STAC_PAGE0) { |
145 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 146 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
146 | soc_ac97_ops->write(codec->ac97, reg, val); | 147 | soc_ac97_ops->write(ac97, reg, val); |
147 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 148 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
148 | return 0; | 149 | return 0; |
149 | } | 150 | } |
150 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) | 151 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) |
151 | return -EIO; | 152 | return -EIO; |
152 | 153 | ||
153 | soc_ac97_ops->write(codec->ac97, reg, val); | 154 | soc_ac97_ops->write(ac97, reg, val); |
154 | cache[reg / 2] = val; | 155 | cache[reg / 2] = val; |
155 | return 0; | 156 | return 0; |
156 | } | 157 | } |
@@ -158,11 +159,12 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
158 | static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | 159 | static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, |
159 | unsigned int reg) | 160 | unsigned int reg) |
160 | { | 161 | { |
162 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
161 | u16 val = 0, *cache = codec->reg_cache; | 163 | u16 val = 0, *cache = codec->reg_cache; |
162 | 164 | ||
163 | if (reg > AC97_STAC_PAGE0) { | 165 | if (reg > AC97_STAC_PAGE0) { |
164 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
165 | val = soc_ac97_ops->read(codec->ac97, reg - AC97_STAC_PAGE0); | 167 | val = soc_ac97_ops->read(ac97, reg - AC97_STAC_PAGE0); |
166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 168 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
167 | return val; | 169 | return val; |
168 | } | 170 | } |
@@ -173,7 +175,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | |||
173 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || | 175 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || |
174 | reg == AC97_VENDOR_ID2) { | 176 | reg == AC97_VENDOR_ID2) { |
175 | 177 | ||
176 | val = soc_ac97_ops->read(codec->ac97, reg); | 178 | val = soc_ac97_ops->read(ac97, reg); |
177 | return val; | 179 | return val; |
178 | } | 180 | } |
179 | return cache[reg / 2]; | 181 | return cache[reg / 2]; |
@@ -240,45 +242,41 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec, | |||
240 | 242 | ||
241 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) | 243 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) |
242 | { | 244 | { |
245 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
246 | |||
243 | if (try_warm && soc_ac97_ops->warm_reset) { | 247 | if (try_warm && soc_ac97_ops->warm_reset) { |
244 | soc_ac97_ops->warm_reset(codec->ac97); | 248 | soc_ac97_ops->warm_reset(ac97); |
245 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) | 249 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) |
246 | return 1; | 250 | return 1; |
247 | } | 251 | } |
248 | 252 | ||
249 | soc_ac97_ops->reset(codec->ac97); | 253 | soc_ac97_ops->reset(ac97); |
250 | if (soc_ac97_ops->warm_reset) | 254 | if (soc_ac97_ops->warm_reset) |
251 | soc_ac97_ops->warm_reset(codec->ac97); | 255 | soc_ac97_ops->warm_reset(ac97); |
252 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) | 256 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) |
253 | return -EIO; | 257 | return -EIO; |
254 | return 0; | 258 | return 0; |
255 | } | 259 | } |
256 | 260 | ||
257 | static int stac9766_codec_suspend(struct snd_soc_codec *codec) | ||
258 | { | ||
259 | stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static int stac9766_codec_resume(struct snd_soc_codec *codec) | 261 | static int stac9766_codec_resume(struct snd_soc_codec *codec) |
264 | { | 262 | { |
263 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
265 | u16 id, reset; | 264 | u16 id, reset; |
266 | 265 | ||
267 | reset = 0; | 266 | reset = 0; |
268 | /* give the codec an AC97 warm reset to start the link */ | 267 | /* give the codec an AC97 warm reset to start the link */ |
269 | reset: | 268 | reset: |
270 | if (reset > 5) { | 269 | if (reset > 5) { |
271 | printk(KERN_ERR "stac9766 failed to resume"); | 270 | dev_err(codec->dev, "Failed to resume\n"); |
272 | return -EIO; | 271 | return -EIO; |
273 | } | 272 | } |
274 | codec->ac97->bus->ops->warm_reset(codec->ac97); | 273 | ac97->bus->ops->warm_reset(ac97); |
275 | id = soc_ac97_ops->read(codec->ac97, AC97_VENDOR_ID2); | 274 | id = soc_ac97_ops->read(ac97, AC97_VENDOR_ID2); |
276 | if (id != 0x4c13) { | 275 | if (id != 0x4c13) { |
277 | stac9766_reset(codec, 0); | 276 | stac9766_reset(codec, 0); |
278 | reset++; | 277 | reset++; |
279 | goto reset; | 278 | goto reset; |
280 | } | 279 | } |
281 | stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
282 | 280 | ||
283 | return 0; | 281 | return 0; |
284 | } | 282 | } |
@@ -294,7 +292,6 @@ static const struct snd_soc_dai_ops stac9766_dai_ops_digital = { | |||
294 | static struct snd_soc_dai_driver stac9766_dai[] = { | 292 | static struct snd_soc_dai_driver stac9766_dai[] = { |
295 | { | 293 | { |
296 | .name = "stac9766-hifi-analog", | 294 | .name = "stac9766-hifi-analog", |
297 | .ac97_control = 1, | ||
298 | 295 | ||
299 | /* stream cababilities */ | 296 | /* stream cababilities */ |
300 | .playback = { | 297 | .playback = { |
@@ -316,7 +313,6 @@ static struct snd_soc_dai_driver stac9766_dai[] = { | |||
316 | }, | 313 | }, |
317 | { | 314 | { |
318 | .name = "stac9766-hifi-IEC958", | 315 | .name = "stac9766-hifi-IEC958", |
319 | .ac97_control = 1, | ||
320 | 316 | ||
321 | /* stream cababilities */ | 317 | /* stream cababilities */ |
322 | .playback = { | 318 | .playback = { |
@@ -334,46 +330,48 @@ static struct snd_soc_dai_driver stac9766_dai[] = { | |||
334 | 330 | ||
335 | static int stac9766_codec_probe(struct snd_soc_codec *codec) | 331 | static int stac9766_codec_probe(struct snd_soc_codec *codec) |
336 | { | 332 | { |
333 | struct snd_ac97 *ac97; | ||
337 | int ret = 0; | 334 | int ret = 0; |
338 | 335 | ||
339 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 336 | ac97 = snd_soc_new_ac97_codec(codec); |
340 | if (ret < 0) | 337 | if (IS_ERR(ac97)) |
341 | goto codec_err; | 338 | return PTR_ERR(ac97); |
339 | |||
340 | snd_soc_codec_set_drvdata(codec, ac97); | ||
342 | 341 | ||
343 | /* do a cold reset for the controller and then try | 342 | /* do a cold reset for the controller and then try |
344 | * a warm reset followed by an optional cold reset for codec */ | 343 | * a warm reset followed by an optional cold reset for codec */ |
345 | stac9766_reset(codec, 0); | 344 | stac9766_reset(codec, 0); |
346 | ret = stac9766_reset(codec, 1); | 345 | ret = stac9766_reset(codec, 1); |
347 | if (ret < 0) { | 346 | if (ret < 0) { |
348 | printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n"); | 347 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); |
349 | goto codec_err; | 348 | goto codec_err; |
350 | } | 349 | } |
351 | 350 | ||
352 | stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
353 | |||
354 | snd_soc_add_codec_controls(codec, stac9766_snd_ac97_controls, | ||
355 | ARRAY_SIZE(stac9766_snd_ac97_controls)); | ||
356 | |||
357 | return 0; | 351 | return 0; |
358 | 352 | ||
359 | codec_err: | 353 | codec_err: |
360 | snd_soc_free_ac97_codec(codec); | 354 | snd_soc_free_ac97_codec(ac97); |
361 | return ret; | 355 | return ret; |
362 | } | 356 | } |
363 | 357 | ||
364 | static int stac9766_codec_remove(struct snd_soc_codec *codec) | 358 | static int stac9766_codec_remove(struct snd_soc_codec *codec) |
365 | { | 359 | { |
366 | snd_soc_free_ac97_codec(codec); | 360 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
361 | |||
362 | snd_soc_free_ac97_codec(ac97); | ||
367 | return 0; | 363 | return 0; |
368 | } | 364 | } |
369 | 365 | ||
370 | static struct snd_soc_codec_driver soc_codec_dev_stac9766 = { | 366 | static struct snd_soc_codec_driver soc_codec_dev_stac9766 = { |
367 | .controls = stac9766_snd_ac97_controls, | ||
368 | .num_controls = ARRAY_SIZE(stac9766_snd_ac97_controls), | ||
371 | .write = stac9766_ac97_write, | 369 | .write = stac9766_ac97_write, |
372 | .read = stac9766_ac97_read, | 370 | .read = stac9766_ac97_read, |
373 | .set_bias_level = stac9766_set_bias_level, | 371 | .set_bias_level = stac9766_set_bias_level, |
372 | .suspend_bias_off = true, | ||
374 | .probe = stac9766_codec_probe, | 373 | .probe = stac9766_codec_probe, |
375 | .remove = stac9766_codec_remove, | 374 | .remove = stac9766_codec_remove, |
376 | .suspend = stac9766_codec_suspend, | ||
377 | .resume = stac9766_codec_resume, | 375 | .resume = stac9766_codec_resume, |
378 | .reg_cache_size = ARRAY_SIZE(stac9766_reg), | 376 | .reg_cache_size = ARRAY_SIZE(stac9766_reg), |
379 | .reg_word_size = sizeof(u16), | 377 | .reg_word_size = sizeof(u16), |
diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index f039dc825971..b505212019e2 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c | |||
@@ -345,7 +345,6 @@ static const struct reg_default tas2552_init_regs[] = { | |||
345 | static int tas2552_codec_probe(struct snd_soc_codec *codec) | 345 | static int tas2552_codec_probe(struct snd_soc_codec *codec) |
346 | { | 346 | { |
347 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); | 347 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); |
348 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
349 | int ret; | 348 | int ret; |
350 | 349 | ||
351 | tas2552->codec = codec; | 350 | tas2552->codec = codec; |
@@ -390,11 +389,6 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec) | |||
390 | snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN | | 389 | snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN | |
391 | TAS2552_APT_EN | TAS2552_LIM_EN); | 390 | TAS2552_APT_EN | TAS2552_LIM_EN); |
392 | 391 | ||
393 | snd_soc_dapm_new_controls(dapm, tas2552_dapm_widgets, | ||
394 | ARRAY_SIZE(tas2552_dapm_widgets)); | ||
395 | snd_soc_dapm_add_routes(dapm, tas2552_audio_map, | ||
396 | ARRAY_SIZE(tas2552_audio_map)); | ||
397 | |||
398 | return 0; | 392 | return 0; |
399 | 393 | ||
400 | patch_fail: | 394 | patch_fail: |
@@ -462,6 +456,10 @@ static struct snd_soc_codec_driver soc_codec_dev_tas2552 = { | |||
462 | .resume = tas2552_resume, | 456 | .resume = tas2552_resume, |
463 | .controls = tas2552_snd_controls, | 457 | .controls = tas2552_snd_controls, |
464 | .num_controls = ARRAY_SIZE(tas2552_snd_controls), | 458 | .num_controls = ARRAY_SIZE(tas2552_snd_controls), |
459 | .dapm_widgets = tas2552_dapm_widgets, | ||
460 | .num_dapm_widgets = ARRAY_SIZE(tas2552_dapm_widgets), | ||
461 | .dapm_routes = tas2552_audio_map, | ||
462 | .num_dapm_routes = ARRAY_SIZE(tas2552_audio_map), | ||
465 | }; | 463 | }; |
466 | 464 | ||
467 | static const struct regmap_config tas2552_regmap_config = { | 465 | static const struct regmap_config tas2552_regmap_config = { |
diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c new file mode 100644 index 000000000000..16f1b71edb55 --- /dev/null +++ b/sound/soc/codecs/tfa9879.c | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | * tfa9879.c -- driver for NXP Semiconductors TFA9879 | ||
3 | * | ||
4 | * Copyright (C) 2014 Axentia Technologies AB | ||
5 | * Author: Peter Rosin <peda@axentia.se> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/regmap.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <sound/tlv.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | |||
22 | #include "tfa9879.h" | ||
23 | |||
24 | struct tfa9879_priv { | ||
25 | struct regmap *regmap; | ||
26 | int lsb_justified; | ||
27 | }; | ||
28 | |||
29 | static int tfa9879_hw_params(struct snd_pcm_substream *substream, | ||
30 | struct snd_pcm_hw_params *params, | ||
31 | struct snd_soc_dai *dai) | ||
32 | { | ||
33 | struct snd_soc_codec *codec = dai->codec; | ||
34 | struct tfa9879_priv *tfa9879 = snd_soc_codec_get_drvdata(codec); | ||
35 | int fs; | ||
36 | int i2s_set = 0; | ||
37 | |||
38 | switch (params_rate(params)) { | ||
39 | case 8000: | ||
40 | fs = TFA9879_I2S_FS_8000; | ||
41 | break; | ||
42 | case 11025: | ||
43 | fs = TFA9879_I2S_FS_11025; | ||
44 | break; | ||
45 | case 12000: | ||
46 | fs = TFA9879_I2S_FS_12000; | ||
47 | break; | ||
48 | case 16000: | ||
49 | fs = TFA9879_I2S_FS_16000; | ||
50 | break; | ||
51 | case 22050: | ||
52 | fs = TFA9879_I2S_FS_22050; | ||
53 | break; | ||
54 | case 24000: | ||
55 | fs = TFA9879_I2S_FS_24000; | ||
56 | break; | ||
57 | case 32000: | ||
58 | fs = TFA9879_I2S_FS_32000; | ||
59 | break; | ||
60 | case 44100: | ||
61 | fs = TFA9879_I2S_FS_44100; | ||
62 | break; | ||
63 | case 48000: | ||
64 | fs = TFA9879_I2S_FS_48000; | ||
65 | break; | ||
66 | case 64000: | ||
67 | fs = TFA9879_I2S_FS_64000; | ||
68 | break; | ||
69 | case 88200: | ||
70 | fs = TFA9879_I2S_FS_88200; | ||
71 | break; | ||
72 | case 96000: | ||
73 | fs = TFA9879_I2S_FS_96000; | ||
74 | break; | ||
75 | default: | ||
76 | return -EINVAL; | ||
77 | } | ||
78 | |||
79 | switch (params_width(params)) { | ||
80 | case 16: | ||
81 | i2s_set = TFA9879_I2S_SET_LSB_J_16; | ||
82 | break; | ||
83 | case 24: | ||
84 | i2s_set = TFA9879_I2S_SET_LSB_J_24; | ||
85 | break; | ||
86 | default: | ||
87 | return -EINVAL; | ||
88 | } | ||
89 | |||
90 | if (tfa9879->lsb_justified) | ||
91 | snd_soc_update_bits(codec, TFA9879_SERIAL_INTERFACE_1, | ||
92 | TFA9879_I2S_SET_MASK, | ||
93 | i2s_set << TFA9879_I2S_SET_SHIFT); | ||
94 | |||
95 | snd_soc_update_bits(codec, TFA9879_SERIAL_INTERFACE_1, | ||
96 | TFA9879_I2S_FS_MASK, | ||
97 | fs << TFA9879_I2S_FS_SHIFT); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int tfa9879_digital_mute(struct snd_soc_dai *dai, int mute) | ||
102 | { | ||
103 | struct snd_soc_codec *codec = dai->codec; | ||
104 | |||
105 | snd_soc_update_bits(codec, TFA9879_MISC_CONTROL, | ||
106 | TFA9879_S_MUTE_MASK, | ||
107 | !!mute << TFA9879_S_MUTE_SHIFT); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int tfa9879_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
113 | { | ||
114 | struct snd_soc_codec *codec = dai->codec; | ||
115 | struct tfa9879_priv *tfa9879 = snd_soc_codec_get_drvdata(codec); | ||
116 | int i2s_set; | ||
117 | int sck_pol; | ||
118 | |||
119 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
120 | case SND_SOC_DAIFMT_CBS_CFS: | ||
121 | break; | ||
122 | default: | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | |||
126 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
127 | case SND_SOC_DAIFMT_NB_NF: | ||
128 | sck_pol = TFA9879_SCK_POL_NORMAL; | ||
129 | break; | ||
130 | case SND_SOC_DAIFMT_IB_NF: | ||
131 | sck_pol = TFA9879_SCK_POL_INVERSE; | ||
132 | break; | ||
133 | default: | ||
134 | return -EINVAL; | ||
135 | } | ||
136 | |||
137 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
138 | case SND_SOC_DAIFMT_I2S: | ||
139 | tfa9879->lsb_justified = 0; | ||
140 | i2s_set = TFA9879_I2S_SET_I2S_24; | ||
141 | break; | ||
142 | case SND_SOC_DAIFMT_LEFT_J: | ||
143 | tfa9879->lsb_justified = 0; | ||
144 | i2s_set = TFA9879_I2S_SET_MSB_J_24; | ||
145 | break; | ||
146 | case SND_SOC_DAIFMT_RIGHT_J: | ||
147 | tfa9879->lsb_justified = 1; | ||
148 | i2s_set = TFA9879_I2S_SET_LSB_J_24; | ||
149 | break; | ||
150 | default: | ||
151 | return -EINVAL; | ||
152 | } | ||
153 | |||
154 | snd_soc_update_bits(codec, TFA9879_SERIAL_INTERFACE_1, | ||
155 | TFA9879_SCK_POL_MASK, | ||
156 | sck_pol << TFA9879_SCK_POL_SHIFT); | ||
157 | snd_soc_update_bits(codec, TFA9879_SERIAL_INTERFACE_1, | ||
158 | TFA9879_I2S_SET_MASK, | ||
159 | i2s_set << TFA9879_I2S_SET_SHIFT); | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static struct reg_default tfa9879_regs[] = { | ||
164 | { TFA9879_DEVICE_CONTROL, 0x0000 }, /* 0x00 */ | ||
165 | { TFA9879_SERIAL_INTERFACE_1, 0x0a18 }, /* 0x01 */ | ||
166 | { TFA9879_PCM_IOM2_FORMAT_1, 0x0007 }, /* 0x02 */ | ||
167 | { TFA9879_SERIAL_INTERFACE_2, 0x0a18 }, /* 0x03 */ | ||
168 | { TFA9879_PCM_IOM2_FORMAT_2, 0x0007 }, /* 0x04 */ | ||
169 | { TFA9879_EQUALIZER_A1, 0x59dd }, /* 0x05 */ | ||
170 | { TFA9879_EQUALIZER_A2, 0xc63e }, /* 0x06 */ | ||
171 | { TFA9879_EQUALIZER_B1, 0x651a }, /* 0x07 */ | ||
172 | { TFA9879_EQUALIZER_B2, 0xe53e }, /* 0x08 */ | ||
173 | { TFA9879_EQUALIZER_C1, 0x4616 }, /* 0x09 */ | ||
174 | { TFA9879_EQUALIZER_C2, 0xd33e }, /* 0x0a */ | ||
175 | { TFA9879_EQUALIZER_D1, 0x4df3 }, /* 0x0b */ | ||
176 | { TFA9879_EQUALIZER_D2, 0xea3e }, /* 0x0c */ | ||
177 | { TFA9879_EQUALIZER_E1, 0x5ee0 }, /* 0x0d */ | ||
178 | { TFA9879_EQUALIZER_E2, 0xf93e }, /* 0x0e */ | ||
179 | { TFA9879_BYPASS_CONTROL, 0x0093 }, /* 0x0f */ | ||
180 | { TFA9879_DYNAMIC_RANGE_COMPR, 0x92ba }, /* 0x10 */ | ||
181 | { TFA9879_BASS_TREBLE, 0x12a5 }, /* 0x11 */ | ||
182 | { TFA9879_HIGH_PASS_FILTER, 0x0004 }, /* 0x12 */ | ||
183 | { TFA9879_VOLUME_CONTROL, 0x10bd }, /* 0x13 */ | ||
184 | { TFA9879_MISC_CONTROL, 0x0000 }, /* 0x14 */ | ||
185 | }; | ||
186 | |||
187 | static bool tfa9879_volatile_reg(struct device *dev, unsigned int reg) | ||
188 | { | ||
189 | return reg == TFA9879_MISC_STATUS; | ||
190 | } | ||
191 | |||
192 | static const DECLARE_TLV_DB_SCALE(volume_tlv, -7050, 50, 1); | ||
193 | static const DECLARE_TLV_DB_SCALE(tb_gain_tlv, -1800, 200, 0); | ||
194 | static const char * const tb_freq_text[] = { | ||
195 | "Low", "Mid", "High" | ||
196 | }; | ||
197 | static const struct soc_enum treble_freq_enum = | ||
198 | SOC_ENUM_SINGLE(TFA9879_BASS_TREBLE, TFA9879_F_TRBLE_SHIFT, | ||
199 | ARRAY_SIZE(tb_freq_text), tb_freq_text); | ||
200 | static const struct soc_enum bass_freq_enum = | ||
201 | SOC_ENUM_SINGLE(TFA9879_BASS_TREBLE, TFA9879_F_BASS_SHIFT, | ||
202 | ARRAY_SIZE(tb_freq_text), tb_freq_text); | ||
203 | |||
204 | static const struct snd_kcontrol_new tfa9879_controls[] = { | ||
205 | SOC_SINGLE_TLV("PCM Playback Volume", TFA9879_VOLUME_CONTROL, | ||
206 | TFA9879_VOL_SHIFT, 0xbd, 1, volume_tlv), | ||
207 | SOC_SINGLE_TLV("Treble Volume", TFA9879_BASS_TREBLE, | ||
208 | TFA9879_G_TRBLE_SHIFT, 18, 0, tb_gain_tlv), | ||
209 | SOC_SINGLE_TLV("Bass Volume", TFA9879_BASS_TREBLE, | ||
210 | TFA9879_G_BASS_SHIFT, 18, 0, tb_gain_tlv), | ||
211 | SOC_ENUM("Treble Corner Freq", treble_freq_enum), | ||
212 | SOC_ENUM("Bass Corner Freq", bass_freq_enum), | ||
213 | }; | ||
214 | |||
215 | static const struct snd_soc_dapm_widget tfa9879_dapm_widgets[] = { | ||
216 | SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0), | ||
217 | SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0), | ||
218 | SND_SOC_DAPM_DAC("DAC", NULL, TFA9879_DEVICE_CONTROL, TFA9879_OPMODE_SHIFT, 0), | ||
219 | SND_SOC_DAPM_OUTPUT("LINEOUT"), | ||
220 | SND_SOC_DAPM_SUPPLY("POWER", TFA9879_DEVICE_CONTROL, TFA9879_POWERUP_SHIFT, 0, | ||
221 | NULL, 0), | ||
222 | }; | ||
223 | |||
224 | static const struct snd_soc_dapm_route tfa9879_dapm_routes[] = { | ||
225 | { "DAC", NULL, "AIFINL" }, | ||
226 | { "DAC", NULL, "AIFINR" }, | ||
227 | |||
228 | { "LINEOUT", NULL, "DAC" }, | ||
229 | |||
230 | { "DAC", NULL, "POWER" }, | ||
231 | }; | ||
232 | |||
233 | static const struct snd_soc_codec_driver tfa9879_codec = { | ||
234 | .controls = tfa9879_controls, | ||
235 | .num_controls = ARRAY_SIZE(tfa9879_controls), | ||
236 | |||
237 | .dapm_widgets = tfa9879_dapm_widgets, | ||
238 | .num_dapm_widgets = ARRAY_SIZE(tfa9879_dapm_widgets), | ||
239 | .dapm_routes = tfa9879_dapm_routes, | ||
240 | .num_dapm_routes = ARRAY_SIZE(tfa9879_dapm_routes), | ||
241 | }; | ||
242 | |||
243 | static const struct regmap_config tfa9879_regmap = { | ||
244 | .reg_bits = 8, | ||
245 | .val_bits = 16, | ||
246 | |||
247 | .volatile_reg = tfa9879_volatile_reg, | ||
248 | .max_register = TFA9879_MISC_STATUS, | ||
249 | .reg_defaults = tfa9879_regs, | ||
250 | .num_reg_defaults = ARRAY_SIZE(tfa9879_regs), | ||
251 | .cache_type = REGCACHE_RBTREE, | ||
252 | }; | ||
253 | |||
254 | static const struct snd_soc_dai_ops tfa9879_dai_ops = { | ||
255 | .hw_params = tfa9879_hw_params, | ||
256 | .digital_mute = tfa9879_digital_mute, | ||
257 | .set_fmt = tfa9879_set_fmt, | ||
258 | }; | ||
259 | |||
260 | #define TFA9879_RATES SNDRV_PCM_RATE_8000_96000 | ||
261 | |||
262 | #define TFA9879_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
263 | SNDRV_PCM_FMTBIT_S24_LE) | ||
264 | |||
265 | static struct snd_soc_dai_driver tfa9879_dai = { | ||
266 | .name = "tfa9879-hifi", | ||
267 | .playback = { | ||
268 | .stream_name = "Playback", | ||
269 | .channels_min = 2, | ||
270 | .channels_max = 2, | ||
271 | .rates = TFA9879_RATES, | ||
272 | .formats = TFA9879_FORMATS, }, | ||
273 | .ops = &tfa9879_dai_ops, | ||
274 | }; | ||
275 | |||
276 | static int tfa9879_i2c_probe(struct i2c_client *i2c, | ||
277 | const struct i2c_device_id *id) | ||
278 | { | ||
279 | struct tfa9879_priv *tfa9879; | ||
280 | int i; | ||
281 | |||
282 | tfa9879 = devm_kzalloc(&i2c->dev, sizeof(*tfa9879), GFP_KERNEL); | ||
283 | if (IS_ERR(tfa9879)) | ||
284 | return PTR_ERR(tfa9879); | ||
285 | |||
286 | i2c_set_clientdata(i2c, tfa9879); | ||
287 | |||
288 | tfa9879->regmap = devm_regmap_init_i2c(i2c, &tfa9879_regmap); | ||
289 | if (IS_ERR(tfa9879->regmap)) | ||
290 | return PTR_ERR(tfa9879->regmap); | ||
291 | |||
292 | /* Ensure the device is in reset state */ | ||
293 | for (i = 0; i < ARRAY_SIZE(tfa9879_regs); i++) | ||
294 | regmap_write(tfa9879->regmap, | ||
295 | tfa9879_regs[i].reg, tfa9879_regs[i].def); | ||
296 | |||
297 | return snd_soc_register_codec(&i2c->dev, &tfa9879_codec, | ||
298 | &tfa9879_dai, 1); | ||
299 | } | ||
300 | |||
301 | static int tfa9879_i2c_remove(struct i2c_client *client) | ||
302 | { | ||
303 | snd_soc_unregister_codec(&client->dev); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static const struct i2c_device_id tfa9879_i2c_id[] = { | ||
309 | { "tfa9879", 0 }, | ||
310 | { } | ||
311 | }; | ||
312 | MODULE_DEVICE_TABLE(i2c, tfa9879_i2c_id); | ||
313 | |||
314 | static struct i2c_driver tfa9879_i2c_driver = { | ||
315 | .driver = { | ||
316 | .name = "tfa9879", | ||
317 | .owner = THIS_MODULE, | ||
318 | }, | ||
319 | .probe = tfa9879_i2c_probe, | ||
320 | .remove = tfa9879_i2c_remove, | ||
321 | .id_table = tfa9879_i2c_id, | ||
322 | }; | ||
323 | |||
324 | module_i2c_driver(tfa9879_i2c_driver); | ||
325 | |||
326 | MODULE_DESCRIPTION("ASoC NXP Semiconductors TFA9879 driver"); | ||
327 | MODULE_AUTHOR("Peter Rosin <peda@axentia.se>"); | ||
328 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tfa9879.h b/sound/soc/codecs/tfa9879.h new file mode 100644 index 000000000000..3408c90c4628 --- /dev/null +++ b/sound/soc/codecs/tfa9879.h | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * tfa9879.h -- driver for NXP Semiconductors TFA9879 | ||
3 | * | ||
4 | * Copyright (C) 2014 Axentia Technologies AB | ||
5 | * Author: Peter Rosin <peda@axentia.se> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef _TFA9879_H | ||
15 | #define _TFA9879_H | ||
16 | |||
17 | #define TFA9879_DEVICE_CONTROL 0x00 | ||
18 | #define TFA9879_SERIAL_INTERFACE_1 0x01 | ||
19 | #define TFA9879_PCM_IOM2_FORMAT_1 0x02 | ||
20 | #define TFA9879_SERIAL_INTERFACE_2 0x03 | ||
21 | #define TFA9879_PCM_IOM2_FORMAT_2 0x04 | ||
22 | #define TFA9879_EQUALIZER_A1 0x05 | ||
23 | #define TFA9879_EQUALIZER_A2 0x06 | ||
24 | #define TFA9879_EQUALIZER_B1 0x07 | ||
25 | #define TFA9879_EQUALIZER_B2 0x08 | ||
26 | #define TFA9879_EQUALIZER_C1 0x09 | ||
27 | #define TFA9879_EQUALIZER_C2 0x0a | ||
28 | #define TFA9879_EQUALIZER_D1 0x0b | ||
29 | #define TFA9879_EQUALIZER_D2 0x0c | ||
30 | #define TFA9879_EQUALIZER_E1 0x0d | ||
31 | #define TFA9879_EQUALIZER_E2 0x0e | ||
32 | #define TFA9879_BYPASS_CONTROL 0x0f | ||
33 | #define TFA9879_DYNAMIC_RANGE_COMPR 0x10 | ||
34 | #define TFA9879_BASS_TREBLE 0x11 | ||
35 | #define TFA9879_HIGH_PASS_FILTER 0x12 | ||
36 | #define TFA9879_VOLUME_CONTROL 0x13 | ||
37 | #define TFA9879_MISC_CONTROL 0x14 | ||
38 | #define TFA9879_MISC_STATUS 0x15 | ||
39 | |||
40 | /* TFA9879_DEVICE_CONTROL */ | ||
41 | #define TFA9879_INPUT_SEL_MASK 0x0010 | ||
42 | #define TFA9879_INPUT_SEL_SHIFT 4 | ||
43 | #define TFA9879_OPMODE_MASK 0x0008 | ||
44 | #define TFA9879_OPMODE_SHIFT 3 | ||
45 | #define TFA9879_RESET_MASK 0x0002 | ||
46 | #define TFA9879_RESET_SHIFT 1 | ||
47 | #define TFA9879_POWERUP_MASK 0x0001 | ||
48 | #define TFA9879_POWERUP_SHIFT 0 | ||
49 | |||
50 | /* TFA9879_SERIAL_INTERFACE */ | ||
51 | #define TFA9879_MONO_SEL_MASK 0x0c00 | ||
52 | #define TFA9879_MONO_SEL_SHIFT 10 | ||
53 | #define TFA9879_MONO_SEL_LEFT 0 | ||
54 | #define TFA9879_MONO_SEL_RIGHT 1 | ||
55 | #define TFA9879_MONO_SEL_BOTH 2 | ||
56 | #define TFA9879_I2S_FS_MASK 0x03c0 | ||
57 | #define TFA9879_I2S_FS_SHIFT 6 | ||
58 | #define TFA9879_I2S_FS_8000 0 | ||
59 | #define TFA9879_I2S_FS_11025 1 | ||
60 | #define TFA9879_I2S_FS_12000 2 | ||
61 | #define TFA9879_I2S_FS_16000 3 | ||
62 | #define TFA9879_I2S_FS_22050 4 | ||
63 | #define TFA9879_I2S_FS_24000 5 | ||
64 | #define TFA9879_I2S_FS_32000 6 | ||
65 | #define TFA9879_I2S_FS_44100 7 | ||
66 | #define TFA9879_I2S_FS_48000 8 | ||
67 | #define TFA9879_I2S_FS_64000 9 | ||
68 | #define TFA9879_I2S_FS_88200 10 | ||
69 | #define TFA9879_I2S_FS_96000 11 | ||
70 | #define TFA9879_I2S_SET_MASK 0x0038 | ||
71 | #define TFA9879_I2S_SET_SHIFT 3 | ||
72 | #define TFA9879_I2S_SET_MSB_J_24 2 | ||
73 | #define TFA9879_I2S_SET_I2S_24 3 | ||
74 | #define TFA9879_I2S_SET_LSB_J_16 4 | ||
75 | #define TFA9879_I2S_SET_LSB_J_18 5 | ||
76 | #define TFA9879_I2S_SET_LSB_J_20 6 | ||
77 | #define TFA9879_I2S_SET_LSB_J_24 7 | ||
78 | #define TFA9879_SCK_POL_MASK 0x0004 | ||
79 | #define TFA9879_SCK_POL_SHIFT 2 | ||
80 | #define TFA9879_SCK_POL_NORMAL 0 | ||
81 | #define TFA9879_SCK_POL_INVERSE 1 | ||
82 | #define TFA9879_I_MODE_MASK 0x0003 | ||
83 | #define TFA9879_I_MODE_SHIFT 0 | ||
84 | #define TFA9879_I_MODE_I2S 0 | ||
85 | #define TFA9879_I_MODE_PCM_IOM2_SHORT 1 | ||
86 | #define TFA9879_I_MODE_PCM_IOM2_LONG 2 | ||
87 | |||
88 | /* TFA9879_PCM_IOM2_FORMAT */ | ||
89 | #define TFA9879_PCM_FS_MASK 0x0800 | ||
90 | #define TFA9879_PCM_FS_SHIFT 11 | ||
91 | #define TFA9879_A_LAW_MASK 0x0400 | ||
92 | #define TFA9879_A_LAW_SHIFT 10 | ||
93 | #define TFA9879_PCM_COMP_MASK 0x0200 | ||
94 | #define TFA9879_PCM_COMP_SHIFT 9 | ||
95 | #define TFA9879_PCM_DL_MASK 0x0100 | ||
96 | #define TFA9879_PCM_DL_SHIFT 8 | ||
97 | #define TFA9879_D1_SLOT_MASK 0x00f0 | ||
98 | #define TFA9879_D1_SLOT_SHIFT 4 | ||
99 | #define TFA9879_D2_SLOT_MASK 0x000f | ||
100 | #define TFA9879_D2_SLOT_SHIFT 0 | ||
101 | |||
102 | /* TFA9879_EQUALIZER_X1 */ | ||
103 | #define TFA9879_T1_MASK 0x8000 | ||
104 | #define TFA9879_T1_SHIFT 15 | ||
105 | #define TFA9879_K1M_MASK 0x7ff0 | ||
106 | #define TFA9879_K1M_SHIFT 4 | ||
107 | #define TFA9879_K1E_MASK 0x000f | ||
108 | #define TFA9879_K1E_SHIFT 0 | ||
109 | |||
110 | /* TFA9879_EQUALIZER_X2 */ | ||
111 | #define TFA9879_T2_MASK 0x8000 | ||
112 | #define TFA9879_T2_SHIFT 15 | ||
113 | #define TFA9879_K2M_MASK 0x7800 | ||
114 | #define TFA9879_K2M_SHIFT 11 | ||
115 | #define TFA9879_K2E_MASK 0x0700 | ||
116 | #define TFA9879_K2E_SHIFT 8 | ||
117 | #define TFA9879_K0_MASK 0x00fe | ||
118 | #define TFA9879_K0_SHIFT 1 | ||
119 | #define TFA9879_S_MASK 0x0001 | ||
120 | #define TFA9879_S_SHIFT 0 | ||
121 | |||
122 | /* TFA9879_BYPASS_CONTROL */ | ||
123 | #define TFA9879_L_OCP_MASK 0x00c0 | ||
124 | #define TFA9879_L_OCP_SHIFT 6 | ||
125 | #define TFA9879_L_OTP_MASK 0x0030 | ||
126 | #define TFA9879_L_OTP_SHIFT 4 | ||
127 | #define TFA9879_CLIPCTRL_MASK 0x0008 | ||
128 | #define TFA9879_CLIPCTRL_SHIFT 3 | ||
129 | #define TFA9879_HPF_BP_MASK 0x0004 | ||
130 | #define TFA9879_HPF_BP_SHIFT 2 | ||
131 | #define TFA9879_DRC_BP_MASK 0x0002 | ||
132 | #define TFA9879_DRC_BP_SHIFT 1 | ||
133 | #define TFA9879_EQ_BP_MASK 0x0001 | ||
134 | #define TFA9879_EQ_BP_SHIFT 0 | ||
135 | |||
136 | /* TFA9879_DYNAMIC_RANGE_COMPR */ | ||
137 | #define TFA9879_AT_LVL_MASK 0xf000 | ||
138 | #define TFA9879_AT_LVL_SHIFT 12 | ||
139 | #define TFA9879_AT_RATE_MASK 0x0f00 | ||
140 | #define TFA9879_AT_RATE_SHIFT 8 | ||
141 | #define TFA9879_RL_LVL_MASK 0x00f0 | ||
142 | #define TFA9879_RL_LVL_SHIFT 4 | ||
143 | #define TFA9879_RL_RATE_MASK 0x000f | ||
144 | #define TFA9879_RL_RATE_SHIFT 0 | ||
145 | |||
146 | /* TFA9879_BASS_TREBLE */ | ||
147 | #define TFA9879_G_TRBLE_MASK 0x3e00 | ||
148 | #define TFA9879_G_TRBLE_SHIFT 9 | ||
149 | #define TFA9879_F_TRBLE_MASK 0x0180 | ||
150 | #define TFA9879_F_TRBLE_SHIFT 7 | ||
151 | #define TFA9879_G_BASS_MASK 0x007c | ||
152 | #define TFA9879_G_BASS_SHIFT 2 | ||
153 | #define TFA9879_F_BASS_MASK 0x0003 | ||
154 | #define TFA9879_F_BASS_SHIFT 0 | ||
155 | |||
156 | /* TFA9879_HIGH_PASS_FILTER */ | ||
157 | #define TFA9879_HP_CTRL_MASK 0x00ff | ||
158 | #define TFA9879_HP_CTRL_SHIFT 0 | ||
159 | |||
160 | /* TFA9879_VOLUME_CONTROL */ | ||
161 | #define TFA9879_ZR_CRSS_MASK 0x1000 | ||
162 | #define TFA9879_ZR_CRSS_SHIFT 12 | ||
163 | #define TFA9879_VOL_MASK 0x00ff | ||
164 | #define TFA9879_VOL_SHIFT 0 | ||
165 | |||
166 | /* TFA9879_MISC_CONTROL */ | ||
167 | #define TFA9879_DE_PHAS_MASK 0x0c00 | ||
168 | #define TFA9879_DE_PHAS_SHIFT 10 | ||
169 | #define TFA9879_H_MUTE_MASK 0x0200 | ||
170 | #define TFA9879_H_MUTE_SHIFT 9 | ||
171 | #define TFA9879_S_MUTE_MASK 0x0100 | ||
172 | #define TFA9879_S_MUTE_SHIFT 8 | ||
173 | #define TFA9879_P_LIM_MASK 0x00ff | ||
174 | #define TFA9879_P_LIM_SHIFT 0 | ||
175 | |||
176 | /* TFA9879_MISC_STATUS */ | ||
177 | #define TFA9879_PS_MASK 0x4000 | ||
178 | #define TFA9879_PS_SHIFT 14 | ||
179 | #define TFA9879_PORA_MASK 0x2000 | ||
180 | #define TFA9879_PORA_SHIFT 13 | ||
181 | #define TFA9879_AMP_MASK 0x0600 | ||
182 | #define TFA9879_AMP_SHIFT 9 | ||
183 | #define TFA9879_IBP_2_MASK 0x0100 | ||
184 | #define TFA9879_IBP_2_SHIFT 8 | ||
185 | #define TFA9879_OFP_2_MASK 0x0080 | ||
186 | #define TFA9879_OFP_2_SHIFT 7 | ||
187 | #define TFA9879_UFP_2_MASK 0x0040 | ||
188 | #define TFA9879_UFP_2_SHIFT 6 | ||
189 | #define TFA9879_IBP_1_MASK 0x0020 | ||
190 | #define TFA9879_IBP_1_SHIFT 5 | ||
191 | #define TFA9879_OFP_1_MASK 0x0010 | ||
192 | #define TFA9879_OFP_1_SHIFT 4 | ||
193 | #define TFA9879_UFP_1_MASK 0x0008 | ||
194 | #define TFA9879_UFP_1_SHIFT 3 | ||
195 | #define TFA9879_OCPOKA_MASK 0x0004 | ||
196 | #define TFA9879_OCPOKA_SHIFT 2 | ||
197 | #define TFA9879_OCPOKB_MASK 0x0002 | ||
198 | #define TFA9879_OCPOKB_SHIFT 1 | ||
199 | #define TFA9879_OTPOK_MASK 0x0001 | ||
200 | #define TFA9879_OTPOK_SHIFT 0 | ||
201 | |||
202 | #endif | ||
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index d67167920c2f..cc17e7e5126e 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -540,19 +540,11 @@ static struct snd_soc_dai_driver tlv320aic23_dai = { | |||
540 | .ops = &tlv320aic23_dai_ops, | 540 | .ops = &tlv320aic23_dai_ops, |
541 | }; | 541 | }; |
542 | 542 | ||
543 | static int tlv320aic23_suspend(struct snd_soc_codec *codec) | ||
544 | { | ||
545 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
546 | |||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | static int tlv320aic23_resume(struct snd_soc_codec *codec) | 543 | static int tlv320aic23_resume(struct snd_soc_codec *codec) |
551 | { | 544 | { |
552 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); | 545 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); |
553 | regcache_mark_dirty(aic23->regmap); | 546 | regcache_mark_dirty(aic23->regmap); |
554 | regcache_sync(aic23->regmap); | 547 | regcache_sync(aic23->regmap); |
555 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
556 | 548 | ||
557 | return 0; | 549 | return 0; |
558 | } | 550 | } |
@@ -562,9 +554,6 @@ static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) | |||
562 | /* Reset codec */ | 554 | /* Reset codec */ |
563 | snd_soc_write(codec, TLV320AIC23_RESET, 0); | 555 | snd_soc_write(codec, TLV320AIC23_RESET, 0); |
564 | 556 | ||
565 | /* power on device */ | ||
566 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
567 | |||
568 | snd_soc_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K); | 557 | snd_soc_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K); |
569 | 558 | ||
570 | /* Unmute input */ | 559 | /* Unmute input */ |
@@ -589,18 +578,12 @@ static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) | |||
589 | return 0; | 578 | return 0; |
590 | } | 579 | } |
591 | 580 | ||
592 | static int tlv320aic23_remove(struct snd_soc_codec *codec) | ||
593 | { | ||
594 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { | 581 | static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { |
599 | .probe = tlv320aic23_codec_probe, | 582 | .probe = tlv320aic23_codec_probe, |
600 | .remove = tlv320aic23_remove, | ||
601 | .suspend = tlv320aic23_suspend, | ||
602 | .resume = tlv320aic23_resume, | 583 | .resume = tlv320aic23_resume, |
603 | .set_bias_level = tlv320aic23_set_bias_level, | 584 | .set_bias_level = tlv320aic23_set_bias_level, |
585 | .suspend_bias_off = true, | ||
586 | |||
604 | .controls = tlv320aic23_snd_controls, | 587 | .controls = tlv320aic23_snd_controls, |
605 | .num_controls = ARRAY_SIZE(tlv320aic23_snd_controls), | 588 | .num_controls = ARRAY_SIZE(tlv320aic23_snd_controls), |
606 | .dapm_widgets = tlv320aic23_dapm_widgets, | 589 | .dapm_widgets = tlv320aic23_dapm_widgets, |
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 145fe5b253d4..dc3223d6eca1 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -911,12 +911,13 @@ static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
911 | } | 911 | } |
912 | aic31xx->p_div = i; | 912 | aic31xx->p_div = i; |
913 | 913 | ||
914 | for (i = 0; aic31xx_divs[i].mclk_p != freq/aic31xx->p_div; i++) { | 914 | for (i = 0; i < ARRAY_SIZE(aic31xx_divs) && |
915 | if (i == ARRAY_SIZE(aic31xx_divs)) { | 915 | aic31xx_divs[i].mclk_p != freq/aic31xx->p_div; i++) |
916 | dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n", | 916 | ; |
917 | __func__, freq); | 917 | if (i == ARRAY_SIZE(aic31xx_divs)) { |
918 | return -EINVAL; | 918 | dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n", |
919 | } | 919 | __func__, freq); |
920 | return -EINVAL; | ||
920 | } | 921 | } |
921 | 922 | ||
922 | /* set clock on MCLK, BCLK, or GPIO1 as PLL input */ | 923 | /* set clock on MCLK, BCLK, or GPIO1 as PLL input */ |
@@ -1056,18 +1057,6 @@ static int aic31xx_set_bias_level(struct snd_soc_codec *codec, | |||
1056 | return 0; | 1057 | return 0; |
1057 | } | 1058 | } |
1058 | 1059 | ||
1059 | static int aic31xx_suspend(struct snd_soc_codec *codec) | ||
1060 | { | ||
1061 | aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1065 | static int aic31xx_resume(struct snd_soc_codec *codec) | ||
1066 | { | ||
1067 | aic31xx_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | static int aic31xx_codec_probe(struct snd_soc_codec *codec) | 1060 | static int aic31xx_codec_probe(struct snd_soc_codec *codec) |
1072 | { | 1061 | { |
1073 | int ret = 0; | 1062 | int ret = 0; |
@@ -1110,8 +1099,6 @@ static int aic31xx_codec_remove(struct snd_soc_codec *codec) | |||
1110 | { | 1099 | { |
1111 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | 1100 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); |
1112 | int i; | 1101 | int i; |
1113 | /* power down chip */ | ||
1114 | aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1115 | 1102 | ||
1116 | for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) | 1103 | for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) |
1117 | regulator_unregister_notifier(aic31xx->supplies[i].consumer, | 1104 | regulator_unregister_notifier(aic31xx->supplies[i].consumer, |
@@ -1123,9 +1110,9 @@ static int aic31xx_codec_remove(struct snd_soc_codec *codec) | |||
1123 | static struct snd_soc_codec_driver soc_codec_driver_aic31xx = { | 1110 | static struct snd_soc_codec_driver soc_codec_driver_aic31xx = { |
1124 | .probe = aic31xx_codec_probe, | 1111 | .probe = aic31xx_codec_probe, |
1125 | .remove = aic31xx_codec_remove, | 1112 | .remove = aic31xx_codec_remove, |
1126 | .suspend = aic31xx_suspend, | ||
1127 | .resume = aic31xx_resume, | ||
1128 | .set_bias_level = aic31xx_set_bias_level, | 1113 | .set_bias_level = aic31xx_set_bias_level, |
1114 | .suspend_bias_off = true, | ||
1115 | |||
1129 | .controls = aic31xx_snd_controls, | 1116 | .controls = aic31xx_snd_controls, |
1130 | .num_controls = ARRAY_SIZE(aic31xx_snd_controls), | 1117 | .num_controls = ARRAY_SIZE(aic31xx_snd_controls), |
1131 | .dapm_widgets = aic31xx_dapm_widgets, | 1118 | .dapm_widgets = aic31xx_dapm_widgets, |
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 6ea662db2410..015467ed606b 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
@@ -597,18 +597,6 @@ static struct snd_soc_dai_driver aic32x4_dai = { | |||
597 | .symmetric_rates = 1, | 597 | .symmetric_rates = 1, |
598 | }; | 598 | }; |
599 | 599 | ||
600 | static int aic32x4_suspend(struct snd_soc_codec *codec) | ||
601 | { | ||
602 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | static int aic32x4_resume(struct snd_soc_codec *codec) | ||
607 | { | ||
608 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static int aic32x4_probe(struct snd_soc_codec *codec) | 600 | static int aic32x4_probe(struct snd_soc_codec *codec) |
613 | { | 601 | { |
614 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | 602 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); |
@@ -654,8 +642,6 @@ static int aic32x4_probe(struct snd_soc_codec *codec) | |||
654 | snd_soc_write(codec, AIC32X4_RMICPGANIN, | 642 | snd_soc_write(codec, AIC32X4_RMICPGANIN, |
655 | AIC32X4_RMICPGANIN_CM1R_10K); | 643 | AIC32X4_RMICPGANIN_CM1R_10K); |
656 | 644 | ||
657 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
658 | |||
659 | /* | 645 | /* |
660 | * Workaround: for an unknown reason, the ADC needs to be powered up | 646 | * Workaround: for an unknown reason, the ADC needs to be powered up |
661 | * and down for the first capture to work properly. It seems related to | 647 | * and down for the first capture to work properly. It seems related to |
@@ -669,18 +655,10 @@ static int aic32x4_probe(struct snd_soc_codec *codec) | |||
669 | return 0; | 655 | return 0; |
670 | } | 656 | } |
671 | 657 | ||
672 | static int aic32x4_remove(struct snd_soc_codec *codec) | ||
673 | { | ||
674 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { | 658 | static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { |
679 | .probe = aic32x4_probe, | 659 | .probe = aic32x4_probe, |
680 | .remove = aic32x4_remove, | ||
681 | .suspend = aic32x4_suspend, | ||
682 | .resume = aic32x4_resume, | ||
683 | .set_bias_level = aic32x4_set_bias_level, | 660 | .set_bias_level = aic32x4_set_bias_level, |
661 | .suspend_bias_off = true, | ||
684 | 662 | ||
685 | .controls = aic32x4_snd_controls, | 663 | .controls = aic32x4_snd_controls, |
686 | .num_controls = ARRAY_SIZE(aic32x4_snd_controls), | 664 | .num_controls = ARRAY_SIZE(aic32x4_snd_controls), |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index f7c2a575a892..b7ebce054b4e 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -78,6 +78,8 @@ struct aic3x_priv { | |||
78 | struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES]; | 78 | struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES]; |
79 | struct aic3x_setup_data *setup; | 79 | struct aic3x_setup_data *setup; |
80 | unsigned int sysclk; | 80 | unsigned int sysclk; |
81 | unsigned int dai_fmt; | ||
82 | unsigned int tdm_delay; | ||
81 | struct list_head list; | 83 | struct list_head list; |
82 | int master; | 84 | int master; |
83 | int gpio_reset; | 85 | int gpio_reset; |
@@ -214,61 +216,78 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, | |||
214 | return 0; | 216 | return 0; |
215 | } | 217 | } |
216 | 218 | ||
217 | static const char *aic3x_left_dac_mux[] = { "DAC_L1", "DAC_L3", "DAC_L2" }; | 219 | static const char * const aic3x_left_dac_mux[] = { |
218 | static const char *aic3x_right_dac_mux[] = { "DAC_R1", "DAC_R3", "DAC_R2" }; | 220 | "DAC_L1", "DAC_L3", "DAC_L2" }; |
219 | static const char *aic3x_left_hpcom_mux[] = | 221 | static SOC_ENUM_SINGLE_DECL(aic3x_left_dac_enum, DAC_LINE_MUX, 6, |
220 | { "differential of HPLOUT", "constant VCM", "single-ended" }; | 222 | aic3x_left_dac_mux); |
221 | static const char *aic3x_right_hpcom_mux[] = | 223 | |
222 | { "differential of HPROUT", "constant VCM", "single-ended", | 224 | static const char * const aic3x_right_dac_mux[] = { |
223 | "differential of HPLCOM", "external feedback" }; | 225 | "DAC_R1", "DAC_R3", "DAC_R2" }; |
224 | static const char *aic3x_linein_mode_mux[] = { "single-ended", "differential" }; | 226 | static SOC_ENUM_SINGLE_DECL(aic3x_right_dac_enum, DAC_LINE_MUX, 4, |
225 | static const char *aic3x_adc_hpf[] = | 227 | aic3x_right_dac_mux); |
226 | { "Disabled", "0.0045xFs", "0.0125xFs", "0.025xFs" }; | 228 | |
227 | 229 | static const char * const aic3x_left_hpcom_mux[] = { | |
228 | #define LDAC_ENUM 0 | 230 | "differential of HPLOUT", "constant VCM", "single-ended" }; |
229 | #define RDAC_ENUM 1 | 231 | static SOC_ENUM_SINGLE_DECL(aic3x_left_hpcom_enum, HPLCOM_CFG, 4, |
230 | #define LHPCOM_ENUM 2 | 232 | aic3x_left_hpcom_mux); |
231 | #define RHPCOM_ENUM 3 | 233 | |
232 | #define LINE1L_2_L_ENUM 4 | 234 | static const char * const aic3x_right_hpcom_mux[] = { |
233 | #define LINE1L_2_R_ENUM 5 | 235 | "differential of HPROUT", "constant VCM", "single-ended", |
234 | #define LINE1R_2_L_ENUM 6 | 236 | "differential of HPLCOM", "external feedback" }; |
235 | #define LINE1R_2_R_ENUM 7 | 237 | static SOC_ENUM_SINGLE_DECL(aic3x_right_hpcom_enum, HPRCOM_CFG, 3, |
236 | #define LINE2L_ENUM 8 | 238 | aic3x_right_hpcom_mux); |
237 | #define LINE2R_ENUM 9 | 239 | |
238 | #define ADC_HPF_ENUM 10 | 240 | static const char * const aic3x_linein_mode_mux[] = { |
239 | 241 | "single-ended", "differential" }; | |
240 | static const struct soc_enum aic3x_enum[] = { | 242 | static SOC_ENUM_SINGLE_DECL(aic3x_line1l_2_l_enum, LINE1L_2_LADC_CTRL, 7, |
241 | SOC_ENUM_SINGLE(DAC_LINE_MUX, 6, 3, aic3x_left_dac_mux), | 243 | aic3x_linein_mode_mux); |
242 | SOC_ENUM_SINGLE(DAC_LINE_MUX, 4, 3, aic3x_right_dac_mux), | 244 | static SOC_ENUM_SINGLE_DECL(aic3x_line1l_2_r_enum, LINE1L_2_RADC_CTRL, 7, |
243 | SOC_ENUM_SINGLE(HPLCOM_CFG, 4, 3, aic3x_left_hpcom_mux), | 245 | aic3x_linein_mode_mux); |
244 | SOC_ENUM_SINGLE(HPRCOM_CFG, 3, 5, aic3x_right_hpcom_mux), | 246 | static SOC_ENUM_SINGLE_DECL(aic3x_line1r_2_l_enum, LINE1R_2_LADC_CTRL, 7, |
245 | SOC_ENUM_SINGLE(LINE1L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 247 | aic3x_linein_mode_mux); |
246 | SOC_ENUM_SINGLE(LINE1L_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 248 | static SOC_ENUM_SINGLE_DECL(aic3x_line1r_2_r_enum, LINE1R_2_RADC_CTRL, 7, |
247 | SOC_ENUM_SINGLE(LINE1R_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 249 | aic3x_linein_mode_mux); |
248 | SOC_ENUM_SINGLE(LINE1R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 250 | static SOC_ENUM_SINGLE_DECL(aic3x_line2l_2_ldac_enum, LINE2L_2_LADC_CTRL, 7, |
249 | SOC_ENUM_SINGLE(LINE2L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 251 | aic3x_linein_mode_mux); |
250 | SOC_ENUM_SINGLE(LINE2R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 252 | static SOC_ENUM_SINGLE_DECL(aic3x_line2r_2_rdac_enum, LINE2R_2_RADC_CTRL, 7, |
251 | SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf), | 253 | aic3x_linein_mode_mux); |
252 | }; | 254 | |
253 | 255 | static const char * const aic3x_adc_hpf[] = { | |
254 | static const char *aic3x_agc_level[] = | 256 | "Disabled", "0.0045xFs", "0.0125xFs", "0.025xFs" }; |
255 | { "-5.5dB", "-8dB", "-10dB", "-12dB", "-14dB", "-17dB", "-20dB", "-24dB" }; | 257 | static SOC_ENUM_DOUBLE_DECL(aic3x_adc_hpf_enum, AIC3X_CODEC_DFILT_CTRL, 6, 4, |
256 | static const struct soc_enum aic3x_agc_level_enum[] = { | 258 | aic3x_adc_hpf); |
257 | SOC_ENUM_SINGLE(LAGC_CTRL_A, 4, 8, aic3x_agc_level), | 259 | |
258 | SOC_ENUM_SINGLE(RAGC_CTRL_A, 4, 8, aic3x_agc_level), | 260 | static const char * const aic3x_agc_level[] = { |
259 | }; | 261 | "-5.5dB", "-8dB", "-10dB", "-12dB", |
260 | 262 | "-14dB", "-17dB", "-20dB", "-24dB" }; | |
261 | static const char *aic3x_agc_attack[] = { "8ms", "11ms", "16ms", "20ms" }; | 263 | static SOC_ENUM_SINGLE_DECL(aic3x_lagc_level_enum, LAGC_CTRL_A, 4, |
262 | static const struct soc_enum aic3x_agc_attack_enum[] = { | 264 | aic3x_agc_level); |
263 | SOC_ENUM_SINGLE(LAGC_CTRL_A, 2, 4, aic3x_agc_attack), | 265 | static SOC_ENUM_SINGLE_DECL(aic3x_ragc_level_enum, RAGC_CTRL_A, 4, |
264 | SOC_ENUM_SINGLE(RAGC_CTRL_A, 2, 4, aic3x_agc_attack), | 266 | aic3x_agc_level); |
265 | }; | 267 | |
266 | 268 | static const char * const aic3x_agc_attack[] = { | |
267 | static const char *aic3x_agc_decay[] = { "100ms", "200ms", "400ms", "500ms" }; | 269 | "8ms", "11ms", "16ms", "20ms" }; |
268 | static const struct soc_enum aic3x_agc_decay_enum[] = { | 270 | static SOC_ENUM_SINGLE_DECL(aic3x_lagc_attack_enum, LAGC_CTRL_A, 2, |
269 | SOC_ENUM_SINGLE(LAGC_CTRL_A, 0, 4, aic3x_agc_decay), | 271 | aic3x_agc_attack); |
270 | SOC_ENUM_SINGLE(RAGC_CTRL_A, 0, 4, aic3x_agc_decay), | 272 | static SOC_ENUM_SINGLE_DECL(aic3x_ragc_attack_enum, RAGC_CTRL_A, 2, |
271 | }; | 273 | aic3x_agc_attack); |
274 | |||
275 | static const char * const aic3x_agc_decay[] = { | ||
276 | "100ms", "200ms", "400ms", "500ms" }; | ||
277 | static SOC_ENUM_SINGLE_DECL(aic3x_lagc_decay_enum, LAGC_CTRL_A, 0, | ||
278 | aic3x_agc_decay); | ||
279 | static SOC_ENUM_SINGLE_DECL(aic3x_ragc_decay_enum, RAGC_CTRL_A, 0, | ||
280 | aic3x_agc_decay); | ||
281 | |||
282 | static const char * const aic3x_poweron_time[] = { | ||
283 | "0us", "10us", "100us", "1ms", "10ms", "50ms", | ||
284 | "100ms", "200ms", "400ms", "800ms", "2s", "4s" }; | ||
285 | static SOC_ENUM_SINGLE_DECL(aic3x_poweron_time_enum, HPOUT_POP_REDUCTION, 4, | ||
286 | aic3x_poweron_time); | ||
287 | |||
288 | static const char * const aic3x_rampup_step[] = { "0ms", "1ms", "2ms", "4ms" }; | ||
289 | static SOC_ENUM_SINGLE_DECL(aic3x_rampup_step_enum, HPOUT_POP_REDUCTION, 2, | ||
290 | aic3x_rampup_step); | ||
272 | 291 | ||
273 | /* | 292 | /* |
274 | * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps | 293 | * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps |
@@ -383,12 +402,12 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
383 | * adjust PGA to max value when ADC is on and will never go back. | 402 | * adjust PGA to max value when ADC is on and will never go back. |
384 | */ | 403 | */ |
385 | SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), | 404 | SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), |
386 | SOC_ENUM("Left AGC Target level", aic3x_agc_level_enum[0]), | 405 | SOC_ENUM("Left AGC Target level", aic3x_lagc_level_enum), |
387 | SOC_ENUM("Right AGC Target level", aic3x_agc_level_enum[1]), | 406 | SOC_ENUM("Right AGC Target level", aic3x_ragc_level_enum), |
388 | SOC_ENUM("Left AGC Attack time", aic3x_agc_attack_enum[0]), | 407 | SOC_ENUM("Left AGC Attack time", aic3x_lagc_attack_enum), |
389 | SOC_ENUM("Right AGC Attack time", aic3x_agc_attack_enum[1]), | 408 | SOC_ENUM("Right AGC Attack time", aic3x_ragc_attack_enum), |
390 | SOC_ENUM("Left AGC Decay time", aic3x_agc_decay_enum[0]), | 409 | SOC_ENUM("Left AGC Decay time", aic3x_lagc_decay_enum), |
391 | SOC_ENUM("Right AGC Decay time", aic3x_agc_decay_enum[1]), | 410 | SOC_ENUM("Right AGC Decay time", aic3x_ragc_decay_enum), |
392 | 411 | ||
393 | /* De-emphasis */ | 412 | /* De-emphasis */ |
394 | SOC_DOUBLE("De-emphasis Switch", AIC3X_CODEC_DFILT_CTRL, 2, 0, 0x01, 0), | 413 | SOC_DOUBLE("De-emphasis Switch", AIC3X_CODEC_DFILT_CTRL, 2, 0, 0x01, 0), |
@@ -398,7 +417,11 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
398 | 0, 119, 0, adc_tlv), | 417 | 0, 119, 0, adc_tlv), |
399 | SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1), | 418 | SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1), |
400 | 419 | ||
401 | SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), | 420 | SOC_ENUM("ADC HPF Cut-off", aic3x_adc_hpf_enum), |
421 | |||
422 | /* Pop reduction */ | ||
423 | SOC_ENUM("Output Driver Power-On time", aic3x_poweron_time_enum), | ||
424 | SOC_ENUM("Output Driver Ramp-up step", aic3x_rampup_step_enum), | ||
402 | }; | 425 | }; |
403 | 426 | ||
404 | static const struct snd_kcontrol_new aic3x_mono_controls[] = { | 427 | static const struct snd_kcontrol_new aic3x_mono_controls[] = { |
@@ -425,19 +448,19 @@ static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl = | |||
425 | 448 | ||
426 | /* Left DAC Mux */ | 449 | /* Left DAC Mux */ |
427 | static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = | 450 | static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = |
428 | SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]); | 451 | SOC_DAPM_ENUM("Route", aic3x_left_dac_enum); |
429 | 452 | ||
430 | /* Right DAC Mux */ | 453 | /* Right DAC Mux */ |
431 | static const struct snd_kcontrol_new aic3x_right_dac_mux_controls = | 454 | static const struct snd_kcontrol_new aic3x_right_dac_mux_controls = |
432 | SOC_DAPM_ENUM("Route", aic3x_enum[RDAC_ENUM]); | 455 | SOC_DAPM_ENUM("Route", aic3x_right_dac_enum); |
433 | 456 | ||
434 | /* Left HPCOM Mux */ | 457 | /* Left HPCOM Mux */ |
435 | static const struct snd_kcontrol_new aic3x_left_hpcom_mux_controls = | 458 | static const struct snd_kcontrol_new aic3x_left_hpcom_mux_controls = |
436 | SOC_DAPM_ENUM("Route", aic3x_enum[LHPCOM_ENUM]); | 459 | SOC_DAPM_ENUM("Route", aic3x_left_hpcom_enum); |
437 | 460 | ||
438 | /* Right HPCOM Mux */ | 461 | /* Right HPCOM Mux */ |
439 | static const struct snd_kcontrol_new aic3x_right_hpcom_mux_controls = | 462 | static const struct snd_kcontrol_new aic3x_right_hpcom_mux_controls = |
440 | SOC_DAPM_ENUM("Route", aic3x_enum[RHPCOM_ENUM]); | 463 | SOC_DAPM_ENUM("Route", aic3x_right_hpcom_enum); |
441 | 464 | ||
442 | /* Left Line Mixer */ | 465 | /* Left Line Mixer */ |
443 | static const struct snd_kcontrol_new aic3x_left_line_mixer_controls[] = { | 466 | static const struct snd_kcontrol_new aic3x_left_line_mixer_controls[] = { |
@@ -529,23 +552,23 @@ static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = { | |||
529 | 552 | ||
530 | /* Left Line1 Mux */ | 553 | /* Left Line1 Mux */ |
531 | static const struct snd_kcontrol_new aic3x_left_line1l_mux_controls = | 554 | static const struct snd_kcontrol_new aic3x_left_line1l_mux_controls = |
532 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_2_L_ENUM]); | 555 | SOC_DAPM_ENUM("Route", aic3x_line1l_2_l_enum); |
533 | static const struct snd_kcontrol_new aic3x_right_line1l_mux_controls = | 556 | static const struct snd_kcontrol_new aic3x_right_line1l_mux_controls = |
534 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_2_R_ENUM]); | 557 | SOC_DAPM_ENUM("Route", aic3x_line1l_2_r_enum); |
535 | 558 | ||
536 | /* Right Line1 Mux */ | 559 | /* Right Line1 Mux */ |
537 | static const struct snd_kcontrol_new aic3x_right_line1r_mux_controls = | 560 | static const struct snd_kcontrol_new aic3x_right_line1r_mux_controls = |
538 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_2_R_ENUM]); | 561 | SOC_DAPM_ENUM("Route", aic3x_line1r_2_r_enum); |
539 | static const struct snd_kcontrol_new aic3x_left_line1r_mux_controls = | 562 | static const struct snd_kcontrol_new aic3x_left_line1r_mux_controls = |
540 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_2_L_ENUM]); | 563 | SOC_DAPM_ENUM("Route", aic3x_line1r_2_l_enum); |
541 | 564 | ||
542 | /* Left Line2 Mux */ | 565 | /* Left Line2 Mux */ |
543 | static const struct snd_kcontrol_new aic3x_left_line2_mux_controls = | 566 | static const struct snd_kcontrol_new aic3x_left_line2_mux_controls = |
544 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE2L_ENUM]); | 567 | SOC_DAPM_ENUM("Route", aic3x_line2l_2_ldac_enum); |
545 | 568 | ||
546 | /* Right Line2 Mux */ | 569 | /* Right Line2 Mux */ |
547 | static const struct snd_kcontrol_new aic3x_right_line2_mux_controls = | 570 | static const struct snd_kcontrol_new aic3x_right_line2_mux_controls = |
548 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE2R_ENUM]); | 571 | SOC_DAPM_ENUM("Route", aic3x_line2r_2_rdac_enum); |
549 | 572 | ||
550 | static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | 573 | static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { |
551 | /* Left DAC to Left Outputs */ | 574 | /* Left DAC to Left Outputs */ |
@@ -1009,6 +1032,25 @@ found: | |||
1009 | return 0; | 1032 | return 0; |
1010 | } | 1033 | } |
1011 | 1034 | ||
1035 | static int aic3x_prepare(struct snd_pcm_substream *substream, | ||
1036 | struct snd_soc_dai *dai) | ||
1037 | { | ||
1038 | struct snd_soc_codec *codec = dai->codec; | ||
1039 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | ||
1040 | int delay = 0; | ||
1041 | |||
1042 | /* TDM slot selection only valid in DSP_A/_B mode */ | ||
1043 | if (aic3x->dai_fmt == SND_SOC_DAIFMT_DSP_A) | ||
1044 | delay += (aic3x->tdm_delay + 1); | ||
1045 | else if (aic3x->dai_fmt == SND_SOC_DAIFMT_DSP_B) | ||
1046 | delay += aic3x->tdm_delay; | ||
1047 | |||
1048 | /* Configure data delay */ | ||
1049 | snd_soc_write(codec, AIC3X_ASD_INTF_CTRLC, aic3x->tdm_delay); | ||
1050 | |||
1051 | return 0; | ||
1052 | } | ||
1053 | |||
1012 | static int aic3x_mute(struct snd_soc_dai *dai, int mute) | 1054 | static int aic3x_mute(struct snd_soc_dai *dai, int mute) |
1013 | { | 1055 | { |
1014 | struct snd_soc_codec *codec = dai->codec; | 1056 | struct snd_soc_codec *codec = dai->codec; |
@@ -1048,7 +1090,6 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1048 | struct snd_soc_codec *codec = codec_dai->codec; | 1090 | struct snd_soc_codec *codec = codec_dai->codec; |
1049 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 1091 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
1050 | u8 iface_areg, iface_breg; | 1092 | u8 iface_areg, iface_breg; |
1051 | int delay = 0; | ||
1052 | 1093 | ||
1053 | iface_areg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f; | 1094 | iface_areg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f; |
1054 | iface_breg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f; | 1095 | iface_breg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f; |
@@ -1076,7 +1117,6 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1076 | case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): | 1117 | case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): |
1077 | break; | 1118 | break; |
1078 | case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF): | 1119 | case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF): |
1079 | delay = 1; | ||
1080 | case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF): | 1120 | case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF): |
1081 | iface_breg |= (0x01 << 6); | 1121 | iface_breg |= (0x01 << 6); |
1082 | break; | 1122 | break; |
@@ -1090,10 +1130,45 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1090 | return -EINVAL; | 1130 | return -EINVAL; |
1091 | } | 1131 | } |
1092 | 1132 | ||
1133 | aic3x->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||
1134 | |||
1093 | /* set iface */ | 1135 | /* set iface */ |
1094 | snd_soc_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg); | 1136 | snd_soc_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg); |
1095 | snd_soc_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg); | 1137 | snd_soc_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg); |
1096 | snd_soc_write(codec, AIC3X_ASD_INTF_CTRLC, delay); | 1138 | |
1139 | return 0; | ||
1140 | } | ||
1141 | |||
1142 | static int aic3x_set_dai_tdm_slot(struct snd_soc_dai *codec_dai, | ||
1143 | unsigned int tx_mask, unsigned int rx_mask, | ||
1144 | int slots, int slot_width) | ||
1145 | { | ||
1146 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1147 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | ||
1148 | unsigned int lsb; | ||
1149 | |||
1150 | if (tx_mask != rx_mask) { | ||
1151 | dev_err(codec->dev, "tx and rx masks must be symmetric\n"); | ||
1152 | return -EINVAL; | ||
1153 | } | ||
1154 | |||
1155 | if (unlikely(!tx_mask)) { | ||
1156 | dev_err(codec->dev, "tx and rx masks need to be non 0\n"); | ||
1157 | return -EINVAL; | ||
1158 | } | ||
1159 | |||
1160 | /* TDM based on DSP mode requires slots to be adjacent */ | ||
1161 | lsb = __ffs(tx_mask); | ||
1162 | if ((lsb + 1) != __fls(tx_mask)) { | ||
1163 | dev_err(codec->dev, "Invalid mask, slots must be adjacent\n"); | ||
1164 | return -EINVAL; | ||
1165 | } | ||
1166 | |||
1167 | aic3x->tdm_delay = lsb * slot_width; | ||
1168 | |||
1169 | /* DOUT in high-impedance on inactive bit clocks */ | ||
1170 | snd_soc_update_bits(codec, AIC3X_ASD_INTF_CTRLA, | ||
1171 | DOUT_TRISTATE, DOUT_TRISTATE); | ||
1097 | 1172 | ||
1098 | return 0; | 1173 | return 0; |
1099 | } | 1174 | } |
@@ -1212,9 +1287,11 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec, | |||
1212 | 1287 | ||
1213 | static const struct snd_soc_dai_ops aic3x_dai_ops = { | 1288 | static const struct snd_soc_dai_ops aic3x_dai_ops = { |
1214 | .hw_params = aic3x_hw_params, | 1289 | .hw_params = aic3x_hw_params, |
1290 | .prepare = aic3x_prepare, | ||
1215 | .digital_mute = aic3x_mute, | 1291 | .digital_mute = aic3x_mute, |
1216 | .set_sysclk = aic3x_set_dai_sysclk, | 1292 | .set_sysclk = aic3x_set_dai_sysclk, |
1217 | .set_fmt = aic3x_set_dai_fmt, | 1293 | .set_fmt = aic3x_set_dai_fmt, |
1294 | .set_tdm_slot = aic3x_set_dai_tdm_slot, | ||
1218 | }; | 1295 | }; |
1219 | 1296 | ||
1220 | static struct snd_soc_dai_driver aic3x_dai = { | 1297 | static struct snd_soc_dai_driver aic3x_dai = { |
@@ -1414,7 +1491,6 @@ static int aic3x_remove(struct snd_soc_codec *codec) | |||
1414 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 1491 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
1415 | int i; | 1492 | int i; |
1416 | 1493 | ||
1417 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1418 | list_del(&aic3x->list); | 1494 | list_del(&aic3x->list); |
1419 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) | 1495 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) |
1420 | regulator_unregister_notifier(aic3x->supplies[i].consumer, | 1496 | regulator_unregister_notifier(aic3x->supplies[i].consumer, |
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index e521ac3ddde8..89fa692df206 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h | |||
@@ -169,6 +169,7 @@ | |||
169 | /* Audio serial data interface control register A bits */ | 169 | /* Audio serial data interface control register A bits */ |
170 | #define BIT_CLK_MASTER 0x80 | 170 | #define BIT_CLK_MASTER 0x80 |
171 | #define WORD_CLK_MASTER 0x40 | 171 | #define WORD_CLK_MASTER 0x40 |
172 | #define DOUT_TRISTATE 0x20 | ||
172 | 173 | ||
173 | /* Codec Datapath setup register 7 */ | 174 | /* Codec Datapath setup register 7 */ |
174 | #define FSREF_44100 (1 << 7) | 175 | #define FSREF_44100 (1 << 7) |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index e21ed934bdbf..0fe2ced5b09f 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -1436,8 +1436,6 @@ static int dac33_soc_remove(struct snd_soc_codec *codec) | |||
1436 | { | 1436 | { |
1437 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 1437 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1438 | 1438 | ||
1439 | dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1440 | |||
1441 | if (dac33->irq >= 0) { | 1439 | if (dac33->irq >= 0) { |
1442 | free_irq(dac33->irq, dac33->codec); | 1440 | free_irq(dac33->irq, dac33->codec); |
1443 | destroy_workqueue(dac33->dac33_wq); | 1441 | destroy_workqueue(dac33->dac33_wq); |
diff --git a/sound/soc/codecs/ts3a227e.c b/sound/soc/codecs/ts3a227e.c new file mode 100644 index 000000000000..1d1205702d23 --- /dev/null +++ b/sound/soc/codecs/ts3a227e.c | |||
@@ -0,0 +1,314 @@ | |||
1 | /* | ||
2 | * TS3A227E Autonomous Audio Accessory Detection and Configuration Switch | ||
3 | * | ||
4 | * Copyright (C) 2014 Google, Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/gpio.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/input.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/of_gpio.h> | ||
17 | #include <linux/regmap.h> | ||
18 | |||
19 | #include <sound/core.h> | ||
20 | #include <sound/jack.h> | ||
21 | #include <sound/soc.h> | ||
22 | |||
23 | struct ts3a227e { | ||
24 | struct regmap *regmap; | ||
25 | struct snd_soc_jack *jack; | ||
26 | bool plugged; | ||
27 | bool mic_present; | ||
28 | unsigned int buttons_held; | ||
29 | }; | ||
30 | |||
31 | /* Button values to be reported on the jack */ | ||
32 | static const int ts3a227e_buttons[] = { | ||
33 | SND_JACK_BTN_0, | ||
34 | SND_JACK_BTN_1, | ||
35 | SND_JACK_BTN_2, | ||
36 | SND_JACK_BTN_3, | ||
37 | }; | ||
38 | |||
39 | #define TS3A227E_NUM_BUTTONS 4 | ||
40 | #define TS3A227E_JACK_MASK (SND_JACK_HEADPHONE | \ | ||
41 | SND_JACK_MICROPHONE | \ | ||
42 | SND_JACK_BTN_0 | \ | ||
43 | SND_JACK_BTN_1 | \ | ||
44 | SND_JACK_BTN_2 | \ | ||
45 | SND_JACK_BTN_3) | ||
46 | |||
47 | /* TS3A227E registers */ | ||
48 | #define TS3A227E_REG_DEVICE_ID 0x00 | ||
49 | #define TS3A227E_REG_INTERRUPT 0x01 | ||
50 | #define TS3A227E_REG_KP_INTERRUPT 0x02 | ||
51 | #define TS3A227E_REG_INTERRUPT_DISABLE 0x03 | ||
52 | #define TS3A227E_REG_SETTING_1 0x04 | ||
53 | #define TS3A227E_REG_SETTING_2 0x05 | ||
54 | #define TS3A227E_REG_SETTING_3 0x06 | ||
55 | #define TS3A227E_REG_SWITCH_CONTROL_1 0x07 | ||
56 | #define TS3A227E_REG_SWITCH_CONTROL_2 0x08 | ||
57 | #define TS3A227E_REG_SWITCH_STATUS_1 0x09 | ||
58 | #define TS3A227E_REG_SWITCH_STATUS_2 0x0a | ||
59 | #define TS3A227E_REG_ACCESSORY_STATUS 0x0b | ||
60 | #define TS3A227E_REG_ADC_OUTPUT 0x0c | ||
61 | #define TS3A227E_REG_KP_THRESHOLD_1 0x0d | ||
62 | #define TS3A227E_REG_KP_THRESHOLD_2 0x0e | ||
63 | #define TS3A227E_REG_KP_THRESHOLD_3 0x0f | ||
64 | |||
65 | /* TS3A227E_REG_INTERRUPT 0x01 */ | ||
66 | #define INS_REM_EVENT 0x01 | ||
67 | #define DETECTION_COMPLETE_EVENT 0x02 | ||
68 | |||
69 | /* TS3A227E_REG_KP_INTERRUPT 0x02 */ | ||
70 | #define PRESS_MASK(idx) (0x01 << (2 * (idx))) | ||
71 | #define RELEASE_MASK(idx) (0x02 << (2 * (idx))) | ||
72 | |||
73 | /* TS3A227E_REG_INTERRUPT_DISABLE 0x03 */ | ||
74 | #define INS_REM_INT_DISABLE 0x01 | ||
75 | #define DETECTION_COMPLETE_INT_DISABLE 0x02 | ||
76 | #define ADC_COMPLETE_INT_DISABLE 0x04 | ||
77 | #define INTB_DISABLE 0x08 | ||
78 | |||
79 | /* TS3A227E_REG_SETTING_2 0x05 */ | ||
80 | #define KP_ENABLE 0x04 | ||
81 | |||
82 | /* TS3A227E_REG_ACCESSORY_STATUS 0x0b */ | ||
83 | #define TYPE_3_POLE 0x01 | ||
84 | #define TYPE_4_POLE_OMTP 0x02 | ||
85 | #define TYPE_4_POLE_STANDARD 0x04 | ||
86 | #define JACK_INSERTED 0x08 | ||
87 | #define EITHER_MIC_MASK (TYPE_4_POLE_OMTP | TYPE_4_POLE_STANDARD) | ||
88 | |||
89 | static const struct reg_default ts3a227e_reg_defaults[] = { | ||
90 | { TS3A227E_REG_DEVICE_ID, 0x10 }, | ||
91 | { TS3A227E_REG_INTERRUPT, 0x00 }, | ||
92 | { TS3A227E_REG_KP_INTERRUPT, 0x00 }, | ||
93 | { TS3A227E_REG_INTERRUPT_DISABLE, 0x08 }, | ||
94 | { TS3A227E_REG_SETTING_1, 0x23 }, | ||
95 | { TS3A227E_REG_SETTING_2, 0x00 }, | ||
96 | { TS3A227E_REG_SETTING_3, 0x0e }, | ||
97 | { TS3A227E_REG_SWITCH_CONTROL_1, 0x00 }, | ||
98 | { TS3A227E_REG_SWITCH_CONTROL_2, 0x00 }, | ||
99 | { TS3A227E_REG_SWITCH_STATUS_1, 0x0c }, | ||
100 | { TS3A227E_REG_SWITCH_STATUS_2, 0x00 }, | ||
101 | { TS3A227E_REG_ACCESSORY_STATUS, 0x00 }, | ||
102 | { TS3A227E_REG_ADC_OUTPUT, 0x00 }, | ||
103 | { TS3A227E_REG_KP_THRESHOLD_1, 0x20 }, | ||
104 | { TS3A227E_REG_KP_THRESHOLD_2, 0x40 }, | ||
105 | { TS3A227E_REG_KP_THRESHOLD_3, 0x68 }, | ||
106 | }; | ||
107 | |||
108 | static bool ts3a227e_readable_reg(struct device *dev, unsigned int reg) | ||
109 | { | ||
110 | switch (reg) { | ||
111 | case TS3A227E_REG_DEVICE_ID ... TS3A227E_REG_KP_THRESHOLD_3: | ||
112 | return true; | ||
113 | default: | ||
114 | return false; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static bool ts3a227e_writeable_reg(struct device *dev, unsigned int reg) | ||
119 | { | ||
120 | switch (reg) { | ||
121 | case TS3A227E_REG_INTERRUPT_DISABLE ... TS3A227E_REG_SWITCH_CONTROL_2: | ||
122 | case TS3A227E_REG_KP_THRESHOLD_1 ... TS3A227E_REG_KP_THRESHOLD_3: | ||
123 | return true; | ||
124 | default: | ||
125 | return false; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static bool ts3a227e_volatile_reg(struct device *dev, unsigned int reg) | ||
130 | { | ||
131 | switch (reg) { | ||
132 | case TS3A227E_REG_INTERRUPT ... TS3A227E_REG_INTERRUPT_DISABLE: | ||
133 | case TS3A227E_REG_SETTING_2: | ||
134 | case TS3A227E_REG_SWITCH_STATUS_1 ... TS3A227E_REG_ADC_OUTPUT: | ||
135 | return true; | ||
136 | default: | ||
137 | return false; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | static void ts3a227e_jack_report(struct ts3a227e *ts3a227e) | ||
142 | { | ||
143 | unsigned int i; | ||
144 | int report = 0; | ||
145 | |||
146 | if (!ts3a227e->jack) | ||
147 | return; | ||
148 | |||
149 | if (ts3a227e->plugged) | ||
150 | report = SND_JACK_HEADPHONE; | ||
151 | if (ts3a227e->mic_present) | ||
152 | report |= SND_JACK_MICROPHONE; | ||
153 | for (i = 0; i < TS3A227E_NUM_BUTTONS; i++) { | ||
154 | if (ts3a227e->buttons_held & (1 << i)) | ||
155 | report |= ts3a227e_buttons[i]; | ||
156 | } | ||
157 | snd_soc_jack_report(ts3a227e->jack, report, TS3A227E_JACK_MASK); | ||
158 | } | ||
159 | |||
160 | static void ts3a227e_new_jack_state(struct ts3a227e *ts3a227e, unsigned acc_reg) | ||
161 | { | ||
162 | bool plugged, mic_present; | ||
163 | |||
164 | plugged = !!(acc_reg & JACK_INSERTED); | ||
165 | mic_present = plugged && !!(acc_reg & EITHER_MIC_MASK); | ||
166 | |||
167 | ts3a227e->plugged = plugged; | ||
168 | |||
169 | if (mic_present != ts3a227e->mic_present) { | ||
170 | ts3a227e->mic_present = mic_present; | ||
171 | ts3a227e->buttons_held = 0; | ||
172 | if (mic_present) { | ||
173 | /* Enable key press detection. */ | ||
174 | regmap_update_bits(ts3a227e->regmap, | ||
175 | TS3A227E_REG_SETTING_2, | ||
176 | KP_ENABLE, KP_ENABLE); | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | |||
181 | static irqreturn_t ts3a227e_interrupt(int irq, void *data) | ||
182 | { | ||
183 | struct ts3a227e *ts3a227e = (struct ts3a227e *)data; | ||
184 | struct regmap *regmap = ts3a227e->regmap; | ||
185 | unsigned int int_reg, kp_int_reg, acc_reg, i; | ||
186 | |||
187 | /* Check for plug/unplug. */ | ||
188 | regmap_read(regmap, TS3A227E_REG_INTERRUPT, &int_reg); | ||
189 | if (int_reg & (DETECTION_COMPLETE_EVENT | INS_REM_EVENT)) { | ||
190 | regmap_read(regmap, TS3A227E_REG_ACCESSORY_STATUS, &acc_reg); | ||
191 | ts3a227e_new_jack_state(ts3a227e, acc_reg); | ||
192 | } | ||
193 | |||
194 | /* Report any key events. */ | ||
195 | regmap_read(regmap, TS3A227E_REG_KP_INTERRUPT, &kp_int_reg); | ||
196 | for (i = 0; i < TS3A227E_NUM_BUTTONS; i++) { | ||
197 | if (kp_int_reg & PRESS_MASK(i)) | ||
198 | ts3a227e->buttons_held |= (1 << i); | ||
199 | if (kp_int_reg & RELEASE_MASK(i)) | ||
200 | ts3a227e->buttons_held &= ~(1 << i); | ||
201 | } | ||
202 | |||
203 | ts3a227e_jack_report(ts3a227e); | ||
204 | |||
205 | return IRQ_HANDLED; | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * ts3a227e_enable_jack_detect - Specify a jack for event reporting | ||
210 | * | ||
211 | * @component: component to register the jack with | ||
212 | * @jack: jack to use to report headset and button events on | ||
213 | * | ||
214 | * After this function has been called the headset insert/remove and button | ||
215 | * events 0-3 will be routed to the given jack. Jack can be null to stop | ||
216 | * reporting. | ||
217 | */ | ||
218 | int ts3a227e_enable_jack_detect(struct snd_soc_component *component, | ||
219 | struct snd_soc_jack *jack) | ||
220 | { | ||
221 | struct ts3a227e *ts3a227e = snd_soc_component_get_drvdata(component); | ||
222 | |||
223 | snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA); | ||
224 | snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); | ||
225 | snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); | ||
226 | snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); | ||
227 | |||
228 | ts3a227e->jack = jack; | ||
229 | ts3a227e_jack_report(ts3a227e); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | EXPORT_SYMBOL_GPL(ts3a227e_enable_jack_detect); | ||
234 | |||
235 | static struct snd_soc_component_driver ts3a227e_soc_driver; | ||
236 | |||
237 | static const struct regmap_config ts3a227e_regmap_config = { | ||
238 | .val_bits = 8, | ||
239 | .reg_bits = 8, | ||
240 | |||
241 | .max_register = TS3A227E_REG_KP_THRESHOLD_3, | ||
242 | .readable_reg = ts3a227e_readable_reg, | ||
243 | .writeable_reg = ts3a227e_writeable_reg, | ||
244 | .volatile_reg = ts3a227e_volatile_reg, | ||
245 | |||
246 | .cache_type = REGCACHE_RBTREE, | ||
247 | .reg_defaults = ts3a227e_reg_defaults, | ||
248 | .num_reg_defaults = ARRAY_SIZE(ts3a227e_reg_defaults), | ||
249 | }; | ||
250 | |||
251 | static int ts3a227e_i2c_probe(struct i2c_client *i2c, | ||
252 | const struct i2c_device_id *id) | ||
253 | { | ||
254 | struct ts3a227e *ts3a227e; | ||
255 | struct device *dev = &i2c->dev; | ||
256 | int ret; | ||
257 | |||
258 | ts3a227e = devm_kzalloc(&i2c->dev, sizeof(*ts3a227e), GFP_KERNEL); | ||
259 | if (ts3a227e == NULL) | ||
260 | return -ENOMEM; | ||
261 | |||
262 | i2c_set_clientdata(i2c, ts3a227e); | ||
263 | |||
264 | ts3a227e->regmap = devm_regmap_init_i2c(i2c, &ts3a227e_regmap_config); | ||
265 | if (IS_ERR(ts3a227e->regmap)) | ||
266 | return PTR_ERR(ts3a227e->regmap); | ||
267 | |||
268 | ret = devm_request_threaded_irq(dev, i2c->irq, NULL, ts3a227e_interrupt, | ||
269 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
270 | "TS3A227E", ts3a227e); | ||
271 | if (ret) { | ||
272 | dev_err(dev, "Cannot request irq %d (%d)\n", i2c->irq, ret); | ||
273 | return ret; | ||
274 | } | ||
275 | |||
276 | ret = devm_snd_soc_register_component(&i2c->dev, &ts3a227e_soc_driver, | ||
277 | NULL, 0); | ||
278 | if (ret) | ||
279 | return ret; | ||
280 | |||
281 | /* Enable interrupts except for ADC complete. */ | ||
282 | regmap_update_bits(ts3a227e->regmap, TS3A227E_REG_INTERRUPT_DISABLE, | ||
283 | INTB_DISABLE | ADC_COMPLETE_INT_DISABLE, | ||
284 | ADC_COMPLETE_INT_DISABLE); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static const struct i2c_device_id ts3a227e_i2c_ids[] = { | ||
290 | { "ts3a227e", 0 }, | ||
291 | { } | ||
292 | }; | ||
293 | MODULE_DEVICE_TABLE(i2c, ts3a227e_i2c_ids); | ||
294 | |||
295 | static const struct of_device_id ts3a227e_of_match[] = { | ||
296 | { .compatible = "ti,ts3a227e", }, | ||
297 | { } | ||
298 | }; | ||
299 | MODULE_DEVICE_TABLE(of, ts3a227e_of_match); | ||
300 | |||
301 | static struct i2c_driver ts3a227e_driver = { | ||
302 | .driver = { | ||
303 | .name = "ts3a227e", | ||
304 | .owner = THIS_MODULE, | ||
305 | .of_match_table = of_match_ptr(ts3a227e_of_match), | ||
306 | }, | ||
307 | .probe = ts3a227e_i2c_probe, | ||
308 | .id_table = ts3a227e_i2c_ids, | ||
309 | }; | ||
310 | module_i2c_driver(ts3a227e_driver); | ||
311 | |||
312 | MODULE_DESCRIPTION("ASoC ts3a227e driver"); | ||
313 | MODULE_AUTHOR("Dylan Reid <dgreid@chromium.org>"); | ||
314 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/ts3a227e.h b/sound/soc/codecs/ts3a227e.h new file mode 100644 index 000000000000..e2acf9c5bebe --- /dev/null +++ b/sound/soc/codecs/ts3a227e.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * TS3A227E Autonous Audio Accessory Detection and Configureation Switch | ||
3 | * | ||
4 | * Copyright (C) 2014 Google, Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef _TS3A227E_H | ||
12 | #define _TS3A227E_H | ||
13 | |||
14 | int ts3a227e_enable_jack_detect(struct snd_soc_component *component, | ||
15 | struct snd_soc_jack *jack); | ||
16 | |||
17 | #endif | ||
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index b6b0cb399599..27f3b21effb2 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -2177,8 +2177,6 @@ static int twl4030_soc_remove(struct snd_soc_codec *codec) | |||
2177 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 2177 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
2178 | struct twl4030_codec_data *pdata = twl4030->pdata; | 2178 | struct twl4030_codec_data *pdata = twl4030->pdata; |
2179 | 2179 | ||
2180 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2181 | |||
2182 | if (pdata && pdata->hs_extmute && gpio_is_valid(pdata->hs_extmute_gpio)) | 2180 | if (pdata && pdata->hs_extmute && gpio_is_valid(pdata->hs_extmute_gpio)) |
2183 | gpio_free(pdata->hs_extmute_gpio); | 2181 | gpio_free(pdata->hs_extmute_gpio); |
2184 | 2182 | ||
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 0f6067f04e29..5ff2b1e4638e 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -1095,25 +1095,6 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
1095 | }, | 1095 | }, |
1096 | }; | 1096 | }; |
1097 | 1097 | ||
1098 | #ifdef CONFIG_PM | ||
1099 | static int twl6040_suspend(struct snd_soc_codec *codec) | ||
1100 | { | ||
1101 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1102 | |||
1103 | return 0; | ||
1104 | } | ||
1105 | |||
1106 | static int twl6040_resume(struct snd_soc_codec *codec) | ||
1107 | { | ||
1108 | twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1109 | |||
1110 | return 0; | ||
1111 | } | ||
1112 | #else | ||
1113 | #define twl6040_suspend NULL | ||
1114 | #define twl6040_resume NULL | ||
1115 | #endif | ||
1116 | |||
1117 | static int twl6040_probe(struct snd_soc_codec *codec) | 1098 | static int twl6040_probe(struct snd_soc_codec *codec) |
1118 | { | 1099 | { |
1119 | struct twl6040_data *priv; | 1100 | struct twl6040_data *priv; |
@@ -1160,7 +1141,6 @@ static int twl6040_remove(struct snd_soc_codec *codec) | |||
1160 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | 1141 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
1161 | 1142 | ||
1162 | free_irq(priv->plug_irq, codec); | 1143 | free_irq(priv->plug_irq, codec); |
1163 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1164 | 1144 | ||
1165 | return 0; | 1145 | return 0; |
1166 | } | 1146 | } |
@@ -1168,11 +1148,10 @@ static int twl6040_remove(struct snd_soc_codec *codec) | |||
1168 | static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { | 1148 | static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { |
1169 | .probe = twl6040_probe, | 1149 | .probe = twl6040_probe, |
1170 | .remove = twl6040_remove, | 1150 | .remove = twl6040_remove, |
1171 | .suspend = twl6040_suspend, | ||
1172 | .resume = twl6040_resume, | ||
1173 | .read = twl6040_read, | 1151 | .read = twl6040_read, |
1174 | .write = twl6040_write, | 1152 | .write = twl6040_write, |
1175 | .set_bias_level = twl6040_set_bias_level, | 1153 | .set_bias_level = twl6040_set_bias_level, |
1154 | .suspend_bias_off = true, | ||
1176 | .ignore_pmdown_time = true, | 1155 | .ignore_pmdown_time = true, |
1177 | 1156 | ||
1178 | .controls = twl6040_snd_controls, | 1157 | .controls = twl6040_snd_controls, |
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index 32b2f78aa62c..4056260a502e 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c | |||
@@ -518,11 +518,6 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec) | |||
518 | 518 | ||
519 | uda134x_reset(codec); | 519 | uda134x_reset(codec); |
520 | 520 | ||
521 | if (pd->is_powered_on_standby) | ||
522 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); | ||
523 | else | ||
524 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
525 | |||
526 | if (pd->model == UDA134X_UDA1341) { | 521 | if (pd->model == UDA134X_UDA1341) { |
527 | widgets = uda1341_dapm_widgets; | 522 | widgets = uda1341_dapm_widgets; |
528 | num_widgets = ARRAY_SIZE(uda1341_dapm_widgets); | 523 | num_widgets = ARRAY_SIZE(uda1341_dapm_widgets); |
@@ -574,44 +569,21 @@ static int uda134x_soc_remove(struct snd_soc_codec *codec) | |||
574 | { | 569 | { |
575 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); | 570 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
576 | 571 | ||
577 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
578 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
579 | |||
580 | kfree(uda134x); | 572 | kfree(uda134x); |
581 | return 0; | 573 | return 0; |
582 | } | 574 | } |
583 | 575 | ||
584 | #if defined(CONFIG_PM) | ||
585 | static int uda134x_soc_suspend(struct snd_soc_codec *codec) | ||
586 | { | ||
587 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
588 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | static int uda134x_soc_resume(struct snd_soc_codec *codec) | ||
593 | { | ||
594 | uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | ||
595 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); | ||
596 | return 0; | ||
597 | } | ||
598 | #else | ||
599 | #define uda134x_soc_suspend NULL | ||
600 | #define uda134x_soc_resume NULL | ||
601 | #endif /* CONFIG_PM */ | ||
602 | |||
603 | static struct snd_soc_codec_driver soc_codec_dev_uda134x = { | 576 | static struct snd_soc_codec_driver soc_codec_dev_uda134x = { |
604 | .probe = uda134x_soc_probe, | 577 | .probe = uda134x_soc_probe, |
605 | .remove = uda134x_soc_remove, | 578 | .remove = uda134x_soc_remove, |
606 | .suspend = uda134x_soc_suspend, | ||
607 | .resume = uda134x_soc_resume, | ||
608 | .reg_cache_size = sizeof(uda134x_reg), | 579 | .reg_cache_size = sizeof(uda134x_reg), |
609 | .reg_word_size = sizeof(u8), | 580 | .reg_word_size = sizeof(u8), |
610 | .reg_cache_default = uda134x_reg, | 581 | .reg_cache_default = uda134x_reg, |
611 | .reg_cache_step = 1, | 582 | .reg_cache_step = 1, |
612 | .read = uda134x_read_reg_cache, | 583 | .read = uda134x_read_reg_cache, |
613 | .write = uda134x_write, | ||
614 | .set_bias_level = uda134x_set_bias_level, | 584 | .set_bias_level = uda134x_set_bias_level, |
585 | .suspend_bias_off = true, | ||
586 | |||
615 | .dapm_widgets = uda134x_dapm_widgets, | 587 | .dapm_widgets = uda134x_dapm_widgets, |
616 | .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets), | 588 | .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets), |
617 | .dapm_routes = uda134x_dapm_routes, | 589 | .dapm_routes = uda134x_dapm_routes, |
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index e62e70781ec2..dc7778b6dd7f 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c | |||
@@ -693,18 +693,6 @@ static struct snd_soc_dai_driver uda1380_dai[] = { | |||
693 | }, | 693 | }, |
694 | }; | 694 | }; |
695 | 695 | ||
696 | static int uda1380_suspend(struct snd_soc_codec *codec) | ||
697 | { | ||
698 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | static int uda1380_resume(struct snd_soc_codec *codec) | ||
703 | { | ||
704 | uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | static int uda1380_probe(struct snd_soc_codec *codec) | 696 | static int uda1380_probe(struct snd_soc_codec *codec) |
709 | { | 697 | { |
710 | struct uda1380_platform_data *pdata =codec->dev->platform_data; | 698 | struct uda1380_platform_data *pdata =codec->dev->platform_data; |
@@ -739,8 +727,6 @@ static int uda1380_probe(struct snd_soc_codec *codec) | |||
739 | 727 | ||
740 | INIT_WORK(&uda1380->work, uda1380_flush_work); | 728 | INIT_WORK(&uda1380->work, uda1380_flush_work); |
741 | 729 | ||
742 | /* power on device */ | ||
743 | uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
744 | /* set clock input */ | 730 | /* set clock input */ |
745 | switch (pdata->dac_clk) { | 731 | switch (pdata->dac_clk) { |
746 | case UDA1380_DAC_CLK_SYSCLK: | 732 | case UDA1380_DAC_CLK_SYSCLK: |
@@ -766,8 +752,6 @@ static int uda1380_remove(struct snd_soc_codec *codec) | |||
766 | { | 752 | { |
767 | struct uda1380_platform_data *pdata =codec->dev->platform_data; | 753 | struct uda1380_platform_data *pdata =codec->dev->platform_data; |
768 | 754 | ||
769 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
770 | |||
771 | gpio_free(pdata->gpio_reset); | 755 | gpio_free(pdata->gpio_reset); |
772 | gpio_free(pdata->gpio_power); | 756 | gpio_free(pdata->gpio_power); |
773 | 757 | ||
@@ -777,11 +761,11 @@ static int uda1380_remove(struct snd_soc_codec *codec) | |||
777 | static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { | 761 | static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { |
778 | .probe = uda1380_probe, | 762 | .probe = uda1380_probe, |
779 | .remove = uda1380_remove, | 763 | .remove = uda1380_remove, |
780 | .suspend = uda1380_suspend, | ||
781 | .resume = uda1380_resume, | ||
782 | .read = uda1380_read_reg_cache, | 764 | .read = uda1380_read_reg_cache, |
783 | .write = uda1380_write, | 765 | .write = uda1380_write, |
784 | .set_bias_level = uda1380_set_bias_level, | 766 | .set_bias_level = uda1380_set_bias_level, |
767 | .suspend_bias_off = true, | ||
768 | |||
785 | .reg_cache_size = ARRAY_SIZE(uda1380_reg), | 769 | .reg_cache_size = ARRAY_SIZE(uda1380_reg), |
786 | .reg_word_size = sizeof(u16), | 770 | .reg_word_size = sizeof(u16), |
787 | .reg_cache_default = uda1380_reg, | 771 | .reg_cache_default = uda1380_reg, |
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index f3d4e88d0b7b..00aea4100bb3 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c | |||
@@ -452,7 +452,6 @@ static int wl1273_probe(struct snd_soc_codec *codec) | |||
452 | { | 452 | { |
453 | struct wl1273_core **core = codec->dev->platform_data; | 453 | struct wl1273_core **core = codec->dev->platform_data; |
454 | struct wl1273_priv *wl1273; | 454 | struct wl1273_priv *wl1273; |
455 | int r; | ||
456 | 455 | ||
457 | dev_dbg(codec->dev, "%s.\n", __func__); | 456 | dev_dbg(codec->dev, "%s.\n", __func__); |
458 | 457 | ||
@@ -470,12 +469,7 @@ static int wl1273_probe(struct snd_soc_codec *codec) | |||
470 | 469 | ||
471 | snd_soc_codec_set_drvdata(codec, wl1273); | 470 | snd_soc_codec_set_drvdata(codec, wl1273); |
472 | 471 | ||
473 | r = snd_soc_add_codec_controls(codec, wl1273_controls, | 472 | return 0; |
474 | ARRAY_SIZE(wl1273_controls)); | ||
475 | if (r) | ||
476 | kfree(wl1273); | ||
477 | |||
478 | return r; | ||
479 | } | 473 | } |
480 | 474 | ||
481 | static int wl1273_remove(struct snd_soc_codec *codec) | 475 | static int wl1273_remove(struct snd_soc_codec *codec) |
@@ -492,6 +486,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wl1273 = { | |||
492 | .probe = wl1273_probe, | 486 | .probe = wl1273_probe, |
493 | .remove = wl1273_remove, | 487 | .remove = wl1273_remove, |
494 | 488 | ||
489 | .controls = wl1273_controls, | ||
490 | .num_controls = ARRAY_SIZE(wl1273_controls), | ||
495 | .dapm_widgets = wl1273_dapm_widgets, | 491 | .dapm_widgets = wl1273_dapm_widgets, |
496 | .num_dapm_widgets = ARRAY_SIZE(wl1273_dapm_widgets), | 492 | .num_dapm_widgets = ARRAY_SIZE(wl1273_dapm_widgets), |
497 | .dapm_routes = wl1273_dapm_routes, | 493 | .dapm_routes = wl1273_dapm_routes, |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index f60234962527..d78fb8dffc8c 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -619,10 +619,10 @@ static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, | |||
619 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 619 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
620 | uint16_t data; | 620 | uint16_t data; |
621 | 621 | ||
622 | mutex_lock(&codec->mutex); | 622 | mutex_lock(&arizona->dac_comp_lock); |
623 | data = cpu_to_be16(arizona->dac_comp_coeff); | 623 | data = cpu_to_be16(arizona->dac_comp_coeff); |
624 | memcpy(ucontrol->value.bytes.data, &data, sizeof(data)); | 624 | memcpy(ucontrol->value.bytes.data, &data, sizeof(data)); |
625 | mutex_unlock(&codec->mutex); | 625 | mutex_unlock(&arizona->dac_comp_lock); |
626 | 626 | ||
627 | return 0; | 627 | return 0; |
628 | } | 628 | } |
@@ -633,11 +633,11 @@ static int wm5102_out_comp_coeff_put(struct snd_kcontrol *kcontrol, | |||
633 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 633 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
634 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 634 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
635 | 635 | ||
636 | mutex_lock(&codec->mutex); | 636 | mutex_lock(&arizona->dac_comp_lock); |
637 | memcpy(&arizona->dac_comp_coeff, ucontrol->value.bytes.data, | 637 | memcpy(&arizona->dac_comp_coeff, ucontrol->value.bytes.data, |
638 | sizeof(arizona->dac_comp_coeff)); | 638 | sizeof(arizona->dac_comp_coeff)); |
639 | arizona->dac_comp_coeff = be16_to_cpu(arizona->dac_comp_coeff); | 639 | arizona->dac_comp_coeff = be16_to_cpu(arizona->dac_comp_coeff); |
640 | mutex_unlock(&codec->mutex); | 640 | mutex_unlock(&arizona->dac_comp_lock); |
641 | 641 | ||
642 | return 0; | 642 | return 0; |
643 | } | 643 | } |
@@ -648,9 +648,9 @@ static int wm5102_out_comp_switch_get(struct snd_kcontrol *kcontrol, | |||
648 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 648 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
649 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 649 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
650 | 650 | ||
651 | mutex_lock(&codec->mutex); | 651 | mutex_lock(&arizona->dac_comp_lock); |
652 | ucontrol->value.integer.value[0] = arizona->dac_comp_enabled; | 652 | ucontrol->value.integer.value[0] = arizona->dac_comp_enabled; |
653 | mutex_unlock(&codec->mutex); | 653 | mutex_unlock(&arizona->dac_comp_lock); |
654 | 654 | ||
655 | return 0; | 655 | return 0; |
656 | } | 656 | } |
@@ -661,9 +661,9 @@ static int wm5102_out_comp_switch_put(struct snd_kcontrol *kcontrol, | |||
661 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 661 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
662 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 662 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
663 | 663 | ||
664 | mutex_lock(&codec->mutex); | 664 | mutex_lock(&arizona->dac_comp_lock); |
665 | arizona->dac_comp_enabled = ucontrol->value.integer.value[0]; | 665 | arizona->dac_comp_enabled = ucontrol->value.integer.value[0]; |
666 | mutex_unlock(&codec->mutex); | 666 | mutex_unlock(&arizona->dac_comp_lock); |
667 | 667 | ||
668 | return 0; | 668 | return 0; |
669 | } | 669 | } |
@@ -1900,6 +1900,8 @@ static int wm5102_probe(struct platform_device *pdev) | |||
1900 | return -ENOMEM; | 1900 | return -ENOMEM; |
1901 | platform_set_drvdata(pdev, wm5102); | 1901 | platform_set_drvdata(pdev, wm5102); |
1902 | 1902 | ||
1903 | mutex_init(&arizona->dac_comp_lock); | ||
1904 | |||
1903 | wm5102->core.arizona = arizona; | 1905 | wm5102->core.arizona = arizona; |
1904 | wm5102->core.num_inputs = 6; | 1906 | wm5102->core.num_inputs = 6; |
1905 | 1907 | ||
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 628ec774cf22..87f664b9cc7d 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -1242,19 +1242,6 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec, | |||
1242 | return 0; | 1242 | return 0; |
1243 | } | 1243 | } |
1244 | 1244 | ||
1245 | static int wm8350_suspend(struct snd_soc_codec *codec) | ||
1246 | { | ||
1247 | wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1248 | return 0; | ||
1249 | } | ||
1250 | |||
1251 | static int wm8350_resume(struct snd_soc_codec *codec) | ||
1252 | { | ||
1253 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1254 | |||
1255 | return 0; | ||
1256 | } | ||
1257 | |||
1258 | static void wm8350_hp_work(struct wm8350_data *priv, | 1245 | static void wm8350_hp_work(struct wm8350_data *priv, |
1259 | struct wm8350_jack_data *jack, | 1246 | struct wm8350_jack_data *jack, |
1260 | u16 mask) | 1247 | u16 mask) |
@@ -1565,9 +1552,6 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) | |||
1565 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD, | 1552 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD, |
1566 | wm8350_mic_handler, 0, "Microphone detect", priv); | 1553 | wm8350_mic_handler, 0, "Microphone detect", priv); |
1567 | 1554 | ||
1568 | |||
1569 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1570 | |||
1571 | return 0; | 1555 | return 0; |
1572 | } | 1556 | } |
1573 | 1557 | ||
@@ -1596,8 +1580,6 @@ static int wm8350_codec_remove(struct snd_soc_codec *codec) | |||
1596 | * wait for its completion */ | 1580 | * wait for its completion */ |
1597 | flush_delayed_work(&codec->dapm.delayed_work); | 1581 | flush_delayed_work(&codec->dapm.delayed_work); |
1598 | 1582 | ||
1599 | wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1600 | |||
1601 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1583 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
1602 | 1584 | ||
1603 | return 0; | 1585 | return 0; |
@@ -1613,10 +1595,9 @@ static struct regmap *wm8350_get_regmap(struct device *dev) | |||
1613 | static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { | 1595 | static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { |
1614 | .probe = wm8350_codec_probe, | 1596 | .probe = wm8350_codec_probe, |
1615 | .remove = wm8350_codec_remove, | 1597 | .remove = wm8350_codec_remove, |
1616 | .suspend = wm8350_suspend, | ||
1617 | .resume = wm8350_resume, | ||
1618 | .get_regmap = wm8350_get_regmap, | 1598 | .get_regmap = wm8350_get_regmap, |
1619 | .set_bias_level = wm8350_set_bias_level, | 1599 | .set_bias_level = wm8350_set_bias_level, |
1600 | .suspend_bias_off = true, | ||
1620 | 1601 | ||
1621 | .controls = wm8350_snd_controls, | 1602 | .controls = wm8350_snd_controls, |
1622 | .num_controls = ARRAY_SIZE(wm8350_snd_controls), | 1603 | .num_controls = ARRAY_SIZE(wm8350_snd_controls), |
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 72471bef2e9a..385894f6e264 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -58,12 +58,10 @@ static struct regulator_bulk_data power[] = { | |||
58 | 58 | ||
59 | /* codec private data */ | 59 | /* codec private data */ |
60 | struct wm8400_priv { | 60 | struct wm8400_priv { |
61 | struct snd_soc_codec *codec; | ||
62 | struct wm8400 *wm8400; | 61 | struct wm8400 *wm8400; |
63 | u16 fake_register; | 62 | u16 fake_register; |
64 | unsigned int sysclk; | 63 | unsigned int sysclk; |
65 | unsigned int pcmclk; | 64 | unsigned int pcmclk; |
66 | struct work_struct work; | ||
67 | int fll_in, fll_out; | 65 | int fll_in, fll_out; |
68 | }; | 66 | }; |
69 | 67 | ||
@@ -1278,30 +1276,6 @@ static struct snd_soc_dai_driver wm8400_dai = { | |||
1278 | .ops = &wm8400_dai_ops, | 1276 | .ops = &wm8400_dai_ops, |
1279 | }; | 1277 | }; |
1280 | 1278 | ||
1281 | static int wm8400_suspend(struct snd_soc_codec *codec) | ||
1282 | { | ||
1283 | wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1284 | |||
1285 | return 0; | ||
1286 | } | ||
1287 | |||
1288 | static int wm8400_resume(struct snd_soc_codec *codec) | ||
1289 | { | ||
1290 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1291 | |||
1292 | return 0; | ||
1293 | } | ||
1294 | |||
1295 | static void wm8400_probe_deferred(struct work_struct *work) | ||
1296 | { | ||
1297 | struct wm8400_priv *priv = container_of(work, struct wm8400_priv, | ||
1298 | work); | ||
1299 | struct snd_soc_codec *codec = priv->codec; | ||
1300 | |||
1301 | /* charge output caps */ | ||
1302 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1303 | } | ||
1304 | |||
1305 | static int wm8400_codec_probe(struct snd_soc_codec *codec) | 1279 | static int wm8400_codec_probe(struct snd_soc_codec *codec) |
1306 | { | 1280 | { |
1307 | struct wm8400 *wm8400 = dev_get_platdata(codec->dev); | 1281 | struct wm8400 *wm8400 = dev_get_platdata(codec->dev); |
@@ -1316,7 +1290,6 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec) | |||
1316 | 1290 | ||
1317 | snd_soc_codec_set_drvdata(codec, priv); | 1291 | snd_soc_codec_set_drvdata(codec, priv); |
1318 | priv->wm8400 = wm8400; | 1292 | priv->wm8400 = wm8400; |
1319 | priv->codec = codec; | ||
1320 | 1293 | ||
1321 | ret = devm_regulator_bulk_get(wm8400->dev, | 1294 | ret = devm_regulator_bulk_get(wm8400->dev, |
1322 | ARRAY_SIZE(power), &power[0]); | 1295 | ARRAY_SIZE(power), &power[0]); |
@@ -1325,8 +1298,6 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec) | |||
1325 | return ret; | 1298 | return ret; |
1326 | } | 1299 | } |
1327 | 1300 | ||
1328 | INIT_WORK(&priv->work, wm8400_probe_deferred); | ||
1329 | |||
1330 | wm8400_codec_reset(codec); | 1301 | wm8400_codec_reset(codec); |
1331 | 1302 | ||
1332 | reg = snd_soc_read(codec, WM8400_POWER_MANAGEMENT_1); | 1303 | reg = snd_soc_read(codec, WM8400_POWER_MANAGEMENT_1); |
@@ -1343,8 +1314,6 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec) | |||
1343 | snd_soc_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1314 | snd_soc_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1344 | snd_soc_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1315 | snd_soc_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1345 | 1316 | ||
1346 | if (!schedule_work(&priv->work)) | ||
1347 | return -EINVAL; | ||
1348 | return 0; | 1317 | return 0; |
1349 | } | 1318 | } |
1350 | 1319 | ||
@@ -1369,10 +1338,9 @@ static struct regmap *wm8400_get_regmap(struct device *dev) | |||
1369 | static struct snd_soc_codec_driver soc_codec_dev_wm8400 = { | 1338 | static struct snd_soc_codec_driver soc_codec_dev_wm8400 = { |
1370 | .probe = wm8400_codec_probe, | 1339 | .probe = wm8400_codec_probe, |
1371 | .remove = wm8400_codec_remove, | 1340 | .remove = wm8400_codec_remove, |
1372 | .suspend = wm8400_suspend, | ||
1373 | .resume = wm8400_resume, | ||
1374 | .get_regmap = wm8400_get_regmap, | 1341 | .get_regmap = wm8400_get_regmap, |
1375 | .set_bias_level = wm8400_set_bias_level, | 1342 | .set_bias_level = wm8400_set_bias_level, |
1343 | .suspend_bias_off = true, | ||
1376 | 1344 | ||
1377 | .controls = wm8400_snd_controls, | 1345 | .controls = wm8400_snd_controls, |
1378 | .num_controls = ARRAY_SIZE(wm8400_snd_controls), | 1346 | .num_controls = ARRAY_SIZE(wm8400_snd_controls), |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index e11127f9069e..8736ad094b24 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -575,41 +575,17 @@ static struct snd_soc_dai_driver wm8510_dai = { | |||
575 | .symmetric_rates = 1, | 575 | .symmetric_rates = 1, |
576 | }; | 576 | }; |
577 | 577 | ||
578 | static int wm8510_suspend(struct snd_soc_codec *codec) | ||
579 | { | ||
580 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | static int wm8510_resume(struct snd_soc_codec *codec) | ||
585 | { | ||
586 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
587 | return 0; | ||
588 | } | ||
589 | |||
590 | static int wm8510_probe(struct snd_soc_codec *codec) | 578 | static int wm8510_probe(struct snd_soc_codec *codec) |
591 | { | 579 | { |
592 | wm8510_reset(codec); | 580 | wm8510_reset(codec); |
593 | 581 | ||
594 | /* power on device */ | ||
595 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
596 | |||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | /* power down chip */ | ||
601 | static int wm8510_remove(struct snd_soc_codec *codec) | ||
602 | { | ||
603 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
604 | return 0; | 582 | return 0; |
605 | } | 583 | } |
606 | 584 | ||
607 | static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { | 585 | static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { |
608 | .probe = wm8510_probe, | 586 | .probe = wm8510_probe, |
609 | .remove = wm8510_remove, | ||
610 | .suspend = wm8510_suspend, | ||
611 | .resume = wm8510_resume, | ||
612 | .set_bias_level = wm8510_set_bias_level, | 587 | .set_bias_level = wm8510_set_bias_level, |
588 | .suspend_bias_off = true, | ||
613 | 589 | ||
614 | .controls = wm8510_snd_controls, | 590 | .controls = wm8510_snd_controls, |
615 | .num_controls = ARRAY_SIZE(wm8510_snd_controls), | 591 | .num_controls = ARRAY_SIZE(wm8510_snd_controls), |
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index ec1f5740dbd0..b1cc94f5fc4b 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -372,23 +372,6 @@ static struct snd_soc_dai_driver wm8523_dai = { | |||
372 | .ops = &wm8523_dai_ops, | 372 | .ops = &wm8523_dai_ops, |
373 | }; | 373 | }; |
374 | 374 | ||
375 | #ifdef CONFIG_PM | ||
376 | static int wm8523_suspend(struct snd_soc_codec *codec) | ||
377 | { | ||
378 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static int wm8523_resume(struct snd_soc_codec *codec) | ||
383 | { | ||
384 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
385 | return 0; | ||
386 | } | ||
387 | #else | ||
388 | #define wm8523_suspend NULL | ||
389 | #define wm8523_resume NULL | ||
390 | #endif | ||
391 | |||
392 | static int wm8523_probe(struct snd_soc_codec *codec) | 375 | static int wm8523_probe(struct snd_soc_codec *codec) |
393 | { | 376 | { |
394 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | 377 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
@@ -402,23 +385,13 @@ static int wm8523_probe(struct snd_soc_codec *codec) | |||
402 | WM8523_DACR_VU, WM8523_DACR_VU); | 385 | WM8523_DACR_VU, WM8523_DACR_VU); |
403 | snd_soc_update_bits(codec, WM8523_DAC_CTRL3, WM8523_ZC, WM8523_ZC); | 386 | snd_soc_update_bits(codec, WM8523_DAC_CTRL3, WM8523_ZC, WM8523_ZC); |
404 | 387 | ||
405 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | static int wm8523_remove(struct snd_soc_codec *codec) | ||
411 | { | ||
412 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
413 | return 0; | 388 | return 0; |
414 | } | 389 | } |
415 | 390 | ||
416 | static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { | 391 | static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { |
417 | .probe = wm8523_probe, | 392 | .probe = wm8523_probe, |
418 | .remove = wm8523_remove, | ||
419 | .suspend = wm8523_suspend, | ||
420 | .resume = wm8523_resume, | ||
421 | .set_bias_level = wm8523_set_bias_level, | 393 | .set_bias_level = wm8523_set_bias_level, |
394 | .suspend_bias_off = true, | ||
422 | 395 | ||
423 | .controls = wm8523_controls, | 396 | .controls = wm8523_controls, |
424 | .num_controls = ARRAY_SIZE(wm8523_controls), | 397 | .num_controls = ARRAY_SIZE(wm8523_controls), |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 911605ee25b0..0a887c5ec83a 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -882,8 +882,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) | |||
882 | goto err_regulator_enable; | 882 | goto err_regulator_enable; |
883 | } | 883 | } |
884 | 884 | ||
885 | wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
886 | |||
887 | return 0; | 885 | return 0; |
888 | 886 | ||
889 | err_regulator_enable: | 887 | err_regulator_enable: |
@@ -897,8 +895,6 @@ static int wm8580_remove(struct snd_soc_codec *codec) | |||
897 | { | 895 | { |
898 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); | 896 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
899 | 897 | ||
900 | wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
901 | |||
902 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 898 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
903 | 899 | ||
904 | return 0; | 900 | return 0; |
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 32187e739b4f..121e46d53779 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -350,19 +350,6 @@ static struct snd_soc_dai_driver wm8711_dai = { | |||
350 | .ops = &wm8711_ops, | 350 | .ops = &wm8711_ops, |
351 | }; | 351 | }; |
352 | 352 | ||
353 | static int wm8711_suspend(struct snd_soc_codec *codec) | ||
354 | { | ||
355 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); | ||
356 | wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static int wm8711_resume(struct snd_soc_codec *codec) | ||
361 | { | ||
362 | wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static int wm8711_probe(struct snd_soc_codec *codec) | 353 | static int wm8711_probe(struct snd_soc_codec *codec) |
367 | { | 354 | { |
368 | int ret; | 355 | int ret; |
@@ -373,8 +360,6 @@ static int wm8711_probe(struct snd_soc_codec *codec) | |||
373 | return ret; | 360 | return ret; |
374 | } | 361 | } |
375 | 362 | ||
376 | wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
377 | |||
378 | /* Latch the update bits */ | 363 | /* Latch the update bits */ |
379 | snd_soc_update_bits(codec, WM8711_LOUT1V, 0x0100, 0x0100); | 364 | snd_soc_update_bits(codec, WM8711_LOUT1V, 0x0100, 0x0100); |
380 | snd_soc_update_bits(codec, WM8711_ROUT1V, 0x0100, 0x0100); | 365 | snd_soc_update_bits(codec, WM8711_ROUT1V, 0x0100, 0x0100); |
@@ -383,19 +368,11 @@ static int wm8711_probe(struct snd_soc_codec *codec) | |||
383 | 368 | ||
384 | } | 369 | } |
385 | 370 | ||
386 | /* power down chip */ | ||
387 | static int wm8711_remove(struct snd_soc_codec *codec) | ||
388 | { | ||
389 | wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { | 371 | static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { |
394 | .probe = wm8711_probe, | 372 | .probe = wm8711_probe, |
395 | .remove = wm8711_remove, | ||
396 | .suspend = wm8711_suspend, | ||
397 | .resume = wm8711_resume, | ||
398 | .set_bias_level = wm8711_set_bias_level, | 373 | .set_bias_level = wm8711_set_bias_level, |
374 | .suspend_bias_off = true, | ||
375 | |||
399 | .controls = wm8711_snd_controls, | 376 | .controls = wm8711_snd_controls, |
400 | .num_controls = ARRAY_SIZE(wm8711_snd_controls), | 377 | .num_controls = ARRAY_SIZE(wm8711_snd_controls), |
401 | .dapm_widgets = wm8711_dapm_widgets, | 378 | .dapm_widgets = wm8711_dapm_widgets, |
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 38ff826f589a..55c7fb4fc786 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -212,40 +212,10 @@ static struct snd_soc_dai_driver wm8728_dai = { | |||
212 | .ops = &wm8728_dai_ops, | 212 | .ops = &wm8728_dai_ops, |
213 | }; | 213 | }; |
214 | 214 | ||
215 | static int wm8728_suspend(struct snd_soc_codec *codec) | ||
216 | { | ||
217 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static int wm8728_resume(struct snd_soc_codec *codec) | ||
223 | { | ||
224 | wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int wm8728_probe(struct snd_soc_codec *codec) | ||
230 | { | ||
231 | /* power on device */ | ||
232 | wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static int wm8728_remove(struct snd_soc_codec *codec) | ||
238 | { | ||
239 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { | 215 | static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { |
244 | .probe = wm8728_probe, | ||
245 | .remove = wm8728_remove, | ||
246 | .suspend = wm8728_suspend, | ||
247 | .resume = wm8728_resume, | ||
248 | .set_bias_level = wm8728_set_bias_level, | 216 | .set_bias_level = wm8728_set_bias_level, |
217 | .suspend_bias_off = true, | ||
218 | |||
249 | .controls = wm8728_snd_controls, | 219 | .controls = wm8728_snd_controls, |
250 | .num_controls = ARRAY_SIZE(wm8728_snd_controls), | 220 | .num_controls = ARRAY_SIZE(wm8728_snd_controls), |
251 | .dapm_widgets = wm8728_dapm_widgets, | 221 | .dapm_widgets = wm8728_dapm_widgets, |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index eebb3280bfad..b9211b42f6e9 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/regulator/consumer.h> | 24 | #include <linux/regulator/consumer.h> |
25 | #include <linux/spi/spi.h> | 25 | #include <linux/spi/spi.h> |
26 | #include <linux/of_device.h> | 26 | #include <linux/of_device.h> |
27 | #include <linux/mutex.h> | ||
27 | #include <sound/core.h> | 28 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 29 | #include <sound/pcm.h> |
29 | #include <sound/pcm_params.h> | 30 | #include <sound/pcm_params.h> |
@@ -50,6 +51,8 @@ struct wm8731_priv { | |||
50 | int sysclk_type; | 51 | int sysclk_type; |
51 | int playback_fs; | 52 | int playback_fs; |
52 | bool deemph; | 53 | bool deemph; |
54 | |||
55 | struct mutex lock; | ||
53 | }; | 56 | }; |
54 | 57 | ||
55 | 58 | ||
@@ -138,7 +141,7 @@ static int wm8731_put_deemph(struct snd_kcontrol *kcontrol, | |||
138 | if (deemph > 1) | 141 | if (deemph > 1) |
139 | return -EINVAL; | 142 | return -EINVAL; |
140 | 143 | ||
141 | mutex_lock(&codec->mutex); | 144 | mutex_lock(&wm8731->lock); |
142 | if (wm8731->deemph != deemph) { | 145 | if (wm8731->deemph != deemph) { |
143 | wm8731->deemph = deemph; | 146 | wm8731->deemph = deemph; |
144 | 147 | ||
@@ -146,7 +149,7 @@ static int wm8731_put_deemph(struct snd_kcontrol *kcontrol, | |||
146 | 149 | ||
147 | ret = 1; | 150 | ret = 1; |
148 | } | 151 | } |
149 | mutex_unlock(&codec->mutex); | 152 | mutex_unlock(&wm8731->lock); |
150 | 153 | ||
151 | return ret; | 154 | return ret; |
152 | } | 155 | } |
@@ -559,25 +562,6 @@ static struct snd_soc_dai_driver wm8731_dai = { | |||
559 | .symmetric_rates = 1, | 562 | .symmetric_rates = 1, |
560 | }; | 563 | }; |
561 | 564 | ||
562 | #ifdef CONFIG_PM | ||
563 | static int wm8731_suspend(struct snd_soc_codec *codec) | ||
564 | { | ||
565 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
566 | |||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | static int wm8731_resume(struct snd_soc_codec *codec) | ||
571 | { | ||
572 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
573 | |||
574 | return 0; | ||
575 | } | ||
576 | #else | ||
577 | #define wm8731_suspend NULL | ||
578 | #define wm8731_resume NULL | ||
579 | #endif | ||
580 | |||
581 | static int wm8731_probe(struct snd_soc_codec *codec) | 565 | static int wm8731_probe(struct snd_soc_codec *codec) |
582 | { | 566 | { |
583 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | 567 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
@@ -633,8 +617,6 @@ static int wm8731_remove(struct snd_soc_codec *codec) | |||
633 | { | 617 | { |
634 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | 618 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
635 | 619 | ||
636 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
637 | |||
638 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 620 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
639 | 621 | ||
640 | return 0; | 622 | return 0; |
@@ -643,9 +625,9 @@ static int wm8731_remove(struct snd_soc_codec *codec) | |||
643 | static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { | 625 | static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { |
644 | .probe = wm8731_probe, | 626 | .probe = wm8731_probe, |
645 | .remove = wm8731_remove, | 627 | .remove = wm8731_remove, |
646 | .suspend = wm8731_suspend, | ||
647 | .resume = wm8731_resume, | ||
648 | .set_bias_level = wm8731_set_bias_level, | 628 | .set_bias_level = wm8731_set_bias_level, |
629 | .suspend_bias_off = true, | ||
630 | |||
649 | .dapm_widgets = wm8731_dapm_widgets, | 631 | .dapm_widgets = wm8731_dapm_widgets, |
650 | .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), | 632 | .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), |
651 | .dapm_routes = wm8731_intercon, | 633 | .dapm_routes = wm8731_intercon, |
@@ -680,11 +662,12 @@ static int wm8731_spi_probe(struct spi_device *spi) | |||
680 | struct wm8731_priv *wm8731; | 662 | struct wm8731_priv *wm8731; |
681 | int ret; | 663 | int ret; |
682 | 664 | ||
683 | wm8731 = devm_kzalloc(&spi->dev, sizeof(struct wm8731_priv), | 665 | wm8731 = devm_kzalloc(&spi->dev, sizeof(*wm8731), GFP_KERNEL); |
684 | GFP_KERNEL); | ||
685 | if (wm8731 == NULL) | 666 | if (wm8731 == NULL) |
686 | return -ENOMEM; | 667 | return -ENOMEM; |
687 | 668 | ||
669 | mutex_init(&wm8731->lock); | ||
670 | |||
688 | wm8731->regmap = devm_regmap_init_spi(spi, &wm8731_regmap); | 671 | wm8731->regmap = devm_regmap_init_spi(spi, &wm8731_regmap); |
689 | if (IS_ERR(wm8731->regmap)) { | 672 | if (IS_ERR(wm8731->regmap)) { |
690 | ret = PTR_ERR(wm8731->regmap); | 673 | ret = PTR_ERR(wm8731->regmap); |
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 744a422ecb05..ada9ac1ba2c6 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c | |||
@@ -277,17 +277,6 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
277 | { "AIF", NULL, "ADCR" }, | 277 | { "AIF", NULL, "ADCR" }, |
278 | }; | 278 | }; |
279 | 279 | ||
280 | static int wm8737_add_widgets(struct snd_soc_codec *codec) | ||
281 | { | ||
282 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
283 | |||
284 | snd_soc_dapm_new_controls(dapm, wm8737_dapm_widgets, | ||
285 | ARRAY_SIZE(wm8737_dapm_widgets)); | ||
286 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | /* codec mclk clock divider coefficients */ | 280 | /* codec mclk clock divider coefficients */ |
292 | static const struct { | 281 | static const struct { |
293 | u32 mclk; | 282 | u32 mclk; |
@@ -548,23 +537,6 @@ static struct snd_soc_dai_driver wm8737_dai = { | |||
548 | .ops = &wm8737_dai_ops, | 537 | .ops = &wm8737_dai_ops, |
549 | }; | 538 | }; |
550 | 539 | ||
551 | #ifdef CONFIG_PM | ||
552 | static int wm8737_suspend(struct snd_soc_codec *codec) | ||
553 | { | ||
554 | wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static int wm8737_resume(struct snd_soc_codec *codec) | ||
559 | { | ||
560 | wm8737_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
561 | return 0; | ||
562 | } | ||
563 | #else | ||
564 | #define wm8737_suspend NULL | ||
565 | #define wm8737_resume NULL | ||
566 | #endif | ||
567 | |||
568 | static int wm8737_probe(struct snd_soc_codec *codec) | 540 | static int wm8737_probe(struct snd_soc_codec *codec) |
569 | { | 541 | { |
570 | struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); | 542 | struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); |
@@ -593,10 +565,6 @@ static int wm8737_probe(struct snd_soc_codec *codec) | |||
593 | /* Bias level configuration will have done an extra enable */ | 565 | /* Bias level configuration will have done an extra enable */ |
594 | regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); | 566 | regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); |
595 | 567 | ||
596 | snd_soc_add_codec_controls(codec, wm8737_snd_controls, | ||
597 | ARRAY_SIZE(wm8737_snd_controls)); | ||
598 | wm8737_add_widgets(codec); | ||
599 | |||
600 | return 0; | 568 | return 0; |
601 | 569 | ||
602 | err_enable: | 570 | err_enable: |
@@ -605,18 +573,17 @@ err_get: | |||
605 | return ret; | 573 | return ret; |
606 | } | 574 | } |
607 | 575 | ||
608 | static int wm8737_remove(struct snd_soc_codec *codec) | ||
609 | { | ||
610 | wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { | 576 | static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { |
615 | .probe = wm8737_probe, | 577 | .probe = wm8737_probe, |
616 | .remove = wm8737_remove, | ||
617 | .suspend = wm8737_suspend, | ||
618 | .resume = wm8737_resume, | ||
619 | .set_bias_level = wm8737_set_bias_level, | 578 | .set_bias_level = wm8737_set_bias_level, |
579 | .suspend_bias_off = true, | ||
580 | |||
581 | .controls = wm8737_snd_controls, | ||
582 | .num_controls = ARRAY_SIZE(wm8737_snd_controls), | ||
583 | .dapm_widgets = wm8737_dapm_widgets, | ||
584 | .num_dapm_widgets = ARRAY_SIZE(wm8737_dapm_widgets), | ||
585 | .dapm_routes = intercon, | ||
586 | .num_dapm_routes = ARRAY_SIZE(intercon), | ||
620 | }; | 587 | }; |
621 | 588 | ||
622 | static const struct of_device_id wm8737_of_match[] = { | 589 | static const struct of_device_id wm8737_of_match[] = { |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 67653a2db223..f6847fdd6ddd 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -686,18 +686,6 @@ static struct snd_soc_dai_driver wm8750_dai = { | |||
686 | .ops = &wm8750_dai_ops, | 686 | .ops = &wm8750_dai_ops, |
687 | }; | 687 | }; |
688 | 688 | ||
689 | static int wm8750_suspend(struct snd_soc_codec *codec) | ||
690 | { | ||
691 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | static int wm8750_resume(struct snd_soc_codec *codec) | ||
696 | { | ||
697 | wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | static int wm8750_probe(struct snd_soc_codec *codec) | 689 | static int wm8750_probe(struct snd_soc_codec *codec) |
702 | { | 690 | { |
703 | int ret; | 691 | int ret; |
@@ -708,9 +696,6 @@ static int wm8750_probe(struct snd_soc_codec *codec) | |||
708 | return ret; | 696 | return ret; |
709 | } | 697 | } |
710 | 698 | ||
711 | /* charge output caps */ | ||
712 | wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
713 | |||
714 | /* set the update bits */ | 699 | /* set the update bits */ |
715 | snd_soc_update_bits(codec, WM8750_LDAC, 0x0100, 0x0100); | 700 | snd_soc_update_bits(codec, WM8750_LDAC, 0x0100, 0x0100); |
716 | snd_soc_update_bits(codec, WM8750_RDAC, 0x0100, 0x0100); | 701 | snd_soc_update_bits(codec, WM8750_RDAC, 0x0100, 0x0100); |
@@ -724,18 +709,10 @@ static int wm8750_probe(struct snd_soc_codec *codec) | |||
724 | return ret; | 709 | return ret; |
725 | } | 710 | } |
726 | 711 | ||
727 | static int wm8750_remove(struct snd_soc_codec *codec) | ||
728 | { | ||
729 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { | 712 | static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { |
734 | .probe = wm8750_probe, | 713 | .probe = wm8750_probe, |
735 | .remove = wm8750_remove, | ||
736 | .suspend = wm8750_suspend, | ||
737 | .resume = wm8750_resume, | ||
738 | .set_bias_level = wm8750_set_bias_level, | 714 | .set_bias_level = wm8750_set_bias_level, |
715 | .suspend_bias_off = true, | ||
739 | 716 | ||
740 | .controls = wm8750_snd_controls, | 717 | .controls = wm8750_snd_controls, |
741 | .num_controls = ARRAY_SIZE(wm8750_snd_controls), | 718 | .num_controls = ARRAY_SIZE(wm8750_snd_controls), |
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 70952ceb278b..c13050b77931 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -408,24 +408,6 @@ static struct snd_soc_dai_driver wm8776_dai[] = { | |||
408 | }, | 408 | }, |
409 | }; | 409 | }; |
410 | 410 | ||
411 | #ifdef CONFIG_PM | ||
412 | static int wm8776_suspend(struct snd_soc_codec *codec) | ||
413 | { | ||
414 | wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | static int wm8776_resume(struct snd_soc_codec *codec) | ||
420 | { | ||
421 | wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
422 | return 0; | ||
423 | } | ||
424 | #else | ||
425 | #define wm8776_suspend NULL | ||
426 | #define wm8776_resume NULL | ||
427 | #endif | ||
428 | |||
429 | static int wm8776_probe(struct snd_soc_codec *codec) | 411 | static int wm8776_probe(struct snd_soc_codec *codec) |
430 | { | 412 | { |
431 | int ret = 0; | 413 | int ret = 0; |
@@ -436,8 +418,6 @@ static int wm8776_probe(struct snd_soc_codec *codec) | |||
436 | return ret; | 418 | return ret; |
437 | } | 419 | } |
438 | 420 | ||
439 | wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
440 | |||
441 | /* Latch the update bits; right channel only since we always | 421 | /* Latch the update bits; right channel only since we always |
442 | * update both. */ | 422 | * update both. */ |
443 | snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); | 423 | snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); |
@@ -446,19 +426,10 @@ static int wm8776_probe(struct snd_soc_codec *codec) | |||
446 | return ret; | 426 | return ret; |
447 | } | 427 | } |
448 | 428 | ||
449 | /* power down chip */ | ||
450 | static int wm8776_remove(struct snd_soc_codec *codec) | ||
451 | { | ||
452 | wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { | 429 | static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { |
457 | .probe = wm8776_probe, | 430 | .probe = wm8776_probe, |
458 | .remove = wm8776_remove, | ||
459 | .suspend = wm8776_suspend, | ||
460 | .resume = wm8776_resume, | ||
461 | .set_bias_level = wm8776_set_bias_level, | 431 | .set_bias_level = wm8776_set_bias_level, |
432 | .suspend_bias_off = true, | ||
462 | 433 | ||
463 | .controls = wm8776_snd_controls, | 434 | .controls = wm8776_snd_controls, |
464 | .num_controls = ARRAY_SIZE(wm8776_snd_controls), | 435 | .num_controls = ARRAY_SIZE(wm8776_snd_controls), |
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 3addc5fe5cb2..1315f7642503 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -524,7 +524,6 @@ static int wm8804_remove(struct snd_soc_codec *codec) | |||
524 | int i; | 524 | int i; |
525 | 525 | ||
526 | wm8804 = snd_soc_codec_get_drvdata(codec); | 526 | wm8804 = snd_soc_codec_get_drvdata(codec); |
527 | wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
528 | 527 | ||
529 | for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i) | 528 | for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i) |
530 | regulator_unregister_notifier(wm8804->supplies[i].consumer, | 529 | regulator_unregister_notifier(wm8804->supplies[i].consumer, |
@@ -606,8 +605,6 @@ static int wm8804_probe(struct snd_soc_codec *codec) | |||
606 | goto err_reg_enable; | 605 | goto err_reg_enable; |
607 | } | 606 | } |
608 | 607 | ||
609 | wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
610 | |||
611 | return 0; | 608 | return 0; |
612 | 609 | ||
613 | err_reg_enable: | 610 | err_reg_enable: |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 44a5f1511f0f..3a0d4b7d692f 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -1209,16 +1209,8 @@ static int wm8900_probe(struct snd_soc_codec *codec) | |||
1209 | return 0; | 1209 | return 0; |
1210 | } | 1210 | } |
1211 | 1211 | ||
1212 | /* power down chip */ | ||
1213 | static int wm8900_remove(struct snd_soc_codec *codec) | ||
1214 | { | ||
1215 | wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { | 1212 | static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { |
1220 | .probe = wm8900_probe, | 1213 | .probe = wm8900_probe, |
1221 | .remove = wm8900_remove, | ||
1222 | .suspend = wm8900_suspend, | 1214 | .suspend = wm8900_suspend, |
1223 | .resume = wm8900_resume, | 1215 | .resume = wm8900_resume, |
1224 | .set_bias_level = wm8900_set_bias_level, | 1216 | .set_bias_level = wm8900_set_bias_level, |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index c038b3e04398..cc6b0ef98a34 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/regmap.h> | 26 | #include <linux/regmap.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/irq.h> | 28 | #include <linux/irq.h> |
29 | #include <linux/mutex.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/jack.h> | 31 | #include <sound/jack.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
@@ -117,12 +118,12 @@ static const struct reg_default wm8903_reg_defaults[] = { | |||
117 | struct wm8903_priv { | 118 | struct wm8903_priv { |
118 | struct wm8903_platform_data *pdata; | 119 | struct wm8903_platform_data *pdata; |
119 | struct device *dev; | 120 | struct device *dev; |
120 | struct snd_soc_codec *codec; | ||
121 | struct regmap *regmap; | 121 | struct regmap *regmap; |
122 | 122 | ||
123 | int sysclk; | 123 | int sysclk; |
124 | int irq; | 124 | int irq; |
125 | 125 | ||
126 | struct mutex lock; | ||
126 | int fs; | 127 | int fs; |
127 | int deemph; | 128 | int deemph; |
128 | 129 | ||
@@ -457,7 +458,7 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol, | |||
457 | if (deemph > 1) | 458 | if (deemph > 1) |
458 | return -EINVAL; | 459 | return -EINVAL; |
459 | 460 | ||
460 | mutex_lock(&codec->mutex); | 461 | mutex_lock(&wm8903->lock); |
461 | if (wm8903->deemph != deemph) { | 462 | if (wm8903->deemph != deemph) { |
462 | wm8903->deemph = deemph; | 463 | wm8903->deemph = deemph; |
463 | 464 | ||
@@ -465,7 +466,7 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol, | |||
465 | 466 | ||
466 | ret = 1; | 467 | ret = 1; |
467 | } | 468 | } |
468 | mutex_unlock(&codec->mutex); | 469 | mutex_unlock(&wm8903->lock); |
469 | 470 | ||
470 | return ret; | 471 | return ret; |
471 | } | 472 | } |
@@ -1757,21 +1758,12 @@ static struct snd_soc_dai_driver wm8903_dai = { | |||
1757 | .symmetric_rates = 1, | 1758 | .symmetric_rates = 1, |
1758 | }; | 1759 | }; |
1759 | 1760 | ||
1760 | static int wm8903_suspend(struct snd_soc_codec *codec) | ||
1761 | { | ||
1762 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1763 | |||
1764 | return 0; | ||
1765 | } | ||
1766 | |||
1767 | static int wm8903_resume(struct snd_soc_codec *codec) | 1761 | static int wm8903_resume(struct snd_soc_codec *codec) |
1768 | { | 1762 | { |
1769 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 1763 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1770 | 1764 | ||
1771 | regcache_sync(wm8903->regmap); | 1765 | regcache_sync(wm8903->regmap); |
1772 | 1766 | ||
1773 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1774 | |||
1775 | return 0; | 1767 | return 0; |
1776 | } | 1768 | } |
1777 | 1769 | ||
@@ -1889,33 +1881,12 @@ static void wm8903_free_gpio(struct wm8903_priv *wm8903) | |||
1889 | } | 1881 | } |
1890 | #endif | 1882 | #endif |
1891 | 1883 | ||
1892 | static int wm8903_probe(struct snd_soc_codec *codec) | ||
1893 | { | ||
1894 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1895 | |||
1896 | wm8903->codec = codec; | ||
1897 | |||
1898 | /* power on device */ | ||
1899 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1900 | |||
1901 | return 0; | ||
1902 | } | ||
1903 | |||
1904 | /* power down chip */ | ||
1905 | static int wm8903_remove(struct snd_soc_codec *codec) | ||
1906 | { | ||
1907 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1908 | |||
1909 | return 0; | ||
1910 | } | ||
1911 | |||
1912 | static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { | 1884 | static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { |
1913 | .probe = wm8903_probe, | ||
1914 | .remove = wm8903_remove, | ||
1915 | .suspend = wm8903_suspend, | ||
1916 | .resume = wm8903_resume, | 1885 | .resume = wm8903_resume, |
1917 | .set_bias_level = wm8903_set_bias_level, | 1886 | .set_bias_level = wm8903_set_bias_level, |
1918 | .seq_notifier = wm8903_seq_notifier, | 1887 | .seq_notifier = wm8903_seq_notifier, |
1888 | .suspend_bias_off = true, | ||
1889 | |||
1919 | .controls = wm8903_snd_controls, | 1890 | .controls = wm8903_snd_controls, |
1920 | .num_controls = ARRAY_SIZE(wm8903_snd_controls), | 1891 | .num_controls = ARRAY_SIZE(wm8903_snd_controls), |
1921 | .dapm_widgets = wm8903_dapm_widgets, | 1892 | .dapm_widgets = wm8903_dapm_widgets, |
@@ -2023,6 +1994,8 @@ static int wm8903_i2c_probe(struct i2c_client *i2c, | |||
2023 | GFP_KERNEL); | 1994 | GFP_KERNEL); |
2024 | if (wm8903 == NULL) | 1995 | if (wm8903 == NULL) |
2025 | return -ENOMEM; | 1996 | return -ENOMEM; |
1997 | |||
1998 | mutex_init(&wm8903->lock); | ||
2026 | wm8903->dev = &i2c->dev; | 1999 | wm8903->dev = &i2c->dev; |
2027 | 2000 | ||
2028 | wm8903->regmap = devm_regmap_init_i2c(i2c, &wm8903_regmap); | 2001 | wm8903->regmap = devm_regmap_init_i2c(i2c, &wm8903_regmap); |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 52011043e54c..e4142b4309eb 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -695,17 +695,6 @@ static struct snd_soc_dai_driver wm8940_dai = { | |||
695 | .symmetric_rates = 1, | 695 | .symmetric_rates = 1, |
696 | }; | 696 | }; |
697 | 697 | ||
698 | static int wm8940_suspend(struct snd_soc_codec *codec) | ||
699 | { | ||
700 | return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
701 | } | ||
702 | |||
703 | static int wm8940_resume(struct snd_soc_codec *codec) | ||
704 | { | ||
705 | wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | static int wm8940_probe(struct snd_soc_codec *codec) | 698 | static int wm8940_probe(struct snd_soc_codec *codec) |
710 | { | 699 | { |
711 | struct wm8940_setup_data *pdata = codec->dev->platform_data; | 700 | struct wm8940_setup_data *pdata = codec->dev->platform_data; |
@@ -736,18 +725,11 @@ static int wm8940_probe(struct snd_soc_codec *codec) | |||
736 | return ret; | 725 | return ret; |
737 | } | 726 | } |
738 | 727 | ||
739 | static int wm8940_remove(struct snd_soc_codec *codec) | ||
740 | { | ||
741 | wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { | 728 | static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { |
746 | .probe = wm8940_probe, | 729 | .probe = wm8940_probe, |
747 | .remove = wm8940_remove, | ||
748 | .suspend = wm8940_suspend, | ||
749 | .resume = wm8940_resume, | ||
750 | .set_bias_level = wm8940_set_bias_level, | 730 | .set_bias_level = wm8940_set_bias_level, |
731 | .suspend_bias_off = true, | ||
732 | |||
751 | .controls = wm8940_snd_controls, | 733 | .controls = wm8940_snd_controls, |
752 | .num_controls = ARRAY_SIZE(wm8940_snd_controls), | 734 | .num_controls = ARRAY_SIZE(wm8940_snd_controls), |
753 | .dapm_widgets = wm8940_dapm_widgets, | 735 | .dapm_widgets = wm8940_dapm_widgets, |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 09d91d9dc4ee..1173f7fef5a7 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -866,29 +866,6 @@ static struct snd_soc_dai_driver wm8955_dai = { | |||
866 | .ops = &wm8955_dai_ops, | 866 | .ops = &wm8955_dai_ops, |
867 | }; | 867 | }; |
868 | 868 | ||
869 | #ifdef CONFIG_PM | ||
870 | static int wm8955_suspend(struct snd_soc_codec *codec) | ||
871 | { | ||
872 | struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); | ||
873 | |||
874 | wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
875 | |||
876 | regcache_mark_dirty(wm8955->regmap); | ||
877 | |||
878 | return 0; | ||
879 | } | ||
880 | |||
881 | static int wm8955_resume(struct snd_soc_codec *codec) | ||
882 | { | ||
883 | wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
884 | |||
885 | return 0; | ||
886 | } | ||
887 | #else | ||
888 | #define wm8955_suspend NULL | ||
889 | #define wm8955_resume NULL | ||
890 | #endif | ||
891 | |||
892 | static int wm8955_probe(struct snd_soc_codec *codec) | 869 | static int wm8955_probe(struct snd_soc_codec *codec) |
893 | { | 870 | { |
894 | struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); | 871 | struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); |
@@ -964,18 +941,10 @@ err_enable: | |||
964 | return ret; | 941 | return ret; |
965 | } | 942 | } |
966 | 943 | ||
967 | static int wm8955_remove(struct snd_soc_codec *codec) | ||
968 | { | ||
969 | wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
970 | return 0; | ||
971 | } | ||
972 | |||
973 | static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { | 944 | static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { |
974 | .probe = wm8955_probe, | 945 | .probe = wm8955_probe, |
975 | .remove = wm8955_remove, | ||
976 | .suspend = wm8955_suspend, | ||
977 | .resume = wm8955_resume, | ||
978 | .set_bias_level = wm8955_set_bias_level, | 946 | .set_bias_level = wm8955_set_bias_level, |
947 | .suspend_bias_off = true, | ||
979 | 948 | ||
980 | .controls = wm8955_snd_controls, | 949 | .controls = wm8955_snd_controls, |
981 | .num_controls = ARRAY_SIZE(wm8955_snd_controls), | 950 | .num_controls = ARRAY_SIZE(wm8955_snd_controls), |
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 0dada7f0105e..3cbc82b33292 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c | |||
@@ -867,9 +867,9 @@ static void wm8958_enh_eq_loaded(const struct firmware *fw, void *context) | |||
867 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 867 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
868 | 868 | ||
869 | if (fw && (wm8958_dsp2_fw(codec, "ENH_EQ", fw, true) == 0)) { | 869 | if (fw && (wm8958_dsp2_fw(codec, "ENH_EQ", fw, true) == 0)) { |
870 | mutex_lock(&codec->mutex); | 870 | mutex_lock(&wm8994->fw_lock); |
871 | wm8994->enh_eq = fw; | 871 | wm8994->enh_eq = fw; |
872 | mutex_unlock(&codec->mutex); | 872 | mutex_unlock(&wm8994->fw_lock); |
873 | } | 873 | } |
874 | } | 874 | } |
875 | 875 | ||
@@ -879,9 +879,9 @@ static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context) | |||
879 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 879 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
880 | 880 | ||
881 | if (fw && (wm8958_dsp2_fw(codec, "MBC+VSS", fw, true) == 0)) { | 881 | if (fw && (wm8958_dsp2_fw(codec, "MBC+VSS", fw, true) == 0)) { |
882 | mutex_lock(&codec->mutex); | 882 | mutex_lock(&wm8994->fw_lock); |
883 | wm8994->mbc_vss = fw; | 883 | wm8994->mbc_vss = fw; |
884 | mutex_unlock(&codec->mutex); | 884 | mutex_unlock(&wm8994->fw_lock); |
885 | } | 885 | } |
886 | } | 886 | } |
887 | 887 | ||
@@ -891,9 +891,9 @@ static void wm8958_mbc_loaded(const struct firmware *fw, void *context) | |||
891 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 891 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
892 | 892 | ||
893 | if (fw && (wm8958_dsp2_fw(codec, "MBC", fw, true) == 0)) { | 893 | if (fw && (wm8958_dsp2_fw(codec, "MBC", fw, true) == 0)) { |
894 | mutex_lock(&codec->mutex); | 894 | mutex_lock(&wm8994->fw_lock); |
895 | wm8994->mbc = fw; | 895 | wm8994->mbc = fw; |
896 | mutex_unlock(&codec->mutex); | 896 | mutex_unlock(&wm8994->fw_lock); |
897 | } | 897 | } |
898 | } | 898 | } |
899 | 899 | ||
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 4dc4e85116cd..031a1ae71d94 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -125,9 +125,10 @@ struct wm8960_priv { | |||
125 | struct snd_soc_dapm_widget *out3; | 125 | struct snd_soc_dapm_widget *out3; |
126 | bool deemph; | 126 | bool deemph; |
127 | int playback_fs; | 127 | int playback_fs; |
128 | struct wm8960_data pdata; | ||
128 | }; | 129 | }; |
129 | 130 | ||
130 | #define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) | 131 | #define wm8960_reset(c) regmap_write(c, WM8960_RESET, 0) |
131 | 132 | ||
132 | /* enumerated controls */ | 133 | /* enumerated controls */ |
133 | static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted", | 134 | static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted", |
@@ -440,8 +441,8 @@ static const struct snd_soc_dapm_route audio_paths_capless[] = { | |||
440 | 441 | ||
441 | static int wm8960_add_widgets(struct snd_soc_codec *codec) | 442 | static int wm8960_add_widgets(struct snd_soc_codec *codec) |
442 | { | 443 | { |
443 | struct wm8960_data *pdata = codec->dev->platform_data; | ||
444 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 444 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
445 | struct wm8960_data *pdata = &wm8960->pdata; | ||
445 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 446 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
446 | struct snd_soc_dapm_widget *w; | 447 | struct snd_soc_dapm_widget *w; |
447 | 448 | ||
@@ -942,56 +943,15 @@ static struct snd_soc_dai_driver wm8960_dai = { | |||
942 | .symmetric_rates = 1, | 943 | .symmetric_rates = 1, |
943 | }; | 944 | }; |
944 | 945 | ||
945 | static int wm8960_suspend(struct snd_soc_codec *codec) | ||
946 | { | ||
947 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
948 | |||
949 | wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | static int wm8960_resume(struct snd_soc_codec *codec) | ||
954 | { | ||
955 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
956 | |||
957 | wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
958 | return 0; | ||
959 | } | ||
960 | |||
961 | static int wm8960_probe(struct snd_soc_codec *codec) | 946 | static int wm8960_probe(struct snd_soc_codec *codec) |
962 | { | 947 | { |
963 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 948 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
964 | struct wm8960_data *pdata = dev_get_platdata(codec->dev); | 949 | struct wm8960_data *pdata = &wm8960->pdata; |
965 | int ret; | ||
966 | |||
967 | wm8960->set_bias_level = wm8960_set_bias_level_out3; | ||
968 | |||
969 | if (!pdata) { | ||
970 | dev_warn(codec->dev, "No platform data supplied\n"); | ||
971 | } else { | ||
972 | if (pdata->capless) | ||
973 | wm8960->set_bias_level = wm8960_set_bias_level_capless; | ||
974 | } | ||
975 | |||
976 | ret = wm8960_reset(codec); | ||
977 | if (ret < 0) { | ||
978 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
979 | return ret; | ||
980 | } | ||
981 | |||
982 | wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
983 | 950 | ||
984 | /* Latch the update bits */ | 951 | if (pdata->capless) |
985 | snd_soc_update_bits(codec, WM8960_LINVOL, 0x100, 0x100); | 952 | wm8960->set_bias_level = wm8960_set_bias_level_capless; |
986 | snd_soc_update_bits(codec, WM8960_RINVOL, 0x100, 0x100); | 953 | else |
987 | snd_soc_update_bits(codec, WM8960_LADC, 0x100, 0x100); | 954 | wm8960->set_bias_level = wm8960_set_bias_level_out3; |
988 | snd_soc_update_bits(codec, WM8960_RADC, 0x100, 0x100); | ||
989 | snd_soc_update_bits(codec, WM8960_LDAC, 0x100, 0x100); | ||
990 | snd_soc_update_bits(codec, WM8960_RDAC, 0x100, 0x100); | ||
991 | snd_soc_update_bits(codec, WM8960_LOUT1, 0x100, 0x100); | ||
992 | snd_soc_update_bits(codec, WM8960_ROUT1, 0x100, 0x100); | ||
993 | snd_soc_update_bits(codec, WM8960_LOUT2, 0x100, 0x100); | ||
994 | snd_soc_update_bits(codec, WM8960_ROUT2, 0x100, 0x100); | ||
995 | 955 | ||
996 | snd_soc_add_codec_controls(codec, wm8960_snd_controls, | 956 | snd_soc_add_codec_controls(codec, wm8960_snd_controls, |
997 | ARRAY_SIZE(wm8960_snd_controls)); | 957 | ARRAY_SIZE(wm8960_snd_controls)); |
@@ -1000,21 +960,10 @@ static int wm8960_probe(struct snd_soc_codec *codec) | |||
1000 | return 0; | 960 | return 0; |
1001 | } | 961 | } |
1002 | 962 | ||
1003 | /* power down chip */ | ||
1004 | static int wm8960_remove(struct snd_soc_codec *codec) | ||
1005 | { | ||
1006 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
1007 | |||
1008 | wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1009 | return 0; | ||
1010 | } | ||
1011 | |||
1012 | static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { | 963 | static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { |
1013 | .probe = wm8960_probe, | 964 | .probe = wm8960_probe, |
1014 | .remove = wm8960_remove, | ||
1015 | .suspend = wm8960_suspend, | ||
1016 | .resume = wm8960_resume, | ||
1017 | .set_bias_level = wm8960_set_bias_level, | 965 | .set_bias_level = wm8960_set_bias_level, |
966 | .suspend_bias_off = true, | ||
1018 | }; | 967 | }; |
1019 | 968 | ||
1020 | static const struct regmap_config wm8960_regmap = { | 969 | static const struct regmap_config wm8960_regmap = { |
@@ -1029,6 +978,18 @@ static const struct regmap_config wm8960_regmap = { | |||
1029 | .volatile_reg = wm8960_volatile, | 978 | .volatile_reg = wm8960_volatile, |
1030 | }; | 979 | }; |
1031 | 980 | ||
981 | static void wm8960_set_pdata_from_of(struct i2c_client *i2c, | ||
982 | struct wm8960_data *pdata) | ||
983 | { | ||
984 | const struct device_node *np = i2c->dev.of_node; | ||
985 | |||
986 | if (of_property_read_bool(np, "wlf,capless")) | ||
987 | pdata->capless = true; | ||
988 | |||
989 | if (of_property_read_bool(np, "wlf,shared-lrclk")) | ||
990 | pdata->shared_lrclk = true; | ||
991 | } | ||
992 | |||
1032 | static int wm8960_i2c_probe(struct i2c_client *i2c, | 993 | static int wm8960_i2c_probe(struct i2c_client *i2c, |
1033 | const struct i2c_device_id *id) | 994 | const struct i2c_device_id *id) |
1034 | { | 995 | { |
@@ -1045,7 +1006,18 @@ static int wm8960_i2c_probe(struct i2c_client *i2c, | |||
1045 | if (IS_ERR(wm8960->regmap)) | 1006 | if (IS_ERR(wm8960->regmap)) |
1046 | return PTR_ERR(wm8960->regmap); | 1007 | return PTR_ERR(wm8960->regmap); |
1047 | 1008 | ||
1048 | if (pdata && pdata->shared_lrclk) { | 1009 | if (pdata) |
1010 | memcpy(&wm8960->pdata, pdata, sizeof(struct wm8960_data)); | ||
1011 | else if (i2c->dev.of_node) | ||
1012 | wm8960_set_pdata_from_of(i2c, &wm8960->pdata); | ||
1013 | |||
1014 | ret = wm8960_reset(wm8960->regmap); | ||
1015 | if (ret != 0) { | ||
1016 | dev_err(&i2c->dev, "Failed to issue reset\n"); | ||
1017 | return ret; | ||
1018 | } | ||
1019 | |||
1020 | if (wm8960->pdata.shared_lrclk) { | ||
1049 | ret = regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2, | 1021 | ret = regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2, |
1050 | 0x4, 0x4); | 1022 | 0x4, 0x4); |
1051 | if (ret != 0) { | 1023 | if (ret != 0) { |
@@ -1055,6 +1027,18 @@ static int wm8960_i2c_probe(struct i2c_client *i2c, | |||
1055 | } | 1027 | } |
1056 | } | 1028 | } |
1057 | 1029 | ||
1030 | /* Latch the update bits */ | ||
1031 | regmap_update_bits(wm8960->regmap, WM8960_LINVOL, 0x100, 0x100); | ||
1032 | regmap_update_bits(wm8960->regmap, WM8960_RINVOL, 0x100, 0x100); | ||
1033 | regmap_update_bits(wm8960->regmap, WM8960_LADC, 0x100, 0x100); | ||
1034 | regmap_update_bits(wm8960->regmap, WM8960_RADC, 0x100, 0x100); | ||
1035 | regmap_update_bits(wm8960->regmap, WM8960_LDAC, 0x100, 0x100); | ||
1036 | regmap_update_bits(wm8960->regmap, WM8960_RDAC, 0x100, 0x100); | ||
1037 | regmap_update_bits(wm8960->regmap, WM8960_LOUT1, 0x100, 0x100); | ||
1038 | regmap_update_bits(wm8960->regmap, WM8960_ROUT1, 0x100, 0x100); | ||
1039 | regmap_update_bits(wm8960->regmap, WM8960_LOUT2, 0x100, 0x100); | ||
1040 | regmap_update_bits(wm8960->regmap, WM8960_ROUT2, 0x100, 0x100); | ||
1041 | |||
1058 | i2c_set_clientdata(i2c, wm8960); | 1042 | i2c_set_clientdata(i2c, wm8960); |
1059 | 1043 | ||
1060 | ret = snd_soc_register_codec(&i2c->dev, | 1044 | ret = snd_soc_register_codec(&i2c->dev, |
@@ -1075,10 +1059,17 @@ static const struct i2c_device_id wm8960_i2c_id[] = { | |||
1075 | }; | 1059 | }; |
1076 | MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id); | 1060 | MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id); |
1077 | 1061 | ||
1062 | static const struct of_device_id wm8960_of_match[] = { | ||
1063 | { .compatible = "wlf,wm8960", }, | ||
1064 | { } | ||
1065 | }; | ||
1066 | MODULE_DEVICE_TABLE(of, wm8960_of_match); | ||
1067 | |||
1078 | static struct i2c_driver wm8960_i2c_driver = { | 1068 | static struct i2c_driver wm8960_i2c_driver = { |
1079 | .driver = { | 1069 | .driver = { |
1080 | .name = "wm8960", | 1070 | .name = "wm8960", |
1081 | .owner = THIS_MODULE, | 1071 | .owner = THIS_MODULE, |
1072 | .of_match_table = wm8960_of_match, | ||
1082 | }, | 1073 | }, |
1083 | .probe = wm8960_i2c_probe, | 1074 | .probe = wm8960_i2c_probe, |
1084 | .remove = wm8960_i2c_remove, | 1075 | .remove = wm8960_i2c_remove, |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 41d23e920ad5..eeffd05384b4 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -835,7 +835,6 @@ static struct snd_soc_dai_driver wm8961_dai = { | |||
835 | 835 | ||
836 | static int wm8961_probe(struct snd_soc_codec *codec) | 836 | static int wm8961_probe(struct snd_soc_codec *codec) |
837 | { | 837 | { |
838 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
839 | u16 reg; | 838 | u16 reg; |
840 | 839 | ||
841 | /* Enable class W */ | 840 | /* Enable class W */ |
@@ -871,50 +870,33 @@ static int wm8961_probe(struct snd_soc_codec *codec) | |||
871 | reg &= ~WM8961_MANUAL_MODE; | 870 | reg &= ~WM8961_MANUAL_MODE; |
872 | snd_soc_write(codec, WM8961_CLOCKING_3, reg); | 871 | snd_soc_write(codec, WM8961_CLOCKING_3, reg); |
873 | 872 | ||
874 | wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
875 | |||
876 | snd_soc_add_codec_controls(codec, wm8961_snd_controls, | ||
877 | ARRAY_SIZE(wm8961_snd_controls)); | ||
878 | snd_soc_dapm_new_controls(dapm, wm8961_dapm_widgets, | ||
879 | ARRAY_SIZE(wm8961_dapm_widgets)); | ||
880 | snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); | ||
881 | |||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | static int wm8961_remove(struct snd_soc_codec *codec) | ||
886 | { | ||
887 | wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
888 | return 0; | 873 | return 0; |
889 | } | 874 | } |
890 | 875 | ||
891 | #ifdef CONFIG_PM | 876 | #ifdef CONFIG_PM |
892 | static int wm8961_suspend(struct snd_soc_codec *codec) | ||
893 | { | ||
894 | wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
895 | |||
896 | return 0; | ||
897 | } | ||
898 | 877 | ||
899 | static int wm8961_resume(struct snd_soc_codec *codec) | 878 | static int wm8961_resume(struct snd_soc_codec *codec) |
900 | { | 879 | { |
901 | snd_soc_cache_sync(codec); | 880 | snd_soc_cache_sync(codec); |
902 | 881 | ||
903 | wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
904 | |||
905 | return 0; | 882 | return 0; |
906 | } | 883 | } |
907 | #else | 884 | #else |
908 | #define wm8961_suspend NULL | ||
909 | #define wm8961_resume NULL | 885 | #define wm8961_resume NULL |
910 | #endif | 886 | #endif |
911 | 887 | ||
912 | static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { | 888 | static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { |
913 | .probe = wm8961_probe, | 889 | .probe = wm8961_probe, |
914 | .remove = wm8961_remove, | ||
915 | .suspend = wm8961_suspend, | ||
916 | .resume = wm8961_resume, | 890 | .resume = wm8961_resume, |
917 | .set_bias_level = wm8961_set_bias_level, | 891 | .set_bias_level = wm8961_set_bias_level, |
892 | .suspend_bias_off = true, | ||
893 | |||
894 | .controls = wm8961_snd_controls, | ||
895 | .num_controls = ARRAY_SIZE(wm8961_snd_controls), | ||
896 | .dapm_widgets = wm8961_dapm_widgets, | ||
897 | .num_dapm_widgets = ARRAY_SIZE(wm8961_dapm_widgets), | ||
898 | .dapm_routes = audio_paths, | ||
899 | .num_dapm_routes = ARRAY_SIZE(audio_paths), | ||
918 | }; | 900 | }; |
919 | 901 | ||
920 | static const struct regmap_config wm8961_regmap = { | 902 | static const struct regmap_config wm8961_regmap = { |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 9077411e62ce..1534d88a66e9 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/regulator/consumer.h> | 26 | #include <linux/regulator/consumer.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
29 | #include <linux/mutex.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/jack.h> | 31 | #include <sound/jack.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
@@ -67,6 +68,7 @@ struct wm8962_priv { | |||
67 | int fll_fref; | 68 | int fll_fref; |
68 | int fll_fout; | 69 | int fll_fout; |
69 | 70 | ||
71 | struct mutex dsp2_ena_lock; | ||
70 | u16 dsp2_ena; | 72 | u16 dsp2_ena; |
71 | 73 | ||
72 | struct delayed_work mic_work; | 74 | struct delayed_work mic_work; |
@@ -1570,7 +1572,7 @@ static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol, | |||
1570 | int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) & | 1572 | int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) & |
1571 | WM8962_DSP2_ENA; | 1573 | WM8962_DSP2_ENA; |
1572 | 1574 | ||
1573 | mutex_lock(&codec->mutex); | 1575 | mutex_lock(&wm8962->dsp2_ena_lock); |
1574 | 1576 | ||
1575 | if (ucontrol->value.integer.value[0]) | 1577 | if (ucontrol->value.integer.value[0]) |
1576 | wm8962->dsp2_ena |= 1 << shift; | 1578 | wm8962->dsp2_ena |= 1 << shift; |
@@ -1590,7 +1592,7 @@ static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol, | |||
1590 | } | 1592 | } |
1591 | 1593 | ||
1592 | out: | 1594 | out: |
1593 | mutex_unlock(&codec->mutex); | 1595 | mutex_unlock(&wm8962->dsp2_ena_lock); |
1594 | 1596 | ||
1595 | return ret; | 1597 | return ret; |
1596 | } | 1598 | } |
@@ -3552,11 +3554,12 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3552 | unsigned int reg; | 3554 | unsigned int reg; |
3553 | int ret, i, irq_pol, trigger; | 3555 | int ret, i, irq_pol, trigger; |
3554 | 3556 | ||
3555 | wm8962 = devm_kzalloc(&i2c->dev, sizeof(struct wm8962_priv), | 3557 | wm8962 = devm_kzalloc(&i2c->dev, sizeof(*wm8962), GFP_KERNEL); |
3556 | GFP_KERNEL); | ||
3557 | if (wm8962 == NULL) | 3558 | if (wm8962 == NULL) |
3558 | return -ENOMEM; | 3559 | return -ENOMEM; |
3559 | 3560 | ||
3561 | mutex_init(&wm8962->dsp2_ena_lock); | ||
3562 | |||
3560 | i2c_set_clientdata(i2c, wm8962); | 3563 | i2c_set_clientdata(i2c, wm8962); |
3561 | 3564 | ||
3562 | INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work); | 3565 | INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work); |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 682e9eda1019..ff0e4646b934 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -568,18 +568,6 @@ static struct snd_soc_dai_driver wm8974_dai = { | |||
568 | .symmetric_rates = 1, | 568 | .symmetric_rates = 1, |
569 | }; | 569 | }; |
570 | 570 | ||
571 | static int wm8974_suspend(struct snd_soc_codec *codec) | ||
572 | { | ||
573 | wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static int wm8974_resume(struct snd_soc_codec *codec) | ||
578 | { | ||
579 | wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static const struct regmap_config wm8974_regmap = { | 571 | static const struct regmap_config wm8974_regmap = { |
584 | .reg_bits = 7, | 572 | .reg_bits = 7, |
585 | .val_bits = 9, | 573 | .val_bits = 9, |
@@ -599,24 +587,13 @@ static int wm8974_probe(struct snd_soc_codec *codec) | |||
599 | return ret; | 587 | return ret; |
600 | } | 588 | } |
601 | 589 | ||
602 | wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
603 | |||
604 | return ret; | ||
605 | } | ||
606 | |||
607 | /* power down chip */ | ||
608 | static int wm8974_remove(struct snd_soc_codec *codec) | ||
609 | { | ||
610 | wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
611 | return 0; | 590 | return 0; |
612 | } | 591 | } |
613 | 592 | ||
614 | static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { | 593 | static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { |
615 | .probe = wm8974_probe, | 594 | .probe = wm8974_probe, |
616 | .remove = wm8974_remove, | ||
617 | .suspend = wm8974_suspend, | ||
618 | .resume = wm8974_resume, | ||
619 | .set_bias_level = wm8974_set_bias_level, | 595 | .set_bias_level = wm8974_set_bias_level, |
596 | .suspend_bias_off = true, | ||
620 | 597 | ||
621 | .controls = wm8974_snd_controls, | 598 | .controls = wm8974_snd_controls, |
622 | .num_controls = ARRAY_SIZE(wm8974_snd_controls), | 599 | .num_controls = ARRAY_SIZE(wm8974_snd_controls), |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index ee2ba574952b..cf7032911721 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -991,21 +991,11 @@ static int wm8978_probe(struct snd_soc_codec *codec) | |||
991 | for (i = 0; i < ARRAY_SIZE(update_reg); i++) | 991 | for (i = 0; i < ARRAY_SIZE(update_reg); i++) |
992 | snd_soc_update_bits(codec, update_reg[i], 0x100, 0x100); | 992 | snd_soc_update_bits(codec, update_reg[i], 0x100, 0x100); |
993 | 993 | ||
994 | wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
995 | |||
996 | return 0; | ||
997 | } | ||
998 | |||
999 | /* power down chip */ | ||
1000 | static int wm8978_remove(struct snd_soc_codec *codec) | ||
1001 | { | ||
1002 | wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1003 | return 0; | 994 | return 0; |
1004 | } | 995 | } |
1005 | 996 | ||
1006 | static struct snd_soc_codec_driver soc_codec_dev_wm8978 = { | 997 | static struct snd_soc_codec_driver soc_codec_dev_wm8978 = { |
1007 | .probe = wm8978_probe, | 998 | .probe = wm8978_probe, |
1008 | .remove = wm8978_remove, | ||
1009 | .suspend = wm8978_suspend, | 999 | .suspend = wm8978_suspend, |
1010 | .resume = wm8978_resume, | 1000 | .resume = wm8978_resume, |
1011 | .set_bias_level = wm8978_set_bias_level, | 1001 | .set_bias_level = wm8978_set_bias_level, |
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index ac5defda8824..5d1cf08a72b8 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c | |||
@@ -967,29 +967,6 @@ static int wm8983_set_bias_level(struct snd_soc_codec *codec, | |||
967 | return 0; | 967 | return 0; |
968 | } | 968 | } |
969 | 969 | ||
970 | #ifdef CONFIG_PM | ||
971 | static int wm8983_suspend(struct snd_soc_codec *codec) | ||
972 | { | ||
973 | wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
974 | return 0; | ||
975 | } | ||
976 | |||
977 | static int wm8983_resume(struct snd_soc_codec *codec) | ||
978 | { | ||
979 | wm8983_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
980 | return 0; | ||
981 | } | ||
982 | #else | ||
983 | #define wm8983_suspend NULL | ||
984 | #define wm8983_resume NULL | ||
985 | #endif | ||
986 | |||
987 | static int wm8983_remove(struct snd_soc_codec *codec) | ||
988 | { | ||
989 | wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | static int wm8983_probe(struct snd_soc_codec *codec) | 970 | static int wm8983_probe(struct snd_soc_codec *codec) |
994 | { | 971 | { |
995 | int ret; | 972 | int ret; |
@@ -1055,10 +1032,8 @@ static struct snd_soc_dai_driver wm8983_dai = { | |||
1055 | 1032 | ||
1056 | static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { | 1033 | static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { |
1057 | .probe = wm8983_probe, | 1034 | .probe = wm8983_probe, |
1058 | .remove = wm8983_remove, | ||
1059 | .suspend = wm8983_suspend, | ||
1060 | .resume = wm8983_resume, | ||
1061 | .set_bias_level = wm8983_set_bias_level, | 1035 | .set_bias_level = wm8983_set_bias_level, |
1036 | .suspend_bias_off = true, | ||
1062 | .controls = wm8983_snd_controls, | 1037 | .controls = wm8983_snd_controls, |
1063 | .num_controls = ARRAY_SIZE(wm8983_snd_controls), | 1038 | .num_controls = ARRAY_SIZE(wm8983_snd_controls), |
1064 | .dapm_widgets = wm8983_dapm_widgets, | 1039 | .dapm_widgets = wm8983_dapm_widgets, |
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index ee380190399f..0b3b54c9971d 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c | |||
@@ -961,29 +961,6 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec, | |||
961 | return 0; | 961 | return 0; |
962 | } | 962 | } |
963 | 963 | ||
964 | #ifdef CONFIG_PM | ||
965 | static int wm8985_suspend(struct snd_soc_codec *codec) | ||
966 | { | ||
967 | wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | static int wm8985_resume(struct snd_soc_codec *codec) | ||
972 | { | ||
973 | wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
974 | return 0; | ||
975 | } | ||
976 | #else | ||
977 | #define wm8985_suspend NULL | ||
978 | #define wm8985_resume NULL | ||
979 | #endif | ||
980 | |||
981 | static int wm8985_remove(struct snd_soc_codec *codec) | ||
982 | { | ||
983 | wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | static int wm8985_probe(struct snd_soc_codec *codec) | 964 | static int wm8985_probe(struct snd_soc_codec *codec) |
988 | { | 965 | { |
989 | size_t i; | 966 | size_t i; |
@@ -1023,7 +1000,6 @@ static int wm8985_probe(struct snd_soc_codec *codec) | |||
1023 | snd_soc_update_bits(codec, WM8985_BIAS_CTRL, WM8985_BIASCUT, | 1000 | snd_soc_update_bits(codec, WM8985_BIAS_CTRL, WM8985_BIASCUT, |
1024 | WM8985_BIASCUT); | 1001 | WM8985_BIASCUT); |
1025 | 1002 | ||
1026 | wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1027 | return 0; | 1003 | return 0; |
1028 | 1004 | ||
1029 | err_reg_enable: | 1005 | err_reg_enable: |
@@ -1064,10 +1040,8 @@ static struct snd_soc_dai_driver wm8985_dai = { | |||
1064 | 1040 | ||
1065 | static struct snd_soc_codec_driver soc_codec_dev_wm8985 = { | 1041 | static struct snd_soc_codec_driver soc_codec_dev_wm8985 = { |
1066 | .probe = wm8985_probe, | 1042 | .probe = wm8985_probe, |
1067 | .remove = wm8985_remove, | ||
1068 | .suspend = wm8985_suspend, | ||
1069 | .resume = wm8985_resume, | ||
1070 | .set_bias_level = wm8985_set_bias_level, | 1043 | .set_bias_level = wm8985_set_bias_level, |
1044 | .suspend_bias_off = true, | ||
1071 | 1045 | ||
1072 | .controls = wm8985_snd_controls, | 1046 | .controls = wm8985_snd_controls, |
1073 | .num_controls = ARRAY_SIZE(wm8985_snd_controls), | 1047 | .num_controls = ARRAY_SIZE(wm8985_snd_controls), |
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index a5130d965146..e418199155a8 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -793,21 +793,6 @@ static struct snd_soc_dai_driver wm8988_dai = { | |||
793 | .symmetric_rates = 1, | 793 | .symmetric_rates = 1, |
794 | }; | 794 | }; |
795 | 795 | ||
796 | static int wm8988_suspend(struct snd_soc_codec *codec) | ||
797 | { | ||
798 | struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); | ||
799 | |||
800 | wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
801 | regcache_mark_dirty(wm8988->regmap); | ||
802 | return 0; | ||
803 | } | ||
804 | |||
805 | static int wm8988_resume(struct snd_soc_codec *codec) | ||
806 | { | ||
807 | wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | static int wm8988_probe(struct snd_soc_codec *codec) | 796 | static int wm8988_probe(struct snd_soc_codec *codec) |
812 | { | 797 | { |
813 | int ret = 0; | 798 | int ret = 0; |
@@ -825,23 +810,13 @@ static int wm8988_probe(struct snd_soc_codec *codec) | |||
825 | snd_soc_update_bits(codec, WM8988_ROUT2V, 0x0100, 0x0100); | 810 | snd_soc_update_bits(codec, WM8988_ROUT2V, 0x0100, 0x0100); |
826 | snd_soc_update_bits(codec, WM8988_RINVOL, 0x0100, 0x0100); | 811 | snd_soc_update_bits(codec, WM8988_RINVOL, 0x0100, 0x0100); |
827 | 812 | ||
828 | wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | |||
833 | static int wm8988_remove(struct snd_soc_codec *codec) | ||
834 | { | ||
835 | wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
836 | return 0; | 813 | return 0; |
837 | } | 814 | } |
838 | 815 | ||
839 | static struct snd_soc_codec_driver soc_codec_dev_wm8988 = { | 816 | static struct snd_soc_codec_driver soc_codec_dev_wm8988 = { |
840 | .probe = wm8988_probe, | 817 | .probe = wm8988_probe, |
841 | .remove = wm8988_remove, | ||
842 | .suspend = wm8988_suspend, | ||
843 | .resume = wm8988_resume, | ||
844 | .set_bias_level = wm8988_set_bias_level, | 818 | .set_bias_level = wm8988_set_bias_level, |
819 | .suspend_bias_off = true, | ||
845 | 820 | ||
846 | .controls = wm8988_snd_controls, | 821 | .controls = wm8988_snd_controls, |
847 | .num_controls = ARRAY_SIZE(wm8988_snd_controls), | 822 | .num_controls = ARRAY_SIZE(wm8988_snd_controls), |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 03e43e3f395e..8a584229310a 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -1271,18 +1271,6 @@ static struct snd_soc_dai_driver wm8990_dai = { | |||
1271 | .ops = &wm8990_dai_ops, | 1271 | .ops = &wm8990_dai_ops, |
1272 | }; | 1272 | }; |
1273 | 1273 | ||
1274 | static int wm8990_suspend(struct snd_soc_codec *codec) | ||
1275 | { | ||
1276 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1277 | return 0; | ||
1278 | } | ||
1279 | |||
1280 | static int wm8990_resume(struct snd_soc_codec *codec) | ||
1281 | { | ||
1282 | wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1283 | return 0; | ||
1284 | } | ||
1285 | |||
1286 | /* | 1274 | /* |
1287 | * initialise the WM8990 driver | 1275 | * initialise the WM8990 driver |
1288 | * register the mixer and dsp interfaces with the kernel | 1276 | * register the mixer and dsp interfaces with the kernel |
@@ -1309,19 +1297,11 @@ static int wm8990_probe(struct snd_soc_codec *codec) | |||
1309 | return 0; | 1297 | return 0; |
1310 | } | 1298 | } |
1311 | 1299 | ||
1312 | /* power down chip */ | ||
1313 | static int wm8990_remove(struct snd_soc_codec *codec) | ||
1314 | { | ||
1315 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1316 | return 0; | ||
1317 | } | ||
1318 | |||
1319 | static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { | 1300 | static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { |
1320 | .probe = wm8990_probe, | 1301 | .probe = wm8990_probe, |
1321 | .remove = wm8990_remove, | ||
1322 | .suspend = wm8990_suspend, | ||
1323 | .resume = wm8990_resume, | ||
1324 | .set_bias_level = wm8990_set_bias_level, | 1302 | .set_bias_level = wm8990_set_bias_level, |
1303 | .suspend_bias_off = true, | ||
1304 | |||
1325 | .controls = wm8990_snd_controls, | 1305 | .controls = wm8990_snd_controls, |
1326 | .num_controls = ARRAY_SIZE(wm8990_snd_controls), | 1306 | .num_controls = ARRAY_SIZE(wm8990_snd_controls), |
1327 | .dapm_widgets = wm8990_dapm_widgets, | 1307 | .dapm_widgets = wm8990_dapm_widgets, |
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index d0be89731cdb..b0ac2c3e31b9 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
@@ -1227,32 +1227,6 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec, | |||
1227 | return 0; | 1227 | return 0; |
1228 | } | 1228 | } |
1229 | 1229 | ||
1230 | static int wm8991_suspend(struct snd_soc_codec *codec) | ||
1231 | { | ||
1232 | wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1233 | return 0; | ||
1234 | } | ||
1235 | |||
1236 | static int wm8991_resume(struct snd_soc_codec *codec) | ||
1237 | { | ||
1238 | wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1239 | return 0; | ||
1240 | } | ||
1241 | |||
1242 | /* power down chip */ | ||
1243 | static int wm8991_remove(struct snd_soc_codec *codec) | ||
1244 | { | ||
1245 | wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1246 | return 0; | ||
1247 | } | ||
1248 | |||
1249 | static int wm8991_probe(struct snd_soc_codec *codec) | ||
1250 | { | ||
1251 | wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1252 | |||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1256 | #define WM8991_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 1230 | #define WM8991_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
1257 | SNDRV_PCM_FMTBIT_S24_LE) | 1231 | SNDRV_PCM_FMTBIT_S24_LE) |
1258 | 1232 | ||
@@ -1293,11 +1267,9 @@ static struct snd_soc_dai_driver wm8991_dai = { | |||
1293 | }; | 1267 | }; |
1294 | 1268 | ||
1295 | static struct snd_soc_codec_driver soc_codec_dev_wm8991 = { | 1269 | static struct snd_soc_codec_driver soc_codec_dev_wm8991 = { |
1296 | .probe = wm8991_probe, | ||
1297 | .remove = wm8991_remove, | ||
1298 | .suspend = wm8991_suspend, | ||
1299 | .resume = wm8991_resume, | ||
1300 | .set_bias_level = wm8991_set_bias_level, | 1270 | .set_bias_level = wm8991_set_bias_level, |
1271 | .suspend_bias_off = true, | ||
1272 | |||
1301 | .controls = wm8991_snd_controls, | 1273 | .controls = wm8991_snd_controls, |
1302 | .num_controls = ARRAY_SIZE(wm8991_snd_controls), | 1274 | .num_controls = ARRAY_SIZE(wm8991_snd_controls), |
1303 | .dapm_widgets = wm8991_dapm_widgets, | 1275 | .dapm_widgets = wm8991_dapm_widgets, |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 1fcb9f3f3097..36b767fa37a6 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -4391,8 +4391,6 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
4391 | struct wm8994 *control = wm8994->wm8994; | 4391 | struct wm8994 *control = wm8994->wm8994; |
4392 | int i; | 4392 | int i; |
4393 | 4393 | ||
4394 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
4395 | |||
4396 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | 4394 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
4397 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i, | 4395 | wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i, |
4398 | &wm8994->fll_locked[i]); | 4396 | &wm8994->fll_locked[i]); |
@@ -4457,6 +4455,8 @@ static int wm8994_probe(struct platform_device *pdev) | |||
4457 | return -ENOMEM; | 4455 | return -ENOMEM; |
4458 | platform_set_drvdata(pdev, wm8994); | 4456 | platform_set_drvdata(pdev, wm8994); |
4459 | 4457 | ||
4458 | mutex_init(&wm8994->fw_lock); | ||
4459 | |||
4460 | wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent); | 4460 | wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent); |
4461 | 4461 | ||
4462 | pm_runtime_enable(&pdev->dev); | 4462 | pm_runtime_enable(&pdev->dev); |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 6536f8d45ac6..dd73387b1cc4 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/firmware.h> | 13 | #include <linux/firmware.h> |
14 | #include <linux/completion.h> | 14 | #include <linux/completion.h> |
15 | #include <linux/workqueue.h> | 15 | #include <linux/workqueue.h> |
16 | #include <linux/mutex.h> | ||
16 | 17 | ||
17 | #include "wm_hubs.h" | 18 | #include "wm_hubs.h" |
18 | 19 | ||
@@ -156,6 +157,7 @@ struct wm8994_priv { | |||
156 | unsigned int aif1clk_disable:1; | 157 | unsigned int aif1clk_disable:1; |
157 | unsigned int aif2clk_disable:1; | 158 | unsigned int aif2clk_disable:1; |
158 | 159 | ||
160 | struct mutex fw_lock; | ||
159 | int dsp_active; | 161 | int dsp_active; |
160 | const struct firmware *cur_fw; | 162 | const struct firmware *cur_fw; |
161 | const struct firmware *mbc; | 163 | const struct firmware *mbc; |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 1288edeb8c7d..c280f0a3a424 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -2004,7 +2004,6 @@ static int wm8995_remove(struct snd_soc_codec *codec) | |||
2004 | int i; | 2004 | int i; |
2005 | 2005 | ||
2006 | wm8995 = snd_soc_codec_get_drvdata(codec); | 2006 | wm8995 = snd_soc_codec_get_drvdata(codec); |
2007 | wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2008 | 2007 | ||
2009 | for (i = 0; i < ARRAY_SIZE(wm8995->supplies); ++i) | 2008 | for (i = 0; i < ARRAY_SIZE(wm8995->supplies); ++i) |
2010 | regulator_unregister_notifier(wm8995->supplies[i].consumer, | 2009 | regulator_unregister_notifier(wm8995->supplies[i].consumer, |
@@ -2078,8 +2077,6 @@ static int wm8995_probe(struct snd_soc_codec *codec) | |||
2078 | goto err_reg_enable; | 2077 | goto err_reg_enable; |
2079 | } | 2078 | } |
2080 | 2079 | ||
2081 | wm8995_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
2082 | |||
2083 | /* Latch volume updates (right only; we always do left then right). */ | 2080 | /* Latch volume updates (right only; we always do left then right). */ |
2084 | snd_soc_update_bits(codec, WM8995_AIF1_DAC1_RIGHT_VOLUME, | 2081 | snd_soc_update_bits(codec, WM8995_AIF1_DAC1_RIGHT_VOLUME, |
2085 | WM8995_AIF1DAC1_VU_MASK, WM8995_AIF1DAC1_VU); | 2082 | WM8995_AIF1DAC1_VU_MASK, WM8995_AIF1DAC1_VU); |
@@ -2102,13 +2099,6 @@ static int wm8995_probe(struct snd_soc_codec *codec) | |||
2102 | 2099 | ||
2103 | wm8995_update_class_w(codec); | 2100 | wm8995_update_class_w(codec); |
2104 | 2101 | ||
2105 | snd_soc_add_codec_controls(codec, wm8995_snd_controls, | ||
2106 | ARRAY_SIZE(wm8995_snd_controls)); | ||
2107 | snd_soc_dapm_new_controls(&codec->dapm, wm8995_dapm_widgets, | ||
2108 | ARRAY_SIZE(wm8995_dapm_widgets)); | ||
2109 | snd_soc_dapm_add_routes(&codec->dapm, wm8995_intercon, | ||
2110 | ARRAY_SIZE(wm8995_intercon)); | ||
2111 | |||
2112 | return 0; | 2102 | return 0; |
2113 | 2103 | ||
2114 | err_reg_enable: | 2104 | err_reg_enable: |
@@ -2205,6 +2195,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8995 = { | |||
2205 | .remove = wm8995_remove, | 2195 | .remove = wm8995_remove, |
2206 | .set_bias_level = wm8995_set_bias_level, | 2196 | .set_bias_level = wm8995_set_bias_level, |
2207 | .idle_bias_off = true, | 2197 | .idle_bias_off = true, |
2198 | |||
2199 | .controls = wm8995_snd_controls, | ||
2200 | .num_controls = ARRAY_SIZE(wm8995_snd_controls), | ||
2201 | .dapm_widgets = wm8995_dapm_widgets, | ||
2202 | .num_dapm_widgets = ARRAY_SIZE(wm8995_dapm_widgets), | ||
2203 | .dapm_routes = wm8995_intercon, | ||
2204 | .num_dapm_routes = ARRAY_SIZE(wm8995_intercon), | ||
2208 | }; | 2205 | }; |
2209 | 2206 | ||
2210 | static struct regmap_config wm8995_regmap = { | 2207 | static struct regmap_config wm8995_regmap = { |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 0cdc9e2184ab..b1d946facd57 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -1277,15 +1277,8 @@ static int wm9081_probe(struct snd_soc_codec *codec) | |||
1277 | return 0; | 1277 | return 0; |
1278 | } | 1278 | } |
1279 | 1279 | ||
1280 | static int wm9081_remove(struct snd_soc_codec *codec) | ||
1281 | { | ||
1282 | wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1283 | return 0; | ||
1284 | } | ||
1285 | |||
1286 | static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { | 1280 | static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { |
1287 | .probe = wm9081_probe, | 1281 | .probe = wm9081_probe, |
1288 | .remove = wm9081_remove, | ||
1289 | 1282 | ||
1290 | .set_sysclk = wm9081_set_sysclk, | 1283 | .set_sysclk = wm9081_set_sysclk, |
1291 | .set_bias_level = wm9081_set_bias_level, | 1284 | .set_bias_level = wm9081_set_bias_level, |
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index c0b7f45dfa37..d3a800fa6f06 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -203,13 +203,14 @@ static const struct snd_soc_dapm_route wm9705_audio_map[] = { | |||
203 | /* We use a register cache to enhance read performance. */ | 203 | /* We use a register cache to enhance read performance. */ |
204 | static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) | 204 | static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) |
205 | { | 205 | { |
206 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
206 | u16 *cache = codec->reg_cache; | 207 | u16 *cache = codec->reg_cache; |
207 | 208 | ||
208 | switch (reg) { | 209 | switch (reg) { |
209 | case AC97_RESET: | 210 | case AC97_RESET: |
210 | case AC97_VENDOR_ID1: | 211 | case AC97_VENDOR_ID1: |
211 | case AC97_VENDOR_ID2: | 212 | case AC97_VENDOR_ID2: |
212 | return soc_ac97_ops->read(codec->ac97, reg); | 213 | return soc_ac97_ops->read(ac97, reg); |
213 | default: | 214 | default: |
214 | reg = reg >> 1; | 215 | reg = reg >> 1; |
215 | 216 | ||
@@ -223,9 +224,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) | |||
223 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 224 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
224 | unsigned int val) | 225 | unsigned int val) |
225 | { | 226 | { |
227 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
226 | u16 *cache = codec->reg_cache; | 228 | u16 *cache = codec->reg_cache; |
227 | 229 | ||
228 | soc_ac97_ops->write(codec->ac97, reg, val); | 230 | soc_ac97_ops->write(ac97, reg, val); |
229 | reg = reg >> 1; | 231 | reg = reg >> 1; |
230 | if (reg < (ARRAY_SIZE(wm9705_reg))) | 232 | if (reg < (ARRAY_SIZE(wm9705_reg))) |
231 | cache[reg] = val; | 233 | cache[reg] = val; |
@@ -263,7 +265,6 @@ static const struct snd_soc_dai_ops wm9705_dai_ops = { | |||
263 | static struct snd_soc_dai_driver wm9705_dai[] = { | 265 | static struct snd_soc_dai_driver wm9705_dai[] = { |
264 | { | 266 | { |
265 | .name = "wm9705-hifi", | 267 | .name = "wm9705-hifi", |
266 | .ac97_control = 1, | ||
267 | .playback = { | 268 | .playback = { |
268 | .stream_name = "HiFi Playback", | 269 | .stream_name = "HiFi Playback", |
269 | .channels_min = 1, | 270 | .channels_min = 1, |
@@ -294,36 +295,41 @@ static struct snd_soc_dai_driver wm9705_dai[] = { | |||
294 | 295 | ||
295 | static int wm9705_reset(struct snd_soc_codec *codec) | 296 | static int wm9705_reset(struct snd_soc_codec *codec) |
296 | { | 297 | { |
298 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
299 | |||
297 | if (soc_ac97_ops->reset) { | 300 | if (soc_ac97_ops->reset) { |
298 | soc_ac97_ops->reset(codec->ac97); | 301 | soc_ac97_ops->reset(ac97); |
299 | if (ac97_read(codec, 0) == wm9705_reg[0]) | 302 | if (ac97_read(codec, 0) == wm9705_reg[0]) |
300 | return 0; /* Success */ | 303 | return 0; /* Success */ |
301 | } | 304 | } |
302 | 305 | ||
306 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); | ||
307 | |||
303 | return -EIO; | 308 | return -EIO; |
304 | } | 309 | } |
305 | 310 | ||
306 | #ifdef CONFIG_PM | 311 | #ifdef CONFIG_PM |
307 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) | 312 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) |
308 | { | 313 | { |
309 | soc_ac97_ops->write(codec->ac97, AC97_POWERDOWN, 0xffff); | 314 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
315 | |||
316 | soc_ac97_ops->write(ac97, AC97_POWERDOWN, 0xffff); | ||
310 | 317 | ||
311 | return 0; | 318 | return 0; |
312 | } | 319 | } |
313 | 320 | ||
314 | static int wm9705_soc_resume(struct snd_soc_codec *codec) | 321 | static int wm9705_soc_resume(struct snd_soc_codec *codec) |
315 | { | 322 | { |
323 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
316 | int i, ret; | 324 | int i, ret; |
317 | u16 *cache = codec->reg_cache; | 325 | u16 *cache = codec->reg_cache; |
318 | 326 | ||
319 | ret = wm9705_reset(codec); | 327 | ret = wm9705_reset(codec); |
320 | if (ret < 0) { | 328 | if (ret < 0) |
321 | printk(KERN_ERR "could not reset AC97 codec\n"); | ||
322 | return ret; | 329 | return ret; |
323 | } | ||
324 | 330 | ||
325 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { | 331 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { |
326 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); | 332 | soc_ac97_ops->write(ac97, i, cache[i>>1]); |
327 | } | 333 | } |
328 | 334 | ||
329 | return 0; | 335 | return 0; |
@@ -335,31 +341,34 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) | |||
335 | 341 | ||
336 | static int wm9705_soc_probe(struct snd_soc_codec *codec) | 342 | static int wm9705_soc_probe(struct snd_soc_codec *codec) |
337 | { | 343 | { |
344 | struct snd_ac97 *ac97; | ||
338 | int ret = 0; | 345 | int ret = 0; |
339 | 346 | ||
340 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 347 | ac97 = snd_soc_new_ac97_codec(codec); |
341 | if (ret < 0) { | 348 | if (IS_ERR(ac97)) { |
342 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); | 349 | ret = PTR_ERR(ac97); |
350 | dev_err(codec->dev, "Failed to register AC97 codec\n"); | ||
343 | return ret; | 351 | return ret; |
344 | } | 352 | } |
345 | 353 | ||
354 | snd_soc_codec_set_drvdata(codec, ac97); | ||
355 | |||
346 | ret = wm9705_reset(codec); | 356 | ret = wm9705_reset(codec); |
347 | if (ret) | 357 | if (ret) |
348 | goto reset_err; | 358 | goto reset_err; |
349 | 359 | ||
350 | snd_soc_add_codec_controls(codec, wm9705_snd_ac97_controls, | ||
351 | ARRAY_SIZE(wm9705_snd_ac97_controls)); | ||
352 | |||
353 | return 0; | 360 | return 0; |
354 | 361 | ||
355 | reset_err: | 362 | reset_err: |
356 | snd_soc_free_ac97_codec(codec); | 363 | snd_soc_free_ac97_codec(ac97); |
357 | return ret; | 364 | return ret; |
358 | } | 365 | } |
359 | 366 | ||
360 | static int wm9705_soc_remove(struct snd_soc_codec *codec) | 367 | static int wm9705_soc_remove(struct snd_soc_codec *codec) |
361 | { | 368 | { |
362 | snd_soc_free_ac97_codec(codec); | 369 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
370 | |||
371 | snd_soc_free_ac97_codec(ac97); | ||
363 | return 0; | 372 | return 0; |
364 | } | 373 | } |
365 | 374 | ||
@@ -374,6 +383,9 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { | |||
374 | .reg_word_size = sizeof(u16), | 383 | .reg_word_size = sizeof(u16), |
375 | .reg_cache_step = 2, | 384 | .reg_cache_step = 2, |
376 | .reg_cache_default = wm9705_reg, | 385 | .reg_cache_default = wm9705_reg, |
386 | |||
387 | .controls = wm9705_snd_ac97_controls, | ||
388 | .num_controls = ARRAY_SIZE(wm9705_snd_ac97_controls), | ||
377 | .dapm_widgets = wm9705_dapm_widgets, | 389 | .dapm_widgets = wm9705_dapm_widgets, |
378 | .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), | 390 | .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), |
379 | .dapm_routes = wm9705_audio_map, | 391 | .dapm_routes = wm9705_audio_map, |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index c5eb746087b4..52a211be5b47 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -23,6 +23,12 @@ | |||
23 | #include <sound/tlv.h> | 23 | #include <sound/tlv.h> |
24 | #include "wm9712.h" | 24 | #include "wm9712.h" |
25 | 25 | ||
26 | struct wm9712_priv { | ||
27 | struct snd_ac97 *ac97; | ||
28 | unsigned int hp_mixer[2]; | ||
29 | struct mutex lock; | ||
30 | }; | ||
31 | |||
26 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 32 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
27 | unsigned int reg); | 33 | unsigned int reg); |
28 | static int ac97_write(struct snd_soc_codec *codec, | 34 | static int ac97_write(struct snd_soc_codec *codec, |
@@ -48,12 +54,10 @@ static const u16 wm9712_reg[] = { | |||
48 | 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */ | 54 | 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */ |
49 | 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */ | 55 | 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */ |
50 | 0x0001, 0x0000, 0x574d, 0x4c12, /* 7e */ | 56 | 0x0001, 0x0000, 0x574d, 0x4c12, /* 7e */ |
51 | 0x0000, 0x0000 /* virtual hp mixers */ | ||
52 | }; | 57 | }; |
53 | 58 | ||
54 | /* virtual HP mixers regs */ | 59 | #define HPL_MIXER 0x0 |
55 | #define HPL_MIXER 0x80 | 60 | #define HPR_MIXER 0x1 |
56 | #define HPR_MIXER 0x82 | ||
57 | 61 | ||
58 | static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"}; | 62 | static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"}; |
59 | static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"}; | 63 | static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"}; |
@@ -157,75 +161,108 @@ SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv), | |||
157 | SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv), | 161 | SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv), |
158 | }; | 162 | }; |
159 | 163 | ||
164 | static const unsigned int wm9712_mixer_mute_regs[] = { | ||
165 | AC97_VIDEO, | ||
166 | AC97_PCM, | ||
167 | AC97_LINE, | ||
168 | AC97_PHONE, | ||
169 | AC97_CD, | ||
170 | AC97_PC_BEEP, | ||
171 | }; | ||
172 | |||
160 | /* We have to create a fake left and right HP mixers because | 173 | /* We have to create a fake left and right HP mixers because |
161 | * the codec only has a single control that is shared by both channels. | 174 | * the codec only has a single control that is shared by both channels. |
162 | * This makes it impossible to determine the audio path. | 175 | * This makes it impossible to determine the audio path. |
163 | */ | 176 | */ |
164 | static int mixer_event(struct snd_soc_dapm_widget *w, | 177 | static int wm9712_hp_mixer_put(struct snd_kcontrol *kcontrol, |
165 | struct snd_kcontrol *k, int event) | 178 | struct snd_ctl_elem_value *ucontrol) |
166 | { | 179 | { |
167 | u16 l, r, beep, line, phone, mic, pcm, aux; | 180 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
168 | 181 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | |
169 | l = ac97_read(w->codec, HPL_MIXER); | 182 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); |
170 | r = ac97_read(w->codec, HPR_MIXER); | 183 | unsigned int val = ucontrol->value.enumerated.item[0]; |
171 | beep = ac97_read(w->codec, AC97_PC_BEEP); | 184 | struct soc_mixer_control *mc = |
172 | mic = ac97_read(w->codec, AC97_VIDEO); | 185 | (struct soc_mixer_control *)kcontrol->private_value; |
173 | phone = ac97_read(w->codec, AC97_PHONE); | 186 | unsigned int mixer, mask, shift, old; |
174 | line = ac97_read(w->codec, AC97_LINE); | 187 | struct snd_soc_dapm_update update; |
175 | pcm = ac97_read(w->codec, AC97_PCM); | 188 | bool change; |
176 | aux = ac97_read(w->codec, AC97_CD); | 189 | |
177 | 190 | mixer = mc->shift >> 8; | |
178 | if (l & 0x1 || r & 0x1) | 191 | shift = mc->shift & 0xff; |
179 | ac97_write(w->codec, AC97_VIDEO, mic & 0x7fff); | 192 | mask = 1 << shift; |
193 | |||
194 | mutex_lock(&wm9712->lock); | ||
195 | old = wm9712->hp_mixer[mixer]; | ||
196 | if (ucontrol->value.enumerated.item[0]) | ||
197 | wm9712->hp_mixer[mixer] |= mask; | ||
180 | else | 198 | else |
181 | ac97_write(w->codec, AC97_VIDEO, mic | 0x8000); | 199 | wm9712->hp_mixer[mixer] &= ~mask; |
200 | |||
201 | change = old != wm9712->hp_mixer[mixer]; | ||
202 | if (change) { | ||
203 | update.kcontrol = kcontrol; | ||
204 | update.reg = wm9712_mixer_mute_regs[shift]; | ||
205 | update.mask = 0x8000; | ||
206 | if ((wm9712->hp_mixer[0] & mask) || | ||
207 | (wm9712->hp_mixer[1] & mask)) | ||
208 | update.val = 0x0; | ||
209 | else | ||
210 | update.val = 0x8000; | ||
211 | |||
212 | snd_soc_dapm_mixer_update_power(dapm, kcontrol, val, | ||
213 | &update); | ||
214 | } | ||
182 | 215 | ||
183 | if (l & 0x2 || r & 0x2) | 216 | mutex_unlock(&wm9712->lock); |
184 | ac97_write(w->codec, AC97_PCM, pcm & 0x7fff); | ||
185 | else | ||
186 | ac97_write(w->codec, AC97_PCM, pcm | 0x8000); | ||
187 | 217 | ||
188 | if (l & 0x4 || r & 0x4) | 218 | return change; |
189 | ac97_write(w->codec, AC97_LINE, line & 0x7fff); | 219 | } |
190 | else | ||
191 | ac97_write(w->codec, AC97_LINE, line | 0x8000); | ||
192 | 220 | ||
193 | if (l & 0x8 || r & 0x8) | 221 | static int wm9712_hp_mixer_get(struct snd_kcontrol *kcontrol, |
194 | ac97_write(w->codec, AC97_PHONE, phone & 0x7fff); | 222 | struct snd_ctl_elem_value *ucontrol) |
195 | else | 223 | { |
196 | ac97_write(w->codec, AC97_PHONE, phone | 0x8000); | 224 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
225 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
226 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
227 | struct soc_mixer_control *mc = | ||
228 | (struct soc_mixer_control *)kcontrol->private_value; | ||
229 | unsigned int shift, mixer; | ||
197 | 230 | ||
198 | if (l & 0x10 || r & 0x10) | 231 | mixer = mc->shift >> 8; |
199 | ac97_write(w->codec, AC97_CD, aux & 0x7fff); | 232 | shift = mc->shift & 0xff; |
200 | else | ||
201 | ac97_write(w->codec, AC97_CD, aux | 0x8000); | ||
202 | 233 | ||
203 | if (l & 0x20 || r & 0x20) | 234 | ucontrol->value.enumerated.item[0] = |
204 | ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff); | 235 | (wm9712->hp_mixer[mixer] >> shift) & 1; |
205 | else | ||
206 | ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000); | ||
207 | 236 | ||
208 | return 0; | 237 | return 0; |
209 | } | 238 | } |
210 | 239 | ||
240 | #define WM9712_HP_MIXER_CTRL(xname, xmixer, xshift) { \ | ||
241 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
242 | .info = snd_soc_info_volsw, \ | ||
243 | .get = wm9712_hp_mixer_get, .put = wm9712_hp_mixer_put, \ | ||
244 | .private_value = SOC_SINGLE_VALUE(SND_SOC_NOPM, \ | ||
245 | (xmixer << 8) | xshift, 1, 0, 0) \ | ||
246 | } | ||
247 | |||
211 | /* Left Headphone Mixers */ | 248 | /* Left Headphone Mixers */ |
212 | static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = { | 249 | static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = { |
213 | SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPL_MIXER, 5, 1, 0), | 250 | WM9712_HP_MIXER_CTRL("PCBeep Bypass Switch", HPL_MIXER, 5), |
214 | SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 4, 1, 0), | 251 | WM9712_HP_MIXER_CTRL("Aux Playback Switch", HPL_MIXER, 4), |
215 | SOC_DAPM_SINGLE("Phone Bypass Switch", HPL_MIXER, 3, 1, 0), | 252 | WM9712_HP_MIXER_CTRL("Phone Bypass Switch", HPL_MIXER, 3), |
216 | SOC_DAPM_SINGLE("Line Bypass Switch", HPL_MIXER, 2, 1, 0), | 253 | WM9712_HP_MIXER_CTRL("Line Bypass Switch", HPL_MIXER, 2), |
217 | SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 1, 1, 0), | 254 | WM9712_HP_MIXER_CTRL("PCM Playback Switch", HPL_MIXER, 1), |
218 | SOC_DAPM_SINGLE("Mic Sidetone Switch", HPL_MIXER, 0, 1, 0), | 255 | WM9712_HP_MIXER_CTRL("Mic Sidetone Switch", HPL_MIXER, 0), |
219 | }; | 256 | }; |
220 | 257 | ||
221 | /* Right Headphone Mixers */ | 258 | /* Right Headphone Mixers */ |
222 | static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = { | 259 | static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = { |
223 | SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPR_MIXER, 5, 1, 0), | 260 | WM9712_HP_MIXER_CTRL("PCBeep Bypass Switch", HPR_MIXER, 5), |
224 | SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 4, 1, 0), | 261 | WM9712_HP_MIXER_CTRL("Aux Playback Switch", HPR_MIXER, 4), |
225 | SOC_DAPM_SINGLE("Phone Bypass Switch", HPR_MIXER, 3, 1, 0), | 262 | WM9712_HP_MIXER_CTRL("Phone Bypass Switch", HPR_MIXER, 3), |
226 | SOC_DAPM_SINGLE("Line Bypass Switch", HPR_MIXER, 2, 1, 0), | 263 | WM9712_HP_MIXER_CTRL("Line Bypass Switch", HPR_MIXER, 2), |
227 | SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 1, 1, 0), | 264 | WM9712_HP_MIXER_CTRL("PCM Playback Switch", HPR_MIXER, 1), |
228 | SOC_DAPM_SINGLE("Mic Sidetone Switch", HPR_MIXER, 0, 1, 0), | 265 | WM9712_HP_MIXER_CTRL("Mic Sidetone Switch", HPR_MIXER, 0), |
229 | }; | 266 | }; |
230 | 267 | ||
231 | /* Speaker Mixer */ | 268 | /* Speaker Mixer */ |
@@ -299,12 +336,10 @@ SND_SOC_DAPM_MUX("Right Mic Select Source", SND_SOC_NOPM, 0, 0, | |||
299 | SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0, | 336 | SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0, |
300 | &wm9712_diff_sel_controls), | 337 | &wm9712_diff_sel_controls), |
301 | SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), | 338 | SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), |
302 | SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_INT_PAGING, 9, 1, | 339 | SND_SOC_DAPM_MIXER("Left HP Mixer", AC97_INT_PAGING, 9, 1, |
303 | &wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls), | 340 | &wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls)), |
304 | mixer_event, SND_SOC_DAPM_POST_REG), | 341 | SND_SOC_DAPM_MIXER("Right HP Mixer", AC97_INT_PAGING, 8, 1, |
305 | SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_INT_PAGING, 8, 1, | 342 | &wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls)), |
306 | &wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls), | ||
307 | mixer_event, SND_SOC_DAPM_POST_REG), | ||
308 | SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1, | 343 | SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1, |
309 | &wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)), | 344 | &wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)), |
310 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1, | 345 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1, |
@@ -450,12 +485,13 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = { | |||
450 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 485 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
451 | unsigned int reg) | 486 | unsigned int reg) |
452 | { | 487 | { |
488 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
453 | u16 *cache = codec->reg_cache; | 489 | u16 *cache = codec->reg_cache; |
454 | 490 | ||
455 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 491 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
456 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 492 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
457 | reg == AC97_REC_GAIN) | 493 | reg == AC97_REC_GAIN) |
458 | return soc_ac97_ops->read(codec->ac97, reg); | 494 | return soc_ac97_ops->read(wm9712->ac97, reg); |
459 | else { | 495 | else { |
460 | reg = reg >> 1; | 496 | reg = reg >> 1; |
461 | 497 | ||
@@ -469,10 +505,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
469 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 505 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
470 | unsigned int val) | 506 | unsigned int val) |
471 | { | 507 | { |
508 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
472 | u16 *cache = codec->reg_cache; | 509 | u16 *cache = codec->reg_cache; |
473 | 510 | ||
474 | if (reg < 0x7c) | 511 | soc_ac97_ops->write(wm9712->ac97, reg, val); |
475 | soc_ac97_ops->write(codec->ac97, reg, val); | ||
476 | reg = reg >> 1; | 512 | reg = reg >> 1; |
477 | if (reg < (ARRAY_SIZE(wm9712_reg))) | 513 | if (reg < (ARRAY_SIZE(wm9712_reg))) |
478 | cache[reg] = val; | 514 | cache[reg] = val; |
@@ -532,7 +568,6 @@ static const struct snd_soc_dai_ops wm9712_dai_ops_aux = { | |||
532 | static struct snd_soc_dai_driver wm9712_dai[] = { | 568 | static struct snd_soc_dai_driver wm9712_dai[] = { |
533 | { | 569 | { |
534 | .name = "wm9712-hifi", | 570 | .name = "wm9712-hifi", |
535 | .ac97_control = 1, | ||
536 | .playback = { | 571 | .playback = { |
537 | .stream_name = "HiFi Playback", | 572 | .stream_name = "HiFi Playback", |
538 | .channels_min = 1, | 573 | .channels_min = 1, |
@@ -581,21 +616,23 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec, | |||
581 | 616 | ||
582 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) | 617 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) |
583 | { | 618 | { |
619 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
620 | |||
584 | if (try_warm && soc_ac97_ops->warm_reset) { | 621 | if (try_warm && soc_ac97_ops->warm_reset) { |
585 | soc_ac97_ops->warm_reset(codec->ac97); | 622 | soc_ac97_ops->warm_reset(wm9712->ac97); |
586 | if (ac97_read(codec, 0) == wm9712_reg[0]) | 623 | if (ac97_read(codec, 0) == wm9712_reg[0]) |
587 | return 1; | 624 | return 1; |
588 | } | 625 | } |
589 | 626 | ||
590 | soc_ac97_ops->reset(codec->ac97); | 627 | soc_ac97_ops->reset(wm9712->ac97); |
591 | if (soc_ac97_ops->warm_reset) | 628 | if (soc_ac97_ops->warm_reset) |
592 | soc_ac97_ops->warm_reset(codec->ac97); | 629 | soc_ac97_ops->warm_reset(wm9712->ac97); |
593 | if (ac97_read(codec, 0) != wm9712_reg[0]) | 630 | if (ac97_read(codec, 0) != wm9712_reg[0]) |
594 | goto err; | 631 | goto err; |
595 | return 0; | 632 | return 0; |
596 | 633 | ||
597 | err: | 634 | err: |
598 | printk(KERN_ERR "WM9712 AC97 reset failed\n"); | 635 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); |
599 | return -EIO; | 636 | return -EIO; |
600 | } | 637 | } |
601 | 638 | ||
@@ -607,14 +644,13 @@ static int wm9712_soc_suspend(struct snd_soc_codec *codec) | |||
607 | 644 | ||
608 | static int wm9712_soc_resume(struct snd_soc_codec *codec) | 645 | static int wm9712_soc_resume(struct snd_soc_codec *codec) |
609 | { | 646 | { |
647 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
610 | int i, ret; | 648 | int i, ret; |
611 | u16 *cache = codec->reg_cache; | 649 | u16 *cache = codec->reg_cache; |
612 | 650 | ||
613 | ret = wm9712_reset(codec, 1); | 651 | ret = wm9712_reset(codec, 1); |
614 | if (ret < 0) { | 652 | if (ret < 0) |
615 | printk(KERN_ERR "could not reset AC97 codec\n"); | ||
616 | return ret; | 653 | return ret; |
617 | } | ||
618 | 654 | ||
619 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 655 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
620 | 656 | ||
@@ -624,7 +660,7 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) | |||
624 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || | 660 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || |
625 | (i > 0x58 && i != 0x5c)) | 661 | (i > 0x58 && i != 0x5c)) |
626 | continue; | 662 | continue; |
627 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); | 663 | soc_ac97_ops->write(wm9712->ac97, i, cache[i>>1]); |
628 | } | 664 | } |
629 | } | 665 | } |
630 | 666 | ||
@@ -633,37 +669,37 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) | |||
633 | 669 | ||
634 | static int wm9712_soc_probe(struct snd_soc_codec *codec) | 670 | static int wm9712_soc_probe(struct snd_soc_codec *codec) |
635 | { | 671 | { |
672 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
636 | int ret = 0; | 673 | int ret = 0; |
637 | 674 | ||
638 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 675 | wm9712->ac97 = snd_soc_new_ac97_codec(codec); |
639 | if (ret < 0) { | 676 | if (IS_ERR(wm9712->ac97)) { |
640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); | 677 | ret = PTR_ERR(wm9712->ac97); |
678 | dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); | ||
641 | return ret; | 679 | return ret; |
642 | } | 680 | } |
643 | 681 | ||
644 | ret = wm9712_reset(codec, 0); | 682 | ret = wm9712_reset(codec, 0); |
645 | if (ret < 0) { | 683 | if (ret < 0) |
646 | printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); | ||
647 | goto reset_err; | 684 | goto reset_err; |
648 | } | ||
649 | 685 | ||
650 | /* set alc mux to none */ | 686 | /* set alc mux to none */ |
651 | ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); | 687 | ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); |
652 | 688 | ||
653 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 689 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
654 | snd_soc_add_codec_controls(codec, wm9712_snd_ac97_controls, | ||
655 | ARRAY_SIZE(wm9712_snd_ac97_controls)); | ||
656 | 690 | ||
657 | return 0; | 691 | return 0; |
658 | 692 | ||
659 | reset_err: | 693 | reset_err: |
660 | snd_soc_free_ac97_codec(codec); | 694 | snd_soc_free_ac97_codec(wm9712->ac97); |
661 | return ret; | 695 | return ret; |
662 | } | 696 | } |
663 | 697 | ||
664 | static int wm9712_soc_remove(struct snd_soc_codec *codec) | 698 | static int wm9712_soc_remove(struct snd_soc_codec *codec) |
665 | { | 699 | { |
666 | snd_soc_free_ac97_codec(codec); | 700 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); |
701 | |||
702 | snd_soc_free_ac97_codec(wm9712->ac97); | ||
667 | return 0; | 703 | return 0; |
668 | } | 704 | } |
669 | 705 | ||
@@ -679,6 +715,9 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { | |||
679 | .reg_word_size = sizeof(u16), | 715 | .reg_word_size = sizeof(u16), |
680 | .reg_cache_step = 2, | 716 | .reg_cache_step = 2, |
681 | .reg_cache_default = wm9712_reg, | 717 | .reg_cache_default = wm9712_reg, |
718 | |||
719 | .controls = wm9712_snd_ac97_controls, | ||
720 | .num_controls = ARRAY_SIZE(wm9712_snd_ac97_controls), | ||
682 | .dapm_widgets = wm9712_dapm_widgets, | 721 | .dapm_widgets = wm9712_dapm_widgets, |
683 | .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), | 722 | .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), |
684 | .dapm_routes = wm9712_audio_map, | 723 | .dapm_routes = wm9712_audio_map, |
@@ -687,6 +726,16 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { | |||
687 | 726 | ||
688 | static int wm9712_probe(struct platform_device *pdev) | 727 | static int wm9712_probe(struct platform_device *pdev) |
689 | { | 728 | { |
729 | struct wm9712_priv *wm9712; | ||
730 | |||
731 | wm9712 = devm_kzalloc(&pdev->dev, sizeof(*wm9712), GFP_KERNEL); | ||
732 | if (wm9712 == NULL) | ||
733 | return -ENOMEM; | ||
734 | |||
735 | mutex_init(&wm9712->lock); | ||
736 | |||
737 | platform_set_drvdata(pdev, wm9712); | ||
738 | |||
690 | return snd_soc_register_codec(&pdev->dev, | 739 | return snd_soc_register_codec(&pdev->dev, |
691 | &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai)); | 740 | &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai)); |
692 | } | 741 | } |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index bddee30a4bc7..6c95d98b0eb1 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -30,7 +30,10 @@ | |||
30 | #include "wm9713.h" | 30 | #include "wm9713.h" |
31 | 31 | ||
32 | struct wm9713_priv { | 32 | struct wm9713_priv { |
33 | struct snd_ac97 *ac97; | ||
33 | u32 pll_in; /* PLL input frequency */ | 34 | u32 pll_in; /* PLL input frequency */ |
35 | unsigned int hp_mixer[2]; | ||
36 | struct mutex lock; | ||
34 | }; | 37 | }; |
35 | 38 | ||
36 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 39 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
@@ -59,13 +62,10 @@ static const u16 wm9713_reg[] = { | |||
59 | 0x0000, 0x0000, 0x0000, 0x0000, | 62 | 0x0000, 0x0000, 0x0000, 0x0000, |
60 | 0x0000, 0x0000, 0x0000, 0x0006, | 63 | 0x0000, 0x0000, 0x0000, 0x0006, |
61 | 0x0001, 0x0000, 0x574d, 0x4c13, | 64 | 0x0001, 0x0000, 0x574d, 0x4c13, |
62 | 0x0000, 0x0000, 0x0000 | ||
63 | }; | 65 | }; |
64 | 66 | ||
65 | /* virtual HP mixers regs */ | 67 | #define HPL_MIXER 0 |
66 | #define HPL_MIXER 0x80 | 68 | #define HPR_MIXER 1 |
67 | #define HPR_MIXER 0x82 | ||
68 | #define MICB_MUX 0x82 | ||
69 | 69 | ||
70 | static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"}; | 70 | static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"}; |
71 | static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"}; | 71 | static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"}; |
@@ -110,7 +110,7 @@ SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 10, 8, wm9713_dac_inv), /* dac invert 2 15 */ | |||
110 | SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */ | 110 | SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */ |
111 | SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */ | 111 | SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */ |
112 | SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */ | 112 | SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */ |
113 | SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */ | 113 | SOC_ENUM_SINGLE_VIRT(2, wm9713_micb_select), /* mic selection 19 */ |
114 | }; | 114 | }; |
115 | 115 | ||
116 | static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0); | 116 | static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0); |
@@ -234,6 +234,14 @@ static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w, | |||
234 | return 0; | 234 | return 0; |
235 | } | 235 | } |
236 | 236 | ||
237 | static const unsigned int wm9713_mixer_mute_regs[] = { | ||
238 | AC97_PC_BEEP, | ||
239 | AC97_MASTER_TONE, | ||
240 | AC97_PHONE, | ||
241 | AC97_REC_SEL, | ||
242 | AC97_PCM, | ||
243 | AC97_AUX, | ||
244 | }; | ||
237 | 245 | ||
238 | /* We have to create a fake left and right HP mixers because | 246 | /* We have to create a fake left and right HP mixers because |
239 | * the codec only has a single control that is shared by both channels. | 247 | * the codec only has a single control that is shared by both channels. |
@@ -241,73 +249,95 @@ static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w, | |||
241 | * register map, thus we add a new (virtual) register to help determine the | 249 | * register map, thus we add a new (virtual) register to help determine the |
242 | * audio route within the device. | 250 | * audio route within the device. |
243 | */ | 251 | */ |
244 | static int mixer_event(struct snd_soc_dapm_widget *w, | 252 | static int wm9713_hp_mixer_put(struct snd_kcontrol *kcontrol, |
245 | struct snd_kcontrol *kcontrol, int event) | 253 | struct snd_ctl_elem_value *ucontrol) |
246 | { | 254 | { |
247 | u16 l, r, beep, tone, phone, rec, pcm, aux; | 255 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
248 | 256 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | |
249 | l = ac97_read(w->codec, HPL_MIXER); | 257 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
250 | r = ac97_read(w->codec, HPR_MIXER); | 258 | unsigned int val = ucontrol->value.enumerated.item[0]; |
251 | beep = ac97_read(w->codec, AC97_PC_BEEP); | 259 | struct soc_mixer_control *mc = |
252 | tone = ac97_read(w->codec, AC97_MASTER_TONE); | 260 | (struct soc_mixer_control *)kcontrol->private_value; |
253 | phone = ac97_read(w->codec, AC97_PHONE); | 261 | unsigned int mixer, mask, shift, old; |
254 | rec = ac97_read(w->codec, AC97_REC_SEL); | 262 | struct snd_soc_dapm_update update; |
255 | pcm = ac97_read(w->codec, AC97_PCM); | 263 | bool change; |
256 | aux = ac97_read(w->codec, AC97_AUX); | 264 | |
257 | 265 | mixer = mc->shift >> 8; | |
258 | if (event & SND_SOC_DAPM_PRE_REG) | 266 | shift = mc->shift & 0xff; |
259 | return 0; | 267 | mask = (1 << shift); |
260 | if ((l & 0x1) || (r & 0x1)) | 268 | |
261 | ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff); | 269 | mutex_lock(&wm9713->lock); |
270 | old = wm9713->hp_mixer[mixer]; | ||
271 | if (ucontrol->value.enumerated.item[0]) | ||
272 | wm9713->hp_mixer[mixer] |= mask; | ||
262 | else | 273 | else |
263 | ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000); | 274 | wm9713->hp_mixer[mixer] &= ~mask; |
275 | |||
276 | change = old != wm9713->hp_mixer[mixer]; | ||
277 | if (change) { | ||
278 | update.kcontrol = kcontrol; | ||
279 | update.reg = wm9713_mixer_mute_regs[shift]; | ||
280 | update.mask = 0x8000; | ||
281 | if ((wm9713->hp_mixer[0] & mask) || | ||
282 | (wm9713->hp_mixer[1] & mask)) | ||
283 | update.val = 0x0; | ||
284 | else | ||
285 | update.val = 0x8000; | ||
286 | |||
287 | snd_soc_dapm_mixer_update_power(dapm, kcontrol, val, | ||
288 | &update); | ||
289 | } | ||
264 | 290 | ||
265 | if ((l & 0x2) || (r & 0x2)) | 291 | mutex_unlock(&wm9713->lock); |
266 | ac97_write(w->codec, AC97_MASTER_TONE, tone & 0x7fff); | ||
267 | else | ||
268 | ac97_write(w->codec, AC97_MASTER_TONE, tone | 0x8000); | ||
269 | 292 | ||
270 | if ((l & 0x4) || (r & 0x4)) | 293 | return change; |
271 | ac97_write(w->codec, AC97_PHONE, phone & 0x7fff); | 294 | } |
272 | else | ||
273 | ac97_write(w->codec, AC97_PHONE, phone | 0x8000); | ||
274 | 295 | ||
275 | if ((l & 0x8) || (r & 0x8)) | 296 | static int wm9713_hp_mixer_get(struct snd_kcontrol *kcontrol, |
276 | ac97_write(w->codec, AC97_REC_SEL, rec & 0x7fff); | 297 | struct snd_ctl_elem_value *ucontrol) |
277 | else | 298 | { |
278 | ac97_write(w->codec, AC97_REC_SEL, rec | 0x8000); | 299 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
300 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
301 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
302 | struct soc_mixer_control *mc = | ||
303 | (struct soc_mixer_control *)kcontrol->private_value; | ||
304 | unsigned int mixer, shift; | ||
279 | 305 | ||
280 | if ((l & 0x10) || (r & 0x10)) | 306 | mixer = mc->shift >> 8; |
281 | ac97_write(w->codec, AC97_PCM, pcm & 0x7fff); | 307 | shift = mc->shift & 0xff; |
282 | else | ||
283 | ac97_write(w->codec, AC97_PCM, pcm | 0x8000); | ||
284 | 308 | ||
285 | if ((l & 0x20) || (r & 0x20)) | 309 | ucontrol->value.enumerated.item[0] = |
286 | ac97_write(w->codec, AC97_AUX, aux & 0x7fff); | 310 | (wm9713->hp_mixer[mixer] >> shift) & 1; |
287 | else | ||
288 | ac97_write(w->codec, AC97_AUX, aux | 0x8000); | ||
289 | 311 | ||
290 | return 0; | 312 | return 0; |
291 | } | 313 | } |
292 | 314 | ||
315 | #define WM9713_HP_MIXER_CTRL(xname, xmixer, xshift) { \ | ||
316 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
317 | .info = snd_soc_info_volsw, \ | ||
318 | .get = wm9713_hp_mixer_get, .put = wm9713_hp_mixer_put, \ | ||
319 | .private_value = SOC_DOUBLE_VALUE(SND_SOC_NOPM, \ | ||
320 | xshift, xmixer, 1, 0, 0) \ | ||
321 | } | ||
322 | |||
293 | /* Left Headphone Mixers */ | 323 | /* Left Headphone Mixers */ |
294 | static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { | 324 | static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { |
295 | SOC_DAPM_SINGLE("Beep Playback Switch", HPL_MIXER, 5, 1, 0), | 325 | WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPL_MIXER, 5), |
296 | SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0), | 326 | WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPL_MIXER, 4), |
297 | SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0), | 327 | WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPL_MIXER, 3), |
298 | SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0), | 328 | WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPL_MIXER, 2), |
299 | SOC_DAPM_SINGLE("MonoIn Playback Switch", HPL_MIXER, 1, 1, 0), | 329 | WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPL_MIXER, 1), |
300 | SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0), | 330 | WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPL_MIXER, 0), |
301 | }; | 331 | }; |
302 | 332 | ||
303 | /* Right Headphone Mixers */ | 333 | /* Right Headphone Mixers */ |
304 | static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = { | 334 | static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = { |
305 | SOC_DAPM_SINGLE("Beep Playback Switch", HPR_MIXER, 5, 1, 0), | 335 | WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPR_MIXER, 5), |
306 | SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0), | 336 | WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPR_MIXER, 4), |
307 | SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0), | 337 | WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPR_MIXER, 3), |
308 | SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0), | 338 | WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPR_MIXER, 2), |
309 | SOC_DAPM_SINGLE("MonoIn Playback Switch", HPR_MIXER, 1, 1, 0), | 339 | WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPR_MIXER, 1), |
310 | SOC_DAPM_SINGLE("Bypass Playback Switch", HPR_MIXER, 0, 1, 0), | 340 | WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPR_MIXER, 0), |
311 | }; | 341 | }; |
312 | 342 | ||
313 | /* headphone capture mux */ | 343 | /* headphone capture mux */ |
@@ -429,12 +459,10 @@ SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM, 0, 0, | |||
429 | &wm9713_mic_sel_mux_controls), | 459 | &wm9713_mic_sel_mux_controls), |
430 | SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0, | 460 | SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0, |
431 | &wm9713_micb_sel_mux_controls), | 461 | &wm9713_micb_sel_mux_controls), |
432 | SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_EXTENDED_MID, 3, 1, | 462 | SND_SOC_DAPM_MIXER("Left HP Mixer", AC97_EXTENDED_MID, 3, 1, |
433 | &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls), | 463 | &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls)), |
434 | mixer_event, SND_SOC_DAPM_POST_REG), | 464 | SND_SOC_DAPM_MIXER("Right HP Mixer", AC97_EXTENDED_MID, 2, 1, |
435 | SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_EXTENDED_MID, 2, 1, | 465 | &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls)), |
436 | &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls), | ||
437 | mixer_event, SND_SOC_DAPM_POST_REG), | ||
438 | SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1, | 466 | SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1, |
439 | &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)), | 467 | &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)), |
440 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1, | 468 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1, |
@@ -647,12 +675,13 @@ static const struct snd_soc_dapm_route wm9713_audio_map[] = { | |||
647 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 675 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
648 | unsigned int reg) | 676 | unsigned int reg) |
649 | { | 677 | { |
678 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
650 | u16 *cache = codec->reg_cache; | 679 | u16 *cache = codec->reg_cache; |
651 | 680 | ||
652 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 681 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
653 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 682 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
654 | reg == AC97_CD) | 683 | reg == AC97_CD) |
655 | return soc_ac97_ops->read(codec->ac97, reg); | 684 | return soc_ac97_ops->read(wm9713->ac97, reg); |
656 | else { | 685 | else { |
657 | reg = reg >> 1; | 686 | reg = reg >> 1; |
658 | 687 | ||
@@ -666,9 +695,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
666 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 695 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
667 | unsigned int val) | 696 | unsigned int val) |
668 | { | 697 | { |
698 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
699 | |||
669 | u16 *cache = codec->reg_cache; | 700 | u16 *cache = codec->reg_cache; |
670 | if (reg < 0x7c) | 701 | soc_ac97_ops->write(wm9713->ac97, reg, val); |
671 | soc_ac97_ops->write(codec->ac97, reg, val); | ||
672 | reg = reg >> 1; | 702 | reg = reg >> 1; |
673 | if (reg < (ARRAY_SIZE(wm9713_reg))) | 703 | if (reg < (ARRAY_SIZE(wm9713_reg))) |
674 | cache[reg] = val; | 704 | cache[reg] = val; |
@@ -689,7 +719,8 @@ struct _pll_div { | |||
689 | * to allow rounding later */ | 719 | * to allow rounding later */ |
690 | #define FIXED_PLL_SIZE ((1 << 22) * 10) | 720 | #define FIXED_PLL_SIZE ((1 << 22) * 10) |
691 | 721 | ||
692 | static void pll_factors(struct _pll_div *pll_div, unsigned int source) | 722 | static void pll_factors(struct snd_soc_codec *codec, |
723 | struct _pll_div *pll_div, unsigned int source) | ||
693 | { | 724 | { |
694 | u64 Kpart; | 725 | u64 Kpart; |
695 | unsigned int K, Ndiv, Nmod, target; | 726 | unsigned int K, Ndiv, Nmod, target; |
@@ -724,7 +755,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int source) | |||
724 | 755 | ||
725 | Ndiv = target / source; | 756 | Ndiv = target / source; |
726 | if ((Ndiv < 5) || (Ndiv > 12)) | 757 | if ((Ndiv < 5) || (Ndiv > 12)) |
727 | printk(KERN_WARNING | 758 | dev_warn(codec->dev, |
728 | "WM9713 PLL N value %u out of recommended range!\n", | 759 | "WM9713 PLL N value %u out of recommended range!\n", |
729 | Ndiv); | 760 | Ndiv); |
730 | 761 | ||
@@ -768,7 +799,7 @@ static int wm9713_set_pll(struct snd_soc_codec *codec, | |||
768 | return 0; | 799 | return 0; |
769 | } | 800 | } |
770 | 801 | ||
771 | pll_factors(&pll_div, freq_in); | 802 | pll_factors(codec, &pll_div, freq_in); |
772 | 803 | ||
773 | if (pll_div.k == 0) { | 804 | if (pll_div.k == 0) { |
774 | reg = (pll_div.n << 12) | (pll_div.lf << 11) | | 805 | reg = (pll_div.n << 12) | (pll_div.lf << 11) | |
@@ -1049,7 +1080,6 @@ static const struct snd_soc_dai_ops wm9713_dai_ops_voice = { | |||
1049 | static struct snd_soc_dai_driver wm9713_dai[] = { | 1080 | static struct snd_soc_dai_driver wm9713_dai[] = { |
1050 | { | 1081 | { |
1051 | .name = "wm9713-hifi", | 1082 | .name = "wm9713-hifi", |
1052 | .ac97_control = 1, | ||
1053 | .playback = { | 1083 | .playback = { |
1054 | .stream_name = "HiFi Playback", | 1084 | .stream_name = "HiFi Playback", |
1055 | .channels_min = 1, | 1085 | .channels_min = 1, |
@@ -1095,17 +1125,22 @@ static struct snd_soc_dai_driver wm9713_dai[] = { | |||
1095 | 1125 | ||
1096 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) | 1126 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) |
1097 | { | 1127 | { |
1128 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
1129 | |||
1098 | if (try_warm && soc_ac97_ops->warm_reset) { | 1130 | if (try_warm && soc_ac97_ops->warm_reset) { |
1099 | soc_ac97_ops->warm_reset(codec->ac97); | 1131 | soc_ac97_ops->warm_reset(wm9713->ac97); |
1100 | if (ac97_read(codec, 0) == wm9713_reg[0]) | 1132 | if (ac97_read(codec, 0) == wm9713_reg[0]) |
1101 | return 1; | 1133 | return 1; |
1102 | } | 1134 | } |
1103 | 1135 | ||
1104 | soc_ac97_ops->reset(codec->ac97); | 1136 | soc_ac97_ops->reset(wm9713->ac97); |
1105 | if (soc_ac97_ops->warm_reset) | 1137 | if (soc_ac97_ops->warm_reset) |
1106 | soc_ac97_ops->warm_reset(codec->ac97); | 1138 | soc_ac97_ops->warm_reset(wm9713->ac97); |
1107 | if (ac97_read(codec, 0) != wm9713_reg[0]) | 1139 | if (ac97_read(codec, 0) != wm9713_reg[0]) { |
1140 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); | ||
1108 | return -EIO; | 1141 | return -EIO; |
1142 | } | ||
1143 | |||
1109 | return 0; | 1144 | return 0; |
1110 | } | 1145 | } |
1111 | EXPORT_SYMBOL_GPL(wm9713_reset); | 1146 | EXPORT_SYMBOL_GPL(wm9713_reset); |
@@ -1163,10 +1198,8 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1163 | u16 *cache = codec->reg_cache; | 1198 | u16 *cache = codec->reg_cache; |
1164 | 1199 | ||
1165 | ret = wm9713_reset(codec, 1); | 1200 | ret = wm9713_reset(codec, 1); |
1166 | if (ret < 0) { | 1201 | if (ret < 0) |
1167 | printk(KERN_ERR "could not reset AC97 codec\n"); | ||
1168 | return ret; | 1202 | return ret; |
1169 | } | ||
1170 | 1203 | ||
1171 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1204 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1172 | 1205 | ||
@@ -1180,7 +1213,7 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1180 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || | 1213 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || |
1181 | i == AC97_EXTENDED_MSTATUS || i > 0x66) | 1214 | i == AC97_EXTENDED_MSTATUS || i > 0x66) |
1182 | continue; | 1215 | continue; |
1183 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); | 1216 | soc_ac97_ops->write(wm9713->ac97, i, cache[i>>1]); |
1184 | } | 1217 | } |
1185 | } | 1218 | } |
1186 | 1219 | ||
@@ -1189,26 +1222,19 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1189 | 1222 | ||
1190 | static int wm9713_soc_probe(struct snd_soc_codec *codec) | 1223 | static int wm9713_soc_probe(struct snd_soc_codec *codec) |
1191 | { | 1224 | { |
1192 | struct wm9713_priv *wm9713; | 1225 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
1193 | int ret = 0, reg; | 1226 | int ret = 0, reg; |
1194 | 1227 | ||
1195 | wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL); | 1228 | wm9713->ac97 = snd_soc_new_ac97_codec(codec); |
1196 | if (wm9713 == NULL) | 1229 | if (IS_ERR(wm9713->ac97)) |
1197 | return -ENOMEM; | 1230 | return PTR_ERR(wm9713->ac97); |
1198 | snd_soc_codec_set_drvdata(codec, wm9713); | ||
1199 | |||
1200 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | ||
1201 | if (ret < 0) | ||
1202 | goto codec_err; | ||
1203 | 1231 | ||
1204 | /* do a cold reset for the controller and then try | 1232 | /* do a cold reset for the controller and then try |
1205 | * a warm reset followed by an optional cold reset for codec */ | 1233 | * a warm reset followed by an optional cold reset for codec */ |
1206 | wm9713_reset(codec, 0); | 1234 | wm9713_reset(codec, 0); |
1207 | ret = wm9713_reset(codec, 1); | 1235 | ret = wm9713_reset(codec, 1); |
1208 | if (ret < 0) { | 1236 | if (ret < 0) |
1209 | printk(KERN_ERR "Failed to reset WM9713: AC97 link error\n"); | ||
1210 | goto reset_err; | 1237 | goto reset_err; |
1211 | } | ||
1212 | 1238 | ||
1213 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1239 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1214 | 1240 | ||
@@ -1216,23 +1242,18 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) | |||
1216 | reg = ac97_read(codec, AC97_CD) & 0x7fff; | 1242 | reg = ac97_read(codec, AC97_CD) & 0x7fff; |
1217 | ac97_write(codec, AC97_CD, reg); | 1243 | ac97_write(codec, AC97_CD, reg); |
1218 | 1244 | ||
1219 | snd_soc_add_codec_controls(codec, wm9713_snd_ac97_controls, | ||
1220 | ARRAY_SIZE(wm9713_snd_ac97_controls)); | ||
1221 | |||
1222 | return 0; | 1245 | return 0; |
1223 | 1246 | ||
1224 | reset_err: | 1247 | reset_err: |
1225 | snd_soc_free_ac97_codec(codec); | 1248 | snd_soc_free_ac97_codec(wm9713->ac97); |
1226 | codec_err: | ||
1227 | kfree(wm9713); | ||
1228 | return ret; | 1249 | return ret; |
1229 | } | 1250 | } |
1230 | 1251 | ||
1231 | static int wm9713_soc_remove(struct snd_soc_codec *codec) | 1252 | static int wm9713_soc_remove(struct snd_soc_codec *codec) |
1232 | { | 1253 | { |
1233 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | 1254 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
1234 | snd_soc_free_ac97_codec(codec); | 1255 | |
1235 | kfree(wm9713); | 1256 | snd_soc_free_ac97_codec(wm9713->ac97); |
1236 | return 0; | 1257 | return 0; |
1237 | } | 1258 | } |
1238 | 1259 | ||
@@ -1248,6 +1269,9 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { | |||
1248 | .reg_word_size = sizeof(u16), | 1269 | .reg_word_size = sizeof(u16), |
1249 | .reg_cache_step = 2, | 1270 | .reg_cache_step = 2, |
1250 | .reg_cache_default = wm9713_reg, | 1271 | .reg_cache_default = wm9713_reg, |
1272 | |||
1273 | .controls = wm9713_snd_ac97_controls, | ||
1274 | .num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls), | ||
1251 | .dapm_widgets = wm9713_dapm_widgets, | 1275 | .dapm_widgets = wm9713_dapm_widgets, |
1252 | .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), | 1276 | .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), |
1253 | .dapm_routes = wm9713_audio_map, | 1277 | .dapm_routes = wm9713_audio_map, |
@@ -1256,6 +1280,16 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { | |||
1256 | 1280 | ||
1257 | static int wm9713_probe(struct platform_device *pdev) | 1281 | static int wm9713_probe(struct platform_device *pdev) |
1258 | { | 1282 | { |
1283 | struct wm9713_priv *wm9713; | ||
1284 | |||
1285 | wm9713 = devm_kzalloc(&pdev->dev, sizeof(*wm9713), GFP_KERNEL); | ||
1286 | if (wm9713 == NULL) | ||
1287 | return -ENOMEM; | ||
1288 | |||
1289 | mutex_init(&wm9713->lock); | ||
1290 | |||
1291 | platform_set_drvdata(pdev, wm9713); | ||
1292 | |||
1259 | return snd_soc_register_codec(&pdev->dev, | 1293 | return snd_soc_register_codec(&pdev->dev, |
1260 | &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); | 1294 | &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); |
1261 | } | 1295 | } |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 67124783558a..720d6e852986 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/regmap.h> | 21 | #include <linux/regmap.h> |
22 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/vmalloc.h> | ||
24 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
@@ -169,11 +170,12 @@ static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len, | |||
169 | if (buf == NULL) | 170 | if (buf == NULL) |
170 | return NULL; | 171 | return NULL; |
171 | 172 | ||
172 | buf->buf = kmemdup(src, len, GFP_KERNEL | GFP_DMA); | 173 | buf->buf = vmalloc(len); |
173 | if (!buf->buf) { | 174 | if (!buf->buf) { |
174 | kfree(buf); | 175 | vfree(buf); |
175 | return NULL; | 176 | return NULL; |
176 | } | 177 | } |
178 | memcpy(buf->buf, src, len); | ||
177 | 179 | ||
178 | if (list) | 180 | if (list) |
179 | list_add_tail(&buf->list, list); | 181 | list_add_tail(&buf->list, list); |
@@ -188,7 +190,7 @@ static void wm_adsp_buf_free(struct list_head *list) | |||
188 | struct wm_adsp_buf, | 190 | struct wm_adsp_buf, |
189 | list); | 191 | list); |
190 | list_del(&buf->list); | 192 | list_del(&buf->list); |
191 | kfree(buf->buf); | 193 | vfree(buf->buf); |
192 | kfree(buf); | 194 | kfree(buf); |
193 | } | 195 | } |
194 | } | 196 | } |
@@ -684,38 +686,24 @@ static int wm_adsp_load(struct wm_adsp *dsp) | |||
684 | } | 686 | } |
685 | 687 | ||
686 | if (reg) { | 688 | if (reg) { |
687 | size_t to_write = PAGE_SIZE; | 689 | buf = wm_adsp_buf_alloc(region->data, |
688 | size_t remain = le32_to_cpu(region->len); | 690 | le32_to_cpu(region->len), |
689 | const u8 *data = region->data; | 691 | &buf_list); |
690 | 692 | if (!buf) { | |
691 | while (remain > 0) { | 693 | adsp_err(dsp, "Out of memory\n"); |
692 | if (remain < PAGE_SIZE) | 694 | ret = -ENOMEM; |
693 | to_write = remain; | 695 | goto out_fw; |
694 | 696 | } | |
695 | buf = wm_adsp_buf_alloc(data, | ||
696 | to_write, | ||
697 | &buf_list); | ||
698 | if (!buf) { | ||
699 | adsp_err(dsp, "Out of memory\n"); | ||
700 | ret = -ENOMEM; | ||
701 | goto out_fw; | ||
702 | } | ||
703 | |||
704 | ret = regmap_raw_write_async(regmap, reg, | ||
705 | buf->buf, | ||
706 | to_write); | ||
707 | if (ret != 0) { | ||
708 | adsp_err(dsp, | ||
709 | "%s.%d: Failed to write %zd bytes at %d in %s: %d\n", | ||
710 | file, regions, | ||
711 | to_write, offset, | ||
712 | region_name, ret); | ||
713 | goto out_fw; | ||
714 | } | ||
715 | 697 | ||
716 | data += to_write; | 698 | ret = regmap_raw_write_async(regmap, reg, buf->buf, |
717 | reg += to_write / 2; | 699 | le32_to_cpu(region->len)); |
718 | remain -= to_write; | 700 | if (ret != 0) { |
701 | adsp_err(dsp, | ||
702 | "%s.%d: Failed to write %d bytes at %d in %s: %d\n", | ||
703 | file, regions, | ||
704 | le32_to_cpu(region->len), offset, | ||
705 | region_name, ret); | ||
706 | goto out_fw; | ||
719 | } | 707 | } |
720 | } | 708 | } |
721 | 709 | ||
@@ -1065,8 +1053,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
1065 | be32_to_cpu(adsp1_alg[i].zm)); | 1053 | be32_to_cpu(adsp1_alg[i].zm)); |
1066 | 1054 | ||
1067 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1055 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
1068 | if (!region) | 1056 | if (!region) { |
1069 | return -ENOMEM; | 1057 | ret = -ENOMEM; |
1058 | goto out; | ||
1059 | } | ||
1070 | region->type = WMFW_ADSP1_DM; | 1060 | region->type = WMFW_ADSP1_DM; |
1071 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); | 1061 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); |
1072 | region->base = be32_to_cpu(adsp1_alg[i].dm); | 1062 | region->base = be32_to_cpu(adsp1_alg[i].dm); |
@@ -1083,8 +1073,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
1083 | } | 1073 | } |
1084 | 1074 | ||
1085 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1075 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
1086 | if (!region) | 1076 | if (!region) { |
1087 | return -ENOMEM; | 1077 | ret = -ENOMEM; |
1078 | goto out; | ||
1079 | } | ||
1088 | region->type = WMFW_ADSP1_ZM; | 1080 | region->type = WMFW_ADSP1_ZM; |
1089 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); | 1081 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); |
1090 | region->base = be32_to_cpu(adsp1_alg[i].zm); | 1082 | region->base = be32_to_cpu(adsp1_alg[i].zm); |
@@ -1113,8 +1105,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
1113 | be32_to_cpu(adsp2_alg[i].zm)); | 1105 | be32_to_cpu(adsp2_alg[i].zm)); |
1114 | 1106 | ||
1115 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1107 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
1116 | if (!region) | 1108 | if (!region) { |
1117 | return -ENOMEM; | 1109 | ret = -ENOMEM; |
1110 | goto out; | ||
1111 | } | ||
1118 | region->type = WMFW_ADSP2_XM; | 1112 | region->type = WMFW_ADSP2_XM; |
1119 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1113 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
1120 | region->base = be32_to_cpu(adsp2_alg[i].xm); | 1114 | region->base = be32_to_cpu(adsp2_alg[i].xm); |
@@ -1131,8 +1125,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
1131 | } | 1125 | } |
1132 | 1126 | ||
1133 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1127 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
1134 | if (!region) | 1128 | if (!region) { |
1135 | return -ENOMEM; | 1129 | ret = -ENOMEM; |
1130 | goto out; | ||
1131 | } | ||
1136 | region->type = WMFW_ADSP2_YM; | 1132 | region->type = WMFW_ADSP2_YM; |
1137 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1133 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
1138 | region->base = be32_to_cpu(adsp2_alg[i].ym); | 1134 | region->base = be32_to_cpu(adsp2_alg[i].ym); |
@@ -1149,8 +1145,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
1149 | } | 1145 | } |
1150 | 1146 | ||
1151 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1147 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
1152 | if (!region) | 1148 | if (!region) { |
1153 | return -ENOMEM; | 1149 | ret = -ENOMEM; |
1150 | goto out; | ||
1151 | } | ||
1154 | region->type = WMFW_ADSP2_ZM; | 1152 | region->type = WMFW_ADSP2_ZM; |
1155 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1153 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
1156 | region->base = be32_to_cpu(adsp2_alg[i].zm); | 1154 | region->base = be32_to_cpu(adsp2_alg[i].zm); |
@@ -1595,13 +1593,6 @@ static void wm_adsp2_boot_work(struct work_struct *work) | |||
1595 | if (ret != 0) | 1593 | if (ret != 0) |
1596 | goto err; | 1594 | goto err; |
1597 | 1595 | ||
1598 | ret = regmap_update_bits_async(dsp->regmap, | ||
1599 | dsp->base + ADSP2_CONTROL, | ||
1600 | ADSP2_CORE_ENA, | ||
1601 | ADSP2_CORE_ENA); | ||
1602 | if (ret != 0) | ||
1603 | goto err; | ||
1604 | |||
1605 | dsp->running = true; | 1596 | dsp->running = true; |
1606 | 1597 | ||
1607 | return; | 1598 | return; |
@@ -1651,8 +1642,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
1651 | 1642 | ||
1652 | ret = regmap_update_bits(dsp->regmap, | 1643 | ret = regmap_update_bits(dsp->regmap, |
1653 | dsp->base + ADSP2_CONTROL, | 1644 | dsp->base + ADSP2_CONTROL, |
1654 | ADSP2_START, | 1645 | ADSP2_CORE_ENA | ADSP2_START, |
1655 | ADSP2_START); | 1646 | ADSP2_CORE_ENA | ADSP2_START); |
1656 | if (ret != 0) | 1647 | if (ret != 0) |
1657 | goto err; | 1648 | goto err; |
1658 | break; | 1649 | break; |