aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2014-02-17 07:16:53 -0500
committerMark Brown <broonie@linaro.org>2014-02-17 20:07:33 -0500
commitc924dc68f7371582cb420c003faadb700cd4f76c (patch)
treeb7dd0e7f19bb4dcbebecd93a0273b31234ee26dd
parentf75ac2d9bd8211c1890ad591046aef0783ad6416 (diff)
ASoC: ssm2602: Split SPI and I2C code into different modules
There are a few known (minor) problems with having the support code for both I2C and SPI in the same module: * We need to be extra careful to make sure to not build the driver into the kernel if one of the subsystems is build as a module (Currently only I2C can be build as a module). * The module init path error handling is rather ugly. E.g. what should be done if either the SPI or the I2C driver fails to register? Most drivers that implement SPI and I2C in the same module currently fallback to undefined behavior in that case. Splitting the the driver into two modules, one for each bus allows the registration of the other bus driver to continue without problems if one of them fails. This patch splits the ssm2602 driver into 3 modules. One core module that implements the device logic, but is independent of the bus method used. And one module for SPI and I2C each that registers the drivers and sets up the regmap struct for the bus. While we are at it also cleanup the include section of the ssm2602 driver and remove unneeded includes. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--sound/soc/blackfin/Kconfig3
-rw-r--r--sound/soc/codecs/Kconfig11
-rw-r--r--sound/soc/codecs/Makefile4
-rw-r--r--sound/soc/codecs/ssm2602-i2c.c57
-rw-r--r--sound/soc/codecs/ssm2602-spi.c41
-rw-r--r--sound/soc/codecs/ssm2602.c158
-rw-r--r--sound/soc/codecs/ssm2602.h14
7 files changed, 148 insertions, 140 deletions
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index 54f74f8cbb75..f9118dc98853 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -14,7 +14,8 @@ config SND_BF5XX_SOC_SSM2602
14 depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) 14 depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
15 select SND_BF5XX_SOC_I2S if !BF60x 15 select SND_BF5XX_SOC_I2S if !BF60x
16 select SND_BF6XX_SOC_I2S if BF60x 16 select SND_BF6XX_SOC_I2S if BF60x
17 select SND_SOC_SSM2602 17 select SND_SOC_SSM2602_SPI if SPI_MASTER
18 select SND_SOC_SSM2602_I2C if I2C
18 help 19 help
19 Say Y if you want to add support for the Analog Devices 20 Say Y if you want to add support for the Analog Devices
20 SSM2602 Audio Codec Add-On Card. 21 SSM2602 Audio Codec Add-On Card.
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 983d087aa92a..f17e6da53ce7 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -66,7 +66,8 @@ config SND_SOC_ALL_CODECS
66 select SND_SOC_SN95031 if INTEL_SCU_IPC 66 select SND_SOC_SN95031 if INTEL_SCU_IPC
67 select SND_SOC_SPDIF 67 select SND_SOC_SPDIF
68 select SND_SOC_SSM2518 if I2C 68 select SND_SOC_SSM2518 if I2C
69 select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI 69 select SND_SOC_SSM2602_SPI if SPI_MASTER
70 select SND_SOC_SSM2602_I2C if I2C
70 select SND_SOC_STA32X if I2C 71 select SND_SOC_STA32X if I2C
71 select SND_SOC_STA529 if I2C 72 select SND_SOC_STA529 if I2C
72 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS 73 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
@@ -342,6 +343,14 @@ config SND_SOC_SSM2518
342config SND_SOC_SSM2602 343config SND_SOC_SSM2602
343 tristate 344 tristate
344 345
346config SND_SOC_SSM2602_SPI
347 select SND_SOC_SSM2602
348 tristate
349
350config SND_SOC_SSM2602_I2C
351 select SND_SOC_SSM2602
352 tristate
353
345config SND_SOC_STA32X 354config SND_SOC_STA32X
346 tristate 355 tristate
347 356
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bc126764a44d..e7a2fb91148f 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -58,6 +58,8 @@ snd-soc-spdif-tx-objs := spdif_transmitter.o
58snd-soc-spdif-rx-objs := spdif_receiver.o 58snd-soc-spdif-rx-objs := spdif_receiver.o
59snd-soc-ssm2518-objs := ssm2518.o 59snd-soc-ssm2518-objs := ssm2518.o
60snd-soc-ssm2602-objs := ssm2602.o 60snd-soc-ssm2602-objs := ssm2602.o
61snd-soc-ssm2602-spi-objs := ssm2602-spi.o
62snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o
61snd-soc-sta32x-objs := sta32x.o 63snd-soc-sta32x-objs := sta32x.o
62snd-soc-sta529-objs := sta529.o 64snd-soc-sta529-objs := sta529.o
63snd-soc-stac9766-objs := stac9766.o 65snd-soc-stac9766-objs := stac9766.o
@@ -188,6 +190,8 @@ obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
188obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o 190obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
189obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o 191obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o
190obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 192obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
193obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o
194obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o
191obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o 195obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
192obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o 196obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
193obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o 197obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c
new file mode 100644
index 000000000000..abd63d537173
--- /dev/null
+++ b/sound/soc/codecs/ssm2602-i2c.c
@@ -0,0 +1,57 @@
1/*
2 * SSM2602/SSM2603/SSM2604 I2C audio driver
3 *
4 * Copyright 2014 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2.
7 */
8
9#include <linux/module.h>
10#include <linux/i2c.h>
11#include <linux/regmap.h>
12
13#include <sound/soc.h>
14
15#include "ssm2602.h"
16
17/*
18 * ssm2602 2 wire address is determined by GPIO5
19 * state during powerup.
20 * low = 0x1a
21 * high = 0x1b
22 */
23static int ssm2602_i2c_probe(struct i2c_client *client,
24 const struct i2c_device_id *id)
25{
26 return ssm2602_probe(&client->dev, id->driver_data,
27 devm_regmap_init_i2c(client, &ssm2602_regmap_config));
28}
29
30static int ssm2602_i2c_remove(struct i2c_client *client)
31{
32 snd_soc_unregister_codec(&client->dev);
33 return 0;
34}
35
36static const struct i2c_device_id ssm2602_i2c_id[] = {
37 { "ssm2602", SSM2602 },
38 { "ssm2603", SSM2602 },
39 { "ssm2604", SSM2604 },
40 { }
41};
42MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
43
44static struct i2c_driver ssm2602_i2c_driver = {
45 .driver = {
46 .name = "ssm2602",
47 .owner = THIS_MODULE,
48 },
49 .probe = ssm2602_i2c_probe,
50 .remove = ssm2602_i2c_remove,
51 .id_table = ssm2602_i2c_id,
52};
53module_i2c_driver(ssm2602_i2c_driver);
54
55MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 I2C driver");
56MODULE_AUTHOR("Cliff Cai");
57MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ssm2602-spi.c b/sound/soc/codecs/ssm2602-spi.c
new file mode 100644
index 000000000000..2bf55e24a7bb
--- /dev/null
+++ b/sound/soc/codecs/ssm2602-spi.c
@@ -0,0 +1,41 @@
1/*
2 * SSM2602 SPI audio driver
3 *
4 * Copyright 2014 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2.
7 */
8
9#include <linux/module.h>
10#include <linux/spi/spi.h>
11#include <linux/regmap.h>
12
13#include <sound/soc.h>
14
15#include "ssm2602.h"
16
17static int ssm2602_spi_probe(struct spi_device *spi)
18{
19 return ssm2602_probe(&spi->dev, SSM2602,
20 devm_regmap_init_spi(spi, &ssm2602_regmap_config));
21}
22
23static int ssm2602_spi_remove(struct spi_device *spi)
24{
25 snd_soc_unregister_codec(&spi->dev);
26 return 0;
27}
28
29static struct spi_driver ssm2602_spi_driver = {
30 .driver = {
31 .name = "ssm2602",
32 .owner = THIS_MODULE,
33 },
34 .probe = ssm2602_spi_probe,
35 .remove = ssm2602_spi_remove,
36};
37module_spi_driver(ssm2602_spi_driver);
38
39MODULE_DESCRIPTION("ASoC SSM2602 SPI driver");
40MODULE_AUTHOR("Cliff Cai");
41MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index f444d585b916..49d28eaa6d73 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -27,28 +27,16 @@
27 */ 27 */
28 28
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/moduleparam.h>
31#include <linux/init.h>
32#include <linux/delay.h>
33#include <linux/pm.h>
34#include <linux/i2c.h>
35#include <linux/spi/spi.h>
36#include <linux/regmap.h> 30#include <linux/regmap.h>
37#include <linux/slab.h> 31#include <linux/slab.h>
38#include <sound/core.h> 32
39#include <sound/pcm.h> 33#include <sound/pcm.h>
40#include <sound/pcm_params.h> 34#include <sound/pcm_params.h>
41#include <sound/soc.h> 35#include <sound/soc.h>
42#include <sound/initval.h>
43#include <sound/tlv.h> 36#include <sound/tlv.h>
44 37
45#include "ssm2602.h" 38#include "ssm2602.h"
46 39
47enum ssm2602_type {
48 SSM2602,
49 SSM2604,
50};
51
52/* codec private data */ 40/* codec private data */
53struct ssm2602_priv { 41struct ssm2602_priv {
54 unsigned int sysclk; 42 unsigned int sysclk;
@@ -529,7 +517,7 @@ static int ssm2602_resume(struct snd_soc_codec *codec)
529 return 0; 517 return 0;
530} 518}
531 519
532static int ssm2602_probe(struct snd_soc_codec *codec) 520static int ssm2602_codec_probe(struct snd_soc_codec *codec)
533{ 521{
534 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 522 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
535 struct snd_soc_dapm_context *dapm = &codec->dapm; 523 struct snd_soc_dapm_context *dapm = &codec->dapm;
@@ -554,7 +542,7 @@ static int ssm2602_probe(struct snd_soc_codec *codec)
554 ARRAY_SIZE(ssm2602_routes)); 542 ARRAY_SIZE(ssm2602_routes));
555} 543}
556 544
557static int ssm2604_probe(struct snd_soc_codec *codec) 545static int ssm2604_codec_probe(struct snd_soc_codec *codec)
558{ 546{
559 struct snd_soc_dapm_context *dapm = &codec->dapm; 547 struct snd_soc_dapm_context *dapm = &codec->dapm;
560 int ret; 548 int ret;
@@ -568,7 +556,7 @@ static int ssm2604_probe(struct snd_soc_codec *codec)
568 ARRAY_SIZE(ssm2604_routes)); 556 ARRAY_SIZE(ssm2604_routes));
569} 557}
570 558
571static int ssm260x_probe(struct snd_soc_codec *codec) 559static int ssm260x_codec_probe(struct snd_soc_codec *codec)
572{ 560{
573 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 561 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
574 int ret; 562 int ret;
@@ -597,10 +585,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
597 585
598 switch (ssm2602->type) { 586 switch (ssm2602->type) {
599 case SSM2602: 587 case SSM2602:
600 ret = ssm2602_probe(codec); 588 ret = ssm2602_codec_probe(codec);
601 break; 589 break;
602 case SSM2604: 590 case SSM2604:
603 ret = ssm2604_probe(codec); 591 ret = ssm2604_codec_probe(codec);
604 break; 592 break;
605 } 593 }
606 594
@@ -620,7 +608,7 @@ static int ssm2602_remove(struct snd_soc_codec *codec)
620} 608}
621 609
622static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { 610static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
623 .probe = ssm260x_probe, 611 .probe = ssm260x_codec_probe,
624 .remove = ssm2602_remove, 612 .remove = ssm2602_remove,
625 .suspend = ssm2602_suspend, 613 .suspend = ssm2602_suspend,
626 .resume = ssm2602_resume, 614 .resume = ssm2602_resume,
@@ -639,7 +627,7 @@ static bool ssm2602_register_volatile(struct device *dev, unsigned int reg)
639 return reg == SSM2602_RESET; 627 return reg == SSM2602_RESET;
640} 628}
641 629
642static const struct regmap_config ssm2602_regmap_config = { 630const struct regmap_config ssm2602_regmap_config = {
643 .val_bits = 9, 631 .val_bits = 9,
644 .reg_bits = 7, 632 .reg_bits = 7,
645 633
@@ -650,134 +638,28 @@ static const struct regmap_config ssm2602_regmap_config = {
650 .reg_defaults_raw = ssm2602_reg, 638 .reg_defaults_raw = ssm2602_reg,
651 .num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg), 639 .num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg),
652}; 640};
641EXPORT_SYMBOL_GPL(ssm2602_regmap_config);
653 642
654#if defined(CONFIG_SPI_MASTER) 643int ssm2602_probe(struct device *dev, enum ssm2602_type type,
655static int ssm2602_spi_probe(struct spi_device *spi) 644 struct regmap *regmap)
656{ 645{
657 struct ssm2602_priv *ssm2602; 646 struct ssm2602_priv *ssm2602;
658 int ret;
659
660 ssm2602 = devm_kzalloc(&spi->dev, sizeof(struct ssm2602_priv),
661 GFP_KERNEL);
662 if (ssm2602 == NULL)
663 return -ENOMEM;
664
665 spi_set_drvdata(spi, ssm2602);
666 ssm2602->type = SSM2602;
667
668 ssm2602->regmap = devm_regmap_init_spi(spi, &ssm2602_regmap_config);
669 if (IS_ERR(ssm2602->regmap))
670 return PTR_ERR(ssm2602->regmap);
671
672 ret = snd_soc_register_codec(&spi->dev,
673 &soc_codec_dev_ssm2602, &ssm2602_dai, 1);
674 return ret;
675}
676 647
677static int ssm2602_spi_remove(struct spi_device *spi) 648 if (IS_ERR(regmap))
678{ 649 return PTR_ERR(regmap);
679 snd_soc_unregister_codec(&spi->dev);
680 return 0;
681}
682
683static struct spi_driver ssm2602_spi_driver = {
684 .driver = {
685 .name = "ssm2602",
686 .owner = THIS_MODULE,
687 },
688 .probe = ssm2602_spi_probe,
689 .remove = ssm2602_spi_remove,
690};
691#endif
692
693#if IS_ENABLED(CONFIG_I2C)
694/*
695 * ssm2602 2 wire address is determined by GPIO5
696 * state during powerup.
697 * low = 0x1a
698 * high = 0x1b
699 */
700static int ssm2602_i2c_probe(struct i2c_client *i2c,
701 const struct i2c_device_id *id)
702{
703 struct ssm2602_priv *ssm2602;
704 int ret;
705 650
706 ssm2602 = devm_kzalloc(&i2c->dev, sizeof(struct ssm2602_priv), 651 ssm2602 = devm_kzalloc(dev, sizeof(*ssm2602), GFP_KERNEL);
707 GFP_KERNEL);
708 if (ssm2602 == NULL) 652 if (ssm2602 == NULL)
709 return -ENOMEM; 653 return -ENOMEM;
710 654
711 i2c_set_clientdata(i2c, ssm2602); 655 dev_set_drvdata(dev, ssm2602);
712 ssm2602->type = id->driver_data; 656 ssm2602->type = SSM2602;
713 657 ssm2602->regmap = regmap;
714 ssm2602->regmap = devm_regmap_init_i2c(i2c, &ssm2602_regmap_config);
715 if (IS_ERR(ssm2602->regmap))
716 return PTR_ERR(ssm2602->regmap);
717
718 ret = snd_soc_register_codec(&i2c->dev,
719 &soc_codec_dev_ssm2602, &ssm2602_dai, 1);
720 return ret;
721}
722
723static int ssm2602_i2c_remove(struct i2c_client *client)
724{
725 snd_soc_unregister_codec(&client->dev);
726 return 0;
727}
728
729static const struct i2c_device_id ssm2602_i2c_id[] = {
730 { "ssm2602", SSM2602 },
731 { "ssm2603", SSM2602 },
732 { "ssm2604", SSM2604 },
733 { }
734};
735MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
736
737/* corgi i2c codec control layer */
738static struct i2c_driver ssm2602_i2c_driver = {
739 .driver = {
740 .name = "ssm2602",
741 .owner = THIS_MODULE,
742 },
743 .probe = ssm2602_i2c_probe,
744 .remove = ssm2602_i2c_remove,
745 .id_table = ssm2602_i2c_id,
746};
747#endif
748
749
750static int __init ssm2602_modinit(void)
751{
752 int ret = 0;
753
754#if defined(CONFIG_SPI_MASTER)
755 ret = spi_register_driver(&ssm2602_spi_driver);
756 if (ret)
757 return ret;
758#endif
759
760#if IS_ENABLED(CONFIG_I2C)
761 ret = i2c_add_driver(&ssm2602_i2c_driver);
762 if (ret)
763 return ret;
764#endif
765
766 return ret;
767}
768module_init(ssm2602_modinit);
769
770static void __exit ssm2602_exit(void)
771{
772#if defined(CONFIG_SPI_MASTER)
773 spi_unregister_driver(&ssm2602_spi_driver);
774#endif
775 658
776#if IS_ENABLED(CONFIG_I2C) 659 return snd_soc_register_codec(dev, &soc_codec_dev_ssm2602,
777 i2c_del_driver(&ssm2602_i2c_driver); 660 &ssm2602_dai, 1);
778#endif
779} 661}
780module_exit(ssm2602_exit); 662EXPORT_SYMBOL_GPL(ssm2602_probe);
781 663
782MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver"); 664MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver");
783MODULE_AUTHOR("Cliff Cai"); 665MODULE_AUTHOR("Cliff Cai");
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h
index fbd07d7b73ca..747538847689 100644
--- a/sound/soc/codecs/ssm2602.h
+++ b/sound/soc/codecs/ssm2602.h
@@ -28,6 +28,20 @@
28#ifndef _SSM2602_H 28#ifndef _SSM2602_H
29#define _SSM2602_H 29#define _SSM2602_H
30 30
31#include <linux/regmap.h>
32
33struct device;
34
35enum ssm2602_type {
36 SSM2602,
37 SSM2604,
38};
39
40extern const struct regmap_config ssm2602_regmap_config;
41
42int ssm2602_probe(struct device *dev, enum ssm2602_type type,
43 struct regmap *regmap);
44
31/* SSM2602 Codec Register definitions */ 45/* SSM2602 Codec Register definitions */
32 46
33#define SSM2602_LINVOL 0x00 47#define SSM2602_LINVOL 0x00