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
,
546 static int sti_sas_driver_probe(struct platform_device
*pdev
)
548 struct device_node
*pnode
= pdev
->dev
.of_node
;
549 struct sti_sas_data
*drvdata
;
550 const struct of_device_id
*of_id
;
552 /* Allocate device structure */
553 drvdata
= devm_kzalloc(&pdev
->dev
, sizeof(struct sti_sas_data
),
558 /* Populate data structure depending on compatibility */
559 of_id
= of_match_node(sti_sas_dev_match
, pnode
);
561 dev_err(&pdev
->dev
, "data associated to device is missing");
565 drvdata
->dev_data
= (struct sti_sas_dev_data
*)of_id
->data
;
567 /* Initialise device structure */
568 drvdata
->dev
= &pdev
->dev
;
570 /* Request the DAC & SPDIF registers memory region */
571 drvdata
->dac
.virt_regmap
= devm_regmap_init(&pdev
->dev
, NULL
, drvdata
,
572 drvdata
->dev_data
->regmap
);
573 if (IS_ERR(drvdata
->dac
.virt_regmap
)) {
574 dev_err(&pdev
->dev
, "audio registers not enabled\n");
575 return PTR_ERR(drvdata
->dac
.virt_regmap
);
578 /* Request the syscon region */
579 drvdata
->dac
.regmap
=
580 syscon_regmap_lookup_by_phandle(pnode
, "st,syscfg");
581 if (IS_ERR(drvdata
->dac
.regmap
)) {
582 dev_err(&pdev
->dev
, "syscon registers not available\n");
583 return PTR_ERR(drvdata
->dac
.regmap
);
585 drvdata
->spdif
.regmap
= drvdata
->dac
.regmap
;
587 /* Set DAC dai probe */
588 if (drvdata
->dev_data
->chipid
== CHIPID_STIH416
)
589 sti_sas_dai
[STI_SAS_DAI_ANALOG_OUT
].probe
= stih416_dac_probe
;
591 sti_sas_dai
[STI_SAS_DAI_ANALOG_OUT
].ops
= drvdata
->dev_data
->dac_ops
;
594 sti_sas_driver
.dapm_widgets
= drvdata
->dev_data
->dapm_widgets
;
595 sti_sas_driver
.num_dapm_widgets
= drvdata
->dev_data
->num_dapm_widgets
;
597 sti_sas_driver
.dapm_routes
= drvdata
->dev_data
->dapm_routes
;
598 sti_sas_driver
.num_dapm_routes
= drvdata
->dev_data
->num_dapm_routes
;
601 dev_set_drvdata(&pdev
->dev
, drvdata
);
603 return snd_soc_register_codec(&pdev
->dev
, &sti_sas_driver
,
605 ARRAY_SIZE(sti_sas_dai
));
608 static int sti_sas_driver_remove(struct platform_device
*pdev
)
610 snd_soc_unregister_codec(&pdev
->dev
);
615 static struct platform_driver sti_sas_platform_driver
= {
617 .name
= "sti-sas-codec",
618 .of_match_table
= sti_sas_dev_match
,
620 .probe
= sti_sas_driver_probe
,
621 .remove
= sti_sas_driver_remove
,
624 module_platform_driver(sti_sas_platform_driver
);
626 MODULE_DESCRIPTION("audio codec for STMicroelectronics sti platforms");
627 MODULE_AUTHOR("Arnaud.pouliquen@st.com");
628 MODULE_LICENSE("GPL v2");