1 // SPDX-License-Identifier: GPL-2.0-only
3 // uda1342.c -- UDA1342 ALSA SoC Codec driver
4 // Based on the WM87xx drivers by Liam Girdwood and Richard Purdie
6 // Copyright 2007 Dension Audio Systems Ltd.
7 // Copyright 2024 Loongson Technology Co.,Ltd.
9 // Modifications by Christian Pellegrin <chripell@evolware.org>
10 // Further cleanup and restructuring by:
11 // Binbin Zhou <zhoubinbin@loongson.cn>
13 #include <linux/module.h>
14 #include <linux/i2c.h>
15 #include <sound/core.h>
16 #include <sound/pcm.h>
17 #include <sound/pcm_params.h>
18 #include <linux/pm_runtime.h>
19 #include <sound/soc.h>
20 #include <sound/tlv.h>
24 #define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
25 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
31 struct snd_pcm_substream
*provider_substream
;
32 struct snd_pcm_substream
*consumer_substream
;
34 struct regmap
*regmap
;
35 struct i2c_client
*i2c
;
38 static const struct reg_default uda1342_reg_defaults
[] = {
48 static int uda1342_mute(struct snd_soc_dai
*dai
, int mute
, int direction
)
50 struct snd_soc_component
*component
= dai
->component
;
51 struct uda1342_priv
*uda1342
= snd_soc_component_get_drvdata(component
);
60 return regmap_update_bits(uda1342
->regmap
, 0x10, mask
, val
);
63 static int uda1342_startup(struct snd_pcm_substream
*substream
,
64 struct snd_soc_dai
*dai
)
66 struct snd_soc_component
*component
= dai
->component
;
67 struct uda1342_priv
*uda1342
= snd_soc_component_get_drvdata(component
);
68 struct snd_pcm_runtime
*provider_runtime
;
70 if (uda1342
->provider_substream
) {
71 provider_runtime
= uda1342
->provider_substream
->runtime
;
73 snd_pcm_hw_constraint_single(substream
->runtime
,
74 SNDRV_PCM_HW_PARAM_RATE
, provider_runtime
->rate
);
75 snd_pcm_hw_constraint_single(substream
->runtime
,
76 SNDRV_PCM_HW_PARAM_SAMPLE_BITS
,
77 provider_runtime
->sample_bits
);
79 uda1342
->consumer_substream
= substream
;
81 uda1342
->provider_substream
= substream
;
87 static void uda1342_shutdown(struct snd_pcm_substream
*substream
,
88 struct snd_soc_dai
*dai
)
90 struct snd_soc_component
*component
= dai
->component
;
91 struct uda1342_priv
*uda1342
= snd_soc_component_get_drvdata(component
);
93 if (uda1342
->provider_substream
== substream
)
94 uda1342
->provider_substream
= uda1342
->consumer_substream
;
96 uda1342
->consumer_substream
= NULL
;
99 static int uda1342_hw_params(struct snd_pcm_substream
*substream
,
100 struct snd_pcm_hw_params
*params
, struct snd_soc_dai
*dai
)
102 struct snd_soc_component
*component
= dai
->component
;
103 struct uda1342_priv
*uda1342
= snd_soc_component_get_drvdata(component
);
104 struct device
*dev
= &uda1342
->i2c
->dev
;
105 unsigned int hw_params
= 0;
107 if (substream
== uda1342
->consumer_substream
)
110 /* set SYSCLK / fs ratio */
111 switch (uda1342
->sysclk
/ params_rate(params
)) {
121 dev_err(dev
, "unsupported frequency\n");
125 /* set DAI format and word length */
126 switch (uda1342
->dai_fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
127 case SND_SOC_DAIFMT_I2S
:
129 case SND_SOC_DAIFMT_RIGHT_J
:
130 switch (params_width(params
)) {
138 hw_params
|= BIT(2) | BIT(1);
141 dev_err(dev
, "unsupported format (right)\n");
145 case SND_SOC_DAIFMT_LEFT_J
:
149 dev_err(dev
, "unsupported format\n");
153 return regmap_update_bits(uda1342
->regmap
, 0x0,
154 STATUS0_DAIFMT_MASK
| STATUS0_SYSCLK_MASK
, hw_params
);
157 static int uda1342_set_dai_sysclk(struct snd_soc_dai
*codec_dai
,
158 int clk_id
, unsigned int freq
, int dir
)
160 struct snd_soc_component
*component
= codec_dai
->component
;
161 struct uda1342_priv
*uda1342
= snd_soc_component_get_drvdata(component
);
162 struct device
*dev
= &uda1342
->i2c
->dev
;
165 * Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
166 * because the codec is slave. Of course limitations of the clock
167 * master (the IIS controller) apply.
168 * We'll error out on set_hw_params if it's not OK
170 if ((freq
>= (256 * 8000)) && (freq
<= (512 * 48000))) {
171 uda1342
->sysclk
= freq
;
175 dev_err(dev
, "unsupported sysclk\n");
180 static int uda1342_set_dai_fmt(struct snd_soc_dai
*codec_dai
, unsigned int fmt
)
182 struct snd_soc_component
*component
= codec_dai
->component
;
183 struct uda1342_priv
*uda1342
= snd_soc_component_get_drvdata(component
);
185 /* codec supports only full consumer mode */
186 if ((fmt
& SND_SOC_DAIFMT_MASTER_MASK
) != SND_SOC_DAIFMT_BC_FC
) {
187 dev_err(&uda1342
->i2c
->dev
, "unsupported consumer mode.\n");
191 /* We can't setup DAI format here as it depends on the word bit num */
192 /* so let's just store the value for later */
193 uda1342
->dai_fmt
= fmt
;
198 static const struct snd_kcontrol_new uda1342_snd_controls
[] = {
199 SOC_SINGLE("Master Playback Volume", 0x11, 0, 0x3F, 1),
200 SOC_SINGLE("Analog1 Volume", 0x12, 0, 0x1F, 1),
203 /* Common DAPM widgets */
204 static const struct snd_soc_dapm_widget uda1342_dapm_widgets
[] = {
205 SND_SOC_DAPM_INPUT("VINL1"),
206 SND_SOC_DAPM_INPUT("VINR1"),
207 SND_SOC_DAPM_INPUT("VINL2"),
208 SND_SOC_DAPM_INPUT("VINR2"),
210 SND_SOC_DAPM_DAC("DAC", "Playback", 0, 1, 0),
211 SND_SOC_DAPM_ADC("ADC", "Capture", 0, 9, 0),
213 SND_SOC_DAPM_OUTPUT("VOUTL"),
214 SND_SOC_DAPM_OUTPUT("VOUTR"),
217 static const struct snd_soc_dapm_route uda1342_dapm_routes
[] = {
218 { "ADC", NULL
, "VINL1" },
219 { "ADC", NULL
, "VINR1" },
220 { "ADC", NULL
, "VINL2" },
221 { "ADC", NULL
, "VINR2" },
222 { "VOUTL", NULL
, "DAC" },
223 { "VOUTR", NULL
, "DAC" },
226 static const struct snd_soc_dai_ops uda1342_dai_ops
= {
227 .startup
= uda1342_startup
,
228 .shutdown
= uda1342_shutdown
,
229 .hw_params
= uda1342_hw_params
,
230 .mute_stream
= uda1342_mute
,
231 .set_sysclk
= uda1342_set_dai_sysclk
,
232 .set_fmt
= uda1342_set_dai_fmt
,
235 static struct snd_soc_dai_driver uda1342_dai
= {
236 .name
= "uda1342-hifi",
237 /* playback capabilities */
239 .stream_name
= "Playback",
242 .rates
= SNDRV_PCM_RATE_8000_48000
,
243 .formats
= UDA134X_FORMATS
,
245 /* capture capabilities */
247 .stream_name
= "Capture",
250 .rates
= SNDRV_PCM_RATE_8000_48000
,
251 .formats
= UDA134X_FORMATS
,
254 .ops
= &uda1342_dai_ops
,
257 static const struct snd_soc_component_driver soc_component_dev_uda1342
= {
258 .controls
= uda1342_snd_controls
,
259 .num_controls
= ARRAY_SIZE(uda1342_snd_controls
),
260 .dapm_widgets
= uda1342_dapm_widgets
,
261 .num_dapm_widgets
= ARRAY_SIZE(uda1342_dapm_widgets
),
262 .dapm_routes
= uda1342_dapm_routes
,
263 .num_dapm_routes
= ARRAY_SIZE(uda1342_dapm_routes
),
264 .suspend_bias_off
= 1,
266 .use_pmdown_time
= 1,
270 static const struct regmap_config uda1342_regmap
= {
273 .max_register
= 0x21,
274 .reg_defaults
= uda1342_reg_defaults
,
275 .num_reg_defaults
= ARRAY_SIZE(uda1342_reg_defaults
),
276 .cache_type
= REGCACHE_MAPLE
,
279 static int uda1342_i2c_probe(struct i2c_client
*i2c
)
281 struct uda1342_priv
*uda1342
;
283 uda1342
= devm_kzalloc(&i2c
->dev
, sizeof(*uda1342
), GFP_KERNEL
);
287 uda1342
->regmap
= devm_regmap_init_i2c(i2c
, &uda1342_regmap
);
288 if (IS_ERR(uda1342
->regmap
))
289 return PTR_ERR(uda1342
->regmap
);
291 i2c_set_clientdata(i2c
, uda1342
);
294 return devm_snd_soc_register_component(&i2c
->dev
,
295 &soc_component_dev_uda1342
,
299 static int uda1342_suspend(struct device
*dev
)
301 struct uda1342_priv
*uda1342
= dev_get_drvdata(dev
);
303 regcache_cache_only(uda1342
->regmap
, true);
308 static int uda1342_resume(struct device
*dev
)
310 struct uda1342_priv
*uda1342
= dev_get_drvdata(dev
);
312 regcache_mark_dirty(uda1342
->regmap
);
313 regcache_sync(uda1342
->regmap
);
318 static DEFINE_RUNTIME_DEV_PM_OPS(uda1342_pm_ops
,
319 uda1342_suspend
, uda1342_resume
, NULL
);
321 static const struct i2c_device_id uda1342_i2c_id
[] = {
325 MODULE_DEVICE_TABLE(i2c
, uda1342_i2c_id
);
327 static const struct of_device_id uda1342_of_match
[] = {
328 { .compatible
= "nxp,uda1342" },
331 MODULE_DEVICE_TABLE(of
, uda1342_of_match
);
333 static struct i2c_driver uda1342_i2c_driver
= {
336 .of_match_table
= uda1342_of_match
,
337 .pm
= pm_sleep_ptr(&uda1342_pm_ops
),
339 .probe
= uda1342_i2c_probe
,
340 .id_table
= uda1342_i2c_id
,
342 module_i2c_driver(uda1342_i2c_driver
);
344 MODULE_DESCRIPTION("UDA1342 ALSA soc codec driver");
345 MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
346 MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>");
347 MODULE_LICENSE("GPL");