aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/ak4671.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/ak4671.c')
-rw-r--r--sound/soc/codecs/ak4671.c161
1 files changed, 35 insertions, 126 deletions
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index 87566932a3b1..88b29f8c748b 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -17,18 +17,16 @@
17#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <sound/soc.h> 19#include <sound/soc.h>
20#include <sound/soc-dapm.h>
21#include <sound/initval.h> 20#include <sound/initval.h>
22#include <sound/tlv.h> 21#include <sound/tlv.h>
23 22
24#include "ak4671.h" 23#include "ak4671.h"
25 24
26static struct snd_soc_codec *ak4671_codec;
27 25
28/* codec private data */ 26/* codec private data */
29struct ak4671_priv { 27struct ak4671_priv {
30 struct snd_soc_codec codec; 28 enum snd_soc_control_type control_type;
31 u8 reg_cache[AK4671_CACHEREGNUM]; 29 void *control_data;
32}; 30};
33 31
34/* ak4671 register cache & default register settings */ 32/* ak4671 register cache & default register settings */
@@ -354,7 +352,7 @@ static const struct snd_soc_dapm_widget ak4671_dapm_widgets[] = {
354 SND_SOC_DAPM_SUPPLY("PMPLL", AK4671_PLL_MODE_SELECT1, 0, 0, NULL, 0), 352 SND_SOC_DAPM_SUPPLY("PMPLL", AK4671_PLL_MODE_SELECT1, 0, 0, NULL, 0),
355}; 353};
356 354
357static const struct snd_soc_dapm_route intercon[] = { 355static const struct snd_soc_dapm_route ak4671_intercon[] = {
358 {"DAC Left", "NULL", "PMPLL"}, 356 {"DAC Left", "NULL", "PMPLL"},
359 {"DAC Right", "NULL", "PMPLL"}, 357 {"DAC Right", "NULL", "PMPLL"},
360 {"ADC Left", "NULL", "PMPLL"}, 358 {"ADC Left", "NULL", "PMPLL"},
@@ -435,16 +433,6 @@ static const struct snd_soc_dapm_route intercon[] = {
435 {"ROUT3 Mixer", "RINS4", "RIN4 Mixing Circuit"}, 433 {"ROUT3 Mixer", "RINS4", "RIN4 Mixing Circuit"},
436}; 434};
437 435
438static int ak4671_add_widgets(struct snd_soc_codec *codec)
439{
440 snd_soc_dapm_new_controls(codec, ak4671_dapm_widgets,
441 ARRAY_SIZE(ak4671_dapm_widgets));
442
443 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
444
445 return 0;
446}
447
448static int ak4671_hw_params(struct snd_pcm_substream *substream, 436static int ak4671_hw_params(struct snd_pcm_substream *substream,
449 struct snd_pcm_hw_params *params, 437 struct snd_pcm_hw_params *params,
450 struct snd_soc_dai *dai) 438 struct snd_soc_dai *dai)
@@ -602,7 +590,7 @@ static int ak4671_set_bias_level(struct snd_soc_codec *codec,
602 snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00); 590 snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00);
603 break; 591 break;
604 } 592 }
605 codec->bias_level = level; 593 codec->dapm.bias_level = level;
606 return 0; 594 return 0;
607} 595}
608 596
@@ -619,8 +607,8 @@ static struct snd_soc_dai_ops ak4671_dai_ops = {
619 .set_fmt = ak4671_set_dai_fmt, 607 .set_fmt = ak4671_set_dai_fmt,
620}; 608};
621 609
622struct snd_soc_dai ak4671_dai = { 610static struct snd_soc_dai_driver ak4671_dai = {
623 .name = "AK4671", 611 .name = "ak4671-hifi",
624 .playback = { 612 .playback = {
625 .stream_name = "Playback", 613 .stream_name = "Playback",
626 .channels_min = 1, 614 .channels_min = 1,
@@ -635,151 +623,72 @@ struct snd_soc_dai ak4671_dai = {
635 .formats = AK4671_FORMATS,}, 623 .formats = AK4671_FORMATS,},
636 .ops = &ak4671_dai_ops, 624 .ops = &ak4671_dai_ops,
637}; 625};
638EXPORT_SYMBOL_GPL(ak4671_dai);
639 626
640static int ak4671_probe(struct platform_device *pdev) 627static int ak4671_probe(struct snd_soc_codec *codec)
641{ 628{
642 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 629 struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
643 struct snd_soc_codec *codec; 630 int ret;
644 int ret = 0;
645
646 if (ak4671_codec == NULL) {
647 dev_err(&pdev->dev, "Codec device not registered\n");
648 return -ENODEV;
649 }
650 631
651 socdev->card->codec = ak4671_codec; 632 codec->hw_write = (hw_write_t)i2c_master_send;
652 codec = ak4671_codec;
653 633
654 /* register pcms */ 634 ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
655 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
656 if (ret < 0) { 635 if (ret < 0) {
657 dev_err(codec->dev, "failed to create pcms: %d\n", ret); 636 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
658 goto pcm_err; 637 return ret;
659 } 638 }
660 639
661 snd_soc_add_controls(codec, ak4671_snd_controls, 640 snd_soc_add_controls(codec, ak4671_snd_controls,
662 ARRAY_SIZE(ak4671_snd_controls)); 641 ARRAY_SIZE(ak4671_snd_controls));
663 ak4671_add_widgets(codec);
664 642
665 ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 643 ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
666 644
667 return ret; 645 return ret;
668
669pcm_err:
670 return ret;
671} 646}
672 647
673static int ak4671_remove(struct platform_device *pdev) 648static int ak4671_remove(struct snd_soc_codec *codec)
674{ 649{
675 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 650 ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF);
676
677 snd_soc_free_pcms(socdev);
678 snd_soc_dapm_free(socdev);
679
680 return 0; 651 return 0;
681} 652}
682 653
683struct snd_soc_codec_device soc_codec_dev_ak4671 = { 654static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
684 .probe = ak4671_probe, 655 .probe = ak4671_probe,
685 .remove = ak4671_remove, 656 .remove = ak4671_remove,
657 .set_bias_level = ak4671_set_bias_level,
658 .reg_cache_size = AK4671_CACHEREGNUM,
659 .reg_word_size = sizeof(u8),
660 .reg_cache_default = ak4671_reg,
661 .dapm_widgets = ak4671_dapm_widgets,
662 .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets),
663 .dapm_routes = ak4671_intercon,
664 .num_dapm_routes = ARRAY_SIZE(ak4671_intercon),
686}; 665};
687EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671);
688
689static int ak4671_register(struct ak4671_priv *ak4671,
690 enum snd_soc_control_type control)
691{
692 int ret;
693 struct snd_soc_codec *codec = &ak4671->codec;
694
695 if (ak4671_codec) {
696 dev_err(codec->dev, "Another AK4671 is registered\n");
697 ret = -EINVAL;
698 goto err;
699 }
700
701 mutex_init(&codec->mutex);
702 INIT_LIST_HEAD(&codec->dapm_widgets);
703 INIT_LIST_HEAD(&codec->dapm_paths);
704
705 snd_soc_codec_set_drvdata(codec, ak4671);
706 codec->name = "AK4671";
707 codec->owner = THIS_MODULE;
708 codec->bias_level = SND_SOC_BIAS_OFF;
709 codec->set_bias_level = ak4671_set_bias_level;
710 codec->dai = &ak4671_dai;
711 codec->num_dai = 1;
712 codec->reg_cache_size = AK4671_CACHEREGNUM;
713 codec->reg_cache = &ak4671->reg_cache;
714
715 memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg));
716
717 ret = snd_soc_codec_set_cache_io(codec, 8, 8, control);
718 if (ret < 0) {
719 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
720 goto err;
721 }
722
723 ak4671_dai.dev = codec->dev;
724 ak4671_codec = codec;
725
726 ret = snd_soc_register_codec(codec);
727 if (ret != 0) {
728 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
729 goto err;
730 }
731
732 ret = snd_soc_register_dai(&ak4671_dai);
733 if (ret != 0) {
734 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
735 goto err_codec;
736 }
737
738 return 0;
739
740err_codec:
741 snd_soc_unregister_codec(codec);
742err:
743 kfree(ak4671);
744 return ret;
745}
746
747static void ak4671_unregister(struct ak4671_priv *ak4671)
748{
749 ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF);
750 snd_soc_unregister_dai(&ak4671_dai);
751 snd_soc_unregister_codec(&ak4671->codec);
752 kfree(ak4671);
753 ak4671_codec = NULL;
754}
755 666
756static int __devinit ak4671_i2c_probe(struct i2c_client *client, 667static int __devinit ak4671_i2c_probe(struct i2c_client *client,
757 const struct i2c_device_id *id) 668 const struct i2c_device_id *id)
758{ 669{
759 struct ak4671_priv *ak4671; 670 struct ak4671_priv *ak4671;
760 struct snd_soc_codec *codec; 671 int ret;
761 672
762 ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL); 673 ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL);
763 if (ak4671 == NULL) 674 if (ak4671 == NULL)
764 return -ENOMEM; 675 return -ENOMEM;
765 676
766 codec = &ak4671->codec;
767 codec->hw_write = (hw_write_t)i2c_master_send;
768
769 i2c_set_clientdata(client, ak4671); 677 i2c_set_clientdata(client, ak4671);
770 codec->control_data = client; 678 ak4671->control_data = client;
771 679 ak4671->control_type = SND_SOC_I2C;
772 codec->dev = &client->dev;
773 680
774 return ak4671_register(ak4671, SND_SOC_I2C); 681 ret = snd_soc_register_codec(&client->dev,
682 &soc_codec_dev_ak4671, &ak4671_dai, 1);
683 if (ret < 0)
684 kfree(ak4671);
685 return ret;
775} 686}
776 687
777static __devexit int ak4671_i2c_remove(struct i2c_client *client) 688static __devexit int ak4671_i2c_remove(struct i2c_client *client)
778{ 689{
779 struct ak4671_priv *ak4671 = i2c_get_clientdata(client); 690 snd_soc_unregister_codec(&client->dev);
780 691 kfree(i2c_get_clientdata(client));
781 ak4671_unregister(ak4671);
782
783 return 0; 692 return 0;
784} 693}
785 694
@@ -791,7 +700,7 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);
791 700
792static struct i2c_driver ak4671_i2c_driver = { 701static struct i2c_driver ak4671_i2c_driver = {
793 .driver = { 702 .driver = {
794 .name = "ak4671", 703 .name = "ak4671-codec",
795 .owner = THIS_MODULE, 704 .owner = THIS_MODULE,
796 }, 705 },
797 .probe = ak4671_i2c_probe, 706 .probe = ak4671_i2c_probe,