Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/codecs/ad1836.c
26439 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Audio Codec driver supporting:
4
* AD1835A, AD1836, AD1837A, AD1838A, AD1839A
5
*
6
* Copyright 2009-2011 Analog Devices Inc.
7
*/
8
9
#include <linux/init.h>
10
#include <linux/slab.h>
11
#include <linux/module.h>
12
#include <linux/kernel.h>
13
#include <linux/device.h>
14
#include <sound/core.h>
15
#include <sound/pcm.h>
16
#include <sound/pcm_params.h>
17
#include <sound/initval.h>
18
#include <sound/soc.h>
19
#include <sound/tlv.h>
20
#include <linux/spi/spi.h>
21
#include <linux/regmap.h>
22
23
#include "ad1836.h"
24
25
enum ad1836_type {
26
AD1835,
27
AD1836,
28
AD1838,
29
};
30
31
/* codec private data */
32
struct ad1836_priv {
33
enum ad1836_type type;
34
struct regmap *regmap;
35
};
36
37
/*
38
* AD1836 volume/mute/de-emphasis etc. controls
39
*/
40
static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"};
41
42
static SOC_ENUM_SINGLE_DECL(ad1836_deemp_enum,
43
AD1836_DAC_CTRL1, 8, ad1836_deemp);
44
45
#define AD1836_DAC_VOLUME(x) \
46
SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \
47
AD1836_DAC_R_VOL(x), 0, 0x3FF, 0)
48
49
#define AD1836_DAC_SWITCH(x) \
50
SOC_DOUBLE("DAC" #x " Playback Switch", AD1836_DAC_CTRL2, \
51
AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)
52
53
#define AD1836_ADC_SWITCH(x) \
54
SOC_DOUBLE("ADC" #x " Capture Switch", AD1836_ADC_CTRL2, \
55
AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)
56
57
static const struct snd_kcontrol_new ad183x_dac_controls[] = {
58
AD1836_DAC_VOLUME(1),
59
AD1836_DAC_SWITCH(1),
60
AD1836_DAC_VOLUME(2),
61
AD1836_DAC_SWITCH(2),
62
AD1836_DAC_VOLUME(3),
63
AD1836_DAC_SWITCH(3),
64
AD1836_DAC_VOLUME(4),
65
AD1836_DAC_SWITCH(4),
66
};
67
68
static const struct snd_soc_dapm_widget ad183x_dac_dapm_widgets[] = {
69
SND_SOC_DAPM_OUTPUT("DAC1OUT"),
70
SND_SOC_DAPM_OUTPUT("DAC2OUT"),
71
SND_SOC_DAPM_OUTPUT("DAC3OUT"),
72
SND_SOC_DAPM_OUTPUT("DAC4OUT"),
73
};
74
75
static const struct snd_soc_dapm_route ad183x_dac_routes[] = {
76
{ "DAC1OUT", NULL, "DAC" },
77
{ "DAC2OUT", NULL, "DAC" },
78
{ "DAC3OUT", NULL, "DAC" },
79
{ "DAC4OUT", NULL, "DAC" },
80
};
81
82
static const struct snd_kcontrol_new ad183x_adc_controls[] = {
83
AD1836_ADC_SWITCH(1),
84
AD1836_ADC_SWITCH(2),
85
AD1836_ADC_SWITCH(3),
86
};
87
88
static const struct snd_soc_dapm_widget ad183x_adc_dapm_widgets[] = {
89
SND_SOC_DAPM_INPUT("ADC1IN"),
90
SND_SOC_DAPM_INPUT("ADC2IN"),
91
};
92
93
static const struct snd_soc_dapm_route ad183x_adc_routes[] = {
94
{ "ADC", NULL, "ADC1IN" },
95
{ "ADC", NULL, "ADC2IN" },
96
};
97
98
static const struct snd_kcontrol_new ad183x_controls[] = {
99
/* ADC high-pass filter */
100
SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1,
101
AD1836_ADC_HIGHPASS_FILTER, 1, 0),
102
103
/* DAC de-emphasis */
104
SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum),
105
};
106
107
static const struct snd_soc_dapm_widget ad183x_dapm_widgets[] = {
108
SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1,
109
AD1836_DAC_POWERDOWN, 1),
110
SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
111
SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1,
112
AD1836_ADC_POWERDOWN, 1, NULL, 0),
113
};
114
115
static const struct snd_soc_dapm_route ad183x_dapm_routes[] = {
116
{ "DAC", NULL, "ADC_PWR" },
117
{ "ADC", NULL, "ADC_PWR" },
118
};
119
120
static const DECLARE_TLV_DB_SCALE(ad1836_in_tlv, 0, 300, 0);
121
122
static const struct snd_kcontrol_new ad1836_controls[] = {
123
SOC_DOUBLE_TLV("ADC2 Capture Volume", AD1836_ADC_CTRL1, 3, 0, 4, 0,
124
ad1836_in_tlv),
125
};
126
127
/*
128
* DAI ops entries
129
*/
130
131
static int ad1836_set_dai_fmt(struct snd_soc_dai *codec_dai,
132
unsigned int fmt)
133
{
134
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
135
/* at present, we support adc aux mode to interface with
136
* blackfin sport tdm mode
137
*/
138
case SND_SOC_DAIFMT_DSP_A:
139
break;
140
default:
141
return -EINVAL;
142
}
143
144
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
145
case SND_SOC_DAIFMT_IB_IF:
146
break;
147
default:
148
return -EINVAL;
149
}
150
151
switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
152
/* ALCLK,ABCLK are both output, AD1836 can only be provider */
153
case SND_SOC_DAIFMT_CBP_CFP:
154
break;
155
default:
156
return -EINVAL;
157
}
158
159
return 0;
160
}
161
162
static int ad1836_hw_params(struct snd_pcm_substream *substream,
163
struct snd_pcm_hw_params *params,
164
struct snd_soc_dai *dai)
165
{
166
struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(dai->component);
167
int word_len = 0;
168
169
/* bit size */
170
switch (params_width(params)) {
171
case 16:
172
word_len = AD1836_WORD_LEN_16;
173
break;
174
case 20:
175
word_len = AD1836_WORD_LEN_20;
176
break;
177
case 24:
178
case 32:
179
word_len = AD1836_WORD_LEN_24;
180
break;
181
default:
182
return -EINVAL;
183
}
184
185
regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1,
186
AD1836_DAC_WORD_LEN_MASK,
187
word_len << AD1836_DAC_WORD_LEN_OFFSET);
188
189
regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,
190
AD1836_ADC_WORD_LEN_MASK,
191
word_len << AD1836_ADC_WORD_OFFSET);
192
193
return 0;
194
}
195
196
static const struct snd_soc_dai_ops ad1836_dai_ops = {
197
.hw_params = ad1836_hw_params,
198
.set_fmt = ad1836_set_dai_fmt,
199
};
200
201
#define AD183X_DAI(_name, num_dacs, num_adcs) \
202
{ \
203
.name = _name "-hifi", \
204
.playback = { \
205
.stream_name = "Playback", \
206
.channels_min = 2, \
207
.channels_max = (num_dacs) * 2, \
208
.rates = SNDRV_PCM_RATE_48000, \
209
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \
210
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \
211
}, \
212
.capture = { \
213
.stream_name = "Capture", \
214
.channels_min = 2, \
215
.channels_max = (num_adcs) * 2, \
216
.rates = SNDRV_PCM_RATE_48000, \
217
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \
218
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \
219
}, \
220
.ops = &ad1836_dai_ops, \
221
}
222
223
static struct snd_soc_dai_driver ad183x_dais[] = {
224
[AD1835] = AD183X_DAI("ad1835", 4, 1),
225
[AD1836] = AD183X_DAI("ad1836", 3, 2),
226
[AD1838] = AD183X_DAI("ad1838", 3, 1),
227
};
228
229
#ifdef CONFIG_PM
230
static int ad1836_suspend(struct snd_soc_component *component)
231
{
232
struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);
233
/* reset clock control mode */
234
return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,
235
AD1836_ADC_SERFMT_MASK, 0);
236
}
237
238
static int ad1836_resume(struct snd_soc_component *component)
239
{
240
struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);
241
/* restore clock control mode */
242
return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,
243
AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX);
244
}
245
#else
246
#define ad1836_suspend NULL
247
#define ad1836_resume NULL
248
#endif
249
250
static int ad1836_probe(struct snd_soc_component *component)
251
{
252
struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);
253
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
254
int num_dacs, num_adcs;
255
int ret = 0;
256
int i;
257
258
num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2;
259
num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2;
260
261
/* default setting for ad1836 */
262
/* de-emphasis: 48kHz, power-on dac */
263
regmap_write(ad1836->regmap, AD1836_DAC_CTRL1, 0x300);
264
/* unmute dac channels */
265
regmap_write(ad1836->regmap, AD1836_DAC_CTRL2, 0x0);
266
/* high-pass filter enable, power-on adc */
267
regmap_write(ad1836->regmap, AD1836_ADC_CTRL1, 0x100);
268
/* unmute adc channles, adc aux mode */
269
regmap_write(ad1836->regmap, AD1836_ADC_CTRL2, 0x180);
270
/* volume */
271
for (i = 1; i <= num_dacs; ++i) {
272
regmap_write(ad1836->regmap, AD1836_DAC_L_VOL(i), 0x3FF);
273
regmap_write(ad1836->regmap, AD1836_DAC_R_VOL(i), 0x3FF);
274
}
275
276
if (ad1836->type == AD1836) {
277
/* left/right diff:PGA/MUX */
278
regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x3A);
279
ret = snd_soc_add_component_controls(component, ad1836_controls,
280
ARRAY_SIZE(ad1836_controls));
281
if (ret)
282
return ret;
283
} else {
284
regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x00);
285
}
286
287
ret = snd_soc_add_component_controls(component, ad183x_dac_controls, num_dacs * 2);
288
if (ret)
289
return ret;
290
291
ret = snd_soc_add_component_controls(component, ad183x_adc_controls, num_adcs);
292
if (ret)
293
return ret;
294
295
ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs);
296
if (ret)
297
return ret;
298
299
ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs);
300
if (ret)
301
return ret;
302
303
ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs);
304
if (ret)
305
return ret;
306
307
ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs);
308
309
return ret;
310
}
311
312
/* power down chip */
313
static void ad1836_remove(struct snd_soc_component *component)
314
{
315
struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);
316
/* reset clock control mode */
317
regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,
318
AD1836_ADC_SERFMT_MASK, 0);
319
}
320
321
static const struct snd_soc_component_driver soc_component_dev_ad1836 = {
322
.probe = ad1836_probe,
323
.remove = ad1836_remove,
324
.suspend = ad1836_suspend,
325
.resume = ad1836_resume,
326
.controls = ad183x_controls,
327
.num_controls = ARRAY_SIZE(ad183x_controls),
328
.dapm_widgets = ad183x_dapm_widgets,
329
.num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets),
330
.dapm_routes = ad183x_dapm_routes,
331
.num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes),
332
.idle_bias_on = 1,
333
.use_pmdown_time = 1,
334
.endianness = 1,
335
};
336
337
static const struct reg_default ad1836_reg_defaults[] = {
338
{ AD1836_DAC_CTRL1, 0x0000 },
339
{ AD1836_DAC_CTRL2, 0x0000 },
340
{ AD1836_DAC_L_VOL(0), 0x0000 },
341
{ AD1836_DAC_R_VOL(0), 0x0000 },
342
{ AD1836_DAC_L_VOL(1), 0x0000 },
343
{ AD1836_DAC_R_VOL(1), 0x0000 },
344
{ AD1836_DAC_L_VOL(2), 0x0000 },
345
{ AD1836_DAC_R_VOL(2), 0x0000 },
346
{ AD1836_DAC_L_VOL(3), 0x0000 },
347
{ AD1836_DAC_R_VOL(3), 0x0000 },
348
{ AD1836_ADC_CTRL1, 0x0000 },
349
{ AD1836_ADC_CTRL2, 0x0000 },
350
{ AD1836_ADC_CTRL3, 0x0000 },
351
};
352
353
static const struct regmap_config ad1836_regmap_config = {
354
.val_bits = 12,
355
.reg_bits = 4,
356
.read_flag_mask = 0x08,
357
358
.max_register = AD1836_ADC_CTRL3,
359
.reg_defaults = ad1836_reg_defaults,
360
.num_reg_defaults = ARRAY_SIZE(ad1836_reg_defaults),
361
.cache_type = REGCACHE_MAPLE,
362
};
363
364
static int ad1836_spi_probe(struct spi_device *spi)
365
{
366
struct ad1836_priv *ad1836;
367
int ret;
368
369
ad1836 = devm_kzalloc(&spi->dev, sizeof(struct ad1836_priv),
370
GFP_KERNEL);
371
if (ad1836 == NULL)
372
return -ENOMEM;
373
374
ad1836->regmap = devm_regmap_init_spi(spi, &ad1836_regmap_config);
375
if (IS_ERR(ad1836->regmap))
376
return PTR_ERR(ad1836->regmap);
377
378
ad1836->type = spi_get_device_id(spi)->driver_data;
379
380
spi_set_drvdata(spi, ad1836);
381
382
ret = devm_snd_soc_register_component(&spi->dev,
383
&soc_component_dev_ad1836, &ad183x_dais[ad1836->type], 1);
384
return ret;
385
}
386
387
static const struct spi_device_id ad1836_ids[] = {
388
{ "ad1835", AD1835 },
389
{ "ad1836", AD1836 },
390
{ "ad1837", AD1835 },
391
{ "ad1838", AD1838 },
392
{ "ad1839", AD1838 },
393
{ },
394
};
395
MODULE_DEVICE_TABLE(spi, ad1836_ids);
396
397
static struct spi_driver ad1836_spi_driver = {
398
.driver = {
399
.name = "ad1836",
400
},
401
.probe = ad1836_spi_probe,
402
.id_table = ad1836_ids,
403
};
404
405
module_spi_driver(ad1836_spi_driver);
406
407
MODULE_DESCRIPTION("ASoC ad1836 driver");
408
MODULE_AUTHOR("Barry Song <[email protected]>");
409
MODULE_LICENSE("GPL");
410
411