1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) STMicroelectronics SA 2015 4 * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com> 5 * for STMicroelectronics. 6 */ 7 8 #include <linux/io.h> 9 #include <linux/module.h> 10 #include <linux/regmap.h> 11 #include <linux/reset.h> 12 #include <linux/mfd/syscon.h> 13 14 #include <sound/soc.h> 15 #include <sound/soc-dapm.h> 16 17 /* DAC definitions */ 18 19 /* stih407 DAC registers */ 20 /* sysconf 5041: Audio-Gue-Control */ 21 #define STIH407_AUDIO_GLUE_CTRL 0x000000A4 22 /* sysconf 5042: Audio-DAC-Control */ 23 #define STIH407_AUDIO_DAC_CTRL 0x000000A8 24 25 /* DAC definitions */ 26 #define STIH407_DAC_SOFTMUTE 0x0 27 #define STIH407_DAC_STANDBY_ANA 0x1 28 #define STIH407_DAC_STANDBY 0x2 29 30 #define STIH407_DAC_SOFTMUTE_MASK BIT(STIH407_DAC_SOFTMUTE) 31 #define STIH407_DAC_STANDBY_ANA_MASK BIT(STIH407_DAC_STANDBY_ANA) 32 #define STIH407_DAC_STANDBY_MASK BIT(STIH407_DAC_STANDBY) 33 34 /* SPDIF definitions */ 35 #define SPDIF_BIPHASE_ENABLE 0x6 36 #define SPDIF_BIPHASE_IDLE 0x7 37 38 #define SPDIF_BIPHASE_ENABLE_MASK BIT(SPDIF_BIPHASE_ENABLE) 39 #define SPDIF_BIPHASE_IDLE_MASK BIT(SPDIF_BIPHASE_IDLE) 40 41 enum { 42 STI_SAS_DAI_SPDIF_OUT, 43 STI_SAS_DAI_ANALOG_OUT, 44 }; 45 46 static const struct reg_default stih407_sas_reg_defaults[] = { 47 { STIH407_AUDIO_DAC_CTRL, 0x000000000 }, 48 { STIH407_AUDIO_GLUE_CTRL, 0x00000040 }, 49 }; 50 51 struct sti_dac_audio { 52 struct regmap *regmap; 53 struct regmap *virt_regmap; 54 int mclk; 55 }; 56 57 struct sti_spdif_audio { 58 struct regmap *regmap; 59 int mclk; 60 }; 61 62 /* device data structure */ 63 struct sti_sas_dev_data { 64 const struct regmap_config *regmap; 65 const struct snd_soc_dai_ops *dac_ops; /* DAC function callbacks */ 66 }; 67 68 /* driver data structure */ 69 struct sti_sas_data { 70 struct device *dev; 71 const struct sti_sas_dev_data *dev_data; 72 struct sti_dac_audio dac; 73 struct sti_spdif_audio spdif; 74 }; 75 76 /* Read a register from the sysconf reg bank */ 77 static int sti_sas_read_reg(void *context, unsigned int reg, 78 unsigned int *value) 79 { 80 struct sti_sas_data *drvdata = context; 81 int status; 82 u32 val; 83 84 status = regmap_read(drvdata->dac.regmap, reg, &val); 85 *value = (unsigned int)val; 86 87 return status; 88 } 89 90 /* Read a register from the sysconf reg bank */ 91 static int sti_sas_write_reg(void *context, unsigned int reg, 92 unsigned int value) 93 { 94 struct sti_sas_data *drvdata = context; 95 96 return regmap_write(drvdata->dac.regmap, reg, value); 97 } 98 99 static int sti_sas_init_sas_registers(struct snd_soc_component *component, 100 struct sti_sas_data *data) 101 { 102 int ret; 103 /* 104 * DAC and SPDIF are activated by default 105 * put them in IDLE to save power 106 */ 107 108 /* Initialise bi-phase formatter to disabled */ 109 ret = snd_soc_component_update_bits(component, STIH407_AUDIO_GLUE_CTRL, 110 SPDIF_BIPHASE_ENABLE_MASK, 0); 111 112 if (!ret) 113 /* Initialise bi-phase formatter idle value to 0 */ 114 ret = snd_soc_component_update_bits(component, STIH407_AUDIO_GLUE_CTRL, 115 SPDIF_BIPHASE_IDLE_MASK, 0); 116 if (ret < 0) { 117 dev_err(component->dev, "Failed to update SPDIF registers\n"); 118 return ret; 119 } 120 121 /* Init DAC configuration */ 122 /* init configuration */ 123 ret = snd_soc_component_update_bits(component, STIH407_AUDIO_DAC_CTRL, 124 STIH407_DAC_STANDBY_MASK, 125 STIH407_DAC_STANDBY_MASK); 126 127 if (!ret) 128 ret = snd_soc_component_update_bits(component, STIH407_AUDIO_DAC_CTRL, 129 STIH407_DAC_STANDBY_ANA_MASK, 130 STIH407_DAC_STANDBY_ANA_MASK); 131 if (!ret) 132 ret = snd_soc_component_update_bits(component, STIH407_AUDIO_DAC_CTRL, 133 STIH407_DAC_SOFTMUTE_MASK, 134 STIH407_DAC_SOFTMUTE_MASK); 135 136 if (ret < 0) { 137 dev_err(component->dev, "Failed to update DAC registers\n"); 138 return ret; 139 } 140 141 return ret; 142 } 143 144 /* 145 * DAC 146 */ 147 static int sti_sas_dac_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 148 { 149 /* Sanity check only */ 150 if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_CBC_CFC) { 151 dev_err(dai->component->dev, 152 "%s: ERROR: Unsupported clocking 0x%x\n", 153 __func__, fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK); 154 return -EINVAL; 155 } 156 157 return 0; 158 } 159 160 static const struct snd_soc_dapm_widget stih407_sas_dapm_widgets[] = { 161 SND_SOC_DAPM_OUT_DRV("DAC standby ana", STIH407_AUDIO_DAC_CTRL, 162 STIH407_DAC_STANDBY_ANA, 1, NULL, 0), 163 SND_SOC_DAPM_DAC("DAC standby", "dac_p", STIH407_AUDIO_DAC_CTRL, 164 STIH407_DAC_STANDBY, 1), 165 SND_SOC_DAPM_OUTPUT("DAC Output"), 166 }; 167 168 static const struct snd_soc_dapm_route stih407_sas_route[] = { 169 {"DAC Output", NULL, "DAC standby ana"}, 170 {"DAC standby ana", NULL, "DAC standby"}, 171 }; 172 173 174 static int stih407_sas_dac_mute(struct snd_soc_dai *dai, int mute, int stream) 175 { 176 struct snd_soc_component *component = dai->component; 177 178 if (mute) { 179 return snd_soc_component_update_bits(component, STIH407_AUDIO_DAC_CTRL, 180 STIH407_DAC_SOFTMUTE_MASK, 181 STIH407_DAC_SOFTMUTE_MASK); 182 } else { 183 return snd_soc_component_update_bits(component, STIH407_AUDIO_DAC_CTRL, 184 STIH407_DAC_SOFTMUTE_MASK, 185 0); 186 } 187 } 188 189 /* 190 * SPDIF 191 */ 192 static int sti_sas_spdif_set_fmt(struct snd_soc_dai *dai, 193 unsigned int fmt) 194 { 195 if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_CBC_CFC) { 196 dev_err(dai->component->dev, 197 "%s: ERROR: Unsupported clocking mask 0x%x\n", 198 __func__, fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK); 199 return -EINVAL; 200 } 201 202 return 0; 203 } 204 205 /* 206 * sti_sas_spdif_trigger: 207 * Trigger function is used to ensure that BiPhase Formater is disabled 208 * before CPU dai is stopped. 209 * This is mandatory to avoid that BPF is stalled 210 */ 211 static int sti_sas_spdif_trigger(struct snd_pcm_substream *substream, int cmd, 212 struct snd_soc_dai *dai) 213 { 214 struct snd_soc_component *component = dai->component; 215 216 switch (cmd) { 217 case SNDRV_PCM_TRIGGER_START: 218 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 219 return snd_soc_component_update_bits(component, STIH407_AUDIO_GLUE_CTRL, 220 SPDIF_BIPHASE_ENABLE_MASK, 221 SPDIF_BIPHASE_ENABLE_MASK); 222 case SNDRV_PCM_TRIGGER_RESUME: 223 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 224 case SNDRV_PCM_TRIGGER_STOP: 225 case SNDRV_PCM_TRIGGER_SUSPEND: 226 return snd_soc_component_update_bits(component, STIH407_AUDIO_GLUE_CTRL, 227 SPDIF_BIPHASE_ENABLE_MASK, 228 0); 229 default: 230 return -EINVAL; 231 } 232 } 233 234 static bool sti_sas_volatile_register(struct device *dev, unsigned int reg) 235 { 236 if (reg == STIH407_AUDIO_GLUE_CTRL) 237 return true; 238 239 return false; 240 } 241 242 /* 243 * CODEC DAIS 244 */ 245 246 /* 247 * sti_sas_set_sysclk: 248 * get MCLK input frequency to check that MCLK-FS ratio is coherent 249 */ 250 static int sti_sas_set_sysclk(struct snd_soc_dai *dai, int clk_id, 251 unsigned int freq, int dir) 252 { 253 struct snd_soc_component *component = dai->component; 254 struct sti_sas_data *drvdata = dev_get_drvdata(component->dev); 255 256 if (dir == SND_SOC_CLOCK_OUT) 257 return 0; 258 259 if (clk_id != 0) 260 return -EINVAL; 261 262 switch (dai->id) { 263 case STI_SAS_DAI_SPDIF_OUT: 264 drvdata->spdif.mclk = freq; 265 break; 266 267 case STI_SAS_DAI_ANALOG_OUT: 268 drvdata->dac.mclk = freq; 269 break; 270 } 271 272 return 0; 273 } 274 275 static int sti_sas_prepare(struct snd_pcm_substream *substream, 276 struct snd_soc_dai *dai) 277 { 278 struct snd_soc_component *component = dai->component; 279 struct sti_sas_data *drvdata = dev_get_drvdata(component->dev); 280 struct snd_pcm_runtime *runtime = substream->runtime; 281 282 switch (dai->id) { 283 case STI_SAS_DAI_SPDIF_OUT: 284 if ((drvdata->spdif.mclk / runtime->rate) != 128) { 285 dev_err(component->dev, "unexpected mclk-fs ratio\n"); 286 return -EINVAL; 287 } 288 break; 289 case STI_SAS_DAI_ANALOG_OUT: 290 if ((drvdata->dac.mclk / runtime->rate) != 256) { 291 dev_err(component->dev, "unexpected mclk-fs ratio\n"); 292 return -EINVAL; 293 } 294 break; 295 } 296 297 return 0; 298 } 299 300 static const struct snd_soc_dai_ops stih407_dac_ops = { 301 .set_fmt = sti_sas_dac_set_fmt, 302 .mute_stream = stih407_sas_dac_mute, 303 .prepare = sti_sas_prepare, 304 .set_sysclk = sti_sas_set_sysclk, 305 }; 306 307 static const struct regmap_config stih407_sas_regmap = { 308 .reg_bits = 32, 309 .val_bits = 32, 310 .fast_io = true, 311 .max_register = STIH407_AUDIO_DAC_CTRL, 312 .reg_defaults = stih407_sas_reg_defaults, 313 .num_reg_defaults = ARRAY_SIZE(stih407_sas_reg_defaults), 314 .volatile_reg = sti_sas_volatile_register, 315 .cache_type = REGCACHE_MAPLE, 316 .reg_read = sti_sas_read_reg, 317 .reg_write = sti_sas_write_reg, 318 }; 319 320 static const struct sti_sas_dev_data stih407_data = { 321 .regmap = &stih407_sas_regmap, 322 .dac_ops = &stih407_dac_ops, 323 }; 324 325 static struct snd_soc_dai_driver sti_sas_dai[] = { 326 { 327 .name = "sas-dai-spdif-out", 328 .id = STI_SAS_DAI_SPDIF_OUT, 329 .playback = { 330 .stream_name = "spdif_p", 331 .channels_min = 2, 332 .channels_max = 2, 333 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | 334 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | 335 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | 336 SNDRV_PCM_RATE_192000, 337 .formats = SNDRV_PCM_FMTBIT_S16_LE | 338 SNDRV_PCM_FMTBIT_S32_LE, 339 }, 340 .ops = (struct snd_soc_dai_ops[]) { 341 { 342 .set_fmt = sti_sas_spdif_set_fmt, 343 .trigger = sti_sas_spdif_trigger, 344 .set_sysclk = sti_sas_set_sysclk, 345 .prepare = sti_sas_prepare, 346 } 347 }, 348 }, 349 { 350 .name = "sas-dai-dac", 351 .id = STI_SAS_DAI_ANALOG_OUT, 352 .playback = { 353 .stream_name = "dac_p", 354 .channels_min = 2, 355 .channels_max = 2, 356 .rates = SNDRV_PCM_RATE_8000_48000, 357 .formats = SNDRV_PCM_FMTBIT_S16_LE | 358 SNDRV_PCM_FMTBIT_S32_LE, 359 }, 360 }, 361 }; 362 363 #ifdef CONFIG_PM_SLEEP 364 static int sti_sas_resume(struct snd_soc_component *component) 365 { 366 struct sti_sas_data *drvdata = dev_get_drvdata(component->dev); 367 368 return sti_sas_init_sas_registers(component, drvdata); 369 } 370 #else 371 #define sti_sas_resume NULL 372 #endif 373 374 static int sti_sas_component_probe(struct snd_soc_component *component) 375 { 376 struct sti_sas_data *drvdata = dev_get_drvdata(component->dev); 377 378 return sti_sas_init_sas_registers(component, drvdata); 379 } 380 381 static const struct snd_soc_component_driver sti_sas_driver = { 382 .probe = sti_sas_component_probe, 383 .resume = sti_sas_resume, 384 .idle_bias_on = 1, 385 .use_pmdown_time = 1, 386 .endianness = 1, 387 .dapm_widgets = stih407_sas_dapm_widgets, 388 .num_dapm_widgets = ARRAY_SIZE(stih407_sas_dapm_widgets), 389 .dapm_routes = stih407_sas_route, 390 .num_dapm_routes = ARRAY_SIZE(stih407_sas_route), 391 }; 392 393 static const struct of_device_id sti_sas_dev_match[] = { 394 { 395 .compatible = "st,stih407-sas-codec", 396 .data = &stih407_data, 397 }, 398 {}, 399 }; 400 MODULE_DEVICE_TABLE(of, sti_sas_dev_match); 401 402 static int sti_sas_driver_probe(struct platform_device *pdev) 403 { 404 struct device_node *pnode = pdev->dev.of_node; 405 struct sti_sas_data *drvdata; 406 const struct of_device_id *of_id; 407 408 /* Allocate device structure */ 409 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct sti_sas_data), 410 GFP_KERNEL); 411 if (!drvdata) 412 return -ENOMEM; 413 414 /* Populate data structure depending on compatibility */ 415 of_id = of_match_node(sti_sas_dev_match, pnode); 416 if (!of_id->data) { 417 dev_err(&pdev->dev, "data associated to device is missing\n"); 418 return -EINVAL; 419 } 420 421 drvdata->dev_data = (struct sti_sas_dev_data *)of_id->data; 422 423 /* Initialise device structure */ 424 drvdata->dev = &pdev->dev; 425 426 /* Request the DAC & SPDIF registers memory region */ 427 drvdata->dac.virt_regmap = devm_regmap_init(&pdev->dev, NULL, drvdata, 428 drvdata->dev_data->regmap); 429 if (IS_ERR(drvdata->dac.virt_regmap)) { 430 dev_err(&pdev->dev, "audio registers not enabled\n"); 431 return PTR_ERR(drvdata->dac.virt_regmap); 432 } 433 434 /* Request the syscon region */ 435 drvdata->dac.regmap = 436 syscon_regmap_lookup_by_phandle(pnode, "st,syscfg"); 437 if (IS_ERR(drvdata->dac.regmap)) { 438 dev_err(&pdev->dev, "syscon registers not available\n"); 439 return PTR_ERR(drvdata->dac.regmap); 440 } 441 drvdata->spdif.regmap = drvdata->dac.regmap; 442 443 sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops; 444 445 /* Store context */ 446 dev_set_drvdata(&pdev->dev, drvdata); 447 448 return devm_snd_soc_register_component(&pdev->dev, &sti_sas_driver, 449 sti_sas_dai, 450 ARRAY_SIZE(sti_sas_dai)); 451 } 452 453 static struct platform_driver sti_sas_platform_driver = { 454 .driver = { 455 .name = "sti-sas-codec", 456 .of_match_table = sti_sas_dev_match, 457 }, 458 .probe = sti_sas_driver_probe, 459 }; 460 461 module_platform_driver(sti_sas_platform_driver); 462 463 MODULE_DESCRIPTION("audio codec for STMicroelectronics sti platforms"); 464 MODULE_AUTHOR("Arnaud.pouliquen@st.com"); 465 MODULE_LICENSE("GPL v2"); 466