1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2014 Marvell
5 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
8 #include <linux/module.h>
9 #include <linux/moduleparam.h>
10 #include <linux/interrupt.h>
11 #include <linux/platform_device.h>
12 #include <linux/slab.h>
13 #include <sound/soc.h>
15 #include <linux/platform_data/asoc-kirkwood.h>
16 #include "../codecs/cs42l51.h"
18 static int a370db_hw_params(struct snd_pcm_substream
*substream
,
19 struct snd_pcm_hw_params
*params
)
21 struct snd_soc_pcm_runtime
*rtd
= asoc_substream_to_rtd(substream
);
22 struct snd_soc_dai
*codec_dai
= asoc_rtd_to_codec(rtd
, 0);
25 switch (params_rate(params
)) {
38 return snd_soc_dai_set_sysclk(codec_dai
, 0, freq
, SND_SOC_CLOCK_IN
);
41 static const struct snd_soc_ops a370db_ops
= {
42 .hw_params
= a370db_hw_params
,
45 static const struct snd_soc_dapm_widget a370db_dapm_widgets
[] = {
46 SND_SOC_DAPM_HP("Out Jack", NULL
),
47 SND_SOC_DAPM_LINE("In Jack", NULL
),
50 static const struct snd_soc_dapm_route a370db_route
[] = {
51 { "Out Jack", NULL
, "HPL" },
52 { "Out Jack", NULL
, "HPR" },
53 { "AIN1L", NULL
, "In Jack" },
54 { "AIN1L", NULL
, "In Jack" },
57 SND_SOC_DAILINK_DEFS(analog
,
58 DAILINK_COMP_ARRAY(COMP_CPU("i2s")),
59 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "cs42l51-hifi")),
60 DAILINK_COMP_ARRAY(COMP_EMPTY()));
62 SND_SOC_DAILINK_DEFS(spdif_out
,
63 DAILINK_COMP_ARRAY(COMP_CPU("spdif")),
64 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "dit-hifi")),
65 DAILINK_COMP_ARRAY(COMP_EMPTY()));
67 SND_SOC_DAILINK_DEFS(spdif_in
,
68 DAILINK_COMP_ARRAY(COMP_CPU("spdif")),
69 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "dir-hifi")),
70 DAILINK_COMP_ARRAY(COMP_EMPTY()));
72 static struct snd_soc_dai_link a370db_dai
[] = {
75 .stream_name
= "analog",
76 .dai_fmt
= SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_CBS_CFS
,
78 SND_SOC_DAILINK_REG(analog
),
82 .stream_name
= "spdif-out",
83 .dai_fmt
= SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_CBS_CFS
,
84 SND_SOC_DAILINK_REG(spdif_out
),
88 .stream_name
= "spdif-in",
89 .dai_fmt
= SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_CBS_CFS
,
90 SND_SOC_DAILINK_REG(spdif_in
),
94 static struct snd_soc_card a370db
= {
97 .dai_link
= a370db_dai
,
98 .num_links
= ARRAY_SIZE(a370db_dai
),
99 .dapm_widgets
= a370db_dapm_widgets
,
100 .num_dapm_widgets
= ARRAY_SIZE(a370db_dapm_widgets
),
101 .dapm_routes
= a370db_route
,
102 .num_dapm_routes
= ARRAY_SIZE(a370db_route
),
105 static int a370db_probe(struct platform_device
*pdev
)
107 struct snd_soc_card
*card
= &a370db
;
109 card
->dev
= &pdev
->dev
;
111 a370db_dai
[0].cpus
->of_node
=
112 of_parse_phandle(pdev
->dev
.of_node
,
113 "marvell,audio-controller", 0);
114 a370db_dai
[0].platforms
->of_node
= a370db_dai
[0].cpus
->of_node
;
116 a370db_dai
[0].codecs
->of_node
=
117 of_parse_phandle(pdev
->dev
.of_node
,
118 "marvell,audio-codec", 0);
120 a370db_dai
[1].cpus
->of_node
= a370db_dai
[0].cpus
->of_node
;
121 a370db_dai
[1].platforms
->of_node
= a370db_dai
[0].cpus
->of_node
;
123 a370db_dai
[1].codecs
->of_node
=
124 of_parse_phandle(pdev
->dev
.of_node
,
125 "marvell,audio-codec", 1);
127 a370db_dai
[2].cpus
->of_node
= a370db_dai
[0].cpus
->of_node
;
128 a370db_dai
[2].platforms
->of_node
= a370db_dai
[0].cpus
->of_node
;
130 a370db_dai
[2].codecs
->of_node
=
131 of_parse_phandle(pdev
->dev
.of_node
,
132 "marvell,audio-codec", 2);
134 return devm_snd_soc_register_card(card
->dev
, card
);
137 static const struct of_device_id a370db_dt_ids
[] __maybe_unused
= {
138 { .compatible
= "marvell,a370db-audio" },
141 MODULE_DEVICE_TABLE(of
, a370db_dt_ids
);
143 static struct platform_driver a370db_driver
= {
145 .name
= "a370db-audio",
146 .of_match_table
= of_match_ptr(a370db_dt_ids
),
148 .probe
= a370db_probe
,
151 module_platform_driver(a370db_driver
);
153 MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
154 MODULE_DESCRIPTION("ALSA SoC a370db audio client");
155 MODULE_LICENSE("GPL");
156 MODULE_ALIAS("platform:a370db-audio");