adau7118.c (14988B)
1// SPDX-License-Identifier: GPL-2.0 2// 3// Analog Devices ADAU7118 8 channel PDM-to-I2S/TDM Converter driver 4// 5// Copyright 2019 Analog Devices Inc. 6 7#include <linux/bitfield.h> 8#include <linux/module.h> 9#include <linux/regmap.h> 10#include <linux/regulator/consumer.h> 11#include <sound/pcm_params.h> 12#include <sound/soc.h> 13 14#include "adau7118.h" 15 16#define ADAU7118_DEC_RATIO_MASK GENMASK(1, 0) 17#define ADAU7118_DEC_RATIO(x) FIELD_PREP(ADAU7118_DEC_RATIO_MASK, x) 18#define ADAU7118_CLK_MAP_MASK GENMASK(7, 4) 19#define ADAU7118_SLOT_WIDTH_MASK GENMASK(5, 4) 20#define ADAU7118_SLOT_WIDTH(x) FIELD_PREP(ADAU7118_SLOT_WIDTH_MASK, x) 21#define ADAU7118_TRISTATE_MASK BIT(6) 22#define ADAU7118_TRISTATE(x) FIELD_PREP(ADAU7118_TRISTATE_MASK, x) 23#define ADAU7118_DATA_FMT_MASK GENMASK(3, 1) 24#define ADAU7118_DATA_FMT(x) FIELD_PREP(ADAU7118_DATA_FMT_MASK, x) 25#define ADAU7118_SAI_MODE_MASK BIT(0) 26#define ADAU7118_SAI_MODE(x) FIELD_PREP(ADAU7118_SAI_MODE_MASK, x) 27#define ADAU7118_LRCLK_BCLK_POL_MASK GENMASK(1, 0) 28#define ADAU7118_LRCLK_BCLK_POL(x) \ 29 FIELD_PREP(ADAU7118_LRCLK_BCLK_POL_MASK, x) 30#define ADAU7118_SPT_SLOT_MASK GENMASK(7, 4) 31#define ADAU7118_SPT_SLOT(x) FIELD_PREP(ADAU7118_SPT_SLOT_MASK, x) 32#define ADAU7118_FULL_SOFT_R_MASK BIT(1) 33#define ADAU7118_FULL_SOFT_R(x) FIELD_PREP(ADAU7118_FULL_SOFT_R_MASK, x) 34 35struct adau7118_data { 36 struct regmap *map; 37 struct device *dev; 38 struct regulator *iovdd; 39 struct regulator *dvdd; 40 u32 slot_width; 41 u32 slots; 42 bool hw_mode; 43 bool right_j; 44}; 45 46/* Input Enable */ 47static const struct snd_kcontrol_new adau7118_dapm_pdm_control[4] = { 48 SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 0, 1, 0), 49 SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 1, 1, 0), 50 SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 2, 1, 0), 51 SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 3, 1, 0), 52}; 53 54static const struct snd_soc_dapm_widget adau7118_widgets_sw[] = { 55 /* Input Enable Switches */ 56 SND_SOC_DAPM_SWITCH("PDM0", SND_SOC_NOPM, 0, 0, 57 &adau7118_dapm_pdm_control[0]), 58 SND_SOC_DAPM_SWITCH("PDM1", SND_SOC_NOPM, 0, 0, 59 &adau7118_dapm_pdm_control[1]), 60 SND_SOC_DAPM_SWITCH("PDM2", SND_SOC_NOPM, 0, 0, 61 &adau7118_dapm_pdm_control[2]), 62 SND_SOC_DAPM_SWITCH("PDM3", SND_SOC_NOPM, 0, 0, 63 &adau7118_dapm_pdm_control[3]), 64 65 /* PDM Clocks */ 66 SND_SOC_DAPM_SUPPLY("PDM_CLK0", ADAU7118_REG_ENABLES, 4, 0, NULL, 0), 67 SND_SOC_DAPM_SUPPLY("PDM_CLK1", ADAU7118_REG_ENABLES, 5, 0, NULL, 0), 68 69 /* Output channels */ 70 SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0, ADAU7118_REG_SPT_CX(0), 71 0, 0), 72 SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 0, ADAU7118_REG_SPT_CX(1), 73 0, 0), 74 SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 0, ADAU7118_REG_SPT_CX(2), 75 0, 0), 76 SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 0, ADAU7118_REG_SPT_CX(3), 77 0, 0), 78 SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 0, ADAU7118_REG_SPT_CX(4), 79 0, 0), 80 SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 0, ADAU7118_REG_SPT_CX(5), 81 0, 0), 82 SND_SOC_DAPM_AIF_OUT("AIF1TX7", "Capture", 0, ADAU7118_REG_SPT_CX(6), 83 0, 0), 84 SND_SOC_DAPM_AIF_OUT("AIF1TX8", "Capture", 0, ADAU7118_REG_SPT_CX(7), 85 0, 0), 86}; 87 88static const struct snd_soc_dapm_route adau7118_routes_sw[] = { 89 { "PDM0", "Capture Switch", "PDM_DAT0" }, 90 { "PDM1", "Capture Switch", "PDM_DAT1" }, 91 { "PDM2", "Capture Switch", "PDM_DAT2" }, 92 { "PDM3", "Capture Switch", "PDM_DAT3" }, 93 { "AIF1TX1", NULL, "PDM0" }, 94 { "AIF1TX2", NULL, "PDM0" }, 95 { "AIF1TX3", NULL, "PDM1" }, 96 { "AIF1TX4", NULL, "PDM1" }, 97 { "AIF1TX5", NULL, "PDM2" }, 98 { "AIF1TX6", NULL, "PDM2" }, 99 { "AIF1TX7", NULL, "PDM3" }, 100 { "AIF1TX8", NULL, "PDM3" }, 101 { "Capture", NULL, "PDM_CLK0" }, 102 { "Capture", NULL, "PDM_CLK1" }, 103}; 104 105static const struct snd_soc_dapm_widget adau7118_widgets_hw[] = { 106 SND_SOC_DAPM_AIF_OUT("AIF1TX", "Capture", 0, SND_SOC_NOPM, 0, 0), 107}; 108 109static const struct snd_soc_dapm_route adau7118_routes_hw[] = { 110 { "AIF1TX", NULL, "PDM_DAT0" }, 111 { "AIF1TX", NULL, "PDM_DAT1" }, 112 { "AIF1TX", NULL, "PDM_DAT2" }, 113 { "AIF1TX", NULL, "PDM_DAT3" }, 114}; 115 116static const struct snd_soc_dapm_widget adau7118_widgets[] = { 117 SND_SOC_DAPM_INPUT("PDM_DAT0"), 118 SND_SOC_DAPM_INPUT("PDM_DAT1"), 119 SND_SOC_DAPM_INPUT("PDM_DAT2"), 120 SND_SOC_DAPM_INPUT("PDM_DAT3"), 121}; 122 123static int adau7118_set_channel_map(struct snd_soc_dai *dai, 124 unsigned int tx_num, unsigned int *tx_slot, 125 unsigned int rx_num, unsigned int *rx_slot) 126{ 127 struct adau7118_data *st = 128 snd_soc_component_get_drvdata(dai->component); 129 int chan, ret; 130 131 dev_dbg(st->dev, "Set channel map, %d", tx_num); 132 133 for (chan = 0; chan < tx_num; chan++) { 134 ret = snd_soc_component_update_bits(dai->component, 135 ADAU7118_REG_SPT_CX(chan), 136 ADAU7118_SPT_SLOT_MASK, 137 ADAU7118_SPT_SLOT(tx_slot[chan])); 138 if (ret < 0) 139 return ret; 140 } 141 142 return 0; 143} 144 145static int adau7118_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 146{ 147 struct adau7118_data *st = 148 snd_soc_component_get_drvdata(dai->component); 149 int ret = 0; 150 u32 regval; 151 152 dev_dbg(st->dev, "Set format, fmt:%d\n", fmt); 153 154 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 155 case SND_SOC_DAIFMT_I2S: 156 ret = snd_soc_component_update_bits(dai->component, 157 ADAU7118_REG_SPT_CTRL1, 158 ADAU7118_DATA_FMT_MASK, 159 ADAU7118_DATA_FMT(0)); 160 break; 161 case SND_SOC_DAIFMT_LEFT_J: 162 ret = snd_soc_component_update_bits(dai->component, 163 ADAU7118_REG_SPT_CTRL1, 164 ADAU7118_DATA_FMT_MASK, 165 ADAU7118_DATA_FMT(1)); 166 break; 167 case SND_SOC_DAIFMT_RIGHT_J: 168 st->right_j = true; 169 break; 170 default: 171 dev_err(st->dev, "Invalid format %d", 172 fmt & SND_SOC_DAIFMT_FORMAT_MASK); 173 return -EINVAL; 174 } 175 176 if (ret < 0) 177 return ret; 178 179 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 180 case SND_SOC_DAIFMT_NB_NF: 181 regval = ADAU7118_LRCLK_BCLK_POL(0); 182 break; 183 case SND_SOC_DAIFMT_NB_IF: 184 regval = ADAU7118_LRCLK_BCLK_POL(2); 185 break; 186 case SND_SOC_DAIFMT_IB_NF: 187 regval = ADAU7118_LRCLK_BCLK_POL(1); 188 break; 189 case SND_SOC_DAIFMT_IB_IF: 190 regval = ADAU7118_LRCLK_BCLK_POL(3); 191 break; 192 default: 193 dev_err(st->dev, "Invalid Inv mask %d", 194 fmt & SND_SOC_DAIFMT_INV_MASK); 195 return -EINVAL; 196 } 197 198 ret = snd_soc_component_update_bits(dai->component, 199 ADAU7118_REG_SPT_CTRL2, 200 ADAU7118_LRCLK_BCLK_POL_MASK, 201 regval); 202 if (ret < 0) 203 return ret; 204 205 return 0; 206} 207 208static int adau7118_set_tristate(struct snd_soc_dai *dai, int tristate) 209{ 210 struct adau7118_data *st = 211 snd_soc_component_get_drvdata(dai->component); 212 int ret; 213 214 dev_dbg(st->dev, "Set tristate, %d\n", tristate); 215 216 ret = snd_soc_component_update_bits(dai->component, 217 ADAU7118_REG_SPT_CTRL1, 218 ADAU7118_TRISTATE_MASK, 219 ADAU7118_TRISTATE(tristate)); 220 if (ret < 0) 221 return ret; 222 223 return 0; 224} 225 226static int adau7118_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 227 unsigned int rx_mask, int slots, 228 int slot_width) 229{ 230 struct adau7118_data *st = 231 snd_soc_component_get_drvdata(dai->component); 232 int ret = 0; 233 u32 regval; 234 235 dev_dbg(st->dev, "Set tdm, slots:%d width:%d\n", slots, slot_width); 236 237 switch (slot_width) { 238 case 32: 239 regval = ADAU7118_SLOT_WIDTH(0); 240 break; 241 case 24: 242 regval = ADAU7118_SLOT_WIDTH(2); 243 break; 244 case 16: 245 regval = ADAU7118_SLOT_WIDTH(1); 246 break; 247 default: 248 dev_err(st->dev, "Invalid slot width:%d\n", slot_width); 249 return -EINVAL; 250 } 251 252 ret = snd_soc_component_update_bits(dai->component, 253 ADAU7118_REG_SPT_CTRL1, 254 ADAU7118_SLOT_WIDTH_MASK, regval); 255 if (ret < 0) 256 return ret; 257 258 st->slot_width = slot_width; 259 st->slots = slots; 260 261 return 0; 262} 263 264static int adau7118_hw_params(struct snd_pcm_substream *substream, 265 struct snd_pcm_hw_params *params, 266 struct snd_soc_dai *dai) 267{ 268 struct adau7118_data *st = 269 snd_soc_component_get_drvdata(dai->component); 270 u32 data_width = params_width(params), slots_width; 271 int ret; 272 u32 regval; 273 274 if (!st->slots) { 275 /* set stereo mode */ 276 ret = snd_soc_component_update_bits(dai->component, 277 ADAU7118_REG_SPT_CTRL1, 278 ADAU7118_SAI_MODE_MASK, 279 ADAU7118_SAI_MODE(0)); 280 if (ret < 0) 281 return ret; 282 283 slots_width = 32; 284 } else { 285 slots_width = st->slot_width; 286 } 287 288 if (data_width > slots_width) { 289 dev_err(st->dev, "Invalid data_width:%d, slots_width:%d", 290 data_width, slots_width); 291 return -EINVAL; 292 } 293 294 if (st->right_j) { 295 switch (slots_width - data_width) { 296 case 8: 297 /* delay bclck by 8 */ 298 regval = ADAU7118_DATA_FMT(2); 299 break; 300 case 12: 301 /* delay bclck by 12 */ 302 regval = ADAU7118_DATA_FMT(3); 303 break; 304 case 16: 305 /* delay bclck by 16 */ 306 regval = ADAU7118_DATA_FMT(4); 307 break; 308 default: 309 dev_err(st->dev, 310 "Cannot set right_j setting, slot_w:%d, data_w:%d\n", 311 slots_width, data_width); 312 return -EINVAL; 313 } 314 315 ret = snd_soc_component_update_bits(dai->component, 316 ADAU7118_REG_SPT_CTRL1, 317 ADAU7118_DATA_FMT_MASK, 318 regval); 319 if (ret < 0) 320 return ret; 321 } 322 323 return 0; 324} 325 326static int adau7118_set_bias_level(struct snd_soc_component *component, 327 enum snd_soc_bias_level level) 328{ 329 struct adau7118_data *st = snd_soc_component_get_drvdata(component); 330 int ret = 0; 331 332 dev_dbg(st->dev, "Set bias level %d\n", level); 333 334 switch (level) { 335 case SND_SOC_BIAS_ON: 336 case SND_SOC_BIAS_PREPARE: 337 break; 338 339 case SND_SOC_BIAS_STANDBY: 340 if (snd_soc_component_get_bias_level(component) == 341 SND_SOC_BIAS_OFF) { 342 /* power on */ 343 ret = regulator_enable(st->iovdd); 344 if (ret) 345 return ret; 346 347 /* there's no timing constraints before enabling dvdd */ 348 ret = regulator_enable(st->dvdd); 349 if (ret) { 350 regulator_disable(st->iovdd); 351 return ret; 352 } 353 354 if (st->hw_mode) 355 return 0; 356 357 regcache_cache_only(st->map, false); 358 /* sync cache */ 359 ret = snd_soc_component_cache_sync(component); 360 } 361 break; 362 case SND_SOC_BIAS_OFF: 363 /* power off */ 364 ret = regulator_disable(st->dvdd); 365 if (ret) 366 return ret; 367 368 ret = regulator_disable(st->iovdd); 369 if (ret) 370 return ret; 371 372 if (st->hw_mode) 373 return 0; 374 375 /* cache only */ 376 regcache_mark_dirty(st->map); 377 regcache_cache_only(st->map, true); 378 379 break; 380 } 381 382 return ret; 383} 384 385static int adau7118_component_probe(struct snd_soc_component *component) 386{ 387 struct adau7118_data *st = snd_soc_component_get_drvdata(component); 388 struct snd_soc_dapm_context *dapm = 389 snd_soc_component_get_dapm(component); 390 int ret = 0; 391 392 if (st->hw_mode) { 393 ret = snd_soc_dapm_new_controls(dapm, adau7118_widgets_hw, 394 ARRAY_SIZE(adau7118_widgets_hw)); 395 if (ret) 396 return ret; 397 398 ret = snd_soc_dapm_add_routes(dapm, adau7118_routes_hw, 399 ARRAY_SIZE(adau7118_routes_hw)); 400 } else { 401 snd_soc_component_init_regmap(component, st->map); 402 ret = snd_soc_dapm_new_controls(dapm, adau7118_widgets_sw, 403 ARRAY_SIZE(adau7118_widgets_sw)); 404 if (ret) 405 return ret; 406 407 ret = snd_soc_dapm_add_routes(dapm, adau7118_routes_sw, 408 ARRAY_SIZE(adau7118_routes_sw)); 409 } 410 411 return ret; 412} 413 414static const struct snd_soc_dai_ops adau7118_ops = { 415 .hw_params = adau7118_hw_params, 416 .set_channel_map = adau7118_set_channel_map, 417 .set_fmt = adau7118_set_fmt, 418 .set_tdm_slot = adau7118_set_tdm_slot, 419 .set_tristate = adau7118_set_tristate, 420}; 421 422static struct snd_soc_dai_driver adau7118_dai = { 423 .name = "adau7118-hifi-capture", 424 .capture = { 425 .stream_name = "Capture", 426 .channels_min = 1, 427 .channels_max = 8, 428 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | 429 SNDRV_PCM_FMTBIT_S20_LE | SNDRV_PCM_FMTBIT_S24_LE | 430 SNDRV_PCM_FMTBIT_S24_3LE, 431 .rates = SNDRV_PCM_RATE_CONTINUOUS, 432 .rate_min = 4000, 433 .rate_max = 192000, 434 .sig_bits = 24, 435 }, 436}; 437 438static const struct snd_soc_component_driver adau7118_component_driver = { 439 .probe = adau7118_component_probe, 440 .set_bias_level = adau7118_set_bias_level, 441 .dapm_widgets = adau7118_widgets, 442 .num_dapm_widgets = ARRAY_SIZE(adau7118_widgets), 443 .use_pmdown_time = 1, 444 .endianness = 1, 445 .non_legacy_dai_naming = 1, 446}; 447 448static void adau7118_regulator_disable(void *data) 449{ 450 struct adau7118_data *st = data; 451 int ret; 452 /* 453 * If we fail to disable DVDD, don't bother in trying IOVDD. We 454 * actually don't want to be left in the situation where DVDD 455 * is enabled and IOVDD is disabled. 456 */ 457 ret = regulator_disable(st->dvdd); 458 if (ret) 459 return; 460 461 regulator_disable(st->iovdd); 462} 463 464static int adau7118_regulator_setup(struct adau7118_data *st) 465{ 466 st->iovdd = devm_regulator_get(st->dev, "iovdd"); 467 if (IS_ERR(st->iovdd)) { 468 dev_err(st->dev, "Could not get iovdd: %ld\n", 469 PTR_ERR(st->iovdd)); 470 return PTR_ERR(st->iovdd); 471 } 472 473 st->dvdd = devm_regulator_get(st->dev, "dvdd"); 474 if (IS_ERR(st->dvdd)) { 475 dev_err(st->dev, "Could not get dvdd: %ld\n", 476 PTR_ERR(st->dvdd)); 477 return PTR_ERR(st->dvdd); 478 } 479 /* just assume the device is in reset */ 480 if (!st->hw_mode) { 481 regcache_mark_dirty(st->map); 482 regcache_cache_only(st->map, true); 483 } 484 485 return devm_add_action_or_reset(st->dev, adau7118_regulator_disable, 486 st); 487} 488 489static int adau7118_parset_dt(const struct adau7118_data *st) 490{ 491 int ret; 492 u32 dec_ratio = 0; 493 /* 4 inputs */ 494 u32 clk_map[4], regval; 495 496 if (st->hw_mode) 497 return 0; 498 499 ret = device_property_read_u32(st->dev, "adi,decimation-ratio", 500 &dec_ratio); 501 if (!ret) { 502 switch (dec_ratio) { 503 case 64: 504 regval = ADAU7118_DEC_RATIO(0); 505 break; 506 case 32: 507 regval = ADAU7118_DEC_RATIO(1); 508 break; 509 case 16: 510 regval = ADAU7118_DEC_RATIO(2); 511 break; 512 default: 513 dev_err(st->dev, "Invalid dec ratio: %u", dec_ratio); 514 return -EINVAL; 515 } 516 517 ret = regmap_update_bits(st->map, 518 ADAU7118_REG_DEC_RATIO_CLK_MAP, 519 ADAU7118_DEC_RATIO_MASK, regval); 520 if (ret) 521 return ret; 522 } 523 524 ret = device_property_read_u32_array(st->dev, "adi,pdm-clk-map", 525 clk_map, ARRAY_SIZE(clk_map)); 526 if (!ret) { 527 int pdm; 528 u32 _clk_map = 0; 529 530 for (pdm = 0; pdm < ARRAY_SIZE(clk_map); pdm++) 531 _clk_map |= (clk_map[pdm] << (pdm + 4)); 532 533 ret = regmap_update_bits(st->map, 534 ADAU7118_REG_DEC_RATIO_CLK_MAP, 535 ADAU7118_CLK_MAP_MASK, _clk_map); 536 if (ret) 537 return ret; 538 } 539 540 return 0; 541} 542 543int adau7118_probe(struct device *dev, struct regmap *map, bool hw_mode) 544{ 545 struct adau7118_data *st; 546 int ret; 547 548 st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); 549 if (!st) 550 return -ENOMEM; 551 552 st->dev = dev; 553 st->hw_mode = hw_mode; 554 dev_set_drvdata(dev, st); 555 556 if (!hw_mode) { 557 st->map = map; 558 adau7118_dai.ops = &adau7118_ops; 559 /* 560 * Perform a full soft reset. This will set all register's 561 * with their reset values. 562 */ 563 ret = regmap_update_bits(map, ADAU7118_REG_RESET, 564 ADAU7118_FULL_SOFT_R_MASK, 565 ADAU7118_FULL_SOFT_R(1)); 566 if (ret) 567 return ret; 568 } 569 570 ret = adau7118_parset_dt(st); 571 if (ret) 572 return ret; 573 574 ret = adau7118_regulator_setup(st); 575 if (ret) 576 return ret; 577 578 return devm_snd_soc_register_component(dev, 579 &adau7118_component_driver, 580 &adau7118_dai, 1); 581} 582EXPORT_SYMBOL_GPL(adau7118_probe); 583 584MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>"); 585MODULE_DESCRIPTION("ADAU7118 8 channel PDM-to-I2S/TDM Converter driver"); 586MODULE_LICENSE("GPL");