1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
3 // Copyright (c) 2018 BayLibre, SAS.
4 // Author: Jerome Brunet <jbrunet@baylibre.com>
7 #include <linux/module.h>
8 #include <linux/of_platform.h>
9 #include <linux/regmap.h>
10 #include <sound/soc.h>
11 #include <sound/soc-dai.h>
12 #include <sound/pcm_params.h>
13 #include <sound/pcm_iec958.h>
17 * The meaning of bits SPDIFOUT_CTRL0_XXX_SEL is actually the opposite
18 * of what the documentation says. Manual control on V, U and C bits is
19 * applied when the related sel bits are cleared
22 #define SPDIFOUT_STAT 0x00
23 #define SPDIFOUT_GAIN0 0x04
24 #define SPDIFOUT_GAIN1 0x08
25 #define SPDIFOUT_CTRL0 0x0c
26 #define SPDIFOUT_CTRL0_EN BIT(31)
27 #define SPDIFOUT_CTRL0_RST_OUT BIT(29)
28 #define SPDIFOUT_CTRL0_RST_IN BIT(28)
29 #define SPDIFOUT_CTRL0_USEL BIT(26)
30 #define SPDIFOUT_CTRL0_USET BIT(25)
31 #define SPDIFOUT_CTRL0_CHSTS_SEL BIT(24)
32 #define SPDIFOUT_CTRL0_DATA_SEL BIT(20)
33 #define SPDIFOUT_CTRL0_MSB_FIRST BIT(19)
34 #define SPDIFOUT_CTRL0_VSEL BIT(18)
35 #define SPDIFOUT_CTRL0_VSET BIT(17)
36 #define SPDIFOUT_CTRL0_MASK_MASK GENMASK(11, 4)
37 #define SPDIFOUT_CTRL0_MASK(x) ((x) << 4)
38 #define SPDIFOUT_CTRL1 0x10
39 #define SPDIFOUT_CTRL1_MSB_POS_MASK GENMASK(12, 8)
40 #define SPDIFOUT_CTRL1_MSB_POS(x) ((x) << 8)
41 #define SPDIFOUT_CTRL1_TYPE_MASK GENMASK(6, 4)
42 #define SPDIFOUT_CTRL1_TYPE(x) ((x) << 4)
43 #define SPDIFOUT_PREAMB 0x14
44 #define SPDIFOUT_SWAP 0x18
45 #define SPDIFOUT_CHSTS0 0x1c
46 #define SPDIFOUT_CHSTS1 0x20
47 #define SPDIFOUT_CHSTS2 0x24
48 #define SPDIFOUT_CHSTS3 0x28
49 #define SPDIFOUT_CHSTS4 0x2c
50 #define SPDIFOUT_CHSTS5 0x30
51 #define SPDIFOUT_CHSTS6 0x34
52 #define SPDIFOUT_CHSTS7 0x38
53 #define SPDIFOUT_CHSTS8 0x3c
54 #define SPDIFOUT_CHSTS9 0x40
55 #define SPDIFOUT_CHSTSA 0x44
56 #define SPDIFOUT_CHSTSB 0x48
57 #define SPDIFOUT_MUTE_VAL 0x4c
65 static void axg_spdifout_enable(struct regmap
*map
)
67 /* Apply both reset */
68 regmap_update_bits(map
, SPDIFOUT_CTRL0
,
69 SPDIFOUT_CTRL0_RST_OUT
| SPDIFOUT_CTRL0_RST_IN
,
72 /* Clear out reset before in reset */
73 regmap_update_bits(map
, SPDIFOUT_CTRL0
,
74 SPDIFOUT_CTRL0_RST_OUT
, SPDIFOUT_CTRL0_RST_OUT
);
75 regmap_update_bits(map
, SPDIFOUT_CTRL0
,
76 SPDIFOUT_CTRL0_RST_IN
, SPDIFOUT_CTRL0_RST_IN
);
79 regmap_update_bits(map
, SPDIFOUT_CTRL0
, SPDIFOUT_CTRL0_EN
,
83 static void axg_spdifout_disable(struct regmap
*map
)
85 regmap_update_bits(map
, SPDIFOUT_CTRL0
, SPDIFOUT_CTRL0_EN
, 0);
88 static int axg_spdifout_trigger(struct snd_pcm_substream
*substream
, int cmd
,
89 struct snd_soc_dai
*dai
)
91 struct axg_spdifout
*priv
= snd_soc_dai_get_drvdata(dai
);
94 case SNDRV_PCM_TRIGGER_START
:
95 case SNDRV_PCM_TRIGGER_RESUME
:
96 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
97 axg_spdifout_enable(priv
->map
);
100 case SNDRV_PCM_TRIGGER_STOP
:
101 case SNDRV_PCM_TRIGGER_SUSPEND
:
102 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
103 axg_spdifout_disable(priv
->map
);
111 static int axg_spdifout_mute(struct snd_soc_dai
*dai
, int mute
, int direction
)
113 struct axg_spdifout
*priv
= snd_soc_dai_get_drvdata(dai
);
115 /* Use spdif valid bit to perform digital mute */
116 regmap_update_bits(priv
->map
, SPDIFOUT_CTRL0
, SPDIFOUT_CTRL0_VSET
,
117 mute
? SPDIFOUT_CTRL0_VSET
: 0);
122 static int axg_spdifout_sample_fmt(struct snd_pcm_hw_params
*params
,
123 struct snd_soc_dai
*dai
)
125 struct axg_spdifout
*priv
= snd_soc_dai_get_drvdata(dai
);
128 /* Set the samples spdifout will pull from the FIFO */
129 switch (params_channels(params
)) {
131 val
= SPDIFOUT_CTRL0_MASK(0x1);
134 val
= SPDIFOUT_CTRL0_MASK(0x3);
137 dev_err(dai
->dev
, "too many channels for spdif dai: %u\n",
138 params_channels(params
));
142 regmap_update_bits(priv
->map
, SPDIFOUT_CTRL0
,
143 SPDIFOUT_CTRL0_MASK_MASK
, val
);
145 /* FIFO data are arranged in chunks of 64bits */
146 switch (params_physical_width(params
)) {
148 /* 8 samples of 8 bits */
149 val
= SPDIFOUT_CTRL1_TYPE(0);
152 /* 4 samples of 16 bits - right justified */
153 val
= SPDIFOUT_CTRL1_TYPE(2);
156 /* 2 samples of 32 bits - right justified */
157 val
= SPDIFOUT_CTRL1_TYPE(4);
160 dev_err(dai
->dev
, "Unsupported physical width: %u\n",
161 params_physical_width(params
));
165 /* Position of the MSB in FIFO samples */
166 val
|= SPDIFOUT_CTRL1_MSB_POS(params_width(params
) - 1);
168 regmap_update_bits(priv
->map
, SPDIFOUT_CTRL1
,
169 SPDIFOUT_CTRL1_MSB_POS_MASK
|
170 SPDIFOUT_CTRL1_TYPE_MASK
, val
);
172 regmap_update_bits(priv
->map
, SPDIFOUT_CTRL0
,
173 SPDIFOUT_CTRL0_MSB_FIRST
| SPDIFOUT_CTRL0_DATA_SEL
,
179 static int axg_spdifout_set_chsts(struct snd_pcm_hw_params
*params
,
180 struct snd_soc_dai
*dai
)
182 struct axg_spdifout
*priv
= snd_soc_dai_get_drvdata(dai
);
188 ret
= snd_pcm_create_iec958_consumer_hw_params(params
, cs
, 4);
190 dev_err(dai
->dev
, "Creating IEC958 channel status failed %d\n",
194 val
= cs
[0] | cs
[1] << 8 | cs
[2] << 16 | cs
[3] << 24;
196 /* Setup channel status A bits [31 - 0]*/
197 regmap_write(priv
->map
, SPDIFOUT_CHSTS0
, val
);
199 /* Clear channel status A bits [191 - 32] */
200 for (offset
= SPDIFOUT_CHSTS1
; offset
<= SPDIFOUT_CHSTS5
;
201 offset
+= regmap_get_reg_stride(priv
->map
))
202 regmap_write(priv
->map
, offset
, 0);
204 /* Setup channel status B bits [31 - 0]*/
205 regmap_write(priv
->map
, SPDIFOUT_CHSTS6
, val
);
207 /* Clear channel status B bits [191 - 32] */
208 for (offset
= SPDIFOUT_CHSTS7
; offset
<= SPDIFOUT_CHSTSB
;
209 offset
+= regmap_get_reg_stride(priv
->map
))
210 regmap_write(priv
->map
, offset
, 0);
215 static int axg_spdifout_hw_params(struct snd_pcm_substream
*substream
,
216 struct snd_pcm_hw_params
*params
,
217 struct snd_soc_dai
*dai
)
219 struct axg_spdifout
*priv
= snd_soc_dai_get_drvdata(dai
);
220 unsigned int rate
= params_rate(params
);
223 /* 2 * 32bits per subframe * 2 channels = 128 */
224 ret
= clk_set_rate(priv
->mclk
, rate
* 128);
226 dev_err(dai
->dev
, "failed to set spdif clock\n");
230 ret
= axg_spdifout_sample_fmt(params
, dai
);
232 dev_err(dai
->dev
, "failed to setup sample format\n");
236 ret
= axg_spdifout_set_chsts(params
, dai
);
238 dev_err(dai
->dev
, "failed to setup channel status words\n");
245 static int axg_spdifout_startup(struct snd_pcm_substream
*substream
,
246 struct snd_soc_dai
*dai
)
248 struct axg_spdifout
*priv
= snd_soc_dai_get_drvdata(dai
);
251 /* Clock the spdif output block */
252 ret
= clk_prepare_enable(priv
->pclk
);
254 dev_err(dai
->dev
, "failed to enable pclk\n");
258 /* Make sure the block is initially stopped */
259 axg_spdifout_disable(priv
->map
);
261 /* Insert data from bit 27 lsb first */
262 regmap_update_bits(priv
->map
, SPDIFOUT_CTRL0
,
263 SPDIFOUT_CTRL0_MSB_FIRST
| SPDIFOUT_CTRL0_DATA_SEL
,
266 /* Manual control of V, C and U, U = 0 */
267 regmap_update_bits(priv
->map
, SPDIFOUT_CTRL0
,
268 SPDIFOUT_CTRL0_CHSTS_SEL
| SPDIFOUT_CTRL0_VSEL
|
269 SPDIFOUT_CTRL0_USEL
| SPDIFOUT_CTRL0_USET
,
272 /* Static SWAP configuration ATM */
273 regmap_write(priv
->map
, SPDIFOUT_SWAP
, 0x10);
278 static void axg_spdifout_shutdown(struct snd_pcm_substream
*substream
,
279 struct snd_soc_dai
*dai
)
281 struct axg_spdifout
*priv
= snd_soc_dai_get_drvdata(dai
);
283 clk_disable_unprepare(priv
->pclk
);
286 static const struct snd_soc_dai_ops axg_spdifout_ops
= {
287 .trigger
= axg_spdifout_trigger
,
288 .mute_stream
= axg_spdifout_mute
,
289 .hw_params
= axg_spdifout_hw_params
,
290 .startup
= axg_spdifout_startup
,
291 .shutdown
= axg_spdifout_shutdown
,
292 .no_capture_mute
= 1,
295 static struct snd_soc_dai_driver axg_spdifout_dai_drv
[] = {
297 .name
= "SPDIF Output",
299 .stream_name
= "Playback",
302 .rates
= (SNDRV_PCM_RATE_32000
|
303 SNDRV_PCM_RATE_44100
|
304 SNDRV_PCM_RATE_48000
|
305 SNDRV_PCM_RATE_88200
|
306 SNDRV_PCM_RATE_96000
|
307 SNDRV_PCM_RATE_176400
|
308 SNDRV_PCM_RATE_192000
),
309 .formats
= (SNDRV_PCM_FMTBIT_S8
|
310 SNDRV_PCM_FMTBIT_S16_LE
|
311 SNDRV_PCM_FMTBIT_S20_LE
|
312 SNDRV_PCM_FMTBIT_S24_LE
),
314 .ops
= &axg_spdifout_ops
,
318 static const char * const spdifout_sel_texts
[] = {
319 "IN 0", "IN 1", "IN 2",
322 static SOC_ENUM_SINGLE_DECL(axg_spdifout_sel_enum
, SPDIFOUT_CTRL1
, 24,
325 static const struct snd_kcontrol_new axg_spdifout_in_mux
=
326 SOC_DAPM_ENUM("Input Source", axg_spdifout_sel_enum
);
328 static const struct snd_soc_dapm_widget axg_spdifout_dapm_widgets
[] = {
329 SND_SOC_DAPM_AIF_IN("IN 0", NULL
, 0, SND_SOC_NOPM
, 0, 0),
330 SND_SOC_DAPM_AIF_IN("IN 1", NULL
, 0, SND_SOC_NOPM
, 0, 0),
331 SND_SOC_DAPM_AIF_IN("IN 2", NULL
, 0, SND_SOC_NOPM
, 0, 0),
332 SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM
, 0, 0, &axg_spdifout_in_mux
),
335 static const struct snd_soc_dapm_route axg_spdifout_dapm_routes
[] = {
336 { "SRC SEL", "IN 0", "IN 0" },
337 { "SRC SEL", "IN 1", "IN 1" },
338 { "SRC SEL", "IN 2", "IN 2" },
339 { "Playback", NULL
, "SRC SEL" },
342 static const struct snd_kcontrol_new axg_spdifout_controls
[] = {
343 SOC_DOUBLE("Playback Volume", SPDIFOUT_GAIN0
, 0, 8, 255, 0),
344 SOC_DOUBLE("Playback Switch", SPDIFOUT_CTRL0
, 22, 21, 1, 1),
345 SOC_SINGLE("Playback Gain Enable Switch",
346 SPDIFOUT_CTRL1
, 26, 1, 0),
347 SOC_SINGLE("Playback Channels Mix Switch",
348 SPDIFOUT_CTRL0
, 23, 1, 0),
351 static int axg_spdifout_set_bias_level(struct snd_soc_component
*component
,
352 enum snd_soc_bias_level level
)
354 struct axg_spdifout
*priv
= snd_soc_component_get_drvdata(component
);
355 enum snd_soc_bias_level now
=
356 snd_soc_component_get_bias_level(component
);
360 case SND_SOC_BIAS_PREPARE
:
361 if (now
== SND_SOC_BIAS_STANDBY
)
362 ret
= clk_prepare_enable(priv
->mclk
);
365 case SND_SOC_BIAS_STANDBY
:
366 if (now
== SND_SOC_BIAS_PREPARE
)
367 clk_disable_unprepare(priv
->mclk
);
370 case SND_SOC_BIAS_OFF
:
371 case SND_SOC_BIAS_ON
:
378 static const struct snd_soc_component_driver axg_spdifout_component_drv
= {
379 .controls
= axg_spdifout_controls
,
380 .num_controls
= ARRAY_SIZE(axg_spdifout_controls
),
381 .dapm_widgets
= axg_spdifout_dapm_widgets
,
382 .num_dapm_widgets
= ARRAY_SIZE(axg_spdifout_dapm_widgets
),
383 .dapm_routes
= axg_spdifout_dapm_routes
,
384 .num_dapm_routes
= ARRAY_SIZE(axg_spdifout_dapm_routes
),
385 .set_bias_level
= axg_spdifout_set_bias_level
,
386 .legacy_dai_naming
= 1,
389 static const struct regmap_config axg_spdifout_regmap_cfg
= {
393 .max_register
= SPDIFOUT_MUTE_VAL
,
396 static const struct of_device_id axg_spdifout_of_match
[] = {
397 { .compatible
= "amlogic,axg-spdifout", },
400 MODULE_DEVICE_TABLE(of
, axg_spdifout_of_match
);
402 static int axg_spdifout_probe(struct platform_device
*pdev
)
404 struct device
*dev
= &pdev
->dev
;
405 struct axg_spdifout
*priv
;
408 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
411 platform_set_drvdata(pdev
, priv
);
413 regs
= devm_platform_ioremap_resource(pdev
, 0);
415 return PTR_ERR(regs
);
417 priv
->map
= devm_regmap_init_mmio(dev
, regs
, &axg_spdifout_regmap_cfg
);
418 if (IS_ERR(priv
->map
)) {
419 dev_err(dev
, "failed to init regmap: %ld\n",
421 return PTR_ERR(priv
->map
);
424 priv
->pclk
= devm_clk_get(dev
, "pclk");
425 if (IS_ERR(priv
->pclk
))
426 return dev_err_probe(dev
, PTR_ERR(priv
->pclk
), "failed to get pclk\n");
428 priv
->mclk
= devm_clk_get(dev
, "mclk");
429 if (IS_ERR(priv
->mclk
))
430 return dev_err_probe(dev
, PTR_ERR(priv
->mclk
), "failed to get mclk\n");
432 return devm_snd_soc_register_component(dev
, &axg_spdifout_component_drv
,
433 axg_spdifout_dai_drv
, ARRAY_SIZE(axg_spdifout_dai_drv
));
436 static struct platform_driver axg_spdifout_pdrv
= {
437 .probe
= axg_spdifout_probe
,
439 .name
= "axg-spdifout",
440 .of_match_table
= axg_spdifout_of_match
,
443 module_platform_driver(axg_spdifout_pdrv
);
445 MODULE_DESCRIPTION("Amlogic AXG SPDIF Output driver");
446 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
447 MODULE_LICENSE("GPL v2");