diff options
Diffstat (limited to 'sound/soc/codecs/tlv320aic26.c')
-rw-r--r-- | sound/soc/codecs/tlv320aic26.c | 195 |
1 files changed, 71 insertions, 124 deletions
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index f0e00fd4b435..7859bdcc93db 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -18,8 +18,6 @@ | |||
18 | #include <sound/pcm.h> | 18 | #include <sound/pcm.h> |
19 | #include <sound/pcm_params.h> | 19 | #include <sound/pcm_params.h> |
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | #include <sound/soc-dapm.h> | ||
22 | #include <sound/soc-of-simple.h> | ||
23 | #include <sound/initval.h> | 21 | #include <sound/initval.h> |
24 | 22 | ||
25 | #include "tlv320aic26.h" | 23 | #include "tlv320aic26.h" |
@@ -32,7 +30,6 @@ MODULE_LICENSE("GPL"); | |||
32 | struct aic26 { | 30 | struct aic26 { |
33 | struct spi_device *spi; | 31 | struct spi_device *spi; |
34 | struct snd_soc_codec codec; | 32 | struct snd_soc_codec codec; |
35 | u16 reg_cache[AIC26_NUM_REGS]; /* shadow registers */ | ||
36 | int master; | 33 | int master; |
37 | int datfm; | 34 | int datfm; |
38 | int mclk; | 35 | int mclk; |
@@ -130,8 +127,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, | |||
130 | struct snd_soc_dai *dai) | 127 | struct snd_soc_dai *dai) |
131 | { | 128 | { |
132 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 129 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
133 | struct snd_soc_device *socdev = rtd->socdev; | 130 | struct snd_soc_codec *codec = rtd->codec; |
134 | struct snd_soc_codec *codec = socdev->card->codec; | ||
135 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); | 131 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); |
136 | int fsref, divisor, wlen, pval, jval, dval, qval; | 132 | int fsref, divisor, wlen, pval, jval, dval, qval; |
137 | u16 reg; | 133 | u16 reg; |
@@ -165,10 +161,18 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, | |||
165 | dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL; | 161 | dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL; |
166 | } | 162 | } |
167 | 163 | ||
168 | /* Configure PLL */ | 164 | /** |
165 | * Configure PLL | ||
166 | * fsref = (mclk * PLLM) / 2048 | ||
167 | * where PLLM = J.DDDD (DDDD register ranges from 0 to 9999, decimal) | ||
168 | */ | ||
169 | pval = 1; | 169 | pval = 1; |
170 | jval = (fsref == 44100) ? 7 : 8; | 170 | /* compute J portion of multiplier */ |
171 | dval = (fsref == 44100) ? 5264 : 1920; | 171 | jval = fsref / (aic26->mclk / 2048); |
172 | /* compute fractional DDDD component of multiplier */ | ||
173 | dval = fsref - (jval * (aic26->mclk / 2048)); | ||
174 | dval = (10000 * dval) / (aic26->mclk / 2048); | ||
175 | dev_dbg(&aic26->spi->dev, "Setting PLLM to %d.%04d\n", jval, dval); | ||
172 | qval = 0; | 176 | qval = 0; |
173 | reg = 0x8000 | qval << 11 | pval << 8 | jval << 2; | 177 | reg = 0x8000 | qval << 11 | pval << 8 | jval << 2; |
174 | aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg); | 178 | aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg); |
@@ -278,8 +282,8 @@ static struct snd_soc_dai_ops aic26_dai_ops = { | |||
278 | .set_fmt = aic26_set_fmt, | 282 | .set_fmt = aic26_set_fmt, |
279 | }; | 283 | }; |
280 | 284 | ||
281 | struct snd_soc_dai aic26_dai = { | 285 | static struct snd_soc_dai_driver aic26_dai = { |
282 | .name = "tlv320aic26", | 286 | .name = "tlv320aic26-hifi", |
283 | .playback = { | 287 | .playback = { |
284 | .stream_name = "Playback", | 288 | .stream_name = "Playback", |
285 | .channels_min = 2, | 289 | .channels_min = 2, |
@@ -296,7 +300,6 @@ struct snd_soc_dai aic26_dai = { | |||
296 | }, | 300 | }, |
297 | .ops = &aic26_dai_ops, | 301 | .ops = &aic26_dai_ops, |
298 | }; | 302 | }; |
299 | EXPORT_SYMBOL_GPL(aic26_dai); | ||
300 | 303 | ||
301 | /* --------------------------------------------------------------------- | 304 | /* --------------------------------------------------------------------- |
302 | * ALSA controls | 305 | * ALSA controls |
@@ -319,61 +322,6 @@ static const struct snd_kcontrol_new aic26_snd_controls[] = { | |||
319 | }; | 322 | }; |
320 | 323 | ||
321 | /* --------------------------------------------------------------------- | 324 | /* --------------------------------------------------------------------- |
322 | * SoC CODEC portion of driver: probe and release routines | ||
323 | */ | ||
324 | static int aic26_probe(struct platform_device *pdev) | ||
325 | { | ||
326 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
327 | struct snd_soc_codec *codec; | ||
328 | struct aic26 *aic26; | ||
329 | int ret, err; | ||
330 | |||
331 | dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n"); | ||
332 | dev_dbg(&pdev->dev, "socdev=%p\n", socdev); | ||
333 | dev_dbg(&pdev->dev, "codec_data=%p\n", socdev->codec_data); | ||
334 | |||
335 | /* Fetch the relevant aic26 private data here (it's already been | ||
336 | * stored in the .codec pointer) */ | ||
337 | aic26 = socdev->codec_data; | ||
338 | if (aic26 == NULL) { | ||
339 | dev_err(&pdev->dev, "aic26: missing codec pointer\n"); | ||
340 | return -ENODEV; | ||
341 | } | ||
342 | codec = &aic26->codec; | ||
343 | socdev->card->codec = codec; | ||
344 | |||
345 | dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n", | ||
346 | &pdev->dev, socdev->dev); | ||
347 | /* register pcms */ | ||
348 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
349 | if (ret < 0) { | ||
350 | dev_err(&pdev->dev, "aic26: failed to create pcms\n"); | ||
351 | return -ENODEV; | ||
352 | } | ||
353 | |||
354 | /* register controls */ | ||
355 | dev_dbg(&pdev->dev, "Registering controls\n"); | ||
356 | err = snd_soc_add_controls(codec, aic26_snd_controls, | ||
357 | ARRAY_SIZE(aic26_snd_controls)); | ||
358 | WARN_ON(err < 0); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int aic26_remove(struct platform_device *pdev) | ||
364 | { | ||
365 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
366 | snd_soc_free_pcms(socdev); | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | struct snd_soc_codec_device aic26_soc_codec_dev = { | ||
371 | .probe = aic26_probe, | ||
372 | .remove = aic26_remove, | ||
373 | }; | ||
374 | EXPORT_SYMBOL_GPL(aic26_soc_codec_dev); | ||
375 | |||
376 | /* --------------------------------------------------------------------- | ||
377 | * SPI device portion of driver: sysfs files for debugging | 325 | * SPI device portion of driver: sysfs files for debugging |
378 | */ | 326 | */ |
379 | 327 | ||
@@ -409,13 +357,61 @@ static ssize_t aic26_keyclick_set(struct device *dev, | |||
409 | static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); | 357 | static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); |
410 | 358 | ||
411 | /* --------------------------------------------------------------------- | 359 | /* --------------------------------------------------------------------- |
360 | * SoC CODEC portion of driver: probe and release routines | ||
361 | */ | ||
362 | static int aic26_probe(struct snd_soc_codec *codec) | ||
363 | { | ||
364 | int ret, err, i, reg; | ||
365 | |||
366 | dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n"); | ||
367 | |||
368 | /* Reset the codec to power on defaults */ | ||
369 | aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00); | ||
370 | |||
371 | /* Power up CODEC */ | ||
372 | aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0); | ||
373 | |||
374 | /* Audio Control 3 (master mode, fsref rate) */ | ||
375 | reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3); | ||
376 | reg &= ~0xf800; | ||
377 | reg |= 0x0800; /* set master mode */ | ||
378 | aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg); | ||
379 | |||
380 | /* Fill register cache */ | ||
381 | for (i = 0; i < codec->driver->reg_cache_size; i++) | ||
382 | aic26_reg_read(codec, i); | ||
383 | |||
384 | /* Register the sysfs files for debugging */ | ||
385 | /* Create SysFS files */ | ||
386 | ret = device_create_file(codec->dev, &dev_attr_keyclick); | ||
387 | if (ret) | ||
388 | dev_info(codec->dev, "error creating sysfs files\n"); | ||
389 | |||
390 | /* register controls */ | ||
391 | dev_dbg(codec->dev, "Registering controls\n"); | ||
392 | err = snd_soc_add_controls(codec, aic26_snd_controls, | ||
393 | ARRAY_SIZE(aic26_snd_controls)); | ||
394 | WARN_ON(err < 0); | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | static struct snd_soc_codec_driver aic26_soc_codec_dev = { | ||
400 | .probe = aic26_probe, | ||
401 | .read = aic26_reg_read, | ||
402 | .write = aic26_reg_write, | ||
403 | .reg_cache_size = AIC26_NUM_REGS, | ||
404 | .reg_word_size = sizeof(u16), | ||
405 | }; | ||
406 | |||
407 | /* --------------------------------------------------------------------- | ||
412 | * SPI device portion of driver: probe and release routines and SPI | 408 | * SPI device portion of driver: probe and release routines and SPI |
413 | * driver registration. | 409 | * driver registration. |
414 | */ | 410 | */ |
415 | static int aic26_spi_probe(struct spi_device *spi) | 411 | static int aic26_spi_probe(struct spi_device *spi) |
416 | { | 412 | { |
417 | struct aic26 *aic26; | 413 | struct aic26 *aic26; |
418 | int ret, i, reg; | 414 | int ret; |
419 | 415 | ||
420 | dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); | 416 | dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); |
421 | 417 | ||
@@ -427,59 +423,13 @@ static int aic26_spi_probe(struct spi_device *spi) | |||
427 | /* Initialize the driver data */ | 423 | /* Initialize the driver data */ |
428 | aic26->spi = spi; | 424 | aic26->spi = spi; |
429 | dev_set_drvdata(&spi->dev, aic26); | 425 | dev_set_drvdata(&spi->dev, aic26); |
430 | |||
431 | /* Setup what we can in the codec structure so that the register | ||
432 | * access functions will work as expected. More will be filled | ||
433 | * out when it is probed by the SoC CODEC part of this driver */ | ||
434 | snd_soc_codec_set_drvdata(&aic26->codec, aic26); | ||
435 | aic26->codec.name = "aic26"; | ||
436 | aic26->codec.owner = THIS_MODULE; | ||
437 | aic26->codec.dai = &aic26_dai; | ||
438 | aic26->codec.num_dai = 1; | ||
439 | aic26->codec.read = aic26_reg_read; | ||
440 | aic26->codec.write = aic26_reg_write; | ||
441 | aic26->master = 1; | 426 | aic26->master = 1; |
442 | mutex_init(&aic26->codec.mutex); | ||
443 | INIT_LIST_HEAD(&aic26->codec.dapm_widgets); | ||
444 | INIT_LIST_HEAD(&aic26->codec.dapm_paths); | ||
445 | aic26->codec.reg_cache_size = AIC26_NUM_REGS; | ||
446 | aic26->codec.reg_cache = aic26->reg_cache; | ||
447 | |||
448 | aic26_dai.dev = &spi->dev; | ||
449 | ret = snd_soc_register_dai(&aic26_dai); | ||
450 | if (ret != 0) { | ||
451 | dev_err(&spi->dev, "Failed to register DAI: %d\n", ret); | ||
452 | kfree(aic26); | ||
453 | return ret; | ||
454 | } | ||
455 | |||
456 | /* Reset the codec to power on defaults */ | ||
457 | aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00); | ||
458 | |||
459 | /* Power up CODEC */ | ||
460 | aic26_reg_write(&aic26->codec, AIC26_REG_POWER_CTRL, 0); | ||
461 | |||
462 | /* Audio Control 3 (master mode, fsref rate) */ | ||
463 | reg = aic26_reg_read(&aic26->codec, AIC26_REG_AUDIO_CTRL3); | ||
464 | reg &= ~0xf800; | ||
465 | reg |= 0x0800; /* set master mode */ | ||
466 | aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL3, reg); | ||
467 | 427 | ||
468 | /* Fill register cache */ | 428 | ret = snd_soc_register_codec(&spi->dev, |
469 | for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++) | 429 | &aic26_soc_codec_dev, &aic26_dai, 1); |
470 | aic26_reg_read(&aic26->codec, i); | 430 | if (ret < 0) |
471 | 431 | kfree(aic26); | |
472 | /* Register the sysfs files for debugging */ | 432 | return ret; |
473 | /* Create SysFS files */ | ||
474 | ret = device_create_file(&spi->dev, &dev_attr_keyclick); | ||
475 | if (ret) | ||
476 | dev_info(&spi->dev, "error creating sysfs files\n"); | ||
477 | |||
478 | #if defined(CONFIG_SND_SOC_OF_SIMPLE) | ||
479 | /* Tell the of_soc helper about this codec */ | ||
480 | of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai, | ||
481 | spi->dev.archdata.of_node); | ||
482 | #endif | ||
483 | 433 | ||
484 | dev_dbg(&spi->dev, "SPI device initialized\n"); | 434 | dev_dbg(&spi->dev, "SPI device initialized\n"); |
485 | return 0; | 435 | return 0; |
@@ -487,17 +437,14 @@ static int aic26_spi_probe(struct spi_device *spi) | |||
487 | 437 | ||
488 | static int aic26_spi_remove(struct spi_device *spi) | 438 | static int aic26_spi_remove(struct spi_device *spi) |
489 | { | 439 | { |
490 | struct aic26 *aic26 = dev_get_drvdata(&spi->dev); | 440 | snd_soc_unregister_codec(&spi->dev); |
491 | 441 | kfree(spi_get_drvdata(spi)); | |
492 | snd_soc_unregister_dai(&aic26_dai); | ||
493 | kfree(aic26); | ||
494 | |||
495 | return 0; | 442 | return 0; |
496 | } | 443 | } |
497 | 444 | ||
498 | static struct spi_driver aic26_spi = { | 445 | static struct spi_driver aic26_spi = { |
499 | .driver = { | 446 | .driver = { |
500 | .name = "tlv320aic26", | 447 | .name = "tlv320aic26-codec", |
501 | .owner = THIS_MODULE, | 448 | .owner = THIS_MODULE, |
502 | }, | 449 | }, |
503 | .probe = aic26_spi_probe, | 450 | .probe = aic26_spi_probe, |