ASoC: cs42l42: Split I2C identity into separate module
authorRichard Fitzgerald <rf@opensource.cirrus.com>
Thu, 15 Sep 2022 09:44:40 +0000 (11:44 +0200)
committerMark Brown <broonie@kernel.org>
Mon, 19 Sep 2022 17:05:33 +0000 (18:05 +0100)
Split the I2C bus driver definition and probe()/remove() into a
separate module so that a SoundWire build of CS42L42 support does
not have a spurious dependency on I2C.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin PoviĊĦer <povik+lin@cutebit.org>
Link: https://lore.kernel.org/r/20220915094444.11434-8-povik+lin@cutebit.org
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/cs42l42-i2c.c [new file with mode: 0644]
sound/soc/codecs/cs42l42.c
sound/soc/codecs/cs42l42.h

index c7d83fe..01725d0 100644 (file)
@@ -692,9 +692,15 @@ config SND_SOC_CS35L45_I2C
          Enable support for Cirrus Logic CS35L45 smart speaker amplifier
          with I2C control.
 
+config SND_SOC_CS42L42_CORE
+       tristate
+
 config SND_SOC_CS42L42
-       tristate "Cirrus Logic CS42L42 CODEC"
+       tristate "Cirrus Logic CS42L42 CODEC (I2C)"
        depends on I2C
+       select REGMAP
+       select REGMAP_I2C
+       select SND_SOC_CS42L42_CORE
 
 config SND_SOC_CS42L51
        tristate
index 16a0163..5b7020a 100644 (file)
@@ -65,6 +65,7 @@ snd-soc-cs35l45-objs := cs35l45.o
 snd-soc-cs35l45-spi-objs := cs35l45-spi.o
 snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o
 snd-soc-cs42l42-objs := cs42l42.o
+snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o
 snd-soc-cs42l51-objs := cs42l51.o
 snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
 snd-soc-cs42l52-objs := cs42l52.o
@@ -422,7 +423,8 @@ obj-$(CONFIG_SND_SOC_CS35L45_TABLES)        += snd-soc-cs35l45-tables.o
 obj-$(CONFIG_SND_SOC_CS35L45)  += snd-soc-cs35l45.o
 obj-$(CONFIG_SND_SOC_CS35L45_SPI)      += snd-soc-cs35l45-spi.o
 obj-$(CONFIG_SND_SOC_CS35L45_I2C)      += snd-soc-cs35l45-i2c.o
-obj-$(CONFIG_SND_SOC_CS42L42)  += snd-soc-cs42l42.o
+obj-$(CONFIG_SND_SOC_CS42L42_CORE)     += snd-soc-cs42l42.o
+obj-$(CONFIG_SND_SOC_CS42L42)  += snd-soc-cs42l42-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L51)  += snd-soc-cs42l51.o
 obj-$(CONFIG_SND_SOC_CS42L51_I2C)      += snd-soc-cs42l51-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L52)  += snd-soc-cs42l52.o
diff --git a/sound/soc/codecs/cs42l42-i2c.c b/sound/soc/codecs/cs42l42-i2c.c
new file mode 100644 (file)
index 0000000..5f01b6a
--- /dev/null
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * cs42l42-i2c.c -- CS42L42 ALSA SoC audio driver for I2C
+ *
+ * Copyright 2016, 2022 Cirrus Logic, Inc.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "cs42l42.h"
+
+static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
+{
+       struct device *dev = &i2c_client->dev;
+       struct cs42l42_private *cs42l42;
+       struct regmap *regmap;
+       int ret;
+
+       cs42l42 = devm_kzalloc(dev, sizeof(*cs42l42), GFP_KERNEL);
+       if (!cs42l42)
+               return -ENOMEM;
+
+       regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+               return ret;
+       }
+
+       cs42l42->dev = dev;
+       cs42l42->regmap = regmap;
+       cs42l42->irq = i2c_client->irq;
+
+       ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
+       if (ret)
+               return ret;
+
+       return cs42l42_init(cs42l42);
+}
+
+static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
+{
+       struct cs42l42_private *cs42l42 = dev_get_drvdata(&i2c_client->dev);
+
+       cs42l42_common_remove(cs42l42);
+
+       return 0;
+}
+
+static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
+{
+       int ret;
+
+       ret = cs42l42_resume(dev);
+       if (ret)
+               return ret;
+
+       cs42l42_resume_restore(dev);
+
+       return 0;
+}
+
+static const struct dev_pm_ops cs42l42_i2c_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_i2c_resume)
+};
+
+static const struct of_device_id __maybe_unused cs42l42_of_match[] = {
+       { .compatible = "cirrus,cs42l42", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, cs42l42_of_match);
+
+static const struct acpi_device_id __maybe_unused cs42l42_acpi_match[] = {
+       {"10134242", 0,},
+       {}
+};
+MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match);
+
+static const struct i2c_device_id cs42l42_id[] = {
+       {"cs42l42", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, cs42l42_id);
+
+static struct i2c_driver cs42l42_i2c_driver = {
+       .driver = {
+               .name = "cs42l42",
+               .pm = &cs42l42_i2c_pm_ops,
+               .of_match_table = of_match_ptr(cs42l42_of_match),
+               .acpi_match_table = ACPI_PTR(cs42l42_acpi_match),
+               },
+       .id_table = cs42l42_id,
+       .probe_new = cs42l42_i2c_probe,
+       .remove = cs42l42_i2c_remove,
+};
+
+module_i2c_driver(cs42l42_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS42L42 I2C driver");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);
index 20d84db..59321be 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
@@ -375,7 +374,7 @@ static const struct regmap_range_cfg cs42l42_page_range = {
        .window_len = 256,
 };
 
-static const struct regmap_config cs42l42_regmap = {
+const struct regmap_config cs42l42_regmap = {
        .reg_bits = 8,
        .val_bits = 8,
 
@@ -393,6 +392,7 @@ static const struct regmap_config cs42l42_regmap = {
        .use_single_read = true,
        .use_single_write = true,
 };
+EXPORT_SYMBOL_NS_GPL(cs42l42_regmap, SND_SOC_CS42L42_CORE);
 
 static DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 100, true);
 static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true);
@@ -579,7 +579,7 @@ static int cs42l42_set_jack(struct snd_soc_component *component, struct snd_soc_
        return 0;
 }
 
-static const struct snd_soc_component_driver cs42l42_soc_component = {
+const struct snd_soc_component_driver cs42l42_soc_component = {
        .set_jack               = cs42l42_set_jack,
        .dapm_widgets           = cs42l42_dapm_widgets,
        .num_dapm_widgets       = ARRAY_SIZE(cs42l42_dapm_widgets),
@@ -590,6 +590,7 @@ static const struct snd_soc_component_driver cs42l42_soc_component = {
        .idle_bias_on           = 1,
        .endianness             = 1,
 };
+EXPORT_SYMBOL_NS_GPL(cs42l42_soc_component, SND_SOC_CS42L42_CORE);
 
 /* Switch to SCLK. Atomic delay after the write to allow the switch to complete. */
 static const struct reg_sequence cs42l42_to_sclk_seq[] = {
@@ -1086,7 +1087,7 @@ static const struct snd_soc_dai_ops cs42l42_ops = {
        .mute_stream    = cs42l42_mute_stream,
 };
 
-static struct snd_soc_dai_driver cs42l42_dai = {
+struct snd_soc_dai_driver cs42l42_dai = {
                .name = "cs42l42",
                .playback = {
                        .stream_name = "Playback",
@@ -1106,6 +1107,7 @@ static struct snd_soc_dai_driver cs42l42_dai = {
                .symmetric_sample_bits = 1,
                .ops = &cs42l42_ops,
 };
+EXPORT_SYMBOL_NS_GPL(cs42l42_dai, SND_SOC_CS42L42_CORE);
 
 static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
 {
@@ -2101,7 +2103,7 @@ static const struct reg_sequence __maybe_unused cs42l42_shutdown_seq[] = {
        REG_SEQ0(CS42L42_PWR_CTL1,              0xFF)
 };
 
-static int __maybe_unused cs42l42_suspend(struct device *dev)
+int cs42l42_suspend(struct device *dev)
 {
        struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
        unsigned int reg;
@@ -2161,8 +2163,9 @@ static int __maybe_unused cs42l42_suspend(struct device *dev)
        return 0;
 
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_suspend, SND_SOC_CS42L42_CORE);
 
-static int __maybe_unused cs42l42_resume(struct device *dev)
+int cs42l42_resume(struct device *dev)
 {
        struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
        int ret;
@@ -2188,8 +2191,9 @@ static int __maybe_unused cs42l42_resume(struct device *dev)
 
        return 0;
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_resume, SND_SOC_CS42L42_CORE);
 
-static void __maybe_unused cs42l42_resume_restore(struct device *dev)
+void cs42l42_resume_restore(struct device *dev)
 {
        struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
 
@@ -2206,6 +2210,7 @@ static void __maybe_unused cs42l42_resume_restore(struct device *dev)
 
        dev_dbg(dev, "System resumed\n");
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_resume_restore, SND_SOC_CS42L42_CORE);
 
 static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
 {
@@ -2220,9 +2225,9 @@ static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
        return 0;
 }
 
-static int cs42l42_common_probe(struct cs42l42_private *cs42l42,
-                               const struct snd_soc_component_driver *component_drv,
-                               struct snd_soc_dai_driver *dai)
+int cs42l42_common_probe(struct cs42l42_private *cs42l42,
+                        const struct snd_soc_component_driver *component_drv,
+                        struct snd_soc_dai_driver *dai)
 {
        int ret, i;
 
@@ -2295,8 +2300,9 @@ err_disable_noreset:
 
        return ret;
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_common_probe, SND_SOC_CS42L42_CORE);
 
-static int cs42l42_init(struct cs42l42_private *cs42l42)
+int cs42l42_init(struct cs42l42_private *cs42l42)
 {
        unsigned int reg;
        int devid, ret;
@@ -2375,8 +2381,9 @@ err_disable:
                                cs42l42->supplies);
        return ret;
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_init, SND_SOC_CS42L42_CORE);
 
-static void cs42l42_common_remove(struct cs42l42_private *cs42l42)
+void cs42l42_common_remove(struct cs42l42_private *cs42l42)
 {
        if (cs42l42->irq)
                free_irq(cs42l42->irq, cs42l42);
@@ -2394,85 +2401,7 @@ static void cs42l42_common_remove(struct cs42l42_private *cs42l42)
        gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
        regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies);
 }
-
-static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
-{
-       struct device *dev = &i2c_client->dev;
-       struct cs42l42_private *cs42l42;
-       struct regmap *regmap;
-       int ret;
-
-       cs42l42 = devm_kzalloc(dev, sizeof(struct cs42l42_private), GFP_KERNEL);
-       if (!cs42l42)
-               return -ENOMEM;
-
-       regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
-       if (IS_ERR(regmap)) {
-               ret = PTR_ERR(regmap);
-               dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
-               return ret;
-       }
-
-       cs42l42->dev = dev;
-       cs42l42->regmap = regmap;
-       cs42l42->irq = i2c_client->irq;
-
-       ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
-       if (ret)
-               return ret;
-
-       return cs42l42_init(cs42l42);
-}
-
-static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
-{
-       struct cs42l42_private *cs42l42 = dev_get_drvdata(&i2c_client->dev);
-
-       cs42l42_common_remove(cs42l42);
-
-       return 0;
-}
-
-static const struct dev_pm_ops cs42l42_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_i2c_resume)
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id cs42l42_of_match[] = {
-       { .compatible = "cirrus,cs42l42", },
-       {}
-};
-MODULE_DEVICE_TABLE(of, cs42l42_of_match);
-#endif
-
-#ifdef CONFIG_ACPI
-static const struct acpi_device_id cs42l42_acpi_match[] = {
-       {"10134242", 0,},
-       {}
-};
-MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match);
-#endif
-
-static const struct i2c_device_id cs42l42_id[] = {
-       {"cs42l42", 0},
-       {}
-};
-
-MODULE_DEVICE_TABLE(i2c, cs42l42_id);
-
-static struct i2c_driver cs42l42_i2c_driver = {
-       .driver = {
-               .name = "cs42l42",
-               .pm = &cs42l42_pm_ops,
-               .of_match_table = of_match_ptr(cs42l42_of_match),
-               .acpi_match_table = ACPI_PTR(cs42l42_acpi_match),
-               },
-       .id_table = cs42l42_id,
-       .probe_new = cs42l42_i2c_probe,
-       .remove = cs42l42_i2c_remove,
-};
-
-module_i2c_driver(cs42l42_i2c_driver);
+EXPORT_SYMBOL_NS_GPL(cs42l42_common_remove, SND_SOC_CS42L42_CORE);
 
 MODULE_DESCRIPTION("ASoC CS42L42 driver");
 MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
index a8e0d5b..2a9f178 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/regulator/consumer.h>
 #include <sound/jack.h>
 #include <sound/cs42l42.h>
+#include <sound/soc-component.h>
+#include <sound/soc-dai.h>
 
 struct  cs42l42_private {
        struct regmap *regmap;
@@ -50,4 +52,17 @@ struct  cs42l42_private {
        bool init_done;
 };
 
+extern const struct regmap_config cs42l42_regmap;
+extern const struct snd_soc_component_driver cs42l42_soc_component;
+extern struct snd_soc_dai_driver cs42l42_dai;
+
+int cs42l42_suspend(struct device *dev);
+int cs42l42_resume(struct device *dev);
+void cs42l42_resume_restore(struct device *dev);
+int cs42l42_common_probe(struct cs42l42_private *cs42l42,
+                        const struct snd_soc_component_driver *component_drv,
+                        struct snd_soc_dai_driver *dai);
+int cs42l42_init(struct cs42l42_private *cs42l42);
+void cs42l42_common_remove(struct cs42l42_private *cs42l42);
+
 #endif /* __CS42L42_H__ */