Commit ae9f5e60 authored by Richard Fitzgerald's avatar Richard Fitzgerald Committed by Mark Brown

ASoC: cs42l42: Split I2C identity into separate module

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: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: default avatarMartin Povišer <povik+lin@cutebit.org>
Link: https://lore.kernel.org/r/20220915094444.11434-8-povik+lin@cutebit.orgSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 52c2e370
...@@ -692,9 +692,15 @@ config SND_SOC_CS35L45_I2C ...@@ -692,9 +692,15 @@ config SND_SOC_CS35L45_I2C
Enable support for Cirrus Logic CS35L45 smart speaker amplifier Enable support for Cirrus Logic CS35L45 smart speaker amplifier
with I2C control. with I2C control.
config SND_SOC_CS42L42_CORE
tristate
config SND_SOC_CS42L42 config SND_SOC_CS42L42
tristate "Cirrus Logic CS42L42 CODEC" tristate "Cirrus Logic CS42L42 CODEC (I2C)"
depends on I2C depends on I2C
select REGMAP
select REGMAP_I2C
select SND_SOC_CS42L42_CORE
config SND_SOC_CS42L51 config SND_SOC_CS42L51
tristate tristate
......
...@@ -65,6 +65,7 @@ snd-soc-cs35l45-objs := cs35l45.o ...@@ -65,6 +65,7 @@ snd-soc-cs35l45-objs := cs35l45.o
snd-soc-cs35l45-spi-objs := cs35l45-spi.o snd-soc-cs35l45-spi-objs := cs35l45-spi.o
snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o
snd-soc-cs42l42-objs := cs42l42.o snd-soc-cs42l42-objs := cs42l42.o
snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o
snd-soc-cs42l51-objs := cs42l51.o snd-soc-cs42l51-objs := cs42l51.o
snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
snd-soc-cs42l52-objs := cs42l52.o snd-soc-cs42l52-objs := cs42l52.o
...@@ -422,7 +423,8 @@ obj-$(CONFIG_SND_SOC_CS35L45_TABLES) += snd-soc-cs35l45-tables.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) += snd-soc-cs35l45.o
obj-$(CONFIG_SND_SOC_CS35L45_SPI) += snd-soc-cs35l45-spi.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_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) += snd-soc-cs42l51.o
obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o
obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
......
// 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);
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -375,7 +374,7 @@ static const struct regmap_range_cfg cs42l42_page_range = { ...@@ -375,7 +374,7 @@ static const struct regmap_range_cfg cs42l42_page_range = {
.window_len = 256, .window_len = 256,
}; };
static const struct regmap_config cs42l42_regmap = { const struct regmap_config cs42l42_regmap = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
...@@ -393,6 +392,7 @@ static const struct regmap_config cs42l42_regmap = { ...@@ -393,6 +392,7 @@ static const struct regmap_config cs42l42_regmap = {
.use_single_read = true, .use_single_read = true,
.use_single_write = 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(adc_tlv, -9700, 100, true);
static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 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_ ...@@ -579,7 +579,7 @@ static int cs42l42_set_jack(struct snd_soc_component *component, struct snd_soc_
return 0; 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, .set_jack = cs42l42_set_jack,
.dapm_widgets = cs42l42_dapm_widgets, .dapm_widgets = cs42l42_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(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 = { ...@@ -590,6 +590,7 @@ static const struct snd_soc_component_driver cs42l42_soc_component = {
.idle_bias_on = 1, .idle_bias_on = 1,
.endianness = 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. */ /* Switch to SCLK. Atomic delay after the write to allow the switch to complete. */
static const struct reg_sequence cs42l42_to_sclk_seq[] = { static const struct reg_sequence cs42l42_to_sclk_seq[] = {
...@@ -1086,7 +1087,7 @@ static const struct snd_soc_dai_ops cs42l42_ops = { ...@@ -1086,7 +1087,7 @@ static const struct snd_soc_dai_ops cs42l42_ops = {
.mute_stream = cs42l42_mute_stream, .mute_stream = cs42l42_mute_stream,
}; };
static struct snd_soc_dai_driver cs42l42_dai = { struct snd_soc_dai_driver cs42l42_dai = {
.name = "cs42l42", .name = "cs42l42",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
...@@ -1106,6 +1107,7 @@ static struct snd_soc_dai_driver cs42l42_dai = { ...@@ -1106,6 +1107,7 @@ static struct snd_soc_dai_driver cs42l42_dai = {
.symmetric_sample_bits = 1, .symmetric_sample_bits = 1,
.ops = &cs42l42_ops, .ops = &cs42l42_ops,
}; };
EXPORT_SYMBOL_NS_GPL(cs42l42_dai, SND_SOC_CS42L42_CORE);
static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42) 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[] = { ...@@ -2101,7 +2103,7 @@ static const struct reg_sequence __maybe_unused cs42l42_shutdown_seq[] = {
REG_SEQ0(CS42L42_PWR_CTL1, 0xFF) 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); struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
unsigned int reg; unsigned int reg;
...@@ -2161,8 +2163,9 @@ static int __maybe_unused cs42l42_suspend(struct device *dev) ...@@ -2161,8 +2163,9 @@ static int __maybe_unused cs42l42_suspend(struct device *dev)
return 0; 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); struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
int ret; int ret;
...@@ -2188,8 +2191,9 @@ static int __maybe_unused cs42l42_resume(struct device *dev) ...@@ -2188,8 +2191,9 @@ static int __maybe_unused cs42l42_resume(struct device *dev)
return 0; 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); struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
...@@ -2206,6 +2210,7 @@ static void __maybe_unused cs42l42_resume_restore(struct device *dev) ...@@ -2206,6 +2210,7 @@ static void __maybe_unused cs42l42_resume_restore(struct device *dev)
dev_dbg(dev, "System resumed\n"); 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) static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
{ {
...@@ -2220,9 +2225,9 @@ 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; return 0;
} }
static int cs42l42_common_probe(struct cs42l42_private *cs42l42, int cs42l42_common_probe(struct cs42l42_private *cs42l42,
const struct snd_soc_component_driver *component_drv, const struct snd_soc_component_driver *component_drv,
struct snd_soc_dai_driver *dai) struct snd_soc_dai_driver *dai)
{ {
int ret, i; int ret, i;
...@@ -2295,8 +2300,9 @@ static int cs42l42_common_probe(struct cs42l42_private *cs42l42, ...@@ -2295,8 +2300,9 @@ static int cs42l42_common_probe(struct cs42l42_private *cs42l42,
return ret; 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; unsigned int reg;
int devid, ret; int devid, ret;
...@@ -2375,8 +2381,9 @@ static int cs42l42_init(struct cs42l42_private *cs42l42) ...@@ -2375,8 +2381,9 @@ static int cs42l42_init(struct cs42l42_private *cs42l42)
cs42l42->supplies); cs42l42->supplies);
return ret; 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) if (cs42l42->irq)
free_irq(cs42l42->irq, cs42l42); free_irq(cs42l42->irq, cs42l42);
...@@ -2394,85 +2401,7 @@ static void cs42l42_common_remove(struct cs42l42_private *cs42l42) ...@@ -2394,85 +2401,7 @@ static void cs42l42_common_remove(struct cs42l42_private *cs42l42)
gpiod_set_value_cansleep(cs42l42->reset_gpio, 0); gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies); regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies);
} }
EXPORT_SYMBOL_NS_GPL(cs42l42_common_remove, SND_SOC_CS42L42_CORE);
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);
MODULE_DESCRIPTION("ASoC CS42L42 driver"); MODULE_DESCRIPTION("ASoC CS42L42 driver");
MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>"); MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <sound/jack.h> #include <sound/jack.h>
#include <sound/cs42l42.h> #include <sound/cs42l42.h>
#include <sound/soc-component.h>
#include <sound/soc-dai.h>
struct cs42l42_private { struct cs42l42_private {
struct regmap *regmap; struct regmap *regmap;
...@@ -50,4 +52,17 @@ struct cs42l42_private { ...@@ -50,4 +52,17 @@ struct cs42l42_private {
bool init_done; 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__ */ #endif /* __CS42L42_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment