aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/cs4270.c
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@slimlogic.co.uk>2010-03-17 16:15:21 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2010-08-12 09:00:00 -0400
commitf0fba2ad1b6b53d5360125c41953b7afcd6deff0 (patch)
treef6ad50905f8daa616593c978d7ae992e73241180 /sound/soc/codecs/cs4270.c
parentbda7d2a862e6b788bca2d02d38a07966a9c92e48 (diff)
ASoC: multi-component - ASoC Multi-Component Support
This patch extends the ASoC API to allow sound cards to have more than one CODEC and more than one platform DMA controller. This is achieved by dividing some current ASoC structures that contain both driver data and device data into structures that only either contain device data or driver data. i.e. struct snd_soc_codec ---> struct snd_soc_codec (device data) +-> struct snd_soc_codec_driver (driver data) struct snd_soc_platform ---> struct snd_soc_platform (device data) +-> struct snd_soc_platform_driver (driver data) struct snd_soc_dai ---> struct snd_soc_dai (device data) +-> struct snd_soc_dai_driver (driver data) struct snd_soc_device ---> deleted This now allows ASoC to be more tightly aligned with the Linux driver model and also means that every ASoC codec, platform and (platform) DAI is a kernel device. ASoC component private data is now stored as device private data. The ASoC sound card struct snd_soc_card has also been updated to store lists of it's components rather than a pointer to a codec and platform. The PCM runtime struct soc_pcm_runtime now has pointers to all its components. This patch adds DAPM support for ASoC multi-component and removes struct snd_soc_socdev from DAPM core. All DAPM calls are now made on a card, codec or runtime PCM level basis rather than using snd_soc_socdev. Other notable multi-component changes:- * Stream operations now de-reference less structures. * close_delayed work() now runs on a DAI basis rather than looping all DAIs in a card. * PM suspend()/resume() operations can now handle N CODECs and Platforms per sound card. * Added soc_bind_dai_link() to bind the component devices to the sound card. * Added soc_dai_link_probe() and soc_dai_link_remove() to probe and remove DAI link components. * sysfs entries can now be registered per component per card. * snd_soc_new_pcms() functionailty rolled into dai_link_probe(). * snd_soc_register_codec() now does all the codec list and mutex init. This patch changes the probe() and remove() of the CODEC drivers as follows:- o Make CODEC driver a platform driver o Moved all struct snd_soc_codec list, mutex, etc initialiasation to core. o Removed all static codec pointers (drivers now support > 1 codec dev) o snd_soc_register_pcms() now done by core. o snd_soc_register_dai() folded into snd_soc_register_codec(). CS4270 portions: Acked-by: Timur Tabi <timur@freescale.com> Some TLV320aic23 and Cirrus platform fixes. Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> TI CODEC and OMAP fixes Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Signed-off-by: Jarkko Nikula <jhnikula@gmail.com> Samsung platform and misc fixes :- Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Jassi Brar <jassi.brar@samsung.com> Signed-off-by: Seungwhan Youn <sw.youn@samsung.com> MPC8610 and PPC fixes. Signed-off-by: Timur Tabi <timur@freescale.com> i.MX fixes and some core fixes. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> J4740 platform fixes:- Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> CC: Tony Lindgren <tony@atomide.com> CC: Nicolas Ferre <nicolas.ferre@atmel.com> CC: Kevin Hilman <khilman@deeprootsystems.com> CC: Sascha Hauer <s.hauer@pengutronix.de> CC: Atsushi Nemoto <anemo@mba.ocn.ne.jp> CC: Kuninori Morimoto <morimoto.kuninori@renesas.com> CC: Daniel Gloeckner <dg@emlix.com> CC: Manuel Lauss <mano@roarinelk.homelinux.net> CC: Mike Frysinger <vapier.adi@gmail.com> CC: Arnaud Patard <apatard@mandriva.com> CC: Wan ZongShun <mcuos.com@gmail.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/codecs/cs4270.c')
-rw-r--r--sound/soc/codecs/cs4270.c393
1 files changed, 138 insertions, 255 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 30d949239def..6542dc038951 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 */
116struct cs4270_private { 114struct 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 */
563static struct snd_soc_codec *cs4270_codec;
564
565static struct snd_soc_dai_ops cs4270_dai_ops = { 514static 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,20 +518,24 @@ 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
572struct snd_soc_dai cs4270_dai = { 521struct 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,
@@ -596,153 +549,19 @@ EXPORT_SYMBOL_GPL(cs4270_dai);
596 * This function is called when ASoC has all the pieces it needs to 549 * This function is called when ASoC has all the pieces it needs to
597 * instantiate a sound driver. 550 * instantiate a sound driver.
598 */ 551 */
599static int cs4270_probe(struct platform_device *pdev) 552static 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
640error_free_regulators:
641 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
642 cs4270->supplies);
643
644error_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 */
656static int cs4270_remove(struct platform_device *pdev)
657{ 553{
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); 554 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
555 int i, ret, reg;
661 556
662 snd_soc_free_pcms(socdev); 557 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 */
677static 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 558
740 /* The I2C interface is set up, so pre-fill our register cache */ 559 /* The I2C interface is set up, so pre-fill our register cache */
741 560
742 ret = cs4270_fill_cache(codec); 561 ret = cs4270_fill_cache(codec);
743 if (ret < 0) { 562 if (ret < 0) {
744 dev_err(&i2c_client->dev, "failed to fill register cache\n"); 563 dev_err(codec->dev, "failed to fill register cache\n");
745 goto error_free_codec; 564 return ret;
746 } 565 }
747 566
748 /* Disable auto-mute. This feature appears to be buggy. In some 567 /* Disable auto-mute. This feature appears to be buggy. In some
@@ -755,7 +574,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
755 reg &= ~CS4270_MUTE_AUTO; 574 reg &= ~CS4270_MUTE_AUTO;
756 ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); 575 ret = cs4270_i2c_write(codec, CS4270_MUTE, reg);
757 if (ret < 0) { 576 if (ret < 0) {
758 dev_err(&i2c_client->dev, "i2c write failed\n"); 577 dev_err(codec->dev, "i2c write failed\n");
759 return ret; 578 return ret;
760 } 579 }
761 580
@@ -769,65 +588,56 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
769 reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); 588 reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
770 ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); 589 ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
771 if (ret < 0) { 590 if (ret < 0) {
772 dev_err(&i2c_client->dev, "i2c write failed\n"); 591 dev_err(codec->dev, "i2c write failed\n");
773 return ret; 592 return ret;
774 } 593 }
775 594
776 /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI 595 /* Add the non-DAPM controls */
777 * structure for each CS4270 device, but the machine driver needs to 596 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 597 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) { 598 if (ret < 0) {
790 dev_err(&i2c_client->dev, "failed to register DAIe\n"); 599 dev_err(codec->dev, "failed to add controls\n");
791 goto error_free_codec; 600 return ret;
792 } 601 }
793 602
794 i2c_set_clientdata(i2c_client, cs4270); 603 /* get the power supply regulators */
604 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
605 cs4270->supplies[i].supply = supply_names[i];
606
607 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
608 cs4270->supplies);
609 if (ret < 0)
610 return ret;
611
612 ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
613 cs4270->supplies);
614 if (ret < 0)
615 goto error_free_regulators;
795 616
796 return 0; 617 return 0;
797 618
798error_free_codec: 619error_free_regulators:
799 kfree(cs4270); 620 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
800 cs4270_codec = NULL; 621 cs4270->supplies);
801 cs4270_dai.dev = NULL;
802 622
803 return ret; 623 return ret;
804} 624}
805 625
806/** 626/**
807 * cs4270_i2c_remove - remove an I2C device 627 * cs4270_remove - ASoC remove function
808 * @i2c_client: the I2C client object 628 * @pdev: platform device
809 * 629 *
810 * This function is the counterpart to cs4270_i2c_probe(). 630 * This function is the counterpart to cs4270_probe().
811 */ 631 */
812static int cs4270_i2c_remove(struct i2c_client *i2c_client) 632static int cs4270_remove(struct snd_soc_codec *codec)
813{ 633{
814 struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); 634 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
815 635
816 kfree(cs4270); 636 regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
817 cs4270_codec = NULL; 637 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
818 cs4270_dai.dev = NULL;
819 638
820 return 0; 639 return 0;
821}
822
823/*
824 * cs4270_id - I2C device IDs supported by this driver
825 */
826static struct i2c_device_id cs4270_id[] = {
827 {"cs4270", 0},
828 {}
829}; 640};
830MODULE_DEVICE_TABLE(i2c, cs4270_id);
831 641
832#ifdef CONFIG_PM 642#ifdef CONFIG_PM
833 643
@@ -840,9 +650,8 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
840 * and all registers are written back to the hardware when resuming. 650 * and all registers are written back to the hardware when resuming.
841 */ 651 */
842 652
843static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) 653static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
844{ 654{
845 struct snd_soc_codec *codec = cs4270_codec;
846 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); 655 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
847 int reg, ret; 656 int reg, ret;
848 657
@@ -860,9 +669,8 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
860 return 0; 669 return 0;
861} 670}
862 671
863static int cs4270_soc_resume(struct platform_device *pdev) 672static int cs4270_soc_resume(struct snd_soc_codec *codec)
864{ 673{
865 struct snd_soc_codec *codec = cs4270_codec;
866 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); 674 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
867 struct i2c_client *i2c_client = codec->control_data; 675 struct i2c_client *i2c_client = codec->control_data;
868 int reg; 676 int reg;
@@ -896,6 +704,95 @@ static int cs4270_soc_resume(struct platform_device *pdev)
896#endif /* CONFIG_PM */ 704#endif /* CONFIG_PM */
897 705
898/* 706/*
707 * ASoC codec device structure
708 *
709 * Assign this variable to the codec_dev field of the machine driver's
710 * snd_soc_device structure.
711 */
712static struct snd_soc_codec_driver soc_codec_device_cs4270 = {
713 .probe = cs4270_probe,
714 .remove = cs4270_remove,
715 .suspend = cs4270_soc_suspend,
716 .resume = cs4270_soc_resume,
717 .read = cs4270_read_reg_cache,
718 .write = cs4270_i2c_write,
719 .reg_cache_size = CS4270_NUMREGS,
720 .reg_word_size = sizeof(u8),
721};
722
723/**
724 * cs4270_i2c_probe - initialize the I2C interface of the CS4270
725 * @i2c_client: the I2C client object
726 * @id: the I2C device ID (ignored)
727 *
728 * This function is called whenever the I2C subsystem finds a device that
729 * matches the device ID given via a prior call to i2c_add_driver().
730 */
731static int cs4270_i2c_probe(struct i2c_client *i2c_client,
732 const struct i2c_device_id *id)
733{
734 struct cs4270_private *cs4270;
735 int ret;
736
737 /* Verify that we have a CS4270 */
738
739 ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
740 if (ret < 0) {
741 dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n",
742 i2c_client->addr);
743 return ret;
744 }
745 /* The top four bits of the chip ID should be 1100. */
746 if ((ret & 0xF0) != 0xC0) {
747 dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n",
748 i2c_client->addr);
749 return -ENODEV;
750 }
751
752 dev_info(&i2c_client->dev, "found device at i2c address %X\n",
753 i2c_client->addr);
754 dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF);
755
756 cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL);
757 if (!cs4270) {
758 dev_err(&i2c_client->dev, "could not allocate codec\n");
759 return -ENOMEM;
760 }
761
762 i2c_set_clientdata(i2c_client, cs4270);
763 cs4270->control_data = i2c_client;
764 cs4270->control_type = SND_SOC_I2C;
765
766 ret = snd_soc_register_codec(&i2c_client->dev,
767 &soc_codec_device_cs4270, &cs4270_dai, 1);
768 if (ret < 0)
769 kfree(cs4270);
770 return ret;
771}
772
773/**
774 * cs4270_i2c_remove - remove an I2C device
775 * @i2c_client: the I2C client object
776 *
777 * This function is the counterpart to cs4270_i2c_probe().
778 */
779static int cs4270_i2c_remove(struct i2c_client *i2c_client)
780{
781 snd_soc_unregister_codec(&i2c_client->dev);
782 kfree(i2c_get_clientdata(i2c_client));
783 return 0;
784}
785
786/*
787 * cs4270_id - I2C device IDs supported by this driver
788 */
789static struct i2c_device_id cs4270_id[] = {
790 {"cs4270", 0},
791 {}
792};
793MODULE_DEVICE_TABLE(i2c, cs4270_id);
794
795/*
899 * cs4270_i2c_driver - I2C device identification 796 * cs4270_i2c_driver - I2C device identification
900 * 797 *
901 * This structure tells the I2C subsystem how to identify and support a 798 * This structure tells the I2C subsystem how to identify and support a
@@ -903,7 +800,7 @@ static int cs4270_soc_resume(struct platform_device *pdev)
903 */ 800 */
904static struct i2c_driver cs4270_i2c_driver = { 801static struct i2c_driver cs4270_i2c_driver = {
905 .driver = { 802 .driver = {
906 .name = "cs4270", 803 .name = "cs4270-codec",
907 .owner = THIS_MODULE, 804 .owner = THIS_MODULE,
908 }, 805 },
909 .id_table = cs4270_id, 806 .id_table = cs4270_id,
@@ -911,20 +808,6 @@ static struct i2c_driver cs4270_i2c_driver = {
911 .remove = cs4270_i2c_remove, 808 .remove = cs4270_i2c_remove,
912}; 809};
913 810
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 */
920struct 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};
926EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
927
928static int __init cs4270_init(void) 811static int __init cs4270_init(void)
929{ 812{
930 pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); 813 pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n");