2 * Copyright (C) STMicroelectronics SA 2015
3 * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com>
4 * for STMicroelectronics.
5 * License terms: GNU General Public License (GPL), version 2
9 #include <linux/module.h>
10 #include <linux/regmap.h>
11 #include <linux/reset.h>
12 #include <linux/mfd/syscon.h>
14 #include <sound/soc.h>
15 #include <sound/soc-dapm.h>
17 /* chipID supported */
18 #define CHIPID_STIH416 0
19 #define CHIPID_STIH407 1
23 /* stih416 DAC registers */
24 /* sysconf 2517: Audio-DAC-Control */
25 #define STIH416_AUDIO_DAC_CTRL 0x00000814
26 /* sysconf 2519: Audio-Gue-Control */
27 #define STIH416_AUDIO_GLUE_CTRL 0x0000081C
29 #define STIH416_DAC_NOT_STANDBY 0x3
30 #define STIH416_DAC_SOFTMUTE 0x4
31 #define STIH416_DAC_ANA_NOT_PWR 0x5
32 #define STIH416_DAC_NOT_PNDBG 0x6
34 #define STIH416_DAC_NOT_STANDBY_MASK BIT(STIH416_DAC_NOT_STANDBY)
35 #define STIH416_DAC_SOFTMUTE_MASK BIT(STIH416_DAC_SOFTMUTE)
36 #define STIH416_DAC_ANA_NOT_PWR_MASK BIT(STIH416_DAC_ANA_NOT_PWR)
37 #define STIH416_DAC_NOT_PNDBG_MASK BIT(STIH416_DAC_NOT_PNDBG)
39 /* stih407 DAC registers */
40 /* sysconf 5041: Audio-Gue-Control */
41 #define STIH407_AUDIO_GLUE_CTRL 0x000000A4
42 /* sysconf 5042: Audio-DAC-Control */
43 #define STIH407_AUDIO_DAC_CTRL 0x000000A8
46 #define STIH407_DAC_SOFTMUTE 0x0
47 #define STIH407_DAC_STANDBY_ANA 0x1
48 #define STIH407_DAC_STANDBY 0x2
50 #define STIH407_DAC_SOFTMUTE_MASK BIT(STIH407_DAC_SOFTMUTE)
51 #define STIH407_DAC_STANDBY_ANA_MASK BIT(STIH407_DAC_STANDBY_ANA)
52 #define STIH407_DAC_STANDBY_MASK BIT(STIH407_DAC_STANDBY)
54 /* SPDIF definitions */
55 #define SPDIF_BIPHASE_ENABLE 0x6
56 #define SPDIF_BIPHASE_IDLE 0x7
58 #define SPDIF_BIPHASE_ENABLE_MASK BIT(SPDIF_BIPHASE_ENABLE)
59 #define SPDIF_BIPHASE_IDLE_MASK BIT(SPDIF_BIPHASE_IDLE)
62 STI_SAS_DAI_SPDIF_OUT,
63 STI_SAS_DAI_ANALOG_OUT,
66 static const struct reg_default stih416_sas_reg_defaults[] = {
67 { STIH407_AUDIO_GLUE_CTRL, 0x00000040 },
68 { STIH407_AUDIO_DAC_CTRL, 0x000000000 },
71 static const struct reg_default stih407_sas_reg_defaults[] = {
72 { STIH416_AUDIO_DAC_CTRL, 0x000000000 },
73 { STIH416_AUDIO_GLUE_CTRL, 0x00000040 },
76 struct sti_dac_audio {
77 struct regmap *regmap;
78 struct regmap *virt_regmap;
79 struct regmap_field **field;
80 struct reset_control *rst;
84 struct sti_spdif_audio {
85 struct regmap *regmap;
86 struct regmap_field **field;
90 /* device data structure */
91 struct sti_sas_dev_data {
92 const int chipid; /* IC version */
93 const struct regmap_config *regmap;
94 const struct snd_soc_dai_ops *dac_ops; /* DAC function callbacks */
95 const struct snd_soc_dapm_widget *dapm_widgets; /* dapms declaration */
96 const int num_dapm_widgets; /* dapms declaration */
97 const struct snd_soc_dapm_route *dapm_routes; /* route declaration */
98 const int num_dapm_routes; /* route declaration */
101 /* driver data structure */
102 struct sti_sas_data {
104 const struct sti_sas_dev_data *dev_data;
105 struct sti_dac_audio dac;
106 struct sti_spdif_audio spdif;
109 /* Read a register from the sysconf reg bank */
110 static int sti_sas_read_reg(void *context, unsigned int reg,
113 struct sti_sas_data *drvdata = context;
117 status = regmap_read(drvdata->dac.regmap, reg, &val);
118 *value = (unsigned int)val;
123 /* Read a register from the sysconf reg bank */
124 static int sti_sas_write_reg(void *context, unsigned int reg,
127 struct sti_sas_data *drvdata = context;
130 status = regmap_write(drvdata->dac.regmap, reg, value);
135 static int sti_sas_init_sas_registers(struct snd_soc_codec *codec,
136 struct sti_sas_data *data)
140 * DAC and SPDIF are activated by default
141 * put them in IDLE to save power
144 /* Initialise bi-phase formatter to disabled */
145 ret = snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
146 SPDIF_BIPHASE_ENABLE_MASK, 0);
149 /* Initialise bi-phase formatter idle value to 0 */
150 ret = snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
151 SPDIF_BIPHASE_IDLE_MASK, 0);
153 dev_err(codec->dev, "Failed to update SPDIF registers");
157 /* Init DAC configuration */
158 switch (data->dev_data->chipid) {
160 /* init configuration */
161 ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
162 STIH407_DAC_STANDBY_MASK,
163 STIH407_DAC_STANDBY_MASK);
166 ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
167 STIH407_DAC_STANDBY_ANA_MASK,
168 STIH407_DAC_STANDBY_ANA_MASK);
170 ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
171 STIH407_DAC_SOFTMUTE_MASK,
172 STIH407_DAC_SOFTMUTE_MASK);
175 ret = snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL,
176 STIH416_DAC_NOT_STANDBY_MASK, 0);
178 ret = snd_soc_update_bits(codec,
179 STIH416_AUDIO_DAC_CTRL,
180 STIH416_DAC_ANA_NOT_PWR, 0);
182 ret = snd_soc_update_bits(codec,
183 STIH416_AUDIO_DAC_CTRL,
184 STIH416_DAC_NOT_PNDBG_MASK,
187 ret = snd_soc_update_bits(codec,
188 STIH416_AUDIO_DAC_CTRL,
189 STIH416_DAC_SOFTMUTE_MASK,
190 STIH416_DAC_SOFTMUTE_MASK);
197 dev_err(codec->dev, "Failed to update DAC registers");
207 static int sti_sas_dac_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
209 /* Sanity check only */
210 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
211 dev_err(dai->codec->dev,
212 "%s: ERROR: Unsupporter master mask 0x%x\n",
213 __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
220 static int stih416_dac_probe(struct snd_soc_dai *dai)
222 struct snd_soc_codec *codec = dai->codec;
223 struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
224 struct sti_dac_audio *dac = &drvdata->dac;
226 /* Get reset control */
227 dac->rst = devm_reset_control_get(codec->dev, "dac_rst");
228 if (IS_ERR(dac->rst)) {
229 dev_err(dai->codec->dev,
230 "%s: ERROR: DAC reset control not defined !\n",
235 /* Put the DAC into reset */
236 reset_control_assert(dac->rst);
241 static const struct snd_soc_dapm_widget stih416_sas_dapm_widgets[] = {
242 SND_SOC_DAPM_PGA("DAC bandgap", STIH416_AUDIO_DAC_CTRL,
243 STIH416_DAC_NOT_PNDBG_MASK, 0, NULL, 0),
244 SND_SOC_DAPM_OUT_DRV("DAC standby ana", STIH416_AUDIO_DAC_CTRL,
245 STIH416_DAC_ANA_NOT_PWR, 0, NULL, 0),
246 SND_SOC_DAPM_DAC("DAC standby", "dac_p", STIH416_AUDIO_DAC_CTRL,
247 STIH416_DAC_NOT_STANDBY, 0),
248 SND_SOC_DAPM_OUTPUT("DAC Output"),
251 static const struct snd_soc_dapm_widget stih407_sas_dapm_widgets[] = {
252 SND_SOC_DAPM_OUT_DRV("DAC standby ana", STIH407_AUDIO_DAC_CTRL,
253 STIH407_DAC_STANDBY_ANA, 1, NULL, 0),
254 SND_SOC_DAPM_DAC("DAC standby", "dac_p", STIH407_AUDIO_DAC_CTRL,
255 STIH407_DAC_STANDBY, 1),
256 SND_SOC_DAPM_OUTPUT("DAC Output"),
259 static const struct snd_soc_dapm_route stih416_sas_route[] = {
260 {"DAC Output", NULL, "DAC bandgap"},
261 {"DAC Output", NULL, "DAC standby ana"},
262 {"DAC standby ana", NULL, "DAC standby"},
265 static const struct snd_soc_dapm_route stih407_sas_route[] = {
266 {"DAC Output", NULL, "DAC standby ana"},
267 {"DAC standby ana", NULL, "DAC standby"},
270 static int stih416_sas_dac_mute(struct snd_soc_dai *dai, int mute, int stream)
272 struct snd_soc_codec *codec = dai->codec;
275 return snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL,
276 STIH416_DAC_SOFTMUTE_MASK,
277 STIH416_DAC_SOFTMUTE_MASK);
279 return snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL,
280 STIH416_DAC_SOFTMUTE_MASK, 0);
284 static int stih407_sas_dac_mute(struct snd_soc_dai *dai, int mute, int stream)
286 struct snd_soc_codec *codec = dai->codec;
289 return snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
290 STIH407_DAC_SOFTMUTE_MASK,
291 STIH407_DAC_SOFTMUTE_MASK);
293 return snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
294 STIH407_DAC_SOFTMUTE_MASK,
302 static int sti_sas_spdif_set_fmt(struct snd_soc_dai *dai,
305 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
306 dev_err(dai->codec->dev,
307 "%s: ERROR: Unsupporter master mask 0x%x\n",
308 __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
316 * sti_sas_spdif_trigger:
317 * Trigger function is used to ensure that BiPhase Formater is disabled
318 * before CPU dai is stopped.
319 * This is mandatory to avoid that BPF is stalled
321 static int sti_sas_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
322 struct snd_soc_dai *dai)
324 struct snd_soc_codec *codec = dai->codec;
327 case SNDRV_PCM_TRIGGER_START:
328 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
329 return snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
330 SPDIF_BIPHASE_ENABLE_MASK,
331 SPDIF_BIPHASE_ENABLE_MASK);
332 case SNDRV_PCM_TRIGGER_RESUME:
333 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
334 case SNDRV_PCM_TRIGGER_STOP:
335 case SNDRV_PCM_TRIGGER_SUSPEND:
336 return snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
337 SPDIF_BIPHASE_ENABLE_MASK,
344 static bool sti_sas_volatile_register(struct device *dev, unsigned int reg)
346 if (reg == STIH407_AUDIO_GLUE_CTRL)
357 * sti_sas_set_sysclk:
358 * get MCLK input frequency to check that MCLK-FS ratio is coherent
360 static int sti_sas_set_sysclk(struct snd_soc_dai *dai, int clk_id,
361 unsigned int freq, int dir)
363 struct snd_soc_codec *codec = dai->codec;
364 struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
366 if (dir == SND_SOC_CLOCK_OUT)
373 case STI_SAS_DAI_SPDIF_OUT:
374 drvdata->spdif.mclk = freq;
377 case STI_SAS_DAI_ANALOG_OUT:
378 drvdata->dac.mclk = freq;
385 static int sti_sas_prepare(struct snd_pcm_substream *substream,
386 struct snd_soc_dai *dai)
388 struct snd_soc_codec *codec = dai->codec;
389 struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
390 struct snd_pcm_runtime *runtime = substream->runtime;
393 case STI_SAS_DAI_SPDIF_OUT:
394 if ((drvdata->spdif.mclk / runtime->rate) != 128) {
395 dev_err(codec->dev, "unexpected mclk-fs ratio");
399 case STI_SAS_DAI_ANALOG_OUT:
400 if ((drvdata->dac.mclk / runtime->rate) != 256) {
401 dev_err(codec->dev, "unexpected mclk-fs ratio");
410 static const struct snd_soc_dai_ops stih416_dac_ops = {
411 .set_fmt = sti_sas_dac_set_fmt,
412 .mute_stream = stih416_sas_dac_mute,
413 .prepare = sti_sas_prepare,
414 .set_sysclk = sti_sas_set_sysclk,
417 static const struct snd_soc_dai_ops stih407_dac_ops = {
418 .set_fmt = sti_sas_dac_set_fmt,
419 .mute_stream = stih407_sas_dac_mute,
420 .prepare = sti_sas_prepare,
421 .set_sysclk = sti_sas_set_sysclk,
424 static const struct regmap_config stih407_sas_regmap = {
428 .max_register = STIH407_AUDIO_DAC_CTRL,
429 .reg_defaults = stih407_sas_reg_defaults,
430 .num_reg_defaults = ARRAY_SIZE(stih407_sas_reg_defaults),
431 .volatile_reg = sti_sas_volatile_register,
432 .cache_type = REGCACHE_RBTREE,
433 .reg_read = sti_sas_read_reg,
434 .reg_write = sti_sas_write_reg,
437 static const struct regmap_config stih416_sas_regmap = {
441 .max_register = STIH416_AUDIO_DAC_CTRL,
442 .reg_defaults = stih416_sas_reg_defaults,
443 .num_reg_defaults = ARRAY_SIZE(stih416_sas_reg_defaults),
444 .volatile_reg = sti_sas_volatile_register,
445 .cache_type = REGCACHE_RBTREE,
446 .reg_read = sti_sas_read_reg,
447 .reg_write = sti_sas_write_reg,
450 static const struct sti_sas_dev_data stih416_data = {
451 .chipid = CHIPID_STIH416,
452 .regmap = &stih416_sas_regmap,
453 .dac_ops = &stih416_dac_ops,
454 .dapm_widgets = stih416_sas_dapm_widgets,
455 .num_dapm_widgets = ARRAY_SIZE(stih416_sas_dapm_widgets),
456 .dapm_routes = stih416_sas_route,
457 .num_dapm_routes = ARRAY_SIZE(stih416_sas_route),
460 static const struct sti_sas_dev_data stih407_data = {
461 .chipid = CHIPID_STIH407,
462 .regmap = &stih407_sas_regmap,
463 .dac_ops = &stih407_dac_ops,
464 .dapm_widgets = stih407_sas_dapm_widgets,
465 .num_dapm_widgets = ARRAY_SIZE(stih407_sas_dapm_widgets),
466 .dapm_routes = stih407_sas_route,
467 .num_dapm_routes = ARRAY_SIZE(stih407_sas_route),
470 static struct snd_soc_dai_driver sti_sas_dai[] = {
472 .name = "sas-dai-spdif-out",
473 .id = STI_SAS_DAI_SPDIF_OUT,
475 .stream_name = "spdif_p",
478 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
479 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 |
480 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
481 SNDRV_PCM_RATE_192000,
482 .formats = SNDRV_PCM_FMTBIT_S16_LE |
483 SNDRV_PCM_FMTBIT_S32_LE,
485 .ops = (struct snd_soc_dai_ops[]) {
487 .set_fmt = sti_sas_spdif_set_fmt,
488 .trigger = sti_sas_spdif_trigger,
489 .set_sysclk = sti_sas_set_sysclk,
490 .prepare = sti_sas_prepare,
495 .name = "sas-dai-dac",
496 .id = STI_SAS_DAI_ANALOG_OUT,
498 .stream_name = "dac_p",
501 .rates = SNDRV_PCM_RATE_8000_48000,
502 .formats = SNDRV_PCM_FMTBIT_S16_LE |
503 SNDRV_PCM_FMTBIT_S32_LE,
508 #ifdef CONFIG_PM_SLEEP
509 static int sti_sas_resume(struct snd_soc_codec *codec)
511 struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
513 return sti_sas_init_sas_registers(codec, drvdata);
516 #define sti_sas_resume NULL
519 static int sti_sas_codec_probe(struct snd_soc_codec *codec)
521 struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
524 ret = sti_sas_init_sas_registers(codec, drvdata);
529 static struct snd_soc_codec_driver sti_sas_driver = {
530 .probe = sti_sas_codec_probe,
531 .resume = sti_sas_resume,
534 static const struct of_device_id sti_sas_dev_match[] = {
536 .compatible = "st,stih416-sas-codec",
537 .data = &stih416_data,
540 .compatible = "st,stih407-sas-codec",
541 .data = &stih407_data,
545 MODULE_DEVICE_TABLE(of, sti_sas_dev_match);
547 static int sti_sas_driver_probe(struct platform_device *pdev)
549 struct device_node *pnode = pdev->dev.of_node;
550 struct sti_sas_data *drvdata;
551 const struct of_device_id *of_id;
553 /* Allocate device structure */
554 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct sti_sas_data),
559 /* Populate data structure depending on compatibility */
560 of_id = of_match_node(sti_sas_dev_match, pnode);
562 dev_err(&pdev->dev, "data associated to device is missing");
566 drvdata->dev_data = (struct sti_sas_dev_data *)of_id->data;
568 /* Initialise device structure */
569 drvdata->dev = &pdev->dev;
571 /* Request the DAC & SPDIF registers memory region */
572 drvdata->dac.virt_regmap = devm_regmap_init(&pdev->dev, NULL, drvdata,
573 drvdata->dev_data->regmap);
574 if (IS_ERR(drvdata->dac.virt_regmap)) {
575 dev_err(&pdev->dev, "audio registers not enabled\n");
576 return PTR_ERR(drvdata->dac.virt_regmap);
579 /* Request the syscon region */
580 drvdata->dac.regmap =
581 syscon_regmap_lookup_by_phandle(pnode, "st,syscfg");
582 if (IS_ERR(drvdata->dac.regmap)) {
583 dev_err(&pdev->dev, "syscon registers not available\n");
584 return PTR_ERR(drvdata->dac.regmap);
586 drvdata->spdif.regmap = drvdata->dac.regmap;
588 /* Set DAC dai probe */
589 if (drvdata->dev_data->chipid == CHIPID_STIH416)
590 sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].probe = stih416_dac_probe;
592 sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops;
595 sti_sas_driver.dapm_widgets = drvdata->dev_data->dapm_widgets;
596 sti_sas_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets;
598 sti_sas_driver.dapm_routes = drvdata->dev_data->dapm_routes;
599 sti_sas_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes;
602 dev_set_drvdata(&pdev->dev, drvdata);
604 return snd_soc_register_codec(&pdev->dev, &sti_sas_driver,
606 ARRAY_SIZE(sti_sas_dai));
609 static int sti_sas_driver_remove(struct platform_device *pdev)
611 snd_soc_unregister_codec(&pdev->dev);
616 static struct platform_driver sti_sas_platform_driver = {
618 .name = "sti-sas-codec",
619 .of_match_table = sti_sas_dev_match,
621 .probe = sti_sas_driver_probe,
622 .remove = sti_sas_driver_remove,
625 module_platform_driver(sti_sas_platform_driver);
627 MODULE_DESCRIPTION("audio codec for STMicroelectronics sti platforms");
628 MODULE_AUTHOR("Arnaud.pouliquen@st.com");
629 MODULE_LICENSE("GPL v2");