diff options
Diffstat (limited to 'sound/soc/codecs/cs4270.c')
-rw-r--r-- | sound/soc/codecs/cs4270.c | 394 |
1 files changed, 138 insertions, 256 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 30d949239def..6d4bdc609ac8 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/regulator/consumer.h> | 32 | #include <linux/regulator/consumer.h> |
33 | 33 | ||
34 | #include "cs4270.h" | ||
35 | |||
36 | /* | 34 | /* |
37 | * The codec isn't really big-endian or little-endian, since the I2S | 35 | * The codec isn't really big-endian or little-endian, since the I2S |
38 | * interface requires data to be sent serially with the MSbit first. | 36 | * interface requires data to be sent serially with the MSbit first. |
@@ -114,7 +112,8 @@ static const char *supply_names[] = { | |||
114 | 112 | ||
115 | /* Private data for the CS4270 */ | 113 | /* Private data for the CS4270 */ |
116 | struct cs4270_private { | 114 | struct cs4270_private { |
117 | struct snd_soc_codec codec; | 115 | enum snd_soc_control_type control_type; |
116 | void *control_data; | ||
118 | u8 reg_cache[CS4270_NUMREGS]; | 117 | u8 reg_cache[CS4270_NUMREGS]; |
119 | unsigned int mclk; /* Input frequency of the MCLK pin */ | 118 | unsigned int mclk; /* Input frequency of the MCLK pin */ |
120 | unsigned int mode; /* The mode (I2S or left-justified) */ | 119 | unsigned int mode; /* The mode (I2S or left-justified) */ |
@@ -212,44 +211,8 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
212 | { | 211 | { |
213 | struct snd_soc_codec *codec = codec_dai->codec; | 212 | struct snd_soc_codec *codec = codec_dai->codec; |
214 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 213 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
215 | unsigned int rates = 0; | ||
216 | unsigned int rate_min = -1; | ||
217 | unsigned int rate_max = 0; | ||
218 | unsigned int i; | ||
219 | 214 | ||
220 | cs4270->mclk = freq; | 215 | cs4270->mclk = freq; |
221 | |||
222 | if (cs4270->mclk) { | ||
223 | for (i = 0; i < NUM_MCLK_RATIOS; i++) { | ||
224 | unsigned int rate = freq / cs4270_mode_ratios[i].ratio; | ||
225 | rates |= snd_pcm_rate_to_rate_bit(rate); | ||
226 | if (rate < rate_min) | ||
227 | rate_min = rate; | ||
228 | if (rate > rate_max) | ||
229 | rate_max = rate; | ||
230 | } | ||
231 | /* FIXME: soc should support a rate list */ | ||
232 | rates &= ~SNDRV_PCM_RATE_KNOT; | ||
233 | |||
234 | if (!rates) { | ||
235 | dev_err(codec->dev, "could not find a valid sample rate\n"); | ||
236 | return -EINVAL; | ||
237 | } | ||
238 | } else { | ||
239 | /* enable all possible rates */ | ||
240 | rates = SNDRV_PCM_RATE_8000_192000; | ||
241 | rate_min = 8000; | ||
242 | rate_max = 192000; | ||
243 | } | ||
244 | |||
245 | codec_dai->playback.rates = rates; | ||
246 | codec_dai->playback.rate_min = rate_min; | ||
247 | codec_dai->playback.rate_max = rate_max; | ||
248 | |||
249 | codec_dai->capture.rates = rates; | ||
250 | codec_dai->capture.rate_min = rate_min; | ||
251 | codec_dai->capture.rate_max = rate_max; | ||
252 | |||
253 | return 0; | 216 | return 0; |
254 | } | 217 | } |
255 | 218 | ||
@@ -410,8 +373,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
410 | struct snd_soc_dai *dai) | 373 | struct snd_soc_dai *dai) |
411 | { | 374 | { |
412 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 375 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
413 | struct snd_soc_device *socdev = rtd->socdev; | 376 | struct snd_soc_codec *codec = rtd->codec; |
414 | struct snd_soc_codec *codec = socdev->card->codec; | ||
415 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 377 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
416 | int ret; | 378 | int ret; |
417 | unsigned int i; | 379 | unsigned int i; |
@@ -549,19 +511,6 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { | |||
549 | snd_soc_get_volsw, cs4270_soc_put_mute), | 511 | snd_soc_get_volsw, cs4270_soc_put_mute), |
550 | }; | 512 | }; |
551 | 513 | ||
552 | /* | ||
553 | * cs4270_codec - global variable to store codec for the ASoC probe function | ||
554 | * | ||
555 | * If struct i2c_driver had a private_data field, we wouldn't need to use | ||
556 | * cs4270_codec. This is the only way to pass the codec structure from | ||
557 | * cs4270_i2c_probe() to cs4270_probe(). Unfortunately, there is no good | ||
558 | * way to synchronize these two functions. cs4270_i2c_probe() can be called | ||
559 | * multiple times before cs4270_probe() is called even once. So for now, we | ||
560 | * also only allow cs4270_i2c_probe() to be run once. That means that we do | ||
561 | * not support more than one cs4270 device in the system, at least for now. | ||
562 | */ | ||
563 | static struct snd_soc_codec *cs4270_codec; | ||
564 | |||
565 | static struct snd_soc_dai_ops cs4270_dai_ops = { | 514 | static struct snd_soc_dai_ops cs4270_dai_ops = { |
566 | .hw_params = cs4270_hw_params, | 515 | .hw_params = cs4270_hw_params, |
567 | .set_sysclk = cs4270_set_dai_sysclk, | 516 | .set_sysclk = cs4270_set_dai_sysclk, |
@@ -569,25 +518,28 @@ static struct snd_soc_dai_ops cs4270_dai_ops = { | |||
569 | .digital_mute = cs4270_dai_mute, | 518 | .digital_mute = cs4270_dai_mute, |
570 | }; | 519 | }; |
571 | 520 | ||
572 | struct snd_soc_dai cs4270_dai = { | 521 | static struct snd_soc_dai_driver cs4270_dai = { |
573 | .name = "cs4270", | 522 | .name = "cs4270-hifi", |
574 | .playback = { | 523 | .playback = { |
575 | .stream_name = "Playback", | 524 | .stream_name = "Playback", |
576 | .channels_min = 1, | 525 | .channels_min = 1, |
577 | .channels_max = 2, | 526 | .channels_max = 2, |
578 | .rates = 0, | 527 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
528 | .rate_min = 4000, | ||
529 | .rate_max = 216000, | ||
579 | .formats = CS4270_FORMATS, | 530 | .formats = CS4270_FORMATS, |
580 | }, | 531 | }, |
581 | .capture = { | 532 | .capture = { |
582 | .stream_name = "Capture", | 533 | .stream_name = "Capture", |
583 | .channels_min = 1, | 534 | .channels_min = 1, |
584 | .channels_max = 2, | 535 | .channels_max = 2, |
585 | .rates = 0, | 536 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
537 | .rate_min = 4000, | ||
538 | .rate_max = 216000, | ||
586 | .formats = CS4270_FORMATS, | 539 | .formats = CS4270_FORMATS, |
587 | }, | 540 | }, |
588 | .ops = &cs4270_dai_ops, | 541 | .ops = &cs4270_dai_ops, |
589 | }; | 542 | }; |
590 | EXPORT_SYMBOL_GPL(cs4270_dai); | ||
591 | 543 | ||
592 | /** | 544 | /** |
593 | * cs4270_probe - ASoC probe function | 545 | * cs4270_probe - ASoC probe function |
@@ -596,153 +548,19 @@ EXPORT_SYMBOL_GPL(cs4270_dai); | |||
596 | * This function is called when ASoC has all the pieces it needs to | 548 | * This function is called when ASoC has all the pieces it needs to |
597 | * instantiate a sound driver. | 549 | * instantiate a sound driver. |
598 | */ | 550 | */ |
599 | static int cs4270_probe(struct platform_device *pdev) | 551 | static int cs4270_probe(struct snd_soc_codec *codec) |
600 | { | ||
601 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
602 | struct snd_soc_codec *codec = cs4270_codec; | ||
603 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | ||
604 | int i, ret; | ||
605 | |||
606 | /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ | ||
607 | socdev->card->codec = codec; | ||
608 | |||
609 | /* Register PCMs */ | ||
610 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
611 | if (ret < 0) { | ||
612 | dev_err(codec->dev, "failed to create pcms\n"); | ||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | /* Add the non-DAPM controls */ | ||
617 | ret = snd_soc_add_controls(codec, cs4270_snd_controls, | ||
618 | ARRAY_SIZE(cs4270_snd_controls)); | ||
619 | if (ret < 0) { | ||
620 | dev_err(codec->dev, "failed to add controls\n"); | ||
621 | goto error_free_pcms; | ||
622 | } | ||
623 | |||
624 | /* get the power supply regulators */ | ||
625 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
626 | cs4270->supplies[i].supply = supply_names[i]; | ||
627 | |||
628 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), | ||
629 | cs4270->supplies); | ||
630 | if (ret < 0) | ||
631 | goto error_free_pcms; | ||
632 | |||
633 | ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), | ||
634 | cs4270->supplies); | ||
635 | if (ret < 0) | ||
636 | goto error_free_regulators; | ||
637 | |||
638 | return 0; | ||
639 | |||
640 | error_free_regulators: | ||
641 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), | ||
642 | cs4270->supplies); | ||
643 | |||
644 | error_free_pcms: | ||
645 | snd_soc_free_pcms(socdev); | ||
646 | |||
647 | return ret; | ||
648 | } | ||
649 | |||
650 | /** | ||
651 | * cs4270_remove - ASoC remove function | ||
652 | * @pdev: platform device | ||
653 | * | ||
654 | * This function is the counterpart to cs4270_probe(). | ||
655 | */ | ||
656 | static int cs4270_remove(struct platform_device *pdev) | ||
657 | { | 552 | { |
658 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
659 | struct snd_soc_codec *codec = cs4270_codec; | ||
660 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 553 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
554 | int i, ret, reg; | ||
661 | 555 | ||
662 | snd_soc_free_pcms(socdev); | 556 | codec->control_data = cs4270->control_data; |
663 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | ||
664 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | ||
665 | |||
666 | return 0; | ||
667 | }; | ||
668 | |||
669 | /** | ||
670 | * cs4270_i2c_probe - initialize the I2C interface of the CS4270 | ||
671 | * @i2c_client: the I2C client object | ||
672 | * @id: the I2C device ID (ignored) | ||
673 | * | ||
674 | * This function is called whenever the I2C subsystem finds a device that | ||
675 | * matches the device ID given via a prior call to i2c_add_driver(). | ||
676 | */ | ||
677 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, | ||
678 | const struct i2c_device_id *id) | ||
679 | { | ||
680 | struct snd_soc_codec *codec; | ||
681 | struct cs4270_private *cs4270; | ||
682 | unsigned int reg; | ||
683 | int ret; | ||
684 | |||
685 | /* For now, we only support one cs4270 device in the system. See the | ||
686 | * comment for cs4270_codec. | ||
687 | */ | ||
688 | if (cs4270_codec) { | ||
689 | dev_err(&i2c_client->dev, "ignoring CS4270 at addr %X\n", | ||
690 | i2c_client->addr); | ||
691 | dev_err(&i2c_client->dev, "only one per board allowed\n"); | ||
692 | /* Should we return something other than ENODEV here? */ | ||
693 | return -ENODEV; | ||
694 | } | ||
695 | |||
696 | /* Verify that we have a CS4270 */ | ||
697 | |||
698 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | ||
699 | if (ret < 0) { | ||
700 | dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", | ||
701 | i2c_client->addr); | ||
702 | return ret; | ||
703 | } | ||
704 | /* The top four bits of the chip ID should be 1100. */ | ||
705 | if ((ret & 0xF0) != 0xC0) { | ||
706 | dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", | ||
707 | i2c_client->addr); | ||
708 | return -ENODEV; | ||
709 | } | ||
710 | |||
711 | dev_info(&i2c_client->dev, "found device at i2c address %X\n", | ||
712 | i2c_client->addr); | ||
713 | dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); | ||
714 | |||
715 | /* Allocate enough space for the snd_soc_codec structure | ||
716 | and our private data together. */ | ||
717 | cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); | ||
718 | if (!cs4270) { | ||
719 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
720 | return -ENOMEM; | ||
721 | } | ||
722 | codec = &cs4270->codec; | ||
723 | |||
724 | mutex_init(&codec->mutex); | ||
725 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
726 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
727 | |||
728 | codec->dev = &i2c_client->dev; | ||
729 | codec->name = "CS4270"; | ||
730 | codec->owner = THIS_MODULE; | ||
731 | codec->dai = &cs4270_dai; | ||
732 | codec->num_dai = 1; | ||
733 | snd_soc_codec_set_drvdata(codec, cs4270); | ||
734 | codec->control_data = i2c_client; | ||
735 | codec->read = cs4270_read_reg_cache; | ||
736 | codec->write = cs4270_i2c_write; | ||
737 | codec->reg_cache = cs4270->reg_cache; | ||
738 | codec->reg_cache_size = CS4270_NUMREGS; | ||
739 | 557 | ||
740 | /* The I2C interface is set up, so pre-fill our register cache */ | 558 | /* The I2C interface is set up, so pre-fill our register cache */ |
741 | 559 | ||
742 | ret = cs4270_fill_cache(codec); | 560 | ret = cs4270_fill_cache(codec); |
743 | if (ret < 0) { | 561 | if (ret < 0) { |
744 | dev_err(&i2c_client->dev, "failed to fill register cache\n"); | 562 | dev_err(codec->dev, "failed to fill register cache\n"); |
745 | goto error_free_codec; | 563 | return ret; |
746 | } | 564 | } |
747 | 565 | ||
748 | /* Disable auto-mute. This feature appears to be buggy. In some | 566 | /* Disable auto-mute. This feature appears to be buggy. In some |
@@ -755,7 +573,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
755 | reg &= ~CS4270_MUTE_AUTO; | 573 | reg &= ~CS4270_MUTE_AUTO; |
756 | ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); | 574 | ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); |
757 | if (ret < 0) { | 575 | if (ret < 0) { |
758 | dev_err(&i2c_client->dev, "i2c write failed\n"); | 576 | dev_err(codec->dev, "i2c write failed\n"); |
759 | return ret; | 577 | return ret; |
760 | } | 578 | } |
761 | 579 | ||
@@ -769,65 +587,56 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
769 | reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); | 587 | reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); |
770 | ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); | 588 | ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); |
771 | if (ret < 0) { | 589 | if (ret < 0) { |
772 | dev_err(&i2c_client->dev, "i2c write failed\n"); | 590 | dev_err(codec->dev, "i2c write failed\n"); |
773 | return ret; | 591 | return ret; |
774 | } | 592 | } |
775 | 593 | ||
776 | /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI | 594 | /* Add the non-DAPM controls */ |
777 | * structure for each CS4270 device, but the machine driver needs to | 595 | ret = snd_soc_add_controls(codec, cs4270_snd_controls, |
778 | * have a pointer to the DAI structure, so for now it must be a global | 596 | ARRAY_SIZE(cs4270_snd_controls)); |
779 | * variable. | ||
780 | */ | ||
781 | cs4270_dai.dev = &i2c_client->dev; | ||
782 | |||
783 | /* Register the DAI. If all the other ASoC driver have already | ||
784 | * registered, then this will call our probe function, so | ||
785 | * cs4270_codec needs to be ready. | ||
786 | */ | ||
787 | cs4270_codec = codec; | ||
788 | ret = snd_soc_register_dai(&cs4270_dai); | ||
789 | if (ret < 0) { | 597 | if (ret < 0) { |
790 | dev_err(&i2c_client->dev, "failed to register DAIe\n"); | 598 | dev_err(codec->dev, "failed to add controls\n"); |
791 | goto error_free_codec; | 599 | return ret; |
792 | } | 600 | } |
793 | 601 | ||
794 | i2c_set_clientdata(i2c_client, cs4270); | 602 | /* get the power supply regulators */ |
603 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
604 | cs4270->supplies[i].supply = supply_names[i]; | ||
605 | |||
606 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), | ||
607 | cs4270->supplies); | ||
608 | if (ret < 0) | ||
609 | return ret; | ||
610 | |||
611 | ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), | ||
612 | cs4270->supplies); | ||
613 | if (ret < 0) | ||
614 | goto error_free_regulators; | ||
795 | 615 | ||
796 | return 0; | 616 | return 0; |
797 | 617 | ||
798 | error_free_codec: | 618 | error_free_regulators: |
799 | kfree(cs4270); | 619 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), |
800 | cs4270_codec = NULL; | 620 | cs4270->supplies); |
801 | cs4270_dai.dev = NULL; | ||
802 | 621 | ||
803 | return ret; | 622 | return ret; |
804 | } | 623 | } |
805 | 624 | ||
806 | /** | 625 | /** |
807 | * cs4270_i2c_remove - remove an I2C device | 626 | * cs4270_remove - ASoC remove function |
808 | * @i2c_client: the I2C client object | 627 | * @pdev: platform device |
809 | * | 628 | * |
810 | * This function is the counterpart to cs4270_i2c_probe(). | 629 | * This function is the counterpart to cs4270_probe(). |
811 | */ | 630 | */ |
812 | static int cs4270_i2c_remove(struct i2c_client *i2c_client) | 631 | static int cs4270_remove(struct snd_soc_codec *codec) |
813 | { | 632 | { |
814 | struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); | 633 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
815 | 634 | ||
816 | kfree(cs4270); | 635 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); |
817 | cs4270_codec = NULL; | 636 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); |
818 | cs4270_dai.dev = NULL; | ||
819 | 637 | ||
820 | return 0; | 638 | return 0; |
821 | } | ||
822 | |||
823 | /* | ||
824 | * cs4270_id - I2C device IDs supported by this driver | ||
825 | */ | ||
826 | static struct i2c_device_id cs4270_id[] = { | ||
827 | {"cs4270", 0}, | ||
828 | {} | ||
829 | }; | 639 | }; |
830 | MODULE_DEVICE_TABLE(i2c, cs4270_id); | ||
831 | 640 | ||
832 | #ifdef CONFIG_PM | 641 | #ifdef CONFIG_PM |
833 | 642 | ||
@@ -840,9 +649,8 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id); | |||
840 | * and all registers are written back to the hardware when resuming. | 649 | * and all registers are written back to the hardware when resuming. |
841 | */ | 650 | */ |
842 | 651 | ||
843 | static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) | 652 | static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg) |
844 | { | 653 | { |
845 | struct snd_soc_codec *codec = cs4270_codec; | ||
846 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 654 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
847 | int reg, ret; | 655 | int reg, ret; |
848 | 656 | ||
@@ -860,9 +668,8 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
860 | return 0; | 668 | return 0; |
861 | } | 669 | } |
862 | 670 | ||
863 | static int cs4270_soc_resume(struct platform_device *pdev) | 671 | static int cs4270_soc_resume(struct snd_soc_codec *codec) |
864 | { | 672 | { |
865 | struct snd_soc_codec *codec = cs4270_codec; | ||
866 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 673 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
867 | struct i2c_client *i2c_client = codec->control_data; | 674 | struct i2c_client *i2c_client = codec->control_data; |
868 | int reg; | 675 | int reg; |
@@ -896,6 +703,95 @@ static int cs4270_soc_resume(struct platform_device *pdev) | |||
896 | #endif /* CONFIG_PM */ | 703 | #endif /* CONFIG_PM */ |
897 | 704 | ||
898 | /* | 705 | /* |
706 | * ASoC codec device structure | ||
707 | * | ||
708 | * Assign this variable to the codec_dev field of the machine driver's | ||
709 | * snd_soc_device structure. | ||
710 | */ | ||
711 | static struct snd_soc_codec_driver soc_codec_device_cs4270 = { | ||
712 | .probe = cs4270_probe, | ||
713 | .remove = cs4270_remove, | ||
714 | .suspend = cs4270_soc_suspend, | ||
715 | .resume = cs4270_soc_resume, | ||
716 | .read = cs4270_read_reg_cache, | ||
717 | .write = cs4270_i2c_write, | ||
718 | .reg_cache_size = CS4270_NUMREGS, | ||
719 | .reg_word_size = sizeof(u8), | ||
720 | }; | ||
721 | |||
722 | /** | ||
723 | * cs4270_i2c_probe - initialize the I2C interface of the CS4270 | ||
724 | * @i2c_client: the I2C client object | ||
725 | * @id: the I2C device ID (ignored) | ||
726 | * | ||
727 | * This function is called whenever the I2C subsystem finds a device that | ||
728 | * matches the device ID given via a prior call to i2c_add_driver(). | ||
729 | */ | ||
730 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, | ||
731 | const struct i2c_device_id *id) | ||
732 | { | ||
733 | struct cs4270_private *cs4270; | ||
734 | int ret; | ||
735 | |||
736 | /* Verify that we have a CS4270 */ | ||
737 | |||
738 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | ||
739 | if (ret < 0) { | ||
740 | dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", | ||
741 | i2c_client->addr); | ||
742 | return ret; | ||
743 | } | ||
744 | /* The top four bits of the chip ID should be 1100. */ | ||
745 | if ((ret & 0xF0) != 0xC0) { | ||
746 | dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", | ||
747 | i2c_client->addr); | ||
748 | return -ENODEV; | ||
749 | } | ||
750 | |||
751 | dev_info(&i2c_client->dev, "found device at i2c address %X\n", | ||
752 | i2c_client->addr); | ||
753 | dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); | ||
754 | |||
755 | cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); | ||
756 | if (!cs4270) { | ||
757 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
758 | return -ENOMEM; | ||
759 | } | ||
760 | |||
761 | i2c_set_clientdata(i2c_client, cs4270); | ||
762 | cs4270->control_data = i2c_client; | ||
763 | cs4270->control_type = SND_SOC_I2C; | ||
764 | |||
765 | ret = snd_soc_register_codec(&i2c_client->dev, | ||
766 | &soc_codec_device_cs4270, &cs4270_dai, 1); | ||
767 | if (ret < 0) | ||
768 | kfree(cs4270); | ||
769 | return ret; | ||
770 | } | ||
771 | |||
772 | /** | ||
773 | * cs4270_i2c_remove - remove an I2C device | ||
774 | * @i2c_client: the I2C client object | ||
775 | * | ||
776 | * This function is the counterpart to cs4270_i2c_probe(). | ||
777 | */ | ||
778 | static int cs4270_i2c_remove(struct i2c_client *i2c_client) | ||
779 | { | ||
780 | snd_soc_unregister_codec(&i2c_client->dev); | ||
781 | kfree(i2c_get_clientdata(i2c_client)); | ||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | * cs4270_id - I2C device IDs supported by this driver | ||
787 | */ | ||
788 | static struct i2c_device_id cs4270_id[] = { | ||
789 | {"cs4270", 0}, | ||
790 | {} | ||
791 | }; | ||
792 | MODULE_DEVICE_TABLE(i2c, cs4270_id); | ||
793 | |||
794 | /* | ||
899 | * cs4270_i2c_driver - I2C device identification | 795 | * cs4270_i2c_driver - I2C device identification |
900 | * | 796 | * |
901 | * This structure tells the I2C subsystem how to identify and support a | 797 | * This structure tells the I2C subsystem how to identify and support a |
@@ -903,7 +799,7 @@ static int cs4270_soc_resume(struct platform_device *pdev) | |||
903 | */ | 799 | */ |
904 | static struct i2c_driver cs4270_i2c_driver = { | 800 | static struct i2c_driver cs4270_i2c_driver = { |
905 | .driver = { | 801 | .driver = { |
906 | .name = "cs4270", | 802 | .name = "cs4270-codec", |
907 | .owner = THIS_MODULE, | 803 | .owner = THIS_MODULE, |
908 | }, | 804 | }, |
909 | .id_table = cs4270_id, | 805 | .id_table = cs4270_id, |
@@ -911,20 +807,6 @@ static struct i2c_driver cs4270_i2c_driver = { | |||
911 | .remove = cs4270_i2c_remove, | 807 | .remove = cs4270_i2c_remove, |
912 | }; | 808 | }; |
913 | 809 | ||
914 | /* | ||
915 | * ASoC codec device structure | ||
916 | * | ||
917 | * Assign this variable to the codec_dev field of the machine driver's | ||
918 | * snd_soc_device structure. | ||
919 | */ | ||
920 | struct snd_soc_codec_device soc_codec_device_cs4270 = { | ||
921 | .probe = cs4270_probe, | ||
922 | .remove = cs4270_remove, | ||
923 | .suspend = cs4270_soc_suspend, | ||
924 | .resume = cs4270_soc_resume, | ||
925 | }; | ||
926 | EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); | ||
927 | |||
928 | static int __init cs4270_init(void) | 810 | static int __init cs4270_init(void) |
929 | { | 811 | { |
930 | pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); | 812 | pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); |