1 // SPDX-License-Identifier: GPL-2.0-only
3 // uda1334.c -- UDA1334 ALSA SoC Audio driver
5 // Based on WM8523 ALSA SoC Audio driver written by Mark Brown
7 #include <linux/module.h>
8 #include <linux/moduleparam.h>
9 #include <linux/init.h>
10 #include <linux/delay.h>
11 #include <linux/slab.h>
12 #include <linux/gpio/consumer.h>
13 #include <linux/of_device.h>
14 #include <sound/core.h>
15 #include <sound/pcm.h>
16 #include <sound/pcm_params.h>
17 #include <sound/soc.h>
18 #include <sound/initval.h>
20 #define UDA1334_NUM_RATES 6
22 /* codec private data */
24 struct gpio_desc
*mute
;
25 struct gpio_desc
*deemph
;
27 unsigned int rate_constraint_list
[UDA1334_NUM_RATES
];
28 struct snd_pcm_hw_constraint_list rate_constraint
;
31 static const struct snd_soc_dapm_widget uda1334_dapm_widgets
[] = {
32 SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM
, 0, 0),
33 SND_SOC_DAPM_OUTPUT("LINEVOUTL"),
34 SND_SOC_DAPM_OUTPUT("LINEVOUTR"),
37 static const struct snd_soc_dapm_route uda1334_dapm_routes
[] = {
38 { "LINEVOUTL", NULL
, "DAC" },
39 { "LINEVOUTR", NULL
, "DAC" },
42 static int uda1334_put_deemph(struct snd_kcontrol
*kcontrol
,
43 struct snd_ctl_elem_value
*ucontrol
)
45 struct snd_soc_component
*component
= snd_soc_kcontrol_component(kcontrol
);
46 struct uda1334_priv
*uda1334
= snd_soc_component_get_drvdata(component
);
47 int deemph
= ucontrol
->value
.integer
.value
[0];
52 gpiod_set_value_cansleep(uda1334
->deemph
, deemph
);
57 static int uda1334_get_deemph(struct snd_kcontrol
*kcontrol
,
58 struct snd_ctl_elem_value
*ucontrol
)
60 struct snd_soc_component
*component
= snd_soc_kcontrol_component(kcontrol
);
61 struct uda1334_priv
*uda1334
= snd_soc_component_get_drvdata(component
);
64 ret
= gpiod_get_value_cansleep(uda1334
->deemph
);
68 ucontrol
->value
.integer
.value
[0] = ret
;
73 static const struct snd_kcontrol_new uda1334_snd_controls
[] = {
74 SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0,
75 uda1334_get_deemph
, uda1334_put_deemph
),
81 } lrclk_ratios
[UDA1334_NUM_RATES
] = {
90 static int uda1334_startup(struct snd_pcm_substream
*substream
,
91 struct snd_soc_dai
*dai
)
93 struct snd_soc_component
*component
= dai
->component
;
94 struct uda1334_priv
*uda1334
= snd_soc_component_get_drvdata(component
);
97 * The set of sample rates that can be supported depends on the
98 * MCLK supplied to the CODEC - enforce this.
100 if (!uda1334
->sysclk
) {
101 dev_err(component
->dev
,
102 "No MCLK configured, call set_sysclk() on init\n");
106 snd_pcm_hw_constraint_list(substream
->runtime
, 0,
107 SNDRV_PCM_HW_PARAM_RATE
,
108 &uda1334
->rate_constraint
);
110 gpiod_set_value_cansleep(uda1334
->mute
, 1);
115 static void uda1334_shutdown(struct snd_pcm_substream
*substream
,
116 struct snd_soc_dai
*dai
)
118 struct snd_soc_component
*component
= dai
->component
;
119 struct uda1334_priv
*uda1334
= snd_soc_component_get_drvdata(component
);
121 gpiod_set_value_cansleep(uda1334
->mute
, 0);
124 static int uda1334_set_dai_sysclk(struct snd_soc_dai
*codec_dai
,
125 int clk_id
, unsigned int freq
, int dir
)
127 struct snd_soc_component
*component
= codec_dai
->component
;
128 struct uda1334_priv
*uda1334
= snd_soc_component_get_drvdata(component
);
132 uda1334
->sysclk
= freq
;
134 uda1334
->rate_constraint
.count
= 0;
135 for (i
= 0; i
< ARRAY_SIZE(lrclk_ratios
); i
++) {
136 val
= freq
/ lrclk_ratios
[i
].ratio
;
138 * Check that it's a standard rate since core can't
139 * cope with others and having the odd rates confuses
140 * constraint matching.
151 dev_dbg(component
->dev
, "Supported sample rate: %dHz\n",
153 uda1334
->rate_constraint_list
[j
++] = val
;
154 uda1334
->rate_constraint
.count
++;
157 dev_dbg(component
->dev
, "Skipping sample rate: %dHz\n",
162 /* Need at least one supported rate... */
163 if (uda1334
->rate_constraint
.count
== 0)
169 static int uda1334_set_fmt(struct snd_soc_dai
*codec_dai
, unsigned int fmt
)
171 fmt
&= (SND_SOC_DAIFMT_FORMAT_MASK
| SND_SOC_DAIFMT_INV_MASK
|
172 SND_SOC_DAIFMT_MASTER_MASK
);
174 if (fmt
!= (SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
|
175 SND_SOC_DAIFMT_CBS_CFS
)) {
176 dev_err(codec_dai
->dev
, "Invalid DAI format\n");
183 static int uda1334_mute_stream(struct snd_soc_dai
*dai
, int mute
, int stream
)
185 struct uda1334_priv
*uda1334
= snd_soc_component_get_drvdata(dai
->component
);
188 gpiod_set_value_cansleep(uda1334
->mute
, mute
);
193 #define UDA1334_RATES SNDRV_PCM_RATE_8000_96000
195 #define UDA1334_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
197 static const struct snd_soc_dai_ops uda1334_dai_ops
= {
198 .startup
= uda1334_startup
,
199 .shutdown
= uda1334_shutdown
,
200 .set_sysclk
= uda1334_set_dai_sysclk
,
201 .set_fmt
= uda1334_set_fmt
,
202 .mute_stream
= uda1334_mute_stream
,
205 static struct snd_soc_dai_driver uda1334_dai
= {
206 .name
= "uda1334-hifi",
208 .stream_name
= "Playback",
211 .rates
= UDA1334_RATES
,
212 .formats
= UDA1334_FORMATS
,
214 .ops
= &uda1334_dai_ops
,
217 static int uda1334_probe(struct snd_soc_component
*component
)
219 struct uda1334_priv
*uda1334
= snd_soc_component_get_drvdata(component
);
221 uda1334
->rate_constraint
.list
= &uda1334
->rate_constraint_list
[0];
222 uda1334
->rate_constraint
.count
=
223 ARRAY_SIZE(uda1334
->rate_constraint_list
);
228 static const struct snd_soc_component_driver soc_component_dev_uda1334
= {
229 .probe
= uda1334_probe
,
230 .controls
= uda1334_snd_controls
,
231 .num_controls
= ARRAY_SIZE(uda1334_snd_controls
),
232 .dapm_widgets
= uda1334_dapm_widgets
,
233 .num_dapm_widgets
= ARRAY_SIZE(uda1334_dapm_widgets
),
234 .dapm_routes
= uda1334_dapm_routes
,
235 .num_dapm_routes
= ARRAY_SIZE(uda1334_dapm_routes
),
237 .use_pmdown_time
= 1,
239 .non_legacy_dai_naming
= 1,
242 static const struct of_device_id uda1334_of_match
[] = {
243 { .compatible
= "nxp,uda1334" },
246 MODULE_DEVICE_TABLE(of
, uda1334_of_match
);
248 static int uda1334_codec_probe(struct platform_device
*pdev
)
250 struct uda1334_priv
*uda1334
;
253 uda1334
= devm_kzalloc(&pdev
->dev
, sizeof(struct uda1334_priv
),
258 platform_set_drvdata(pdev
, uda1334
);
260 uda1334
->mute
= devm_gpiod_get(&pdev
->dev
, "nxp,mute", GPIOD_OUT_LOW
);
261 if (IS_ERR(uda1334
->mute
)) {
262 ret
= PTR_ERR(uda1334
->mute
);
263 dev_err(&pdev
->dev
, "Failed to get mute line: %d\n", ret
);
267 uda1334
->deemph
= devm_gpiod_get(&pdev
->dev
, "nxp,deemph", GPIOD_OUT_LOW
);
268 if (IS_ERR(uda1334
->deemph
)) {
269 ret
= PTR_ERR(uda1334
->deemph
);
270 dev_err(&pdev
->dev
, "Failed to get deemph line: %d\n", ret
);
274 ret
= devm_snd_soc_register_component(&pdev
->dev
,
275 &soc_component_dev_uda1334
,
278 dev_err(&pdev
->dev
, "Failed to register component: %d\n", ret
);
283 static struct platform_driver uda1334_codec_driver
= {
284 .probe
= uda1334_codec_probe
,
286 .name
= "uda1334-codec",
287 .of_match_table
= uda1334_of_match
,
290 module_platform_driver(uda1334_codec_driver
);
292 MODULE_DESCRIPTION("ASoC UDA1334 driver");
293 MODULE_AUTHOR("Andra Danciu <andradanciu1997@gmail.com>");
294 MODULE_ALIAS("platform:uda1334-codec");
295 MODULE_LICENSE("GPL v2");