| .. | .. |
|---|
| 11 | 11 | #include <linux/module.h> |
|---|
| 12 | 12 | #include <linux/pm_runtime.h> |
|---|
| 13 | 13 | #include <linux/regmap.h> |
|---|
| 14 | +#include <linux/regulator/consumer.h> |
|---|
| 14 | 15 | #include <linux/slab.h> |
|---|
| 15 | 16 | |
|---|
| 16 | 17 | #include <sound/initval.h> |
|---|
| .. | .. |
|---|
| 22 | 23 | |
|---|
| 23 | 24 | #include "ak5558.h" |
|---|
| 24 | 25 | |
|---|
| 26 | +#define AK5558_NUM_SUPPLIES 2 |
|---|
| 27 | +static const char *ak5558_supply_names[AK5558_NUM_SUPPLIES] = { |
|---|
| 28 | + "DVDD", |
|---|
| 29 | + "AVDD", |
|---|
| 30 | +}; |
|---|
| 31 | + |
|---|
| 25 | 32 | /* AK5558 Codec Private Data */ |
|---|
| 26 | 33 | struct ak5558_priv { |
|---|
| 34 | + struct regulator_bulk_data supplies[AK5558_NUM_SUPPLIES]; |
|---|
| 27 | 35 | struct snd_soc_component component; |
|---|
| 28 | 36 | struct regmap *regmap; |
|---|
| 29 | 37 | struct i2c_client *i2c; |
|---|
| .. | .. |
|---|
| 130 | 138 | u8 bits; |
|---|
| 131 | 139 | int pcm_width = max(params_physical_width(params), ak5558->slot_width); |
|---|
| 132 | 140 | |
|---|
| 133 | | - /* set master/slave audio interface */ |
|---|
| 134 | | - bits = snd_soc_component_read32(component, AK5558_02_CONTROL1); |
|---|
| 135 | | - bits &= ~AK5558_BITS; |
|---|
| 136 | | - |
|---|
| 137 | 141 | switch (pcm_width) { |
|---|
| 138 | 142 | case 16: |
|---|
| 139 | | - bits |= AK5558_DIF_24BIT_MODE; |
|---|
| 143 | + bits = AK5558_DIF_24BIT_MODE; |
|---|
| 140 | 144 | break; |
|---|
| 141 | 145 | case 32: |
|---|
| 142 | | - bits |= AK5558_DIF_32BIT_MODE; |
|---|
| 146 | + bits = AK5558_DIF_32BIT_MODE; |
|---|
| 143 | 147 | break; |
|---|
| 144 | 148 | default: |
|---|
| 145 | 149 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 168 | 172 | } |
|---|
| 169 | 173 | |
|---|
| 170 | 174 | /* set master/slave audio interface */ |
|---|
| 171 | | - format = snd_soc_component_read32(component, AK5558_02_CONTROL1); |
|---|
| 172 | | - format &= ~AK5558_DIF; |
|---|
| 173 | | - |
|---|
| 174 | 175 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
|---|
| 175 | 176 | case SND_SOC_DAIFMT_I2S: |
|---|
| 176 | | - format |= AK5558_DIF_I2S_MODE; |
|---|
| 177 | + format = AK5558_DIF_I2S_MODE; |
|---|
| 177 | 178 | break; |
|---|
| 178 | 179 | case SND_SOC_DAIFMT_LEFT_J: |
|---|
| 179 | | - format |= AK5558_DIF_MSB_MODE; |
|---|
| 180 | + format = AK5558_DIF_MSB_MODE; |
|---|
| 180 | 181 | break; |
|---|
| 181 | 182 | case SND_SOC_DAIFMT_DSP_B: |
|---|
| 182 | | - format |= AK5558_DIF_MSB_MODE; |
|---|
| 183 | + format = AK5558_DIF_MSB_MODE; |
|---|
| 183 | 184 | break; |
|---|
| 184 | 185 | default: |
|---|
| 185 | 186 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 246 | 247 | &ak5558_rate_constraints); |
|---|
| 247 | 248 | } |
|---|
| 248 | 249 | |
|---|
| 249 | | -static struct snd_soc_dai_ops ak5558_dai_ops = { |
|---|
| 250 | +static const struct snd_soc_dai_ops ak5558_dai_ops = { |
|---|
| 250 | 251 | .startup = ak5558_startup, |
|---|
| 251 | 252 | .hw_params = ak5558_hw_params, |
|---|
| 252 | 253 | |
|---|
| .. | .. |
|---|
| 306 | 307 | regcache_cache_only(ak5558->regmap, true); |
|---|
| 307 | 308 | ak5558_power_off(ak5558); |
|---|
| 308 | 309 | |
|---|
| 310 | + regulator_bulk_disable(ARRAY_SIZE(ak5558->supplies), |
|---|
| 311 | + ak5558->supplies); |
|---|
| 309 | 312 | return 0; |
|---|
| 310 | 313 | } |
|---|
| 311 | 314 | |
|---|
| 312 | 315 | static int __maybe_unused ak5558_runtime_resume(struct device *dev) |
|---|
| 313 | 316 | { |
|---|
| 314 | 317 | struct ak5558_priv *ak5558 = dev_get_drvdata(dev); |
|---|
| 318 | + int ret; |
|---|
| 319 | + |
|---|
| 320 | + ret = regulator_bulk_enable(ARRAY_SIZE(ak5558->supplies), |
|---|
| 321 | + ak5558->supplies); |
|---|
| 322 | + if (ret != 0) { |
|---|
| 323 | + dev_err(dev, "Failed to enable supplies: %d\n", ret); |
|---|
| 324 | + return ret; |
|---|
| 325 | + } |
|---|
| 315 | 326 | |
|---|
| 316 | 327 | ak5558_power_off(ak5558); |
|---|
| 317 | 328 | ak5558_power_on(ak5558); |
|---|
| .. | .. |
|---|
| 357 | 368 | { |
|---|
| 358 | 369 | struct ak5558_priv *ak5558; |
|---|
| 359 | 370 | int ret = 0; |
|---|
| 371 | + int i; |
|---|
| 360 | 372 | |
|---|
| 361 | 373 | ak5558 = devm_kzalloc(&i2c->dev, sizeof(*ak5558), GFP_KERNEL); |
|---|
| 362 | 374 | if (!ak5558) |
|---|
| .. | .. |
|---|
| 374 | 386 | if (IS_ERR(ak5558->reset_gpiod)) |
|---|
| 375 | 387 | return PTR_ERR(ak5558->reset_gpiod); |
|---|
| 376 | 388 | |
|---|
| 389 | + for (i = 0; i < ARRAY_SIZE(ak5558->supplies); i++) |
|---|
| 390 | + ak5558->supplies[i].supply = ak5558_supply_names[i]; |
|---|
| 391 | + |
|---|
| 392 | + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(ak5558->supplies), |
|---|
| 393 | + ak5558->supplies); |
|---|
| 394 | + if (ret != 0) { |
|---|
| 395 | + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); |
|---|
| 396 | + return ret; |
|---|
| 397 | + } |
|---|
| 398 | + |
|---|
| 377 | 399 | ret = devm_snd_soc_register_component(&i2c->dev, |
|---|
| 378 | 400 | &soc_codec_dev_ak5558, |
|---|
| 379 | 401 | &ak5558_dai, 1); |
|---|
| .. | .. |
|---|
| 381 | 403 | return ret; |
|---|
| 382 | 404 | |
|---|
| 383 | 405 | pm_runtime_enable(&i2c->dev); |
|---|
| 406 | + regcache_cache_only(ak5558->regmap, true); |
|---|
| 384 | 407 | |
|---|
| 385 | 408 | return 0; |
|---|
| 386 | 409 | } |
|---|