diff options
Diffstat (limited to 'sound/soc/codecs/ak4671.c')
-rw-r--r-- | sound/soc/codecs/ak4671.c | 161 |
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 | ||
26 | static struct snd_soc_codec *ak4671_codec; | ||
27 | 25 | ||
28 | /* codec private data */ | 26 | /* codec private data */ |
29 | struct ak4671_priv { | 27 | struct 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 | ||
357 | static const struct snd_soc_dapm_route intercon[] = { | 355 | static 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 | ||
438 | static 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 | |||
448 | static int ak4671_hw_params(struct snd_pcm_substream *substream, | 436 | static 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 | ||
622 | struct snd_soc_dai ak4671_dai = { | 610 | static 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 | }; |
638 | EXPORT_SYMBOL_GPL(ak4671_dai); | ||
639 | 626 | ||
640 | static int ak4671_probe(struct platform_device *pdev) | 627 | static 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 | |||
669 | pcm_err: | ||
670 | return ret; | ||
671 | } | 646 | } |
672 | 647 | ||
673 | static int ak4671_remove(struct platform_device *pdev) | 648 | static 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 | ||
683 | struct snd_soc_codec_device soc_codec_dev_ak4671 = { | 654 | static 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 | }; |
687 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671); | ||
688 | |||
689 | static 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 | |||
740 | err_codec: | ||
741 | snd_soc_unregister_codec(codec); | ||
742 | err: | ||
743 | kfree(ak4671); | ||
744 | return ret; | ||
745 | } | ||
746 | |||
747 | static 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 | ||
756 | static int __devinit ak4671_i2c_probe(struct i2c_client *client, | 667 | static 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 | ||
777 | static __devexit int ak4671_i2c_remove(struct i2c_client *client) | 688 | static __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 | ||
792 | static struct i2c_driver ak4671_i2c_driver = { | 701 | static 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, |