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