aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/ak4104.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/ak4104.c')
-rw-r--r--sound/soc/codecs/ak4104.c62
1 files changed, 55 insertions, 7 deletions
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 10adf25d4c14..1fd7f72b2a62 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -11,13 +11,14 @@
11 11
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <sound/core.h>
15#include <sound/soc.h>
16#include <sound/initval.h>
17#include <linux/spi/spi.h> 14#include <linux/spi/spi.h>
18#include <linux/of_device.h> 15#include <linux/of_device.h>
19#include <linux/of_gpio.h> 16#include <linux/of_gpio.h>
17#include <linux/regulator/consumer.h>
20#include <sound/asoundef.h> 18#include <sound/asoundef.h>
19#include <sound/core.h>
20#include <sound/soc.h>
21#include <sound/initval.h>
21 22
22/* AK4104 registers addresses */ 23/* AK4104 registers addresses */
23#define AK4104_REG_CONTROL1 0x00 24#define AK4104_REG_CONTROL1 0x00
@@ -47,6 +48,7 @@
47 48
48struct ak4104_private { 49struct ak4104_private {
49 struct regmap *regmap; 50 struct regmap *regmap;
51 struct regulator *regulator;
50}; 52};
51 53
52static const struct snd_soc_dapm_widget ak4104_dapm_widgets[] = { 54static const struct snd_soc_dapm_widget ak4104_dapm_widgets[] = {
@@ -174,20 +176,30 @@ static int ak4104_probe(struct snd_soc_codec *codec)
174 struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); 176 struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
175 int ret; 177 int ret;
176 178
179 ret = regulator_enable(ak4104->regulator);
180 if (ret < 0) {
181 dev_err(codec->dev, "Unable to enable regulator: %d\n", ret);
182 return ret;
183 }
184
177 /* set power-up and non-reset bits */ 185 /* set power-up and non-reset bits */
178 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1, 186 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
179 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 187 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
180 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); 188 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
181 if (ret < 0) 189 if (ret < 0)
182 return ret; 190 goto exit_disable_regulator;
183 191
184 /* enable transmitter */ 192 /* enable transmitter */
185 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX, 193 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
186 AK4104_TX_TXE, AK4104_TX_TXE); 194 AK4104_TX_TXE, AK4104_TX_TXE);
187 if (ret < 0) 195 if (ret < 0)
188 return ret; 196 goto exit_disable_regulator;
189 197
190 return 0; 198 return 0;
199
200exit_disable_regulator:
201 regulator_disable(ak4104->regulator);
202 return ret;
191} 203}
192 204
193static int ak4104_remove(struct snd_soc_codec *codec) 205static int ak4104_remove(struct snd_soc_codec *codec)
@@ -196,13 +208,42 @@ static int ak4104_remove(struct snd_soc_codec *codec)
196 208
197 regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1, 209 regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
198 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0); 210 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
211 regulator_disable(ak4104->regulator);
199 212
200 return 0; 213 return 0;
201} 214}
202 215
216#ifdef CONFIG_PM
217static int ak4104_soc_suspend(struct snd_soc_codec *codec)
218{
219 struct ak4104_private *priv = snd_soc_codec_get_drvdata(codec);
220
221 regulator_disable(priv->regulator);
222
223 return 0;
224}
225
226static int ak4104_soc_resume(struct snd_soc_codec *codec)
227{
228 struct ak4104_private *priv = snd_soc_codec_get_drvdata(codec);
229 int ret;
230
231 ret = regulator_enable(priv->regulator);
232 if (ret < 0)
233 return ret;
234
235 return 0;
236}
237#else
238#define ak4104_soc_suspend NULL
239#define ak4104_soc_resume NULL
240#endif /* CONFIG_PM */
241
203static struct snd_soc_codec_driver soc_codec_device_ak4104 = { 242static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
204 .probe = ak4104_probe, 243 .probe = ak4104_probe,
205 .remove = ak4104_remove, 244 .remove = ak4104_remove,
245 .suspend = ak4104_soc_suspend,
246 .resume = ak4104_soc_resume,
206 247
207 .dapm_widgets = ak4104_dapm_widgets, 248 .dapm_widgets = ak4104_dapm_widgets,
208 .num_dapm_widgets = ARRAY_SIZE(ak4104_dapm_widgets), 249 .num_dapm_widgets = ARRAY_SIZE(ak4104_dapm_widgets),
@@ -239,6 +280,13 @@ static int ak4104_spi_probe(struct spi_device *spi)
239 if (ak4104 == NULL) 280 if (ak4104 == NULL)
240 return -ENOMEM; 281 return -ENOMEM;
241 282
283 ak4104->regulator = devm_regulator_get(&spi->dev, "vdd");
284 if (IS_ERR(ak4104->regulator)) {
285 ret = PTR_ERR(ak4104->regulator);
286 dev_err(&spi->dev, "Unable to get Vdd regulator: %d\n", ret);
287 return ret;
288 }
289
242 ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap); 290 ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap);
243 if (IS_ERR(ak4104->regmap)) { 291 if (IS_ERR(ak4104->regmap)) {
244 ret = PTR_ERR(ak4104->regmap); 292 ret = PTR_ERR(ak4104->regmap);