0001
0002
0003
0004
0005
0006
0007 #include <linux/bitfield.h>
0008 #include <linux/module.h>
0009 #include <linux/regmap.h>
0010 #include <linux/regulator/consumer.h>
0011 #include <sound/pcm_params.h>
0012 #include <sound/soc.h>
0013
0014 #include "adau7118.h"
0015
0016 #define ADAU7118_DEC_RATIO_MASK GENMASK(1, 0)
0017 #define ADAU7118_DEC_RATIO(x) FIELD_PREP(ADAU7118_DEC_RATIO_MASK, x)
0018 #define ADAU7118_CLK_MAP_MASK GENMASK(7, 4)
0019 #define ADAU7118_SLOT_WIDTH_MASK GENMASK(5, 4)
0020 #define ADAU7118_SLOT_WIDTH(x) FIELD_PREP(ADAU7118_SLOT_WIDTH_MASK, x)
0021 #define ADAU7118_TRISTATE_MASK BIT(6)
0022 #define ADAU7118_TRISTATE(x) FIELD_PREP(ADAU7118_TRISTATE_MASK, x)
0023 #define ADAU7118_DATA_FMT_MASK GENMASK(3, 1)
0024 #define ADAU7118_DATA_FMT(x) FIELD_PREP(ADAU7118_DATA_FMT_MASK, x)
0025 #define ADAU7118_SAI_MODE_MASK BIT(0)
0026 #define ADAU7118_SAI_MODE(x) FIELD_PREP(ADAU7118_SAI_MODE_MASK, x)
0027 #define ADAU7118_LRCLK_BCLK_POL_MASK GENMASK(1, 0)
0028 #define ADAU7118_LRCLK_BCLK_POL(x) \
0029 FIELD_PREP(ADAU7118_LRCLK_BCLK_POL_MASK, x)
0030 #define ADAU7118_SPT_SLOT_MASK GENMASK(7, 4)
0031 #define ADAU7118_SPT_SLOT(x) FIELD_PREP(ADAU7118_SPT_SLOT_MASK, x)
0032 #define ADAU7118_FULL_SOFT_R_MASK BIT(1)
0033 #define ADAU7118_FULL_SOFT_R(x) FIELD_PREP(ADAU7118_FULL_SOFT_R_MASK, x)
0034
0035 struct adau7118_data {
0036 struct regmap *map;
0037 struct device *dev;
0038 struct regulator *iovdd;
0039 struct regulator *dvdd;
0040 u32 slot_width;
0041 u32 slots;
0042 bool hw_mode;
0043 bool right_j;
0044 };
0045
0046
0047 static const struct snd_kcontrol_new adau7118_dapm_pdm_control[4] = {
0048 SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 0, 1, 0),
0049 SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 1, 1, 0),
0050 SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 2, 1, 0),
0051 SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 3, 1, 0),
0052 };
0053
0054 static const struct snd_soc_dapm_widget adau7118_widgets_sw[] = {
0055
0056 SND_SOC_DAPM_SWITCH("PDM0", SND_SOC_NOPM, 0, 0,
0057 &adau7118_dapm_pdm_control[0]),
0058 SND_SOC_DAPM_SWITCH("PDM1", SND_SOC_NOPM, 0, 0,
0059 &adau7118_dapm_pdm_control[1]),
0060 SND_SOC_DAPM_SWITCH("PDM2", SND_SOC_NOPM, 0, 0,
0061 &adau7118_dapm_pdm_control[2]),
0062 SND_SOC_DAPM_SWITCH("PDM3", SND_SOC_NOPM, 0, 0,
0063 &adau7118_dapm_pdm_control[3]),
0064
0065
0066 SND_SOC_DAPM_SUPPLY("PDM_CLK0", ADAU7118_REG_ENABLES, 4, 0, NULL, 0),
0067 SND_SOC_DAPM_SUPPLY("PDM_CLK1", ADAU7118_REG_ENABLES, 5, 0, NULL, 0),
0068
0069
0070 SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0, ADAU7118_REG_SPT_CX(0),
0071 0, 0),
0072 SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 0, ADAU7118_REG_SPT_CX(1),
0073 0, 0),
0074 SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 0, ADAU7118_REG_SPT_CX(2),
0075 0, 0),
0076 SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 0, ADAU7118_REG_SPT_CX(3),
0077 0, 0),
0078 SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 0, ADAU7118_REG_SPT_CX(4),
0079 0, 0),
0080 SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 0, ADAU7118_REG_SPT_CX(5),
0081 0, 0),
0082 SND_SOC_DAPM_AIF_OUT("AIF1TX7", "Capture", 0, ADAU7118_REG_SPT_CX(6),
0083 0, 0),
0084 SND_SOC_DAPM_AIF_OUT("AIF1TX8", "Capture", 0, ADAU7118_REG_SPT_CX(7),
0085 0, 0),
0086 };
0087
0088 static const struct snd_soc_dapm_route adau7118_routes_sw[] = {
0089 { "PDM0", "Capture Switch", "PDM_DAT0" },
0090 { "PDM1", "Capture Switch", "PDM_DAT1" },
0091 { "PDM2", "Capture Switch", "PDM_DAT2" },
0092 { "PDM3", "Capture Switch", "PDM_DAT3" },
0093 { "AIF1TX1", NULL, "PDM0" },
0094 { "AIF1TX2", NULL, "PDM0" },
0095 { "AIF1TX3", NULL, "PDM1" },
0096 { "AIF1TX4", NULL, "PDM1" },
0097 { "AIF1TX5", NULL, "PDM2" },
0098 { "AIF1TX6", NULL, "PDM2" },
0099 { "AIF1TX7", NULL, "PDM3" },
0100 { "AIF1TX8", NULL, "PDM3" },
0101 { "Capture", NULL, "PDM_CLK0" },
0102 { "Capture", NULL, "PDM_CLK1" },
0103 };
0104
0105 static const struct snd_soc_dapm_widget adau7118_widgets_hw[] = {
0106 SND_SOC_DAPM_AIF_OUT("AIF1TX", "Capture", 0, SND_SOC_NOPM, 0, 0),
0107 };
0108
0109 static const struct snd_soc_dapm_route adau7118_routes_hw[] = {
0110 { "AIF1TX", NULL, "PDM_DAT0" },
0111 { "AIF1TX", NULL, "PDM_DAT1" },
0112 { "AIF1TX", NULL, "PDM_DAT2" },
0113 { "AIF1TX", NULL, "PDM_DAT3" },
0114 };
0115
0116 static const struct snd_soc_dapm_widget adau7118_widgets[] = {
0117 SND_SOC_DAPM_INPUT("PDM_DAT0"),
0118 SND_SOC_DAPM_INPUT("PDM_DAT1"),
0119 SND_SOC_DAPM_INPUT("PDM_DAT2"),
0120 SND_SOC_DAPM_INPUT("PDM_DAT3"),
0121 };
0122
0123 static int adau7118_set_channel_map(struct snd_soc_dai *dai,
0124 unsigned int tx_num, unsigned int *tx_slot,
0125 unsigned int rx_num, unsigned int *rx_slot)
0126 {
0127 struct adau7118_data *st =
0128 snd_soc_component_get_drvdata(dai->component);
0129 int chan, ret;
0130
0131 dev_dbg(st->dev, "Set channel map, %d", tx_num);
0132
0133 for (chan = 0; chan < tx_num; chan++) {
0134 ret = snd_soc_component_update_bits(dai->component,
0135 ADAU7118_REG_SPT_CX(chan),
0136 ADAU7118_SPT_SLOT_MASK,
0137 ADAU7118_SPT_SLOT(tx_slot[chan]));
0138 if (ret < 0)
0139 return ret;
0140 }
0141
0142 return 0;
0143 }
0144
0145 static int adau7118_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0146 {
0147 struct adau7118_data *st =
0148 snd_soc_component_get_drvdata(dai->component);
0149 int ret = 0;
0150 u32 regval;
0151
0152 dev_dbg(st->dev, "Set format, fmt:%d\n", fmt);
0153
0154 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0155 case SND_SOC_DAIFMT_I2S:
0156 ret = snd_soc_component_update_bits(dai->component,
0157 ADAU7118_REG_SPT_CTRL1,
0158 ADAU7118_DATA_FMT_MASK,
0159 ADAU7118_DATA_FMT(0));
0160 break;
0161 case SND_SOC_DAIFMT_LEFT_J:
0162 ret = snd_soc_component_update_bits(dai->component,
0163 ADAU7118_REG_SPT_CTRL1,
0164 ADAU7118_DATA_FMT_MASK,
0165 ADAU7118_DATA_FMT(1));
0166 break;
0167 case SND_SOC_DAIFMT_RIGHT_J:
0168 st->right_j = true;
0169 break;
0170 default:
0171 dev_err(st->dev, "Invalid format %d",
0172 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
0173 return -EINVAL;
0174 }
0175
0176 if (ret < 0)
0177 return ret;
0178
0179 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
0180 case SND_SOC_DAIFMT_NB_NF:
0181 regval = ADAU7118_LRCLK_BCLK_POL(0);
0182 break;
0183 case SND_SOC_DAIFMT_NB_IF:
0184 regval = ADAU7118_LRCLK_BCLK_POL(2);
0185 break;
0186 case SND_SOC_DAIFMT_IB_NF:
0187 regval = ADAU7118_LRCLK_BCLK_POL(1);
0188 break;
0189 case SND_SOC_DAIFMT_IB_IF:
0190 regval = ADAU7118_LRCLK_BCLK_POL(3);
0191 break;
0192 default:
0193 dev_err(st->dev, "Invalid Inv mask %d",
0194 fmt & SND_SOC_DAIFMT_INV_MASK);
0195 return -EINVAL;
0196 }
0197
0198 ret = snd_soc_component_update_bits(dai->component,
0199 ADAU7118_REG_SPT_CTRL2,
0200 ADAU7118_LRCLK_BCLK_POL_MASK,
0201 regval);
0202 if (ret < 0)
0203 return ret;
0204
0205 return 0;
0206 }
0207
0208 static int adau7118_set_tristate(struct snd_soc_dai *dai, int tristate)
0209 {
0210 struct adau7118_data *st =
0211 snd_soc_component_get_drvdata(dai->component);
0212 int ret;
0213
0214 dev_dbg(st->dev, "Set tristate, %d\n", tristate);
0215
0216 ret = snd_soc_component_update_bits(dai->component,
0217 ADAU7118_REG_SPT_CTRL1,
0218 ADAU7118_TRISTATE_MASK,
0219 ADAU7118_TRISTATE(tristate));
0220 if (ret < 0)
0221 return ret;
0222
0223 return 0;
0224 }
0225
0226 static int adau7118_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
0227 unsigned int rx_mask, int slots,
0228 int slot_width)
0229 {
0230 struct adau7118_data *st =
0231 snd_soc_component_get_drvdata(dai->component);
0232 int ret = 0;
0233 u32 regval;
0234
0235 dev_dbg(st->dev, "Set tdm, slots:%d width:%d\n", slots, slot_width);
0236
0237 switch (slot_width) {
0238 case 32:
0239 regval = ADAU7118_SLOT_WIDTH(0);
0240 break;
0241 case 24:
0242 regval = ADAU7118_SLOT_WIDTH(2);
0243 break;
0244 case 16:
0245 regval = ADAU7118_SLOT_WIDTH(1);
0246 break;
0247 default:
0248 dev_err(st->dev, "Invalid slot width:%d\n", slot_width);
0249 return -EINVAL;
0250 }
0251
0252 ret = snd_soc_component_update_bits(dai->component,
0253 ADAU7118_REG_SPT_CTRL1,
0254 ADAU7118_SLOT_WIDTH_MASK, regval);
0255 if (ret < 0)
0256 return ret;
0257
0258 st->slot_width = slot_width;
0259 st->slots = slots;
0260
0261 return 0;
0262 }
0263
0264 static int adau7118_hw_params(struct snd_pcm_substream *substream,
0265 struct snd_pcm_hw_params *params,
0266 struct snd_soc_dai *dai)
0267 {
0268 struct adau7118_data *st =
0269 snd_soc_component_get_drvdata(dai->component);
0270 u32 data_width = params_width(params), slots_width;
0271 int ret;
0272 u32 regval;
0273
0274 if (!st->slots) {
0275
0276 ret = snd_soc_component_update_bits(dai->component,
0277 ADAU7118_REG_SPT_CTRL1,
0278 ADAU7118_SAI_MODE_MASK,
0279 ADAU7118_SAI_MODE(0));
0280 if (ret < 0)
0281 return ret;
0282
0283 slots_width = 32;
0284 } else {
0285 slots_width = st->slot_width;
0286 }
0287
0288 if (data_width > slots_width) {
0289 dev_err(st->dev, "Invalid data_width:%d, slots_width:%d",
0290 data_width, slots_width);
0291 return -EINVAL;
0292 }
0293
0294 if (st->right_j) {
0295 switch (slots_width - data_width) {
0296 case 8:
0297
0298 regval = ADAU7118_DATA_FMT(2);
0299 break;
0300 case 12:
0301
0302 regval = ADAU7118_DATA_FMT(3);
0303 break;
0304 case 16:
0305
0306 regval = ADAU7118_DATA_FMT(4);
0307 break;
0308 default:
0309 dev_err(st->dev,
0310 "Cannot set right_j setting, slot_w:%d, data_w:%d\n",
0311 slots_width, data_width);
0312 return -EINVAL;
0313 }
0314
0315 ret = snd_soc_component_update_bits(dai->component,
0316 ADAU7118_REG_SPT_CTRL1,
0317 ADAU7118_DATA_FMT_MASK,
0318 regval);
0319 if (ret < 0)
0320 return ret;
0321 }
0322
0323 return 0;
0324 }
0325
0326 static int adau7118_set_bias_level(struct snd_soc_component *component,
0327 enum snd_soc_bias_level level)
0328 {
0329 struct adau7118_data *st = snd_soc_component_get_drvdata(component);
0330 int ret = 0;
0331
0332 dev_dbg(st->dev, "Set bias level %d\n", level);
0333
0334 switch (level) {
0335 case SND_SOC_BIAS_ON:
0336 case SND_SOC_BIAS_PREPARE:
0337 break;
0338
0339 case SND_SOC_BIAS_STANDBY:
0340 if (snd_soc_component_get_bias_level(component) ==
0341 SND_SOC_BIAS_OFF) {
0342
0343 ret = regulator_enable(st->iovdd);
0344 if (ret)
0345 return ret;
0346
0347
0348 ret = regulator_enable(st->dvdd);
0349 if (ret) {
0350 regulator_disable(st->iovdd);
0351 return ret;
0352 }
0353
0354 if (st->hw_mode)
0355 return 0;
0356
0357 regcache_cache_only(st->map, false);
0358
0359 ret = snd_soc_component_cache_sync(component);
0360 }
0361 break;
0362 case SND_SOC_BIAS_OFF:
0363
0364 ret = regulator_disable(st->dvdd);
0365 if (ret)
0366 return ret;
0367
0368 ret = regulator_disable(st->iovdd);
0369 if (ret)
0370 return ret;
0371
0372 if (st->hw_mode)
0373 return 0;
0374
0375
0376 regcache_mark_dirty(st->map);
0377 regcache_cache_only(st->map, true);
0378
0379 break;
0380 }
0381
0382 return ret;
0383 }
0384
0385 static int adau7118_component_probe(struct snd_soc_component *component)
0386 {
0387 struct adau7118_data *st = snd_soc_component_get_drvdata(component);
0388 struct snd_soc_dapm_context *dapm =
0389 snd_soc_component_get_dapm(component);
0390 int ret = 0;
0391
0392 if (st->hw_mode) {
0393 ret = snd_soc_dapm_new_controls(dapm, adau7118_widgets_hw,
0394 ARRAY_SIZE(adau7118_widgets_hw));
0395 if (ret)
0396 return ret;
0397
0398 ret = snd_soc_dapm_add_routes(dapm, adau7118_routes_hw,
0399 ARRAY_SIZE(adau7118_routes_hw));
0400 } else {
0401 snd_soc_component_init_regmap(component, st->map);
0402 ret = snd_soc_dapm_new_controls(dapm, adau7118_widgets_sw,
0403 ARRAY_SIZE(adau7118_widgets_sw));
0404 if (ret)
0405 return ret;
0406
0407 ret = snd_soc_dapm_add_routes(dapm, adau7118_routes_sw,
0408 ARRAY_SIZE(adau7118_routes_sw));
0409 }
0410
0411 return ret;
0412 }
0413
0414 static const struct snd_soc_dai_ops adau7118_ops = {
0415 .hw_params = adau7118_hw_params,
0416 .set_channel_map = adau7118_set_channel_map,
0417 .set_fmt = adau7118_set_fmt,
0418 .set_tdm_slot = adau7118_set_tdm_slot,
0419 .set_tristate = adau7118_set_tristate,
0420 };
0421
0422 static struct snd_soc_dai_driver adau7118_dai = {
0423 .name = "adau7118-hifi-capture",
0424 .capture = {
0425 .stream_name = "Capture",
0426 .channels_min = 1,
0427 .channels_max = 8,
0428 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |
0429 SNDRV_PCM_FMTBIT_S20_LE | SNDRV_PCM_FMTBIT_S24_LE |
0430 SNDRV_PCM_FMTBIT_S24_3LE,
0431 .rates = SNDRV_PCM_RATE_CONTINUOUS,
0432 .rate_min = 4000,
0433 .rate_max = 192000,
0434 .sig_bits = 24,
0435 },
0436 };
0437
0438 static const struct snd_soc_component_driver adau7118_component_driver = {
0439 .probe = adau7118_component_probe,
0440 .set_bias_level = adau7118_set_bias_level,
0441 .dapm_widgets = adau7118_widgets,
0442 .num_dapm_widgets = ARRAY_SIZE(adau7118_widgets),
0443 .use_pmdown_time = 1,
0444 .endianness = 1,
0445 };
0446
0447 static void adau7118_regulator_disable(void *data)
0448 {
0449 struct adau7118_data *st = data;
0450 int ret;
0451
0452
0453
0454
0455
0456 ret = regulator_disable(st->dvdd);
0457 if (ret)
0458 return;
0459
0460 regulator_disable(st->iovdd);
0461 }
0462
0463 static int adau7118_regulator_setup(struct adau7118_data *st)
0464 {
0465 st->iovdd = devm_regulator_get(st->dev, "iovdd");
0466 if (IS_ERR(st->iovdd)) {
0467 dev_err(st->dev, "Could not get iovdd: %ld\n",
0468 PTR_ERR(st->iovdd));
0469 return PTR_ERR(st->iovdd);
0470 }
0471
0472 st->dvdd = devm_regulator_get(st->dev, "dvdd");
0473 if (IS_ERR(st->dvdd)) {
0474 dev_err(st->dev, "Could not get dvdd: %ld\n",
0475 PTR_ERR(st->dvdd));
0476 return PTR_ERR(st->dvdd);
0477 }
0478
0479 if (!st->hw_mode) {
0480 regcache_mark_dirty(st->map);
0481 regcache_cache_only(st->map, true);
0482 }
0483
0484 return devm_add_action_or_reset(st->dev, adau7118_regulator_disable,
0485 st);
0486 }
0487
0488 static int adau7118_parset_dt(const struct adau7118_data *st)
0489 {
0490 int ret;
0491 u32 dec_ratio = 0;
0492
0493 u32 clk_map[4], regval;
0494
0495 if (st->hw_mode)
0496 return 0;
0497
0498 ret = device_property_read_u32(st->dev, "adi,decimation-ratio",
0499 &dec_ratio);
0500 if (!ret) {
0501 switch (dec_ratio) {
0502 case 64:
0503 regval = ADAU7118_DEC_RATIO(0);
0504 break;
0505 case 32:
0506 regval = ADAU7118_DEC_RATIO(1);
0507 break;
0508 case 16:
0509 regval = ADAU7118_DEC_RATIO(2);
0510 break;
0511 default:
0512 dev_err(st->dev, "Invalid dec ratio: %u", dec_ratio);
0513 return -EINVAL;
0514 }
0515
0516 ret = regmap_update_bits(st->map,
0517 ADAU7118_REG_DEC_RATIO_CLK_MAP,
0518 ADAU7118_DEC_RATIO_MASK, regval);
0519 if (ret)
0520 return ret;
0521 }
0522
0523 ret = device_property_read_u32_array(st->dev, "adi,pdm-clk-map",
0524 clk_map, ARRAY_SIZE(clk_map));
0525 if (!ret) {
0526 int pdm;
0527 u32 _clk_map = 0;
0528
0529 for (pdm = 0; pdm < ARRAY_SIZE(clk_map); pdm++)
0530 _clk_map |= (clk_map[pdm] << (pdm + 4));
0531
0532 ret = regmap_update_bits(st->map,
0533 ADAU7118_REG_DEC_RATIO_CLK_MAP,
0534 ADAU7118_CLK_MAP_MASK, _clk_map);
0535 if (ret)
0536 return ret;
0537 }
0538
0539 return 0;
0540 }
0541
0542 int adau7118_probe(struct device *dev, struct regmap *map, bool hw_mode)
0543 {
0544 struct adau7118_data *st;
0545 int ret;
0546
0547 st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
0548 if (!st)
0549 return -ENOMEM;
0550
0551 st->dev = dev;
0552 st->hw_mode = hw_mode;
0553 dev_set_drvdata(dev, st);
0554
0555 if (!hw_mode) {
0556 st->map = map;
0557 adau7118_dai.ops = &adau7118_ops;
0558
0559
0560
0561
0562 ret = regmap_update_bits(map, ADAU7118_REG_RESET,
0563 ADAU7118_FULL_SOFT_R_MASK,
0564 ADAU7118_FULL_SOFT_R(1));
0565 if (ret)
0566 return ret;
0567 }
0568
0569 ret = adau7118_parset_dt(st);
0570 if (ret)
0571 return ret;
0572
0573 ret = adau7118_regulator_setup(st);
0574 if (ret)
0575 return ret;
0576
0577 return devm_snd_soc_register_component(dev,
0578 &adau7118_component_driver,
0579 &adau7118_dai, 1);
0580 }
0581 EXPORT_SYMBOL_GPL(adau7118_probe);
0582
0583 MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
0584 MODULE_DESCRIPTION("ADAU7118 8 channel PDM-to-I2S/TDM Converter driver");
0585 MODULE_LICENSE("GPL");