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.c210
1 files changed, 64 insertions, 146 deletions
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index a01006c8c606..754c496412bd 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -27,21 +27,15 @@
27#include <sound/initval.h> 27#include <sound/initval.h>
28#include <sound/soc.h> 28#include <sound/soc.h>
29#include <sound/tlv.h> 29#include <sound/tlv.h>
30#include <sound/soc-dapm.h>
31#include <linux/spi/spi.h> 30#include <linux/spi/spi.h>
32#include "ad1836.h" 31#include "ad1836.h"
33 32
34/* codec private data */ 33/* codec private data */
35struct ad1836_priv { 34struct ad1836_priv {
36 struct snd_soc_codec codec; 35 enum snd_soc_control_type control_type;
37 u16 reg_cache[AD1836_NUM_REGS]; 36 void *control_data;
38}; 37};
39 38
40static struct snd_soc_codec *ad1836_codec;
41struct snd_soc_codec_device soc_codec_dev_ad1836;
42static int ad1836_register(struct ad1836_priv *ad1836);
43static void ad1836_unregister(struct ad1836_priv *ad1836);
44
45/* 39/*
46 * AD1836 volume/mute/de-emphasis etc. controls 40 * AD1836 volume/mute/de-emphasis etc. controls
47 */ 41 */
@@ -146,39 +140,35 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
146 int word_len = 0; 140 int word_len = 0;
147 141
148 struct snd_soc_pcm_runtime *rtd = substream->private_data; 142 struct snd_soc_pcm_runtime *rtd = substream->private_data;
149 struct snd_soc_device *socdev = rtd->socdev; 143 struct snd_soc_codec *codec = rtd->codec;
150 struct snd_soc_codec *codec = socdev->card->codec;
151 144
152 /* bit size */ 145 /* bit size */
153 switch (params_format(params)) { 146 switch (params_format(params)) {
154 case SNDRV_PCM_FORMAT_S16_LE: 147 case SNDRV_PCM_FORMAT_S16_LE:
155 word_len = 3; 148 word_len = AD1836_WORD_LEN_16;
156 break; 149 break;
157 case SNDRV_PCM_FORMAT_S20_3LE: 150 case SNDRV_PCM_FORMAT_S20_3LE:
158 word_len = 1; 151 word_len = AD1836_WORD_LEN_20;
159 break; 152 break;
160 case SNDRV_PCM_FORMAT_S24_LE: 153 case SNDRV_PCM_FORMAT_S24_LE:
161 case SNDRV_PCM_FORMAT_S32_LE: 154 case SNDRV_PCM_FORMAT_S32_LE:
162 word_len = 0; 155 word_len = AD1836_WORD_LEN_24;
163 break; 156 break;
164 } 157 }
165 158
166 snd_soc_update_bits(codec, AD1836_DAC_CTRL1, 159 snd_soc_update_bits(codec, AD1836_DAC_CTRL1, AD1836_DAC_WORD_LEN_MASK,
167 AD1836_DAC_WORD_LEN_MASK, word_len); 160 word_len << AD1836_DAC_WORD_LEN_OFFSET);
168 161
169 snd_soc_update_bits(codec, AD1836_ADC_CTRL2, 162 snd_soc_update_bits(codec, AD1836_ADC_CTRL2, AD1836_ADC_WORD_LEN_MASK,
170 AD1836_ADC_WORD_LEN_MASK, word_len); 163 word_len << AD1836_ADC_WORD_OFFSET);
171 164
172 return 0; 165 return 0;
173} 166}
174 167
175#ifdef CONFIG_PM 168#ifdef CONFIG_PM
176static int ad1836_soc_suspend(struct platform_device *pdev, 169static int ad1836_soc_suspend(struct snd_soc_codec *codec,
177 pm_message_t state) 170 pm_message_t state)
178{ 171{
179 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
180 struct snd_soc_codec *codec = socdev->card->codec;
181
182 /* reset clock control mode */ 172 /* reset clock control mode */
183 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); 173 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
184 adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; 174 adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
@@ -186,11 +176,8 @@ static int ad1836_soc_suspend(struct platform_device *pdev,
186 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); 176 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
187} 177}
188 178
189static int ad1836_soc_resume(struct platform_device *pdev) 179static int ad1836_soc_resume(struct snd_soc_codec *codec)
190{ 180{
191 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
192 struct snd_soc_codec *codec = socdev->card->codec;
193
194 /* restore clock control mode */ 181 /* restore clock control mode */
195 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); 182 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
196 adc_ctrl2 |= AD1836_ADC_AUX; 183 adc_ctrl2 |= AD1836_ADC_AUX;
@@ -202,49 +189,14 @@ static int ad1836_soc_resume(struct platform_device *pdev)
202#define ad1836_soc_resume NULL 189#define ad1836_soc_resume NULL
203#endif 190#endif
204 191
205static int __devinit ad1836_spi_probe(struct spi_device *spi)
206{
207 struct snd_soc_codec *codec;
208 struct ad1836_priv *ad1836;
209
210 ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
211 if (ad1836 == NULL)
212 return -ENOMEM;
213
214 codec = &ad1836->codec;
215 codec->control_data = spi;
216 codec->dev = &spi->dev;
217
218 dev_set_drvdata(&spi->dev, ad1836);
219
220 return ad1836_register(ad1836);
221}
222
223static int __devexit ad1836_spi_remove(struct spi_device *spi)
224{
225 struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev);
226
227 ad1836_unregister(ad1836);
228 return 0;
229}
230
231static struct spi_driver ad1836_spi_driver = {
232 .driver = {
233 .name = "ad1836",
234 .owner = THIS_MODULE,
235 },
236 .probe = ad1836_spi_probe,
237 .remove = __devexit_p(ad1836_spi_remove),
238};
239
240static struct snd_soc_dai_ops ad1836_dai_ops = { 192static struct snd_soc_dai_ops ad1836_dai_ops = {
241 .hw_params = ad1836_hw_params, 193 .hw_params = ad1836_hw_params,
242 .set_fmt = ad1836_set_dai_fmt, 194 .set_fmt = ad1836_set_dai_fmt,
243}; 195};
244 196
245/* codec DAI instance */ 197/* codec DAI instance */
246struct snd_soc_dai ad1836_dai = { 198static struct snd_soc_dai_driver ad1836_dai = {
247 .name = "AD1836", 199 .name = "ad1836-hifi",
248 .playback = { 200 .playback = {
249 .stream_name = "Playback", 201 .stream_name = "Playback",
250 .channels_min = 2, 202 .channels_min = 2,
@@ -263,40 +215,18 @@ struct snd_soc_dai ad1836_dai = {
263 }, 215 },
264 .ops = &ad1836_dai_ops, 216 .ops = &ad1836_dai_ops,
265}; 217};
266EXPORT_SYMBOL_GPL(ad1836_dai);
267 218
268static int ad1836_register(struct ad1836_priv *ad1836) 219static int ad1836_probe(struct snd_soc_codec *codec)
269{ 220{
270 int ret; 221 struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
271 struct snd_soc_codec *codec = &ad1836->codec; 222 struct snd_soc_dapm_context *dapm = &codec->dapm;
272 223 int ret = 0;
273 if (ad1836_codec) {
274 dev_err(codec->dev, "Another ad1836 is registered\n");
275 kfree(ad1836);
276 return -EINVAL;
277 }
278
279 mutex_init(&codec->mutex);
280 INIT_LIST_HEAD(&codec->dapm_widgets);
281 INIT_LIST_HEAD(&codec->dapm_paths);
282 snd_soc_codec_set_drvdata(codec, ad1836);
283 codec->reg_cache = ad1836->reg_cache;
284 codec->reg_cache_size = AD1836_NUM_REGS;
285 codec->name = "AD1836";
286 codec->owner = THIS_MODULE;
287 codec->dai = &ad1836_dai;
288 codec->num_dai = 1;
289 INIT_LIST_HEAD(&codec->dapm_widgets);
290 INIT_LIST_HEAD(&codec->dapm_paths);
291
292 ad1836_dai.dev = codec->dev;
293 ad1836_codec = codec;
294 224
225 codec->control_data = ad1836->control_data;
295 ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); 226 ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI);
296 if (ret < 0) { 227 if (ret < 0) {
297 dev_err(codec->dev, "failed to set cache I/O: %d\n", 228 dev_err(codec->dev, "failed to set cache I/O: %d\n",
298 ret); 229 ret);
299 kfree(ad1836);
300 return ret; 230 return ret;
301 } 231 }
302 232
@@ -319,81 +249,69 @@ static int ad1836_register(struct ad1836_priv *ad1836)
319 snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); 249 snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF);
320 snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); 250 snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF);
321 251
322 ret = snd_soc_register_codec(codec); 252 snd_soc_add_controls(codec, ad1836_snd_controls,
323 if (ret != 0) { 253 ARRAY_SIZE(ad1836_snd_controls));
324 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 254 snd_soc_dapm_new_controls(dapm, ad1836_dapm_widgets,
325 kfree(ad1836); 255 ARRAY_SIZE(ad1836_dapm_widgets));
326 return ret; 256 snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));
327 }
328
329 ret = snd_soc_register_dai(&ad1836_dai);
330 if (ret != 0) {
331 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
332 snd_soc_unregister_codec(codec);
333 kfree(ad1836);
334 return ret;
335 }
336 257
337 return 0; 258 return ret;
338} 259}
339 260
340static void ad1836_unregister(struct ad1836_priv *ad1836) 261/* power down chip */
262static int ad1836_remove(struct snd_soc_codec *codec)
341{ 263{
342 snd_soc_unregister_dai(&ad1836_dai); 264 /* reset clock control mode */
343 snd_soc_unregister_codec(&ad1836->codec); 265 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
344 kfree(ad1836); 266 adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
345 ad1836_codec = NULL;
346}
347 267
348static int ad1836_probe(struct platform_device *pdev) 268 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
349{ 269}
350 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
351 struct snd_soc_codec *codec;
352 int ret = 0;
353 270
354 if (ad1836_codec == NULL) { 271static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
355 dev_err(&pdev->dev, "Codec device not registered\n"); 272 .probe = ad1836_probe,
356 return -ENODEV; 273 .remove = ad1836_remove,
357 } 274 .suspend = ad1836_soc_suspend,
275 .resume = ad1836_soc_resume,
276 .reg_cache_size = AD1836_NUM_REGS,
277 .reg_word_size = sizeof(u16),
278};
358 279
359 socdev->card->codec = ad1836_codec; 280static int __devinit ad1836_spi_probe(struct spi_device *spi)
360 codec = ad1836_codec; 281{
282 struct ad1836_priv *ad1836;
283 int ret;
361 284
362 /* register pcms */ 285 ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
363 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 286 if (ad1836 == NULL)
364 if (ret < 0) { 287 return -ENOMEM;
365 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
366 goto pcm_err;
367 }
368 288
369 snd_soc_add_controls(codec, ad1836_snd_controls, 289 spi_set_drvdata(spi, ad1836);
370 ARRAY_SIZE(ad1836_snd_controls)); 290 ad1836->control_data = spi;
371 snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, 291 ad1836->control_type = SND_SOC_SPI;
372 ARRAY_SIZE(ad1836_dapm_widgets));
373 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
374 292
375pcm_err: 293 ret = snd_soc_register_codec(&spi->dev,
294 &soc_codec_dev_ad1836, &ad1836_dai, 1);
295 if (ret < 0)
296 kfree(ad1836);
376 return ret; 297 return ret;
377} 298}
378 299
379/* power down chip */ 300static int __devexit ad1836_spi_remove(struct spi_device *spi)
380static int ad1836_remove(struct platform_device *pdev)
381{ 301{
382 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 302 snd_soc_unregister_codec(&spi->dev);
383 303 kfree(spi_get_drvdata(spi));
384 snd_soc_free_pcms(socdev);
385 snd_soc_dapm_free(socdev);
386
387 return 0; 304 return 0;
388} 305}
389 306
390struct snd_soc_codec_device soc_codec_dev_ad1836 = { 307static struct spi_driver ad1836_spi_driver = {
391 .probe = ad1836_probe, 308 .driver = {
392 .remove = ad1836_remove, 309 .name = "ad1836-codec",
393 .suspend = ad1836_soc_suspend, 310 .owner = THIS_MODULE,
394 .resume = ad1836_soc_resume, 311 },
312 .probe = ad1836_spi_probe,
313 .remove = __devexit_p(ad1836_spi_remove),
395}; 314};
396EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836);
397 315
398static int __init ad1836_init(void) 316static int __init ad1836_init(void)
399{ 317{