aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/ad1836.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/ad1836.c')
-rw-r--r--sound/soc/codecs/ad1836.c313
1 files changed, 187 insertions, 126 deletions
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 754c496412bd..4e5c5726366b 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -1,19 +1,10 @@
1/* 1 /*
2 * File: sound/soc/codecs/ad1836.c 2 * Audio Codec driver supporting:
3 * Author: Barry Song <Barry.Song@analog.com> 3 * AD1835A, AD1836, AD1837A, AD1838A, AD1839A
4 *
5 * Created: Aug 04 2009
6 * Description: Driver for AD1836 sound chip
7 *
8 * Modified:
9 * Copyright 2009 Analog Devices Inc.
10 * 4 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/ 5 * Copyright 2009-2011 Analog Devices Inc.
12 * 6 *
13 * This program is free software; you can redistribute it and/or modify 7 * Licensed under the GPL-2 or later.
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */ 8 */
18 9
19#include <linux/init.h> 10#include <linux/init.h>
@@ -30,10 +21,15 @@
30#include <linux/spi/spi.h> 21#include <linux/spi/spi.h>
31#include "ad1836.h" 22#include "ad1836.h"
32 23
24enum ad1836_type {
25 AD1835,
26 AD1836,
27 AD1838,
28};
29
33/* codec private data */ 30/* codec private data */
34struct ad1836_priv { 31struct ad1836_priv {
35 enum snd_soc_control_type control_type; 32 enum ad1836_type type;
36 void *control_data;
37}; 33};
38 34
39/* 35/*
@@ -44,29 +40,60 @@ static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"};
44static const struct soc_enum ad1836_deemp_enum = 40static const struct soc_enum ad1836_deemp_enum =
45 SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp); 41 SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp);
46 42
47static const struct snd_kcontrol_new ad1836_snd_controls[] = { 43#define AD1836_DAC_VOLUME(x) \
48 /* DAC volume control */ 44 SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \
49 SOC_DOUBLE_R("DAC1 Volume", AD1836_DAC_L1_VOL, 45 AD1836_DAC_R_VOL(x), 0, 0x3FF, 0)
50 AD1836_DAC_R1_VOL, 0, 0x3FF, 0), 46
51 SOC_DOUBLE_R("DAC2 Volume", AD1836_DAC_L2_VOL, 47#define AD1836_DAC_SWITCH(x) \
52 AD1836_DAC_R2_VOL, 0, 0x3FF, 0), 48 SOC_DOUBLE("DAC" #x " Playback Switch", AD1836_DAC_CTRL2, \
53 SOC_DOUBLE_R("DAC3 Volume", AD1836_DAC_L3_VOL, 49 AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)
54 AD1836_DAC_R3_VOL, 0, 0x3FF, 0), 50
55 51#define AD1836_ADC_SWITCH(x) \
56 /* ADC switch control */ 52 SOC_DOUBLE("ADC" #x " Capture Switch", AD1836_ADC_CTRL2, \
57 SOC_DOUBLE("ADC1 Switch", AD1836_ADC_CTRL2, AD1836_ADCL1_MUTE, 53 AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)
58 AD1836_ADCR1_MUTE, 1, 1), 54
59 SOC_DOUBLE("ADC2 Switch", AD1836_ADC_CTRL2, AD1836_ADCL2_MUTE, 55static const struct snd_kcontrol_new ad183x_dac_controls[] = {
60 AD1836_ADCR2_MUTE, 1, 1), 56 AD1836_DAC_VOLUME(1),
61 57 AD1836_DAC_SWITCH(1),
62 /* DAC switch control */ 58 AD1836_DAC_VOLUME(2),
63 SOC_DOUBLE("DAC1 Switch", AD1836_DAC_CTRL2, AD1836_DACL1_MUTE, 59 AD1836_DAC_SWITCH(2),
64 AD1836_DACR1_MUTE, 1, 1), 60 AD1836_DAC_VOLUME(3),
65 SOC_DOUBLE("DAC2 Switch", AD1836_DAC_CTRL2, AD1836_DACL2_MUTE, 61 AD1836_DAC_SWITCH(3),
66 AD1836_DACR2_MUTE, 1, 1), 62 AD1836_DAC_VOLUME(4),
67 SOC_DOUBLE("DAC3 Switch", AD1836_DAC_CTRL2, AD1836_DACL3_MUTE, 63 AD1836_DAC_SWITCH(4),
68 AD1836_DACR3_MUTE, 1, 1), 64};
65
66static const struct snd_soc_dapm_widget ad183x_dac_dapm_widgets[] = {
67 SND_SOC_DAPM_OUTPUT("DAC1OUT"),
68 SND_SOC_DAPM_OUTPUT("DAC2OUT"),
69 SND_SOC_DAPM_OUTPUT("DAC3OUT"),
70 SND_SOC_DAPM_OUTPUT("DAC4OUT"),
71};
72
73static const struct snd_soc_dapm_route ad183x_dac_routes[] = {
74 { "DAC1OUT", NULL, "DAC" },
75 { "DAC2OUT", NULL, "DAC" },
76 { "DAC3OUT", NULL, "DAC" },
77 { "DAC4OUT", NULL, "DAC" },
78};
79
80static const struct snd_kcontrol_new ad183x_adc_controls[] = {
81 AD1836_ADC_SWITCH(1),
82 AD1836_ADC_SWITCH(2),
83 AD1836_ADC_SWITCH(3),
84};
85
86static const struct snd_soc_dapm_widget ad183x_adc_dapm_widgets[] = {
87 SND_SOC_DAPM_INPUT("ADC1IN"),
88 SND_SOC_DAPM_INPUT("ADC2IN"),
89};
90
91static const struct snd_soc_dapm_route ad183x_adc_routes[] = {
92 { "ADC", NULL, "ADC1IN" },
93 { "ADC", NULL, "ADC2IN" },
94};
69 95
96static const struct snd_kcontrol_new ad183x_controls[] = {
70 /* ADC high-pass filter */ 97 /* ADC high-pass filter */
71 SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1, 98 SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1,
72 AD1836_ADC_HIGHPASS_FILTER, 1, 0), 99 AD1836_ADC_HIGHPASS_FILTER, 1, 0),
@@ -75,27 +102,24 @@ static const struct snd_kcontrol_new ad1836_snd_controls[] = {
75 SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum), 102 SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum),
76}; 103};
77 104
78static const struct snd_soc_dapm_widget ad1836_dapm_widgets[] = { 105static const struct snd_soc_dapm_widget ad183x_dapm_widgets[] = {
79 SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1, 106 SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1,
80 AD1836_DAC_POWERDOWN, 1), 107 AD1836_DAC_POWERDOWN, 1),
81 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), 108 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
82 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1, 109 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1,
83 AD1836_ADC_POWERDOWN, 1, NULL, 0), 110 AD1836_ADC_POWERDOWN, 1, NULL, 0),
84 SND_SOC_DAPM_OUTPUT("DAC1OUT"),
85 SND_SOC_DAPM_OUTPUT("DAC2OUT"),
86 SND_SOC_DAPM_OUTPUT("DAC3OUT"),
87 SND_SOC_DAPM_INPUT("ADC1IN"),
88 SND_SOC_DAPM_INPUT("ADC2IN"),
89}; 111};
90 112
91static const struct snd_soc_dapm_route audio_paths[] = { 113static const struct snd_soc_dapm_route ad183x_dapm_routes[] = {
92 { "DAC", NULL, "ADC_PWR" }, 114 { "DAC", NULL, "ADC_PWR" },
93 { "ADC", NULL, "ADC_PWR" }, 115 { "ADC", NULL, "ADC_PWR" },
94 { "DAC1OUT", "DAC1 Switch", "DAC" }, 116};
95 { "DAC2OUT", "DAC2 Switch", "DAC" }, 117
96 { "DAC3OUT", "DAC3 Switch", "DAC" }, 118static const DECLARE_TLV_DB_SCALE(ad1836_in_tlv, 0, 300, 0);
97 { "ADC", "ADC1 Switch", "ADC1IN" }, 119
98 { "ADC", "ADC2 Switch", "ADC2IN" }, 120static const struct snd_kcontrol_new ad1836_controls[] = {
121 SOC_DOUBLE_TLV("ADC2 Capture Volume", AD1836_ADC_CTRL1, 3, 0, 4, 0,
122 ad1836_in_tlv),
99}; 123};
100 124
101/* 125/*
@@ -165,64 +189,69 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
165 return 0; 189 return 0;
166} 190}
167 191
192static struct snd_soc_dai_ops ad1836_dai_ops = {
193 .hw_params = ad1836_hw_params,
194 .set_fmt = ad1836_set_dai_fmt,
195};
196
197#define AD183X_DAI(_name, num_dacs, num_adcs) \
198{ \
199 .name = _name "-hifi", \
200 .playback = { \
201 .stream_name = "Playback", \
202 .channels_min = 2, \
203 .channels_max = (num_dacs) * 2, \
204 .rates = SNDRV_PCM_RATE_48000, \
205 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \
206 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \
207 }, \
208 .capture = { \
209 .stream_name = "Capture", \
210 .channels_min = 2, \
211 .channels_max = (num_adcs) * 2, \
212 .rates = SNDRV_PCM_RATE_48000, \
213 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \
214 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \
215 }, \
216 .ops = &ad1836_dai_ops, \
217}
218
219static struct snd_soc_dai_driver ad183x_dais[] = {
220 [AD1835] = AD183X_DAI("ad1835", 4, 1),
221 [AD1836] = AD183X_DAI("ad1836", 3, 2),
222 [AD1838] = AD183X_DAI("ad1838", 3, 1),
223};
224
168#ifdef CONFIG_PM 225#ifdef CONFIG_PM
169static int ad1836_soc_suspend(struct snd_soc_codec *codec, 226static int ad1836_suspend(struct snd_soc_codec *codec, pm_message_t state)
170 pm_message_t state)
171{ 227{
172 /* reset clock control mode */ 228 /* reset clock control mode */
173 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); 229 return snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
174 adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; 230 AD1836_ADC_SERFMT_MASK, 0);
175
176 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
177} 231}
178 232
179static int ad1836_soc_resume(struct snd_soc_codec *codec) 233static int ad1836_resume(struct snd_soc_codec *codec)
180{ 234{
181 /* restore clock control mode */ 235 /* restore clock control mode */
182 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); 236 return snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
183 adc_ctrl2 |= AD1836_ADC_AUX; 237 AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX);
184
185 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
186} 238}
187#else 239#else
188#define ad1836_soc_suspend NULL 240#define ad1836_suspend NULL
189#define ad1836_soc_resume NULL 241#define ad1836_resume NULL
190#endif 242#endif
191 243
192static struct snd_soc_dai_ops ad1836_dai_ops = {
193 .hw_params = ad1836_hw_params,
194 .set_fmt = ad1836_set_dai_fmt,
195};
196
197/* codec DAI instance */
198static struct snd_soc_dai_driver ad1836_dai = {
199 .name = "ad1836-hifi",
200 .playback = {
201 .stream_name = "Playback",
202 .channels_min = 2,
203 .channels_max = 6,
204 .rates = SNDRV_PCM_RATE_48000,
205 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
206 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
207 },
208 .capture = {
209 .stream_name = "Capture",
210 .channels_min = 2,
211 .channels_max = 4,
212 .rates = SNDRV_PCM_RATE_48000,
213 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
214 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
215 },
216 .ops = &ad1836_dai_ops,
217};
218
219static int ad1836_probe(struct snd_soc_codec *codec) 244static int ad1836_probe(struct snd_soc_codec *codec)
220{ 245{
221 struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); 246 struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
222 struct snd_soc_dapm_context *dapm = &codec->dapm; 247 struct snd_soc_dapm_context *dapm = &codec->dapm;
248 int num_dacs, num_adcs;
223 int ret = 0; 249 int ret = 0;
250 int i;
251
252 num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2;
253 num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2;
224 254
225 codec->control_data = ad1836->control_data;
226 ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); 255 ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI);
227 if (ret < 0) { 256 if (ret < 0) {
228 dev_err(codec->dev, "failed to set cache I/O: %d\n", 257 dev_err(codec->dev, "failed to set cache I/O: %d\n",
@@ -239,21 +268,46 @@ static int ad1836_probe(struct snd_soc_codec *codec)
239 snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); 268 snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100);
240 /* unmute adc channles, adc aux mode */ 269 /* unmute adc channles, adc aux mode */
241 snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); 270 snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180);
242 /* left/right diff:PGA/MUX */
243 snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A);
244 /* volume */ 271 /* volume */
245 snd_soc_write(codec, AD1836_DAC_L1_VOL, 0x3FF); 272 for (i = 1; i <= num_dacs; ++i) {
246 snd_soc_write(codec, AD1836_DAC_R1_VOL, 0x3FF); 273 snd_soc_write(codec, AD1836_DAC_L_VOL(i), 0x3FF);
247 snd_soc_write(codec, AD1836_DAC_L2_VOL, 0x3FF); 274 snd_soc_write(codec, AD1836_DAC_R_VOL(i), 0x3FF);
248 snd_soc_write(codec, AD1836_DAC_R2_VOL, 0x3FF); 275 }
249 snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); 276
250 snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); 277 if (ad1836->type == AD1836) {
251 278 /* left/right diff:PGA/MUX */
252 snd_soc_add_controls(codec, ad1836_snd_controls, 279 snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A);
253 ARRAY_SIZE(ad1836_snd_controls)); 280 ret = snd_soc_add_controls(codec, ad1836_controls,
254 snd_soc_dapm_new_controls(dapm, ad1836_dapm_widgets, 281 ARRAY_SIZE(ad1836_controls));
255 ARRAY_SIZE(ad1836_dapm_widgets)); 282 if (ret)
256 snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); 283 return ret;
284 } else {
285 snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00);
286 }
287
288 ret = snd_soc_add_controls(codec, ad183x_dac_controls, num_dacs * 2);
289 if (ret)
290 return ret;
291
292 ret = snd_soc_add_controls(codec, ad183x_adc_controls, num_adcs);
293 if (ret)
294 return ret;
295
296 ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs);
297 if (ret)
298 return ret;
299
300 ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs);
301 if (ret)
302 return ret;
303
304 ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs);
305 if (ret)
306 return ret;
307
308 ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs);
309 if (ret)
310 return ret;
257 311
258 return ret; 312 return ret;
259} 313}
@@ -262,19 +316,24 @@ static int ad1836_probe(struct snd_soc_codec *codec)
262static int ad1836_remove(struct snd_soc_codec *codec) 316static int ad1836_remove(struct snd_soc_codec *codec)
263{ 317{
264 /* reset clock control mode */ 318 /* reset clock control mode */
265 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); 319 return snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
266 adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; 320 AD1836_ADC_SERFMT_MASK, 0);
267
268 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
269} 321}
270 322
271static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { 323static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
272 .probe = ad1836_probe, 324 .probe = ad1836_probe,
273 .remove = ad1836_remove, 325 .remove = ad1836_remove,
274 .suspend = ad1836_soc_suspend, 326 .suspend = ad1836_suspend,
275 .resume = ad1836_soc_resume, 327 .resume = ad1836_resume,
276 .reg_cache_size = AD1836_NUM_REGS, 328 .reg_cache_size = AD1836_NUM_REGS,
277 .reg_word_size = sizeof(u16), 329 .reg_word_size = sizeof(u16),
330
331 .controls = ad183x_controls,
332 .num_controls = ARRAY_SIZE(ad183x_controls),
333 .dapm_widgets = ad183x_dapm_widgets,
334 .num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets),
335 .dapm_routes = ad183x_dapm_routes,
336 .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes),
278}; 337};
279 338
280static int __devinit ad1836_spi_probe(struct spi_device *spi) 339static int __devinit ad1836_spi_probe(struct spi_device *spi)
@@ -286,12 +345,12 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi)
286 if (ad1836 == NULL) 345 if (ad1836 == NULL)
287 return -ENOMEM; 346 return -ENOMEM;
288 347
348 ad1836->type = spi_get_device_id(spi)->driver_data;
349
289 spi_set_drvdata(spi, ad1836); 350 spi_set_drvdata(spi, ad1836);
290 ad1836->control_data = spi;
291 ad1836->control_type = SND_SOC_SPI;
292 351
293 ret = snd_soc_register_codec(&spi->dev, 352 ret = snd_soc_register_codec(&spi->dev,
294 &soc_codec_dev_ad1836, &ad1836_dai, 1); 353 &soc_codec_dev_ad1836, &ad183x_dais[ad1836->type], 1);
295 if (ret < 0) 354 if (ret < 0)
296 kfree(ad1836); 355 kfree(ad1836);
297 return ret; 356 return ret;
@@ -303,27 +362,29 @@ static int __devexit ad1836_spi_remove(struct spi_device *spi)
303 kfree(spi_get_drvdata(spi)); 362 kfree(spi_get_drvdata(spi));
304 return 0; 363 return 0;
305} 364}
365static const struct spi_device_id ad1836_ids[] = {
366 { "ad1835", AD1835 },
367 { "ad1836", AD1836 },
368 { "ad1837", AD1835 },
369 { "ad1838", AD1838 },
370 { "ad1839", AD1838 },
371 { },
372};
373MODULE_DEVICE_TABLE(spi, ad1836_ids);
306 374
307static struct spi_driver ad1836_spi_driver = { 375static struct spi_driver ad1836_spi_driver = {
308 .driver = { 376 .driver = {
309 .name = "ad1836-codec", 377 .name = "ad1836",
310 .owner = THIS_MODULE, 378 .owner = THIS_MODULE,
311 }, 379 },
312 .probe = ad1836_spi_probe, 380 .probe = ad1836_spi_probe,
313 .remove = __devexit_p(ad1836_spi_remove), 381 .remove = __devexit_p(ad1836_spi_remove),
382 .id_table = ad1836_ids,
314}; 383};
315 384
316static int __init ad1836_init(void) 385static int __init ad1836_init(void)
317{ 386{
318 int ret; 387 return spi_register_driver(&ad1836_spi_driver);
319
320 ret = spi_register_driver(&ad1836_spi_driver);
321 if (ret != 0) {
322 printk(KERN_ERR "Failed to register ad1836 SPI driver: %d\n",
323 ret);
324 }
325
326 return ret;
327} 388}
328module_init(ad1836_init); 389module_init(ad1836_init);
329 390