Alsa-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
May 2020
- 153 participants
- 351 discussions
All boards with Ingenic SoCs probe with devicetree already, we have no
use for a non-devicetree path.
This solves some compilation warnings that were caused by unused
variables in the case where CONFIG_OF was disabled.
Signed-off-by: Paul Cercueil <paul(a)crapouillou.net>
Reported-by: kbuild test robot <lkp(a)intel.com>
---
sound/soc/codecs/Kconfig | 3 +++
sound/soc/codecs/jz4725b.c | 4 +---
sound/soc/codecs/jz4740.c | 4 +---
sound/soc/codecs/jz4770.c | 2 +-
sound/soc/jz4740/Kconfig | 2 +-
sound/soc/jz4740/jz4740-i2s.c | 4 +---
6 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index e60e0b6a689c..3a0a6824e278 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -681,6 +681,7 @@ config SND_SOC_CX2072X
config SND_SOC_JZ4740_CODEC
depends on MIPS || COMPILE_TEST
+ depends on OF
select REGMAP_MMIO
tristate "Ingenic JZ4740 internal CODEC"
help
@@ -692,6 +693,7 @@ config SND_SOC_JZ4740_CODEC
config SND_SOC_JZ4725B_CODEC
depends on MIPS || COMPILE_TEST
+ depends on OF
select REGMAP
tristate "Ingenic JZ4725B internal CODEC"
help
@@ -703,6 +705,7 @@ config SND_SOC_JZ4725B_CODEC
config SND_SOC_JZ4770_CODEC
depends on MIPS || COMPILE_TEST
+ depends on OF
select REGMAP
tristate "Ingenic JZ4770 internal CODEC"
help
diff --git a/sound/soc/codecs/jz4725b.c b/sound/soc/codecs/jz4725b.c
index 2567a5d15b55..e49374c72e70 100644
--- a/sound/soc/codecs/jz4725b.c
+++ b/sound/soc/codecs/jz4725b.c
@@ -574,19 +574,17 @@ static int jz4725b_codec_probe(struct platform_device *pdev)
return ret;
}
-#ifdef CONFIG_OF
static const struct of_device_id jz4725b_codec_of_matches[] = {
{ .compatible = "ingenic,jz4725b-codec", },
{ }
};
MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches);
-#endif
static struct platform_driver jz4725b_codec_driver = {
.probe = jz4725b_codec_probe,
.driver = {
.name = "jz4725b-codec",
- .of_match_table = of_match_ptr(jz4725b_codec_of_matches),
+ .of_match_table = jz4725b_codec_of_matches,
},
};
module_platform_driver(jz4725b_codec_driver);
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 460aa1fd1efe..c9900d1cd5c2 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -344,19 +344,17 @@ static int jz4740_codec_probe(struct platform_device *pdev)
return ret;
}
-#ifdef CONFIG_OF
static const struct of_device_id jz4740_codec_of_matches[] = {
{ .compatible = "ingenic,jz4740-codec", },
{ }
};
MODULE_DEVICE_TABLE(of, jz4740_codec_of_matches);
-#endif
static struct platform_driver jz4740_codec_driver = {
.probe = jz4740_codec_probe,
.driver = {
.name = "jz4740-codec",
- .of_match_table = of_match_ptr(jz4740_codec_of_matches),
+ .of_match_table = jz4740_codec_of_matches,
},
};
diff --git a/sound/soc/codecs/jz4770.c b/sound/soc/codecs/jz4770.c
index e7cf2c107607..34775aa62402 100644
--- a/sound/soc/codecs/jz4770.c
+++ b/sound/soc/codecs/jz4770.c
@@ -937,7 +937,7 @@ static struct platform_driver jz4770_codec_driver = {
.probe = jz4770_codec_probe,
.driver = {
.name = "jz4770-codec",
- .of_match_table = of_match_ptr(jz4770_codec_of_matches),
+ .of_match_table = jz4770_codec_of_matches,
},
};
module_platform_driver(jz4770_codec_driver);
diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
index e72f826062e9..29144720cb62 100644
--- a/sound/soc/jz4740/Kconfig
+++ b/sound/soc/jz4740/Kconfig
@@ -2,7 +2,7 @@
config SND_JZ4740_SOC_I2S
tristate "SoC Audio (I2S protocol) for Ingenic JZ4740 SoC"
depends on MIPS || COMPILE_TEST
- depends on HAS_IOMEM
+ depends on OF && HAS_IOMEM
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y if you want to use I2S protocol and I2S codec on Ingenic JZ4740
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index 6f6f8dad0356..52460adf6ca1 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -504,7 +504,6 @@ static const struct snd_soc_component_driver jz4740_i2s_component = {
.resume = jz4740_i2s_resume,
};
-#ifdef CONFIG_OF
static const struct of_device_id jz4740_of_matches[] = {
{ .compatible = "ingenic,jz4740-i2s", .data = &jz4740_i2s_soc_info },
{ .compatible = "ingenic,jz4760-i2s", .data = &jz4760_i2s_soc_info },
@@ -513,7 +512,6 @@ static const struct of_device_id jz4740_of_matches[] = {
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, jz4740_of_matches);
-#endif
static int jz4740_i2s_dev_probe(struct platform_device *pdev)
{
@@ -558,7 +556,7 @@ static struct platform_driver jz4740_i2s_driver = {
.probe = jz4740_i2s_dev_probe,
.driver = {
.name = "jz4740-i2s",
- .of_match_table = of_match_ptr(jz4740_of_matches)
+ .of_match_table = jz4740_of_matches,
},
};
--
2.26.2
2
1
28 May '20
With SND_SOC_AMD_RV_RT5682_MACH using the i2c version of the
driver, we can easily get a build failure when I2C is built-in
but soundwire is not:
WARNING: unmet direct dependencies detected for SND_SOC_RT5682
Depends on [m]: SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && (I2C [=y] || SOUNDWIRE [=m]) && (SOUNDWIRE [=m] || !SOUNDWIRE [=m]) && (I2C [=y] || !I2C [=y])
Selected by [y]:
- SND_SOC_AMD_RV_RT5682_MACH [=y] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_SOC_AMD_ACP3x [=y] && I2C [=y] && CROS_EC [=y]
Selected by [m]:
- SND_SOC_RT5682_SDW [=m] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SOUNDWIRE [=m] && (I2C [=y] || !I2C [=y])
Rework the driver to have three separate modules, with the
main driver just dealing with the common bits and the actual
initialization as part of i2c and sdw specific modules.
The conversion is fairly mechanical to keep it easy to review,
i.e. it moves code around with the minimal required renaming
and changes.
Fixes: 6b8e4e7db3cd ("ASoC: amd: Add machine driver for Raven based platform")
Fixes: fd443a20c2f0 ("ASoC: rt5682: fix I2C/Soundwire dependencies")
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com>
Signed-off-by: Arnd Bergmann <arnd(a)arndb.de>
---
sound/soc/amd/Kconfig | 2 +-
sound/soc/codecs/Kconfig | 11 +-
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/rt5682-i2c.c | 306 +++++++++++++
sound/soc/codecs/rt5682-sdw.c | 459 +++++++++++++++++++-
sound/soc/codecs/rt5682-sdw.h | 20 -
sound/soc/codecs/rt5682.c | 773 ++-------------------------------
sound/soc/codecs/rt5682.h | 32 +-
sound/soc/intel/boards/Kconfig | 6 +-
9 files changed, 847 insertions(+), 764 deletions(-)
create mode 100644 sound/soc/codecs/rt5682-i2c.c
delete mode 100644 sound/soc/codecs/rt5682-sdw.h
diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 77ffdb41bee5..e37cf72f2bab 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -29,7 +29,7 @@ config SND_SOC_AMD_ACP3x
config SND_SOC_AMD_RV_RT5682_MACH
tristate "AMD RV support for RT5682"
- select SND_SOC_RT5682
+ select SND_SOC_RT5682_I2C
select SND_SOC_MAX98357A
select SND_SOC_CROS_EC_CODEC
select I2C_CROS_EC_TUNNEL
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 2d4f1b4bc011..243a48aaec2a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -167,7 +167,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_RT5668
imply SND_SOC_RT5670
imply SND_SOC_RT5677
- imply SND_SOC_RT5682
+ imply SND_SOC_RT5682_I2C
imply SND_SOC_RT5682_SDW
imply SND_SOC_RT700_SDW
imply SND_SOC_RT711_SDW
@@ -1135,14 +1135,15 @@ config SND_SOC_RT5677_SPI
config SND_SOC_RT5682
tristate
- depends on I2C || SOUNDWIRE
- depends on SOUNDWIRE || !SOUNDWIRE
- depends on I2C || !I2C
+
+config SND_SOC_RT5682_I2C
+ tristate
+ depends on I2C
+ select SND_SOC_RT5682
config SND_SOC_RT5682_SDW
tristate "Realtek RT5682 Codec - SDW"
depends on SOUNDWIRE
- depends on I2C || !I2C
select SND_SOC_RT5682
select REGMAP_SOUNDWIRE
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index a603532c7af5..34fb7ba5c77f 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -178,6 +178,7 @@ snd-soc-rt5677-objs := rt5677.o
snd-soc-rt5677-spi-objs := rt5677-spi.o
snd-soc-rt5682-objs := rt5682.o
snd-soc-rt5682-sdw-objs := rt5682-sdw.o
+snd-soc-rt5682-i2c-objs := rt5682-i2c.o
snd-soc-rt700-objs := rt700.o rt700-sdw.o
snd-soc-rt711-objs := rt711.o rt711-sdw.o
snd-soc-rt715-objs := rt715.o rt715-sdw.o
@@ -479,6 +480,7 @@ obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o
obj-$(CONFIG_SND_SOC_RT5682) += snd-soc-rt5682.o
+obj-$(CONFIG_SND_SOC_RT5682_I2C) += snd-soc-rt5682-i2c.o
obj-$(CONFIG_SND_SOC_RT5682_SDW) += snd-soc-rt5682-sdw.o
obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o
obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o
diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c
new file mode 100644
index 000000000000..e28d08b1cd65
--- /dev/null
+++ b/sound/soc/codecs/rt5682-i2c.c
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// rt5682.c -- RT5682 ALSA SoC audio component driver
+//
+// Copyright 2018 Realtek Semiconductor Corp.
+// Author: Bard Liao <bardliao(a)realtek.com>
+//
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/acpi.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/mutex.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/rt5682.h>
+
+#include "rl6231.h"
+#include "rt5682.h"
+
+static const struct rt5682_platform_data i2s_default_platform_data = {
+ .dmic1_data_pin = RT5682_DMIC1_DATA_GPIO2,
+ .dmic1_clk_pin = RT5682_DMIC1_CLK_GPIO3,
+ .jd_src = RT5682_JD1,
+ .btndet_delay = 16,
+ .dai_clk_names[RT5682_DAI_WCLK_IDX] = "rt5682-dai-wclk",
+ .dai_clk_names[RT5682_DAI_BCLK_IDX] = "rt5682-dai-bclk",
+};
+
+static const struct regmap_config rt5682_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+ .max_register = RT5682_I2C_MODE,
+ .volatile_reg = rt5682_volatile_register,
+ .readable_reg = rt5682_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt5682_reg,
+ .num_reg_defaults = RT5682_REG_NUM,
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
+static void rt5682_jd_check_handler(struct work_struct *work)
+{
+ struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv,
+ jd_check_work.work);
+
+ if (snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL)
+ & RT5682_JDH_RS_MASK) {
+ /* jack out */
+ rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0);
+
+ snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type,
+ SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3);
+ } else {
+ schedule_delayed_work(&rt5682->jd_check_work, 500);
+ }
+}
+
+static irqreturn_t rt5682_irq(int irq, void *data)
+{
+ struct rt5682_priv *rt5682 = data;
+
+ mod_delayed_work(system_power_efficient_wq,
+ &rt5682->jack_detect_work, msecs_to_jiffies(250));
+
+ return IRQ_HANDLED;
+}
+
+static struct snd_soc_dai_driver rt5682_dai[] = {
+ {
+ .name = "rt5682-aif1",
+ .id = RT5682_AIF1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .ops = &rt5682_aif1_dai_ops,
+ },
+ {
+ .name = "rt5682-aif2",
+ .id = RT5682_AIF2,
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .ops = &rt5682_aif2_dai_ops,
+ },
+};
+
+static int rt5682_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct rt5682_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ struct rt5682_priv *rt5682;
+ int i, ret;
+ unsigned int val;
+
+ rt5682 = devm_kzalloc(&i2c->dev, sizeof(struct rt5682_priv),
+ GFP_KERNEL);
+ if (!rt5682)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, rt5682);
+
+ rt5682->pdata = i2s_default_platform_data;
+
+ if (pdata)
+ rt5682->pdata = *pdata;
+ else
+ rt5682_parse_dt(rt5682, &i2c->dev);
+
+ rt5682->regmap = devm_regmap_init_i2c(i2c, &rt5682_regmap);
+ if (IS_ERR(rt5682->regmap)) {
+ ret = PTR_ERR(rt5682->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(rt5682->supplies); i++)
+ rt5682->supplies[i].supply = rt5682_supply_names[i];
+
+ ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5682->supplies),
+ rt5682->supplies);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies),
+ rt5682->supplies);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ if (gpio_is_valid(rt5682->pdata.ldo1_en)) {
+ if (devm_gpio_request_one(&i2c->dev, rt5682->pdata.ldo1_en,
+ GPIOF_OUT_INIT_HIGH, "rt5682"))
+ dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n");
+ }
+
+ /* Sleep for 300 ms miniumum */
+ usleep_range(300000, 350000);
+
+ regmap_write(rt5682->regmap, RT5682_I2C_MODE, 0x1);
+ usleep_range(10000, 15000);
+
+ regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
+ if (val != DEVICE_ID) {
+ dev_err(&i2c->dev,
+ "Device with ID register %x is not rt5682\n", val);
+ return -ENODEV;
+ }
+
+ mutex_init(&rt5682->calibrate_mutex);
+ rt5682_calibrate(rt5682);
+
+ rt5682_apply_patch_list(rt5682, &i2c->dev);
+
+ regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000);
+
+ /* DMIC pin*/
+ if (rt5682->pdata.dmic1_data_pin != RT5682_DMIC1_NULL) {
+ switch (rt5682->pdata.dmic1_data_pin) {
+ case RT5682_DMIC1_DATA_GPIO2: /* share with LRCK2 */
+ regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
+ RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO2);
+ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
+ RT5682_GP2_PIN_MASK, RT5682_GP2_PIN_DMIC_SDA);
+ break;
+
+ case RT5682_DMIC1_DATA_GPIO5: /* share with DACDAT1 */
+ regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
+ RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO5);
+ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
+ RT5682_GP5_PIN_MASK, RT5682_GP5_PIN_DMIC_SDA);
+ break;
+
+ default:
+ dev_warn(&i2c->dev, "invalid DMIC_DAT pin\n");
+ break;
+ }
+
+ switch (rt5682->pdata.dmic1_clk_pin) {
+ case RT5682_DMIC1_CLK_GPIO1: /* share with IRQ */
+ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
+ RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_DMIC_CLK);
+ break;
+
+ case RT5682_DMIC1_CLK_GPIO3: /* share with BCLK2 */
+ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
+ RT5682_GP3_PIN_MASK, RT5682_GP3_PIN_DMIC_CLK);
+ break;
+
+ default:
+ dev_warn(&i2c->dev, "invalid DMIC_CLK pin\n");
+ break;
+ }
+ }
+
+ regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
+ RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK,
+ RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X);
+ regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380);
+ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
+ RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK,
+ RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1);
+ regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000);
+ regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8,
+ RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA);
+ regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1,
+ RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ);
+ regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1,
+ RT5682_PM_HP_MASK, RT5682_PM_HP_HV);
+ regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
+ RT5682_FIFO_CLK_DIV_MASK, RT5682_FIFO_CLK_DIV_2);
+
+ INIT_DELAYED_WORK(&rt5682->jack_detect_work,
+ rt5682_jack_detect_handler);
+ INIT_DELAYED_WORK(&rt5682->jd_check_work,
+ rt5682_jd_check_handler);
+
+ if (i2c->irq) {
+ ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
+ rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+ | IRQF_ONESHOT, "rt5682", rt5682);
+ if (ret)
+ dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
+ }
+
+ return devm_snd_soc_register_component(&i2c->dev,
+ &rt5682_soc_component_dev,
+ rt5682_dai, ARRAY_SIZE(rt5682_dai));
+}
+
+static void rt5682_i2c_shutdown(struct i2c_client *client)
+{
+ struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
+
+ rt5682_reset(rt5682);
+}
+
+static const struct of_device_id rt5682_of_match[] = {
+ {.compatible = "realtek,rt5682i"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, rt5682_of_match);
+
+static const struct acpi_device_id rt5682_acpi_match[] = {
+ {"10EC5682", 0,},
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match);
+
+static const struct i2c_device_id rt5682_i2c_id[] = {
+ {"rt5682", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, rt5682_i2c_id);
+
+static struct i2c_driver rt5682_i2c_driver = {
+ .driver = {
+ .name = "rt5682",
+ .of_match_table = rt5682_of_match,
+ .acpi_match_table = rt5682_acpi_match,
+ },
+ .probe = rt5682_i2c_probe,
+ .shutdown = rt5682_i2c_shutdown,
+ .id_table = rt5682_i2c_id,
+};
+module_i2c_driver(rt5682_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT5682 driver");
+MODULE_AUTHOR("Bard Liao <bardliao(a)realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c
index 99dd48d2a1d6..4cecc5ce545c 100644
--- a/sound/soc/codecs/rt5682-sdw.c
+++ b/sound/soc/codecs/rt5682-sdw.c
@@ -14,6 +14,7 @@
#include <linux/acpi.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
+#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/mutex.h>
#include <linux/soundwire/sdw.h>
@@ -28,7 +29,461 @@
#include <sound/tlv.h>
#include "rt5682.h"
-#include "rt5682-sdw.h"
+
+#define RT5682_SDW_ADDR_L 0x3000
+#define RT5682_SDW_ADDR_H 0x3001
+#define RT5682_SDW_DATA_L 0x3004
+#define RT5682_SDW_DATA_H 0x3005
+#define RT5682_SDW_CMD 0x3008
+
+static int rt5682_sdw_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct device *dev = context;
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+ unsigned int data_l, data_h;
+
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 0);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
+ regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_H, &data_h);
+ regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_L, &data_l);
+
+ *val = (data_h << 8) | data_l;
+
+ dev_vdbg(dev, "[%s] %04x => %04x\n", __func__, reg, *val);
+
+ return 0;
+}
+
+static int rt5682_sdw_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct device *dev = context;
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 1);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_H, (val >> 8) & 0xff);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_L, (val & 0xff));
+
+ dev_vdbg(dev, "[%s] %04x <= %04x\n", __func__, reg, val);
+
+ return 0;
+}
+
+static const struct regmap_config rt5682_sdw_indirect_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+ .max_register = RT5682_I2C_MODE,
+ .volatile_reg = rt5682_volatile_register,
+ .readable_reg = rt5682_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt5682_reg,
+ .num_reg_defaults = RT5682_REG_NUM,
+ .use_single_read = true,
+ .use_single_write = true,
+ .reg_read = rt5682_sdw_read,
+ .reg_write = rt5682_sdw_write,
+};
+
+struct sdw_stream_data {
+ struct sdw_stream_runtime *sdw_stream;
+};
+
+static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
+ int direction)
+{
+ struct sdw_stream_data *stream;
+
+ if (!sdw_stream)
+ return 0;
+
+ stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+ if (!stream)
+ return -ENOMEM;
+
+ stream->sdw_stream = (struct sdw_stream_runtime *)sdw_stream;
+
+ /* Use tx_mask or rx_mask to configure stream tag and set dma_data */
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+ dai->playback_dma_data = stream;
+ else
+ dai->capture_dma_data = stream;
+
+ return 0;
+}
+
+static void rt5682_sdw_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct sdw_stream_data *stream;
+
+ stream = snd_soc_dai_get_dma_data(dai, substream);
+ snd_soc_dai_set_dma_data(dai, substream, NULL);
+ kfree(stream);
+}
+
+static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_config stream_config;
+ struct sdw_port_config port_config;
+ enum sdw_data_direction direction;
+ struct sdw_stream_data *stream;
+ int retval, port, num_channels;
+ unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0;
+
+ dev_dbg(dai->dev, "%s %s", __func__, dai->name);
+
+ stream = snd_soc_dai_get_dma_data(dai, substream);
+ if (!stream)
+ return -ENOMEM;
+
+ if (!rt5682->slave)
+ return -EINVAL;
+
+ /* SoundWire specific configuration */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ direction = SDW_DATA_DIR_RX;
+ port = 1;
+ } else {
+ direction = SDW_DATA_DIR_TX;
+ port = 2;
+ }
+
+ stream_config.frame_rate = params_rate(params);
+ stream_config.ch_count = params_channels(params);
+ stream_config.bps = snd_pcm_format_width(params_format(params));
+ stream_config.direction = direction;
+
+ num_channels = params_channels(params);
+ port_config.ch_mask = (1 << (num_channels)) - 1;
+ port_config.num = port;
+
+ retval = sdw_stream_add_slave(rt5682->slave, &stream_config,
+ &port_config, 1, stream->sdw_stream);
+ if (retval) {
+ dev_err(dai->dev, "Unable to configure port\n");
+ return retval;
+ }
+
+ switch (params_rate(params)) {
+ case 48000:
+ val_p = RT5682_SDW_REF_1_48K;
+ val_c = RT5682_SDW_REF_2_48K;
+ break;
+ case 96000:
+ val_p = RT5682_SDW_REF_1_96K;
+ val_c = RT5682_SDW_REF_2_96K;
+ break;
+ case 192000:
+ val_p = RT5682_SDW_REF_1_192K;
+ val_c = RT5682_SDW_REF_2_192K;
+ break;
+ case 32000:
+ val_p = RT5682_SDW_REF_1_32K;
+ val_c = RT5682_SDW_REF_2_32K;
+ break;
+ case 24000:
+ val_p = RT5682_SDW_REF_1_24K;
+ val_c = RT5682_SDW_REF_2_24K;
+ break;
+ case 16000:
+ val_p = RT5682_SDW_REF_1_16K;
+ val_c = RT5682_SDW_REF_2_16K;
+ break;
+ case 12000:
+ val_p = RT5682_SDW_REF_1_12K;
+ val_c = RT5682_SDW_REF_2_12K;
+ break;
+ case 8000:
+ val_p = RT5682_SDW_REF_1_8K;
+ val_c = RT5682_SDW_REF_2_8K;
+ break;
+ case 44100:
+ val_p = RT5682_SDW_REF_1_44K;
+ val_c = RT5682_SDW_REF_2_44K;
+ break;
+ case 88200:
+ val_p = RT5682_SDW_REF_1_88K;
+ val_c = RT5682_SDW_REF_2_88K;
+ break;
+ case 176400:
+ val_p = RT5682_SDW_REF_1_176K;
+ val_c = RT5682_SDW_REF_2_176K;
+ break;
+ case 22050:
+ val_p = RT5682_SDW_REF_1_22K;
+ val_c = RT5682_SDW_REF_2_22K;
+ break;
+ case 11025:
+ val_p = RT5682_SDW_REF_1_11K;
+ val_c = RT5682_SDW_REF_2_11K;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (params_rate(params) <= 48000) {
+ osr_p = RT5682_DAC_OSR_D_8;
+ osr_c = RT5682_ADC_OSR_D_8;
+ } else if (params_rate(params) <= 96000) {
+ osr_p = RT5682_DAC_OSR_D_4;
+ osr_c = RT5682_ADC_OSR_D_4;
+ } else {
+ osr_p = RT5682_DAC_OSR_D_2;
+ osr_c = RT5682_ADC_OSR_D_2;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
+ RT5682_SDW_REF_1_MASK, val_p);
+ regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
+ RT5682_DAC_OSR_MASK, osr_p);
+ } else {
+ regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
+ RT5682_SDW_REF_2_MASK, val_c);
+ regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
+ RT5682_ADC_OSR_MASK, osr_c);
+ }
+
+ return retval;
+}
+
+static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_data *stream =
+ snd_soc_dai_get_dma_data(dai, substream);
+
+ if (!rt5682->slave)
+ return -EINVAL;
+
+ sdw_stream_remove_slave(rt5682->slave, stream->sdw_stream);
+ return 0;
+}
+
+static struct snd_soc_dai_ops rt5682_sdw_ops = {
+ .hw_params = rt5682_sdw_hw_params,
+ .hw_free = rt5682_sdw_hw_free,
+ .set_sdw_stream = rt5682_set_sdw_stream,
+ .shutdown = rt5682_sdw_shutdown,
+};
+
+static struct snd_soc_dai_driver rt5682_dai[] = {
+ {
+ .name = "rt5682-aif1",
+ .id = RT5682_AIF1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .ops = &rt5682_aif1_dai_ops,
+ },
+ {
+ .name = "rt5682-aif2",
+ .id = RT5682_AIF2,
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .ops = &rt5682_aif2_dai_ops,
+ },
+ {
+ .name = "rt5682-sdw",
+ .id = RT5682_SDW,
+ .playback = {
+ .stream_name = "SDW Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .capture = {
+ .stream_name = "SDW Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .ops = &rt5682_sdw_ops,
+ },
+};
+
+static int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
+ struct sdw_slave *slave)
+{
+ struct rt5682_priv *rt5682;
+ int ret;
+
+ rt5682 = devm_kzalloc(dev, sizeof(*rt5682), GFP_KERNEL);
+ if (!rt5682)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, rt5682);
+ rt5682->slave = slave;
+ rt5682->sdw_regmap = regmap;
+ rt5682->is_sdw = true;
+
+ rt5682->regmap = devm_regmap_init(dev, NULL, dev,
+ &rt5682_sdw_indirect_regmap);
+ if (IS_ERR(rt5682->regmap)) {
+ ret = PTR_ERR(rt5682->regmap);
+ dev_err(dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ /*
+ * Mark hw_init to false
+ * HW init will be performed when device reports present
+ */
+ rt5682->hw_init = false;
+ rt5682->first_hw_init = false;
+
+ mutex_init(&rt5682->calibrate_mutex);
+ INIT_DELAYED_WORK(&rt5682->jack_detect_work,
+ rt5682_jack_detect_handler);
+
+ ret = devm_snd_soc_register_component(dev,
+ &rt5682_soc_component_dev,
+ rt5682_dai, ARRAY_SIZE(rt5682_dai));
+ dev_dbg(&slave->dev, "%s\n", __func__);
+
+ return ret;
+}
+
+static int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
+{
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+ int ret = 0;
+ unsigned int val;
+
+ if (rt5682->hw_init)
+ return 0;
+
+ regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
+ if (val != DEVICE_ID) {
+ dev_err(dev, "Device with ID register %x is not rt5682\n", val);
+ return -ENODEV;
+ }
+
+ /*
+ * PM runtime is only enabled when a Slave reports as Attached
+ */
+ if (!rt5682->first_hw_init) {
+ /* set autosuspend parameters */
+ pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
+ pm_runtime_use_autosuspend(&slave->dev);
+
+ /* update count of parent 'active' children */
+ pm_runtime_set_active(&slave->dev);
+
+ /* make sure the device does not suspend immediately */
+ pm_runtime_mark_last_busy(&slave->dev);
+
+ pm_runtime_enable(&slave->dev);
+ }
+
+ pm_runtime_get_noresume(&slave->dev);
+
+ if (rt5682->first_hw_init) {
+ regcache_cache_only(rt5682->regmap, false);
+ regcache_cache_bypass(rt5682->regmap, true);
+ }
+
+ rt5682_calibrate(rt5682);
+
+ if (rt5682->first_hw_init) {
+ regcache_cache_bypass(rt5682->regmap, false);
+ regcache_mark_dirty(rt5682->regmap);
+ regcache_sync(rt5682->regmap);
+
+ /* volatile registers */
+ regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
+ RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
+
+ goto reinit;
+ }
+
+ rt5682_apply_patch_list(rt5682, dev);
+
+ regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000);
+
+ regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
+ RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK,
+ RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X);
+ regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380);
+ regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000);
+ regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8,
+ RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA);
+ regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1,
+ RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ);
+ regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1,
+ RT5682_PM_HP_MASK, RT5682_PM_HP_HV);
+
+ /* Soundwire */
+ regmap_write(rt5682->regmap, RT5682_PLL2_INTERNAL, 0xa266);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_1, 0x1700);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_2, 0x0006);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_3, 0x2600);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_4, 0x0c8f);
+ regmap_write(rt5682->regmap, RT5682_PLL_TRACK_2, 0x3000);
+ regmap_write(rt5682->regmap, RT5682_PLL_TRACK_3, 0x4000);
+ regmap_update_bits(rt5682->regmap, RT5682_GLB_CLK,
+ RT5682_SCLK_SRC_MASK | RT5682_PLL2_SRC_MASK,
+ RT5682_SCLK_SRC_PLL2 | RT5682_PLL2_SRC_SDW);
+
+ regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
+ RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
+ regmap_write(rt5682->regmap, RT5682_CBJ_CTRL_1, 0xd042);
+ regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_3,
+ RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN);
+ regmap_update_bits(rt5682->regmap, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN);
+ regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
+ RT5682_POW_IRQ | RT5682_POW_JDH |
+ RT5682_POW_ANA, RT5682_POW_IRQ |
+ RT5682_POW_JDH | RT5682_POW_ANA);
+ regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2,
+ RT5682_PWR_JDH, RT5682_PWR_JDH);
+ regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
+ RT5682_JD1_EN_MASK | RT5682_JD1_IRQ_MASK,
+ RT5682_JD1_EN | RT5682_JD1_IRQ_PUL);
+
+reinit:
+ mod_delayed_work(system_power_efficient_wq,
+ &rt5682->jack_detect_work, msecs_to_jiffies(250));
+
+ /* Mark Slave initialization complete */
+ rt5682->hw_init = true;
+ rt5682->first_hw_init = true;
+
+ pm_runtime_mark_last_busy(&slave->dev);
+ pm_runtime_put_autosuspend(&slave->dev);
+
+ dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
+
+ return ret;
+}
static bool rt5682_sdw_readable_register(struct device *dev, unsigned int reg)
{
@@ -46,7 +501,7 @@ static bool rt5682_sdw_readable_register(struct device *dev, unsigned int reg)
}
}
-const struct regmap_config rt5682_sdw_regmap = {
+static const struct regmap_config rt5682_sdw_regmap = {
.name = "sdw",
.reg_bits = 32,
.val_bits = 8,
diff --git a/sound/soc/codecs/rt5682-sdw.h b/sound/soc/codecs/rt5682-sdw.h
deleted file mode 100644
index 76e6f607066e..000000000000
--- a/sound/soc/codecs/rt5682-sdw.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only
- *
- * rt5682-sdw.h -- RT5682 SDW ALSA SoC audio driver
- *
- * Copyright 2019 Realtek Semiconductor Corp.
- * Author: Oder Chiou <oder_chiou(a)realtek.com>
- */
-
-#ifndef __RT5682_SDW_H__
-#define __RT5682_SDW_H__
-
-#define RT5682_SDW_ADDR_L 0x3000
-#define RT5682_SDW_ADDR_H 0x3001
-#define RT5682_SDW_DATA_L 0x3004
-#define RT5682_SDW_DATA_H 0x3005
-#define RT5682_SDW_CMD 0x3008
-
-#define RT5682_PROBE_TIMEOUT 2000
-
-#endif /* __RT5682_SDW_H__ */
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index 046e6110de73..d3245123101d 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
-/*
- * rt5682.c -- RT5682 ALSA SoC audio component driver
- *
- * Copyright 2018 Realtek Semiconductor Corp.
- * Author: Bard Liao <bardliao(a)realtek.com>
- */
+//
+// rt5682.c -- RT5682 ALSA SoC audio component driver
+//
+// Copyright 2018 Realtek Semiconductor Corp.
+// Author: Bard Liao <bardliao(a)realtek.com>
+//
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -12,7 +12,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
-#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/acpi.h>
@@ -31,22 +30,13 @@
#include "rl6231.h"
#include "rt5682.h"
-#include "rt5682-sdw.h"
-static const char *rt5682_supply_names[RT5682_NUM_SUPPLIES] = {
+const char *rt5682_supply_names[RT5682_NUM_SUPPLIES] = {
"AVDD",
"MICVDD",
"VBAT",
};
-
-static const struct rt5682_platform_data i2s_default_platform_data = {
- .dmic1_data_pin = RT5682_DMIC1_DATA_GPIO2,
- .dmic1_clk_pin = RT5682_DMIC1_CLK_GPIO3,
- .jd_src = RT5682_JD1,
- .btndet_delay = 16,
- .dai_clk_names[RT5682_DAI_WCLK_IDX] = "rt5682-dai-wclk",
- .dai_clk_names[RT5682_DAI_BCLK_IDX] = "rt5682-dai-bclk",
-};
+EXPORT_SYMBOL_GPL(rt5682_supply_names);
static const struct reg_sequence patch_list[] = {
{RT5682_HP_IMP_SENS_CTRL_19, 0x1000},
@@ -55,7 +45,18 @@ static const struct reg_sequence patch_list[] = {
{RT5682_PLL2_INTERNAL, 0x8266},
};
-static const struct reg_default rt5682_reg[] = {
+void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev)
+{
+ int ret;
+
+ ret = regmap_multi_reg_write(rt5682->regmap, patch_list,
+ ARRAY_SIZE(patch_list));
+ if (ret)
+ dev_warn(dev, "Failed to apply regmap patch: %d\n", ret);
+}
+EXPORT_SYMBOL_GPL(rt5682_apply_patch_list);
+
+const struct reg_default rt5682_reg[RT5682_REG_NUM] = {
{0x0002, 0x8080},
{0x0003, 0x8000},
{0x0005, 0x0000},
@@ -375,8 +376,9 @@ static const struct reg_default rt5682_reg[] = {
{0x03f2, 0x0800},
{0x03f3, 0x0800},
};
+EXPORT_SYMBOL_GPL(rt5682_reg);
-static bool rt5682_volatile_register(struct device *dev, unsigned int reg)
+bool rt5682_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5682_RESET:
@@ -403,8 +405,9 @@ static bool rt5682_volatile_register(struct device *dev, unsigned int reg)
return false;
}
}
+EXPORT_SYMBOL_GPL(rt5682_volatile_register);
-static bool rt5682_readable_register(struct device *dev, unsigned int reg)
+bool rt5682_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5682_RESET:
@@ -733,6 +736,7 @@ static bool rt5682_readable_register(struct device *dev, unsigned int reg)
return false;
}
}
+EXPORT_SYMBOL_GPL(rt5682_readable_register);
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0);
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0);
@@ -800,12 +804,13 @@ static SOC_ENUM_SINGLE_DECL(rt5682_dacr_enum,
static const struct snd_kcontrol_new rt5682_dac_r_mux =
SOC_DAPM_ENUM("DAC R Mux", rt5682_dacr_enum);
-static void rt5682_reset(struct rt5682_priv *rt5682)
+void rt5682_reset(struct rt5682_priv *rt5682)
{
regmap_write(rt5682->regmap, RT5682_RESET, 0);
if (!rt5682->is_sdw)
regmap_write(rt5682->regmap, RT5682_I2C_MODE, 1);
}
+EXPORT_SYMBOL_GPL(rt5682_reset);
/**
* rt5682_sel_asrc_clk_src - select ASRC clock source for a set of filters
@@ -910,8 +915,7 @@ static void rt5682_enable_push_button_irq(struct snd_soc_component *component,
*
* Returns detect status.
*/
-static int rt5682_headset_detect(struct snd_soc_component *component,
- int jack_insert)
+int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
{
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm = &component->dapm;
@@ -972,35 +976,7 @@ static int rt5682_headset_detect(struct snd_soc_component *component,
dev_dbg(component->dev, "jack_type = %d\n", rt5682->jack_type);
return rt5682->jack_type;
}
-
-static irqreturn_t rt5682_irq(int irq, void *data)
-{
- struct rt5682_priv *rt5682 = data;
-
- mod_delayed_work(system_power_efficient_wq,
- &rt5682->jack_detect_work, msecs_to_jiffies(250));
-
- return IRQ_HANDLED;
-}
-
-static void rt5682_jd_check_handler(struct work_struct *work)
-{
- struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv,
- jd_check_work.work);
-
- if (snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL)
- & RT5682_JDH_RS_MASK) {
- /* jack out */
- rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0);
-
- snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type,
- SND_JACK_HEADSET |
- SND_JACK_BTN_0 | SND_JACK_BTN_1 |
- SND_JACK_BTN_2 | SND_JACK_BTN_3);
- } else {
- schedule_delayed_work(&rt5682->jd_check_work, 500);
- }
-}
+EXPORT_SYMBOL_GPL(rt5682_headset_detect);
static int rt5682_set_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *hs_jack, void *data)
@@ -1077,7 +1053,7 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
return 0;
}
-static void rt5682_jack_detect_handler(struct work_struct *work)
+void rt5682_jack_detect_handler(struct work_struct *work)
{
struct rt5682_priv *rt5682 =
container_of(work, struct rt5682_priv, jack_detect_work.work);
@@ -1160,6 +1136,7 @@ static void rt5682_jack_detect_handler(struct work_struct *work)
mutex_unlock(&rt5682->calibrate_mutex);
}
+EXPORT_SYMBOL_GPL(rt5682_jack_detect_handler);
static const struct snd_kcontrol_new rt5682_snd_controls[] = {
/* DAC Digital Volume */
@@ -2899,7 +2876,8 @@ static int rt5682_resume(struct snd_soc_component *component)
regcache_cache_only(rt5682->regmap, false);
regcache_sync(rt5682->regmap);
- rt5682_irq(0, rt5682);
+ mod_delayed_work(system_power_efficient_wq,
+ &rt5682->jack_detect_work, msecs_to_jiffies(250));
return 0;
}
@@ -2908,270 +2886,22 @@ static int rt5682_resume(struct snd_soc_component *component)
#define rt5682_resume NULL
#endif
-#define RT5682_STEREO_RATES SNDRV_PCM_RATE_8000_192000
-#define RT5682_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
- SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
-
-static const struct snd_soc_dai_ops rt5682_aif1_dai_ops = {
+const struct snd_soc_dai_ops rt5682_aif1_dai_ops = {
.hw_params = rt5682_hw_params,
.set_fmt = rt5682_set_dai_fmt,
.set_tdm_slot = rt5682_set_tdm_slot,
.set_bclk_ratio = rt5682_set_bclk1_ratio,
};
+EXPORT_SYMBOL_GPL(rt5682_aif1_dai_ops);
-static const struct snd_soc_dai_ops rt5682_aif2_dai_ops = {
+const struct snd_soc_dai_ops rt5682_aif2_dai_ops = {
.hw_params = rt5682_hw_params,
.set_fmt = rt5682_set_dai_fmt,
.set_bclk_ratio = rt5682_set_bclk2_ratio,
};
+EXPORT_SYMBOL_GPL(rt5682_aif2_dai_ops);
-#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW)
-struct sdw_stream_data {
- struct sdw_stream_runtime *sdw_stream;
-};
-
-static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
- int direction)
-{
- struct sdw_stream_data *stream;
-
- if (!sdw_stream)
- return 0;
-
- stream = kzalloc(sizeof(*stream), GFP_KERNEL);
- if (!stream)
- return -ENOMEM;
-
- stream->sdw_stream = (struct sdw_stream_runtime *)sdw_stream;
-
- /* Use tx_mask or rx_mask to configure stream tag and set dma_data */
- if (direction == SNDRV_PCM_STREAM_PLAYBACK)
- dai->playback_dma_data = stream;
- else
- dai->capture_dma_data = stream;
-
- return 0;
-}
-
-static void rt5682_sdw_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct sdw_stream_data *stream;
-
- stream = snd_soc_dai_get_dma_data(dai, substream);
- snd_soc_dai_set_dma_data(dai, substream, NULL);
- kfree(stream);
-}
-
-static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_component *component = dai->component;
- struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
- struct sdw_stream_config stream_config;
- struct sdw_port_config port_config;
- enum sdw_data_direction direction;
- struct sdw_stream_data *stream;
- int retval, port, num_channels;
- unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0;
-
- dev_dbg(dai->dev, "%s %s", __func__, dai->name);
-
- stream = snd_soc_dai_get_dma_data(dai, substream);
- if (!stream)
- return -ENOMEM;
-
- if (!rt5682->slave)
- return -EINVAL;
-
- /* SoundWire specific configuration */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- direction = SDW_DATA_DIR_RX;
- port = 1;
- } else {
- direction = SDW_DATA_DIR_TX;
- port = 2;
- }
-
- stream_config.frame_rate = params_rate(params);
- stream_config.ch_count = params_channels(params);
- stream_config.bps = snd_pcm_format_width(params_format(params));
- stream_config.direction = direction;
-
- num_channels = params_channels(params);
- port_config.ch_mask = (1 << (num_channels)) - 1;
- port_config.num = port;
-
- retval = sdw_stream_add_slave(rt5682->slave, &stream_config,
- &port_config, 1, stream->sdw_stream);
- if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
- return retval;
- }
-
- switch (params_rate(params)) {
- case 48000:
- val_p = RT5682_SDW_REF_1_48K;
- val_c = RT5682_SDW_REF_2_48K;
- break;
- case 96000:
- val_p = RT5682_SDW_REF_1_96K;
- val_c = RT5682_SDW_REF_2_96K;
- break;
- case 192000:
- val_p = RT5682_SDW_REF_1_192K;
- val_c = RT5682_SDW_REF_2_192K;
- break;
- case 32000:
- val_p = RT5682_SDW_REF_1_32K;
- val_c = RT5682_SDW_REF_2_32K;
- break;
- case 24000:
- val_p = RT5682_SDW_REF_1_24K;
- val_c = RT5682_SDW_REF_2_24K;
- break;
- case 16000:
- val_p = RT5682_SDW_REF_1_16K;
- val_c = RT5682_SDW_REF_2_16K;
- break;
- case 12000:
- val_p = RT5682_SDW_REF_1_12K;
- val_c = RT5682_SDW_REF_2_12K;
- break;
- case 8000:
- val_p = RT5682_SDW_REF_1_8K;
- val_c = RT5682_SDW_REF_2_8K;
- break;
- case 44100:
- val_p = RT5682_SDW_REF_1_44K;
- val_c = RT5682_SDW_REF_2_44K;
- break;
- case 88200:
- val_p = RT5682_SDW_REF_1_88K;
- val_c = RT5682_SDW_REF_2_88K;
- break;
- case 176400:
- val_p = RT5682_SDW_REF_1_176K;
- val_c = RT5682_SDW_REF_2_176K;
- break;
- case 22050:
- val_p = RT5682_SDW_REF_1_22K;
- val_c = RT5682_SDW_REF_2_22K;
- break;
- case 11025:
- val_p = RT5682_SDW_REF_1_11K;
- val_c = RT5682_SDW_REF_2_11K;
- break;
- default:
- return -EINVAL;
- }
-
- if (params_rate(params) <= 48000) {
- osr_p = RT5682_DAC_OSR_D_8;
- osr_c = RT5682_ADC_OSR_D_8;
- } else if (params_rate(params) <= 96000) {
- osr_p = RT5682_DAC_OSR_D_4;
- osr_c = RT5682_ADC_OSR_D_4;
- } else {
- osr_p = RT5682_DAC_OSR_D_2;
- osr_c = RT5682_ADC_OSR_D_2;
- }
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
- RT5682_SDW_REF_1_MASK, val_p);
- regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
- RT5682_DAC_OSR_MASK, osr_p);
- } else {
- regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
- RT5682_SDW_REF_2_MASK, val_c);
- regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
- RT5682_ADC_OSR_MASK, osr_c);
- }
-
- return retval;
-}
-
-static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_component *component = dai->component;
- struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
- struct sdw_stream_data *stream =
- snd_soc_dai_get_dma_data(dai, substream);
-
- if (!rt5682->slave)
- return -EINVAL;
-
- sdw_stream_remove_slave(rt5682->slave, stream->sdw_stream);
- return 0;
-}
-
-static struct snd_soc_dai_ops rt5682_sdw_ops = {
- .hw_params = rt5682_sdw_hw_params,
- .hw_free = rt5682_sdw_hw_free,
- .set_sdw_stream = rt5682_set_sdw_stream,
- .shutdown = rt5682_sdw_shutdown,
-};
-#endif
-
-static struct snd_soc_dai_driver rt5682_dai[] = {
- {
- .name = "rt5682-aif1",
- .id = RT5682_AIF1,
- .playback = {
- .stream_name = "AIF1 Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = RT5682_STEREO_RATES,
- .formats = RT5682_FORMATS,
- },
- .capture = {
- .stream_name = "AIF1 Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = RT5682_STEREO_RATES,
- .formats = RT5682_FORMATS,
- },
- .ops = &rt5682_aif1_dai_ops,
- },
- {
- .name = "rt5682-aif2",
- .id = RT5682_AIF2,
- .capture = {
- .stream_name = "AIF2 Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = RT5682_STEREO_RATES,
- .formats = RT5682_FORMATS,
- },
- .ops = &rt5682_aif2_dai_ops,
- },
-#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW)
- {
- .name = "rt5682-sdw",
- .id = RT5682_SDW,
- .playback = {
- .stream_name = "SDW Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = RT5682_STEREO_RATES,
- .formats = RT5682_FORMATS,
- },
- .capture = {
- .stream_name = "SDW Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = RT5682_STEREO_RATES,
- .formats = RT5682_FORMATS,
- },
- .ops = &rt5682_sdw_ops,
- },
-#endif
-};
-
-static const struct snd_soc_component_driver soc_component_dev_rt5682 = {
+const struct snd_soc_component_driver rt5682_soc_component_dev = {
.probe = rt5682_probe,
.remove = rt5682_remove,
.suspend = rt5682_suspend,
@@ -3190,27 +2920,9 @@ static const struct snd_soc_component_driver soc_component_dev_rt5682 = {
.endianness = 1,
.non_legacy_dai_naming = 1,
};
+EXPORT_SYMBOL_GPL(rt5682_soc_component_dev);
-static const struct regmap_config rt5682_regmap = {
- .reg_bits = 16,
- .val_bits = 16,
- .max_register = RT5682_I2C_MODE,
- .volatile_reg = rt5682_volatile_register,
- .readable_reg = rt5682_readable_register,
- .cache_type = REGCACHE_RBTREE,
- .reg_defaults = rt5682_reg,
- .num_reg_defaults = ARRAY_SIZE(rt5682_reg),
- .use_single_read = true,
- .use_single_write = true,
-};
-
-static const struct i2c_device_id rt5682_i2c_id[] = {
- {"rt5682", 0},
- {}
-};
-MODULE_DEVICE_TABLE(i2c, rt5682_i2c_id);
-
-static int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev)
+int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev)
{
device_property_read_u32(dev, "realtek,dmic1-data-pin",
@@ -3238,8 +2950,9 @@ static int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev)
return 0;
}
+EXPORT_SYMBOL_GPL(rt5682_parse_dt);
-static void rt5682_calibrate(struct rt5682_priv *rt5682)
+void rt5682_calibrate(struct rt5682_priv *rt5682)
{
int value, count;
@@ -3289,407 +3002,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682)
mutex_unlock(&rt5682->calibrate_mutex);
}
-
-#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW)
-static int rt5682_sdw_read(void *context, unsigned int reg, unsigned int *val)
-{
- struct device *dev = context;
- struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
- unsigned int data_l, data_h;
-
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 0);
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
- regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_H, &data_h);
- regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_L, &data_l);
-
- *val = (data_h << 8) | data_l;
-
- dev_vdbg(dev, "[%s] %04x => %04x\n", __func__, reg, *val);
-
- return 0;
-}
-
-static int rt5682_sdw_write(void *context, unsigned int reg, unsigned int val)
-{
- struct device *dev = context;
- struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
-
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 1);
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_H, (val >> 8) & 0xff);
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_L, (val & 0xff));
-
- dev_vdbg(dev, "[%s] %04x <= %04x\n", __func__, reg, val);
-
- return 0;
-}
-
-static const struct regmap_config rt5682_sdw_regmap = {
- .reg_bits = 16,
- .val_bits = 16,
- .max_register = RT5682_I2C_MODE,
- .volatile_reg = rt5682_volatile_register,
- .readable_reg = rt5682_readable_register,
- .cache_type = REGCACHE_RBTREE,
- .reg_defaults = rt5682_reg,
- .num_reg_defaults = ARRAY_SIZE(rt5682_reg),
- .use_single_read = true,
- .use_single_write = true,
- .reg_read = rt5682_sdw_read,
- .reg_write = rt5682_sdw_write,
-};
-
-int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
- struct sdw_slave *slave)
-{
- struct rt5682_priv *rt5682;
- int ret;
-
- rt5682 = devm_kzalloc(dev, sizeof(*rt5682), GFP_KERNEL);
- if (!rt5682)
- return -ENOMEM;
-
- dev_set_drvdata(dev, rt5682);
- rt5682->slave = slave;
- rt5682->sdw_regmap = regmap;
- rt5682->is_sdw = true;
-
- rt5682->regmap = devm_regmap_init(dev, NULL, dev, &rt5682_sdw_regmap);
- if (IS_ERR(rt5682->regmap)) {
- ret = PTR_ERR(rt5682->regmap);
- dev_err(dev, "Failed to allocate register map: %d\n",
- ret);
- return ret;
- }
-
- /*
- * Mark hw_init to false
- * HW init will be performed when device reports present
- */
- rt5682->hw_init = false;
- rt5682->first_hw_init = false;
-
- mutex_init(&rt5682->calibrate_mutex);
- INIT_DELAYED_WORK(&rt5682->jack_detect_work,
- rt5682_jack_detect_handler);
-
- ret = devm_snd_soc_register_component(dev, &soc_component_dev_rt5682,
- rt5682_dai, ARRAY_SIZE(rt5682_dai));
-
- dev_dbg(&slave->dev, "%s\n", __func__);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(rt5682_sdw_init);
-
-int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
-{
- struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
- int ret = 0;
- unsigned int val;
-
- if (rt5682->hw_init)
- return 0;
-
- regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
- if (val != DEVICE_ID) {
- dev_err(dev, "Device with ID register %x is not rt5682\n", val);
- return -ENODEV;
- }
-
- /*
- * PM runtime is only enabled when a Slave reports as Attached
- */
- if (!rt5682->first_hw_init) {
- /* set autosuspend parameters */
- pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
- pm_runtime_use_autosuspend(&slave->dev);
-
- /* update count of parent 'active' children */
- pm_runtime_set_active(&slave->dev);
-
- /* make sure the device does not suspend immediately */
- pm_runtime_mark_last_busy(&slave->dev);
-
- pm_runtime_enable(&slave->dev);
- }
-
- pm_runtime_get_noresume(&slave->dev);
-
- if (rt5682->first_hw_init) {
- regcache_cache_only(rt5682->regmap, false);
- regcache_cache_bypass(rt5682->regmap, true);
- }
-
- rt5682_calibrate(rt5682);
-
- if (rt5682->first_hw_init) {
- regcache_cache_bypass(rt5682->regmap, false);
- regcache_mark_dirty(rt5682->regmap);
- regcache_sync(rt5682->regmap);
-
- /* volatile registers */
- regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
- RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
-
- goto reinit;
- }
-
- ret = regmap_multi_reg_write(rt5682->regmap, patch_list,
- ARRAY_SIZE(patch_list));
- if (ret)
- dev_warn(dev, "Failed to apply regmap patch: %d\n", ret);
-
- regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000);
-
- regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
- RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK,
- RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X);
- regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380);
- regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000);
- regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8,
- RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA);
- regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1,
- RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ);
- regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1,
- RT5682_PM_HP_MASK, RT5682_PM_HP_HV);
-
- /* Soundwire */
- regmap_write(rt5682->regmap, RT5682_PLL2_INTERNAL, 0xa266);
- regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_1, 0x1700);
- regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_2, 0x0006);
- regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_3, 0x2600);
- regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_4, 0x0c8f);
- regmap_write(rt5682->regmap, RT5682_PLL_TRACK_2, 0x3000);
- regmap_write(rt5682->regmap, RT5682_PLL_TRACK_3, 0x4000);
- regmap_update_bits(rt5682->regmap, RT5682_GLB_CLK,
- RT5682_SCLK_SRC_MASK | RT5682_PLL2_SRC_MASK,
- RT5682_SCLK_SRC_PLL2 | RT5682_PLL2_SRC_SDW);
-
- regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
- RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
- regmap_write(rt5682->regmap, RT5682_CBJ_CTRL_1, 0xd042);
- regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_3,
- RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN);
- regmap_update_bits(rt5682->regmap, RT5682_SAR_IL_CMD_1,
- RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN);
- regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
- RT5682_POW_IRQ | RT5682_POW_JDH |
- RT5682_POW_ANA, RT5682_POW_IRQ |
- RT5682_POW_JDH | RT5682_POW_ANA);
- regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2,
- RT5682_PWR_JDH, RT5682_PWR_JDH);
- regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
- RT5682_JD1_EN_MASK | RT5682_JD1_IRQ_MASK,
- RT5682_JD1_EN | RT5682_JD1_IRQ_PUL);
-
-reinit:
- mod_delayed_work(system_power_efficient_wq,
- &rt5682->jack_detect_work, msecs_to_jiffies(250));
-
- /* Mark Slave initialization complete */
- rt5682->hw_init = true;
- rt5682->first_hw_init = true;
-
- pm_runtime_mark_last_busy(&slave->dev);
- pm_runtime_put_autosuspend(&slave->dev);
-
- dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(rt5682_io_init);
-#endif
-
-static int rt5682_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
-{
- struct rt5682_platform_data *pdata = dev_get_platdata(&i2c->dev);
- struct rt5682_priv *rt5682;
- int i, ret;
- unsigned int val;
-
- rt5682 = devm_kzalloc(&i2c->dev, sizeof(struct rt5682_priv),
- GFP_KERNEL);
- if (!rt5682)
- return -ENOMEM;
-
- i2c_set_clientdata(i2c, rt5682);
-
- rt5682->pdata = i2s_default_platform_data;
-
- if (pdata)
- rt5682->pdata = *pdata;
- else
- rt5682_parse_dt(rt5682, &i2c->dev);
-
- rt5682->regmap = devm_regmap_init_i2c(i2c, &rt5682_regmap);
- if (IS_ERR(rt5682->regmap)) {
- ret = PTR_ERR(rt5682->regmap);
- dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
- ret);
- return ret;
- }
-
- for (i = 0; i < ARRAY_SIZE(rt5682->supplies); i++)
- rt5682->supplies[i].supply = rt5682_supply_names[i];
-
- ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5682->supplies),
- rt5682->supplies);
- if (ret) {
- dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
- return ret;
- }
-
- ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies),
- rt5682->supplies);
- if (ret) {
- dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
- return ret;
- }
-
- if (gpio_is_valid(rt5682->pdata.ldo1_en)) {
- if (devm_gpio_request_one(&i2c->dev, rt5682->pdata.ldo1_en,
- GPIOF_OUT_INIT_HIGH, "rt5682"))
- dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n");
- }
-
- /* Sleep for 300 ms miniumum */
- usleep_range(300000, 350000);
-
- regmap_write(rt5682->regmap, RT5682_I2C_MODE, 0x1);
- usleep_range(10000, 15000);
-
- regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
- if (val != DEVICE_ID) {
- dev_err(&i2c->dev,
- "Device with ID register %x is not rt5682\n", val);
- return -ENODEV;
- }
-
- mutex_init(&rt5682->calibrate_mutex);
- rt5682_calibrate(rt5682);
-
- ret = regmap_multi_reg_write(rt5682->regmap, patch_list,
- ARRAY_SIZE(patch_list));
- if (ret)
- dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
-
- regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000);
-
- /* DMIC pin*/
- if (rt5682->pdata.dmic1_data_pin != RT5682_DMIC1_NULL) {
- switch (rt5682->pdata.dmic1_data_pin) {
- case RT5682_DMIC1_DATA_GPIO2: /* share with LRCK2 */
- regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
- RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO2);
- regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
- RT5682_GP2_PIN_MASK, RT5682_GP2_PIN_DMIC_SDA);
- break;
-
- case RT5682_DMIC1_DATA_GPIO5: /* share with DACDAT1 */
- regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
- RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO5);
- regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
- RT5682_GP5_PIN_MASK, RT5682_GP5_PIN_DMIC_SDA);
- break;
-
- default:
- dev_warn(&i2c->dev, "invalid DMIC_DAT pin\n");
- break;
- }
-
- switch (rt5682->pdata.dmic1_clk_pin) {
- case RT5682_DMIC1_CLK_GPIO1: /* share with IRQ */
- regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
- RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_DMIC_CLK);
- break;
-
- case RT5682_DMIC1_CLK_GPIO3: /* share with BCLK2 */
- regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
- RT5682_GP3_PIN_MASK, RT5682_GP3_PIN_DMIC_CLK);
- break;
-
- default:
- dev_warn(&i2c->dev, "invalid DMIC_CLK pin\n");
- break;
- }
- }
-
- regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
- RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK,
- RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X);
- regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380);
- regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
- RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK,
- RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1);
- regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000);
- regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8,
- RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA);
- regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1,
- RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ);
- regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1,
- RT5682_PM_HP_MASK, RT5682_PM_HP_HV);
- regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
- RT5682_FIFO_CLK_DIV_MASK, RT5682_FIFO_CLK_DIV_2);
-
- INIT_DELAYED_WORK(&rt5682->jack_detect_work,
- rt5682_jack_detect_handler);
- INIT_DELAYED_WORK(&rt5682->jd_check_work,
- rt5682_jd_check_handler);
-
- if (i2c->irq) {
- ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
- rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
- | IRQF_ONESHOT, "rt5682", rt5682);
- if (ret)
- dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
- }
-
- return devm_snd_soc_register_component(&i2c->dev,
- &soc_component_dev_rt5682,
- rt5682_dai, ARRAY_SIZE(rt5682_dai));
-}
-
-static void rt5682_i2c_shutdown(struct i2c_client *client)
-{
- struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
-
- rt5682_reset(rt5682);
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id rt5682_of_match[] = {
- {.compatible = "realtek,rt5682i"},
- {},
-};
-MODULE_DEVICE_TABLE(of, rt5682_of_match);
-#endif
-
-#ifdef CONFIG_ACPI
-static const struct acpi_device_id rt5682_acpi_match[] = {
- {"10EC5682", 0,},
- {},
-};
-MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match);
-#endif
-
-static struct i2c_driver __maybe_unused rt5682_i2c_driver = {
- .driver = {
- .name = "rt5682",
- .of_match_table = of_match_ptr(rt5682_of_match),
- .acpi_match_table = ACPI_PTR(rt5682_acpi_match),
- },
- .probe = rt5682_i2c_probe,
- .shutdown = rt5682_i2c_shutdown,
- .id_table = rt5682_i2c_id,
-};
-
-#ifdef CONFIG_I2C
-module_i2c_driver(rt5682_i2c_driver);
-#endif
+EXPORT_SYMBOL_GPL(rt5682_calibrate);
MODULE_DESCRIPTION("ASoC RT5682 driver");
MODULE_AUTHOR("Bard Liao <bardliao(a)realtek.com>");
diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h
index 0baeece84ec4..f172c9ebd227 100644
--- a/sound/soc/codecs/rt5682.h
+++ b/sound/soc/codecs/rt5682.h
@@ -1337,6 +1337,13 @@
#define RT5682_SAR_SOUR_BTN (0x3f)
#define RT5682_SAR_SOUR_TYPE (0x0)
+/* soundwire timeout */
+#define RT5682_PROBE_TIMEOUT 2000
+
+
+#define RT5682_STEREO_RATES SNDRV_PCM_RATE_8000_192000
+#define RT5682_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
/* System Clock Source */
enum {
@@ -1418,10 +1425,29 @@ struct rt5682_priv {
int jack_type;
};
+extern const char *rt5682_supply_names[RT5682_NUM_SUPPLIES];
+
int rt5682_sel_asrc_clk_src(struct snd_soc_component *component,
unsigned int filter_mask, unsigned int clk_src);
-int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
- struct sdw_slave *slave);
-int rt5682_io_init(struct device *dev, struct sdw_slave *slave);
+
+void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev);
+
+int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert);
+void rt5682_jack_detect_handler(struct work_struct *work);
+
+bool rt5682_volatile_register(struct device *dev, unsigned int reg);
+bool rt5682_readable_register(struct device *dev, unsigned int reg);
+
+int rt5682_register_component(struct device *dev);
+void rt5682_calibrate(struct rt5682_priv *rt5682);
+void rt5682_reset(struct rt5682_priv *rt5682);
+int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev);
+
+#define RT5682_REG_NUM 318
+extern const struct reg_default rt5682_reg[RT5682_REG_NUM];
+
+extern const struct snd_soc_dai_ops rt5682_aif1_dai_ops;
+extern const struct snd_soc_dai_ops rt5682_aif2_dai_ops;
+extern const struct snd_soc_component_driver rt5682_soc_component_dev;
#endif /* __RT5682_H__ */
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index 91ce347b3a45..46073c04364a 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -430,7 +430,7 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
depends on SND_HDA_CODEC_HDMI
- select SND_SOC_RT5682
+ select SND_SOC_RT5682_I2C
select SND_SOC_MAX98357A
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
@@ -468,7 +468,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH
depends on SND_HDA_CODEC_HDMI
select SND_SOC_MAX98373
select SND_SOC_RT1015
- select SND_SOC_RT5682
+ select SND_SOC_RT5682_I2C
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
help
@@ -511,7 +511,7 @@ config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH
depends on MFD_INTEL_LPSS || COMPILE_TEST
depends on SND_HDA_CODEC_HDMI
select SND_SOC_RT1011
- select SND_SOC_RT5682
+ select SND_SOC_RT5682_I2C
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
help
--
2.26.2
2
1
Having mixer control to switch between DMICs prevents user to
initiate capture simultaneously on both the DMIcs.
Earlier 2 separate devices, one for each DMIC, gave an option of
using them simultaneously, which is not supported.
Signed-off-by: Akshu Agrawal <akshu.agrawal(a)amd.com>
---
v2: Modified "Front Mic" to "DMIC Switch"
sound/soc/amd/acp3x-rt5682-max9836.c | 43 +++++++++++-----------------
1 file changed, 16 insertions(+), 27 deletions(-)
diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c
index e499c00e0c66..0d3422b5f1a9 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -188,25 +188,27 @@ static int acp3x_ec_dmic0_startup(struct snd_pcm_substream *substream)
machine->cap_i2s_instance = I2S_BT_INSTANCE;
snd_soc_dai_set_bclk_ratio(codec_dai, 64);
- if (dmic_sel)
- gpiod_set_value(dmic_sel, 0);
return rt5682_clk_enable(substream);
}
-static int acp3x_ec_dmic1_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_card *card = rtd->card;
- struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
- struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
+static int dmic_switch;
- machine->cap_i2s_instance = I2S_BT_INSTANCE;
- snd_soc_dai_set_bclk_ratio(codec_dai, 64);
- if (dmic_sel)
- gpiod_set_value(dmic_sel, 1);
+static int dmic_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = dmic_switch;
+ return 0;
+}
- return rt5682_clk_enable(substream);
+static int dmic_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (dmic_sel) {
+ dmic_switch = ucontrol->value.integer.value[0];
+ gpiod_set_value(dmic_sel, !dmic_switch);
+ }
+ return 0;
}
static void rt5682_shutdown(struct snd_pcm_substream *substream)
@@ -229,11 +231,6 @@ static const struct snd_soc_ops acp3x_ec_cap0_ops = {
.shutdown = rt5682_shutdown,
};
-static const struct snd_soc_ops acp3x_ec_cap1_ops = {
- .startup = acp3x_ec_dmic1_startup,
- .shutdown = rt5682_shutdown,
-};
-
SND_SOC_DAILINK_DEF(acp3x_i2s,
DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0")));
SND_SOC_DAILINK_DEF(acp3x_bt,
@@ -279,15 +276,6 @@ static struct snd_soc_dai_link acp3x_dai_5682_98357[] = {
.ops = &acp3x_ec_cap0_ops,
SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
},
- {
- .name = "acp3x-ec-dmic1-capture",
- .stream_name = "Capture DMIC1",
- .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
- | SND_SOC_DAIFMT_CBS_CFS,
- .dpcm_capture = 1,
- .ops = &acp3x_ec_cap1_ops,
- SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
- },
};
static const struct snd_soc_dapm_widget acp3x_widgets[] = {
@@ -307,6 +295,7 @@ static const struct snd_kcontrol_new acp3x_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Spk"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
+ SOC_SINGLE_BOOL_EXT("DMIC Switch", 0, dmic_get, dmic_set),
};
static struct snd_soc_card acp3x_card = {
--
2.20.1
2
1
Hi all,
For uni-directional dai links there are these fields of snd_soc_dai_link:
* playback_only
* capture_only
But what about bi-directional DAI links?
Is it safe to assume that if playback_only = 0 and capture_only = 0
then the link is bi-directional?
We need this in sound/soc/soc-core.c: soc_check_tplg_fes
where a non-DPCM link is converted to a BE DPCM and we
need to inherit the directions supported.
For reference see: https://github.com/thesofproject/linux/pull/2143
thanks,
Daniel.
1
0
28 May '20
Add documentation for DT binding of max98390 amplifier driver.
Signed-off-by: Steve Lee <steves.lee(a)maximintegrated.com>
---
Changed since V4:
* No changes.
Changed since V3:
* No changes.
Changed since V2:
* No changes.
Changed since V1:
* Modified sample text in example
.../devicetree/bindings/sound/max98390.txt | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/max98390.txt
diff --git a/Documentation/devicetree/bindings/sound/max98390.txt b/Documentation/devicetree/bindings/sound/max98390.txt
new file mode 100644
index 000000000000..0ddd4c6ae55e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/max98390.txt
@@ -0,0 +1,26 @@
+Maxim Integrated MAX98390 Speaker Amplifier
+
+This device supports I2C.
+
+Required properties:
+
+ - compatible : "maxim,max98390"
+
+ - reg : the I2C address of the device.
+
+Optional properties:
+
+- maxim,temperature_calib
+ u32. The calculated temperature data was measured while doing the calibration. Data : Temp / 100 * 2^12
+
+- maxim,r0_calib
+ u32. This is r0 calibration data which was measured in factory mode.
+
+Example:
+
+codec: max98390@38 {
+ compatible = "maxim,max98390";
+ reg = <0x38>;
+ maxim,temperature_calib = <1024>;
+ maxim,r0_calib = <100232>;
+};
--
2.17.1
3
2
Having mixer control to switch between DMICs prevents user to
initiate capture simultaneously on both the DMIcs.
Earlier 2 separate devices, one for each DMIC, gave an option of
using them simultaneously, which is not supported.
Signed-off-by: Akshu Agrawal <akshu.agrawal(a)amd.com>
---
sound/soc/amd/acp3x-rt5682-max9836.c | 43 +++++++++++-----------------
1 file changed, 16 insertions(+), 27 deletions(-)
diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c
index e499c00e0c66..19f55a814547 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -188,25 +188,27 @@ static int acp3x_ec_dmic0_startup(struct snd_pcm_substream *substream)
machine->cap_i2s_instance = I2S_BT_INSTANCE;
snd_soc_dai_set_bclk_ratio(codec_dai, 64);
- if (dmic_sel)
- gpiod_set_value(dmic_sel, 0);
return rt5682_clk_enable(substream);
}
-static int acp3x_ec_dmic1_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_card *card = rtd->card;
- struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
- struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
+static int front_mic_enabled;
- machine->cap_i2s_instance = I2S_BT_INSTANCE;
- snd_soc_dai_set_bclk_ratio(codec_dai, 64);
- if (dmic_sel)
- gpiod_set_value(dmic_sel, 1);
+static int front_mic_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = front_mic_enabled;
+ return 0;
+}
- return rt5682_clk_enable(substream);
+static int front_mic_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (dmic_sel) {
+ front_mic_enabled = ucontrol->value.integer.value[0];
+ gpiod_set_value(dmic_sel, !front_mic_enabled);
+ }
+ return 0;
}
static void rt5682_shutdown(struct snd_pcm_substream *substream)
@@ -229,11 +231,6 @@ static const struct snd_soc_ops acp3x_ec_cap0_ops = {
.shutdown = rt5682_shutdown,
};
-static const struct snd_soc_ops acp3x_ec_cap1_ops = {
- .startup = acp3x_ec_dmic1_startup,
- .shutdown = rt5682_shutdown,
-};
-
SND_SOC_DAILINK_DEF(acp3x_i2s,
DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0")));
SND_SOC_DAILINK_DEF(acp3x_bt,
@@ -279,15 +276,6 @@ static struct snd_soc_dai_link acp3x_dai_5682_98357[] = {
.ops = &acp3x_ec_cap0_ops,
SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
},
- {
- .name = "acp3x-ec-dmic1-capture",
- .stream_name = "Capture DMIC1",
- .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
- | SND_SOC_DAIFMT_CBS_CFS,
- .dpcm_capture = 1,
- .ops = &acp3x_ec_cap1_ops,
- SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
- },
};
static const struct snd_soc_dapm_widget acp3x_widgets[] = {
@@ -307,6 +295,7 @@ static const struct snd_kcontrol_new acp3x_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Spk"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
+ SOC_SINGLE_BOOL_EXT("Front Mic", 0, front_mic_get, front_mic_set),
};
static struct snd_soc_card acp3x_card = {
--
2.20.1
3
2
Hi Mark
Current ALSA SoC is handling snd_soc_card related operation,
but it is implmemented directly without using function/macro,
and at random place.
This patch-set creates new snd_soc_card_xxx() functions
which handles snd_soc_card related operation,
and implmement these at new soc-card.c.
Kuninori Morimoto (19):
ASoC: soc.h: convert bool to bit field for snd_soc_card
ASoC: add soc-card.c
ASoC: soc-card: move snd_soc_card_get_kcontrol() to soc-card
ASoC: soc-card: move snd_soc_card_jack_new() to soc-card
ASoC: soc-card: move snd_soc_card_set/get_drvdata() to soc-card
ASoC: soc-card: move snd_soc_card_get_codec_dai() to soc-card
ASoC: soc-card: move snd_soc_card_subclass to soc-card
ASoC: soc-card: add snd_soc_card_suspend_pre()
ASoC: soc-card: add snd_soc_card_suspend_post()
ASoC: soc-card: add snd_soc_card_resume_pre()
ASoC: soc-card: add snd_soc_card_resume_post()
ASoC: soc-card: add probed bit field to snd_soc_card
ASoC: soc-card: add snd_soc_card_probe()
ASoC: soc-card: add snd_soc_card_late_probe()
ASoC: soc-card: add snd_soc_card_remove()
ASoC: soc-card: add snd_soc_card_set_bias_level()
ASoC: soc-card: add snd_soc_card_set_bias_level_post()
ASoC: soc-card: add snd_soc_card_add_dai_link()
ASoC: soc-card: add snd_soc_card_remove_dai_link()
include/sound/soc-card.h | 69 +++++++++++++
include/sound/soc.h | 53 ++--------
sound/soc/Makefile | 2 +-
sound/soc/soc-card.c | 218 +++++++++++++++++++++++++++++++++++++++
sound/soc/soc-core.c | 71 ++++---------
sound/soc/soc-dapm.c | 8 +-
sound/soc/soc-jack.c | 38 -------
7 files changed, 320 insertions(+), 139 deletions(-)
create mode 100644 include/sound/soc-card.h
create mode 100644 sound/soc/soc-card.c
--
2.17.1
3
27
I'm swapping out a vanilla loop based on RW_INTERLEAVED for
MMAP_INTERLEAVED, to reduce memory copies:
The equivalent code becomes:
snd_pcm_avail_update()
snd_pcm_mmap_begin()
snd_pcm_mmap_commit()
but what I find no longer works:
* Blocking I/O: it's necessary to make explicit calls to snd_pcm_wait()
with syscall overhead of poll()
* Automatic start (and perhaps others): so I have to count the frames
committed and call snd_pcm_start() explicitly.
I don't think these are conceptually incompatible with mmap, so is this
the intended behaviour and an important omission from the docs? Or is the
mmap API not widely used and I'm stumbling on bugs?
--
Mark
1
0
With SND_SOC_AMD_RV_RT5682_MACH using the i2c version of the
driver, we can easily get a build failure when I2C is built-in
but soundwire is not:
WARNING: unmet direct dependencies detected for SND_SOC_RT5682
Depends on [m]: SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && (I2C [=y] || SOUNDWIRE [=m]) && (SOUNDWIRE [=m] || !SOUNDWIRE [=m]) && (I2C [=y] || !I2C [=y])
Selected by [y]:
- SND_SOC_AMD_RV_RT5682_MACH [=y] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_SOC_AMD_ACP3x [=y] && I2C [=y] && CROS_EC [=y]
Selected by [m]:
- SND_SOC_RT5682_SDW [=m] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SOUNDWIRE [=m] && (I2C [=y] || !I2C [=y])
Rework the driver to have three separate modules, with the
main driver just dealing with the common bits and the actual
initialization as part of i2c and sdw specific modules.
The conversion is fairly mechanical to keep it easy to review,
i.e. it moves code around with the minimal required renaming
and changes.
Fixes: 6b8e4e7db3cd ("ASoC: amd: Add machine driver for Raven based platform")
Fixes: fd443a20c2f0 ("ASoC: rt5682: fix I2C/Soundwire dependencies")
Signed-off-by: Arnd Bergmann <arnd(a)arndb.de>
---
sound/soc/amd/Kconfig | 2 +-
sound/soc/codecs/Kconfig | 11 +-
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/rt5682-i2c.c | 341 ++++++++++++++
sound/soc/codecs/rt5682-sdw.c | 459 ++++++++++++++++++-
sound/soc/codecs/rt5682-sdw.h | 20 -
sound/soc/codecs/rt5682.c | 790 ++-------------------------------
sound/soc/codecs/rt5682.h | 29 +-
sound/soc/intel/boards/Kconfig | 6 +-
9 files changed, 869 insertions(+), 791 deletions(-)
create mode 100644 sound/soc/codecs/rt5682-i2c.c
delete mode 100644 sound/soc/codecs/rt5682-sdw.h
diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 77ffdb41bee5..e37cf72f2bab 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -29,7 +29,7 @@ config SND_SOC_AMD_ACP3x
config SND_SOC_AMD_RV_RT5682_MACH
tristate "AMD RV support for RT5682"
- select SND_SOC_RT5682
+ select SND_SOC_RT5682_I2C
select SND_SOC_MAX98357A
select SND_SOC_CROS_EC_CODEC
select I2C_CROS_EC_TUNNEL
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 2d4f1b4bc011..243a48aaec2a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -167,7 +167,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_RT5668
imply SND_SOC_RT5670
imply SND_SOC_RT5677
- imply SND_SOC_RT5682
+ imply SND_SOC_RT5682_I2C
imply SND_SOC_RT5682_SDW
imply SND_SOC_RT700_SDW
imply SND_SOC_RT711_SDW
@@ -1135,14 +1135,15 @@ config SND_SOC_RT5677_SPI
config SND_SOC_RT5682
tristate
- depends on I2C || SOUNDWIRE
- depends on SOUNDWIRE || !SOUNDWIRE
- depends on I2C || !I2C
+
+config SND_SOC_RT5682_I2C
+ tristate
+ depends on I2C
+ select SND_SOC_RT5682
config SND_SOC_RT5682_SDW
tristate "Realtek RT5682 Codec - SDW"
depends on SOUNDWIRE
- depends on I2C || !I2C
select SND_SOC_RT5682
select REGMAP_SOUNDWIRE
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index a603532c7af5..34fb7ba5c77f 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -178,6 +178,7 @@ snd-soc-rt5677-objs := rt5677.o
snd-soc-rt5677-spi-objs := rt5677-spi.o
snd-soc-rt5682-objs := rt5682.o
snd-soc-rt5682-sdw-objs := rt5682-sdw.o
+snd-soc-rt5682-i2c-objs := rt5682-i2c.o
snd-soc-rt700-objs := rt700.o rt700-sdw.o
snd-soc-rt711-objs := rt711.o rt711-sdw.o
snd-soc-rt715-objs := rt715.o rt715-sdw.o
@@ -479,6 +480,7 @@ obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o
obj-$(CONFIG_SND_SOC_RT5682) += snd-soc-rt5682.o
+obj-$(CONFIG_SND_SOC_RT5682_I2C) += snd-soc-rt5682-i2c.o
obj-$(CONFIG_SND_SOC_RT5682_SDW) += snd-soc-rt5682-sdw.o
obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o
obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o
diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c
new file mode 100644
index 000000000000..c891aa80757f
--- /dev/null
+++ b/sound/soc/codecs/rt5682-i2c.c
@@ -0,0 +1,341 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * rt5682.c -- RT5682 ALSA SoC audio component driver
+ *
+ * Copyright 2018 Realtek Semiconductor Corp.
+ * Author: Bard Liao <bardliao(a)realtek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/acpi.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/mutex.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/rt5682.h>
+
+#include "rl6231.h"
+#include "rt5682.h"
+
+static const char *rt5682_supply_names[RT5682_NUM_SUPPLIES] = {
+ "AVDD",
+ "MICVDD",
+ "VBAT",
+};
+
+static const struct rt5682_platform_data i2s_default_platform_data = {
+ .dmic1_data_pin = RT5682_DMIC1_DATA_GPIO2,
+ .dmic1_clk_pin = RT5682_DMIC1_CLK_GPIO3,
+ .jd_src = RT5682_JD1,
+ .btndet_delay = 16,
+ .dai_clk_names[RT5682_DAI_WCLK_IDX] = "rt5682-dai-wclk",
+ .dai_clk_names[RT5682_DAI_BCLK_IDX] = "rt5682-dai-bclk",
+};
+
+static const struct regmap_config rt5682_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+ .max_register = RT5682_I2C_MODE,
+ .volatile_reg = rt5682_volatile_register,
+ .readable_reg = rt5682_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt5682_reg,
+ .num_reg_defaults = RT5682_REG_NUM,
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
+static void rt5682_jd_check_handler(struct work_struct *work)
+{
+ struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv,
+ jd_check_work.work);
+
+ if (snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL)
+ & RT5682_JDH_RS_MASK) {
+ /* jack out */
+ rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0);
+
+ snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type,
+ SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3);
+ } else {
+ schedule_delayed_work(&rt5682->jd_check_work, 500);
+ }
+}
+
+static int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev)
+{
+
+ device_property_read_u32(dev, "realtek,dmic1-data-pin",
+ &rt5682->pdata.dmic1_data_pin);
+ device_property_read_u32(dev, "realtek,dmic1-clk-pin",
+ &rt5682->pdata.dmic1_clk_pin);
+ device_property_read_u32(dev, "realtek,jd-src",
+ &rt5682->pdata.jd_src);
+ device_property_read_u32(dev, "realtek,btndet-delay",
+ &rt5682->pdata.btndet_delay);
+ device_property_read_u32(dev, "realtek,dmic-clk-rate-hz",
+ &rt5682->pdata.dmic_clk_rate);
+ device_property_read_u32(dev, "realtek,dmic-delay-ms",
+ &rt5682->pdata.dmic_delay);
+
+ rt5682->pdata.ldo1_en = of_get_named_gpio(dev->of_node,
+ "realtek,ldo1-en-gpios", 0);
+
+ if (device_property_read_string_array(dev, "clock-output-names",
+ rt5682->pdata.dai_clk_names,
+ RT5682_DAI_NUM_CLKS) < 0)
+ dev_warn(dev, "Using default DAI clk names: %s, %s\n",
+ rt5682->pdata.dai_clk_names[RT5682_DAI_WCLK_IDX],
+ rt5682->pdata.dai_clk_names[RT5682_DAI_BCLK_IDX]);
+
+ return 0;
+}
+
+static irqreturn_t rt5682_irq(int irq, void *data)
+{
+ struct rt5682_priv *rt5682 = data;
+
+ mod_delayed_work(system_power_efficient_wq,
+ &rt5682->jack_detect_work, msecs_to_jiffies(250));
+
+ return IRQ_HANDLED;
+}
+
+static struct snd_soc_dai_driver rt5682_dai[] = {
+ {
+ .name = "rt5682-aif1",
+ .id = RT5682_AIF1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .ops = &rt5682_aif1_dai_ops,
+ },
+ {
+ .name = "rt5682-aif2",
+ .id = RT5682_AIF2,
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .ops = &rt5682_aif2_dai_ops,
+ },
+};
+
+static int rt5682_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct rt5682_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ struct rt5682_priv *rt5682;
+ int i, ret;
+ unsigned int val;
+
+ rt5682 = devm_kzalloc(&i2c->dev, sizeof(struct rt5682_priv),
+ GFP_KERNEL);
+ if (!rt5682)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, rt5682);
+
+ rt5682->pdata = i2s_default_platform_data;
+
+ if (pdata)
+ rt5682->pdata = *pdata;
+ else
+ rt5682_parse_dt(rt5682, &i2c->dev);
+
+ rt5682->regmap = devm_regmap_init_i2c(i2c, &rt5682_regmap);
+ if (IS_ERR(rt5682->regmap)) {
+ ret = PTR_ERR(rt5682->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(rt5682->supplies); i++)
+ rt5682->supplies[i].supply = rt5682_supply_names[i];
+
+ ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5682->supplies),
+ rt5682->supplies);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies),
+ rt5682->supplies);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ if (gpio_is_valid(rt5682->pdata.ldo1_en)) {
+ if (devm_gpio_request_one(&i2c->dev, rt5682->pdata.ldo1_en,
+ GPIOF_OUT_INIT_HIGH, "rt5682"))
+ dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n");
+ }
+
+ /* Sleep for 300 ms miniumum */
+ usleep_range(300000, 350000);
+
+ regmap_write(rt5682->regmap, RT5682_I2C_MODE, 0x1);
+ usleep_range(10000, 15000);
+
+ regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
+ if (val != DEVICE_ID) {
+ dev_err(&i2c->dev,
+ "Device with ID register %x is not rt5682\n", val);
+ return -ENODEV;
+ }
+
+ mutex_init(&rt5682->calibrate_mutex);
+ rt5682_calibrate(rt5682);
+
+ rt5682_apply_patch_list(rt5682, &i2c->dev);
+
+ regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000);
+
+ /* DMIC pin*/
+ if (rt5682->pdata.dmic1_data_pin != RT5682_DMIC1_NULL) {
+ switch (rt5682->pdata.dmic1_data_pin) {
+ case RT5682_DMIC1_DATA_GPIO2: /* share with LRCK2 */
+ regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
+ RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO2);
+ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
+ RT5682_GP2_PIN_MASK, RT5682_GP2_PIN_DMIC_SDA);
+ break;
+
+ case RT5682_DMIC1_DATA_GPIO5: /* share with DACDAT1 */
+ regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
+ RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO5);
+ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
+ RT5682_GP5_PIN_MASK, RT5682_GP5_PIN_DMIC_SDA);
+ break;
+
+ default:
+ dev_warn(&i2c->dev, "invalid DMIC_DAT pin\n");
+ break;
+ }
+
+ switch (rt5682->pdata.dmic1_clk_pin) {
+ case RT5682_DMIC1_CLK_GPIO1: /* share with IRQ */
+ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
+ RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_DMIC_CLK);
+ break;
+
+ case RT5682_DMIC1_CLK_GPIO3: /* share with BCLK2 */
+ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
+ RT5682_GP3_PIN_MASK, RT5682_GP3_PIN_DMIC_CLK);
+ break;
+
+ default:
+ dev_warn(&i2c->dev, "invalid DMIC_CLK pin\n");
+ break;
+ }
+ }
+
+ regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
+ RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK,
+ RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X);
+ regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380);
+ regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
+ RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK,
+ RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1);
+ regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000);
+ regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8,
+ RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA);
+ regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1,
+ RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ);
+ regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1,
+ RT5682_PM_HP_MASK, RT5682_PM_HP_HV);
+ regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
+ RT5682_FIFO_CLK_DIV_MASK, RT5682_FIFO_CLK_DIV_2);
+
+ INIT_DELAYED_WORK(&rt5682->jack_detect_work,
+ rt5682_jack_detect_handler);
+ INIT_DELAYED_WORK(&rt5682->jd_check_work,
+ rt5682_jd_check_handler);
+
+ if (i2c->irq) {
+ ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
+ rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+ | IRQF_ONESHOT, "rt5682", rt5682);
+ if (ret)
+ dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
+ }
+
+ return devm_snd_soc_register_component(&i2c->dev,
+ &rt5682_soc_component_dev,
+ rt5682_dai, ARRAY_SIZE(rt5682_dai));
+}
+
+static void rt5682_i2c_shutdown(struct i2c_client *client)
+{
+ struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
+
+ rt5682_reset(rt5682);
+}
+
+static const struct of_device_id rt5682_of_match[] = {
+ {.compatible = "realtek,rt5682i"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, rt5682_of_match);
+
+static const struct acpi_device_id rt5682_acpi_match[] = {
+ {"10EC5682", 0,},
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match);
+
+static const struct i2c_device_id rt5682_i2c_id[] = {
+ {"rt5682", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, rt5682_i2c_id);
+
+static struct i2c_driver rt5682_i2c_driver = {
+ .driver = {
+ .name = "rt5682",
+ .of_match_table = rt5682_of_match,
+ .acpi_match_table = rt5682_acpi_match,
+ },
+ .probe = rt5682_i2c_probe,
+ .shutdown = rt5682_i2c_shutdown,
+ .id_table = rt5682_i2c_id,
+};
+module_i2c_driver(rt5682_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT5682 driver");
+MODULE_AUTHOR("Bard Liao <bardliao(a)realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c
index 99dd48d2a1d6..4cecc5ce545c 100644
--- a/sound/soc/codecs/rt5682-sdw.c
+++ b/sound/soc/codecs/rt5682-sdw.c
@@ -14,6 +14,7 @@
#include <linux/acpi.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
+#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/mutex.h>
#include <linux/soundwire/sdw.h>
@@ -28,7 +29,461 @@
#include <sound/tlv.h>
#include "rt5682.h"
-#include "rt5682-sdw.h"
+
+#define RT5682_SDW_ADDR_L 0x3000
+#define RT5682_SDW_ADDR_H 0x3001
+#define RT5682_SDW_DATA_L 0x3004
+#define RT5682_SDW_DATA_H 0x3005
+#define RT5682_SDW_CMD 0x3008
+
+static int rt5682_sdw_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct device *dev = context;
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+ unsigned int data_l, data_h;
+
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 0);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
+ regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_H, &data_h);
+ regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_L, &data_l);
+
+ *val = (data_h << 8) | data_l;
+
+ dev_vdbg(dev, "[%s] %04x => %04x\n", __func__, reg, *val);
+
+ return 0;
+}
+
+static int rt5682_sdw_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct device *dev = context;
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 1);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_H, (val >> 8) & 0xff);
+ regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_L, (val & 0xff));
+
+ dev_vdbg(dev, "[%s] %04x <= %04x\n", __func__, reg, val);
+
+ return 0;
+}
+
+static const struct regmap_config rt5682_sdw_indirect_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+ .max_register = RT5682_I2C_MODE,
+ .volatile_reg = rt5682_volatile_register,
+ .readable_reg = rt5682_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt5682_reg,
+ .num_reg_defaults = RT5682_REG_NUM,
+ .use_single_read = true,
+ .use_single_write = true,
+ .reg_read = rt5682_sdw_read,
+ .reg_write = rt5682_sdw_write,
+};
+
+struct sdw_stream_data {
+ struct sdw_stream_runtime *sdw_stream;
+};
+
+static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
+ int direction)
+{
+ struct sdw_stream_data *stream;
+
+ if (!sdw_stream)
+ return 0;
+
+ stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+ if (!stream)
+ return -ENOMEM;
+
+ stream->sdw_stream = (struct sdw_stream_runtime *)sdw_stream;
+
+ /* Use tx_mask or rx_mask to configure stream tag and set dma_data */
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+ dai->playback_dma_data = stream;
+ else
+ dai->capture_dma_data = stream;
+
+ return 0;
+}
+
+static void rt5682_sdw_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct sdw_stream_data *stream;
+
+ stream = snd_soc_dai_get_dma_data(dai, substream);
+ snd_soc_dai_set_dma_data(dai, substream, NULL);
+ kfree(stream);
+}
+
+static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_config stream_config;
+ struct sdw_port_config port_config;
+ enum sdw_data_direction direction;
+ struct sdw_stream_data *stream;
+ int retval, port, num_channels;
+ unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0;
+
+ dev_dbg(dai->dev, "%s %s", __func__, dai->name);
+
+ stream = snd_soc_dai_get_dma_data(dai, substream);
+ if (!stream)
+ return -ENOMEM;
+
+ if (!rt5682->slave)
+ return -EINVAL;
+
+ /* SoundWire specific configuration */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ direction = SDW_DATA_DIR_RX;
+ port = 1;
+ } else {
+ direction = SDW_DATA_DIR_TX;
+ port = 2;
+ }
+
+ stream_config.frame_rate = params_rate(params);
+ stream_config.ch_count = params_channels(params);
+ stream_config.bps = snd_pcm_format_width(params_format(params));
+ stream_config.direction = direction;
+
+ num_channels = params_channels(params);
+ port_config.ch_mask = (1 << (num_channels)) - 1;
+ port_config.num = port;
+
+ retval = sdw_stream_add_slave(rt5682->slave, &stream_config,
+ &port_config, 1, stream->sdw_stream);
+ if (retval) {
+ dev_err(dai->dev, "Unable to configure port\n");
+ return retval;
+ }
+
+ switch (params_rate(params)) {
+ case 48000:
+ val_p = RT5682_SDW_REF_1_48K;
+ val_c = RT5682_SDW_REF_2_48K;
+ break;
+ case 96000:
+ val_p = RT5682_SDW_REF_1_96K;
+ val_c = RT5682_SDW_REF_2_96K;
+ break;
+ case 192000:
+ val_p = RT5682_SDW_REF_1_192K;
+ val_c = RT5682_SDW_REF_2_192K;
+ break;
+ case 32000:
+ val_p = RT5682_SDW_REF_1_32K;
+ val_c = RT5682_SDW_REF_2_32K;
+ break;
+ case 24000:
+ val_p = RT5682_SDW_REF_1_24K;
+ val_c = RT5682_SDW_REF_2_24K;
+ break;
+ case 16000:
+ val_p = RT5682_SDW_REF_1_16K;
+ val_c = RT5682_SDW_REF_2_16K;
+ break;
+ case 12000:
+ val_p = RT5682_SDW_REF_1_12K;
+ val_c = RT5682_SDW_REF_2_12K;
+ break;
+ case 8000:
+ val_p = RT5682_SDW_REF_1_8K;
+ val_c = RT5682_SDW_REF_2_8K;
+ break;
+ case 44100:
+ val_p = RT5682_SDW_REF_1_44K;
+ val_c = RT5682_SDW_REF_2_44K;
+ break;
+ case 88200:
+ val_p = RT5682_SDW_REF_1_88K;
+ val_c = RT5682_SDW_REF_2_88K;
+ break;
+ case 176400:
+ val_p = RT5682_SDW_REF_1_176K;
+ val_c = RT5682_SDW_REF_2_176K;
+ break;
+ case 22050:
+ val_p = RT5682_SDW_REF_1_22K;
+ val_c = RT5682_SDW_REF_2_22K;
+ break;
+ case 11025:
+ val_p = RT5682_SDW_REF_1_11K;
+ val_c = RT5682_SDW_REF_2_11K;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (params_rate(params) <= 48000) {
+ osr_p = RT5682_DAC_OSR_D_8;
+ osr_c = RT5682_ADC_OSR_D_8;
+ } else if (params_rate(params) <= 96000) {
+ osr_p = RT5682_DAC_OSR_D_4;
+ osr_c = RT5682_ADC_OSR_D_4;
+ } else {
+ osr_p = RT5682_DAC_OSR_D_2;
+ osr_c = RT5682_ADC_OSR_D_2;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
+ RT5682_SDW_REF_1_MASK, val_p);
+ regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
+ RT5682_DAC_OSR_MASK, osr_p);
+ } else {
+ regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
+ RT5682_SDW_REF_2_MASK, val_c);
+ regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
+ RT5682_ADC_OSR_MASK, osr_c);
+ }
+
+ return retval;
+}
+
+static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_data *stream =
+ snd_soc_dai_get_dma_data(dai, substream);
+
+ if (!rt5682->slave)
+ return -EINVAL;
+
+ sdw_stream_remove_slave(rt5682->slave, stream->sdw_stream);
+ return 0;
+}
+
+static struct snd_soc_dai_ops rt5682_sdw_ops = {
+ .hw_params = rt5682_sdw_hw_params,
+ .hw_free = rt5682_sdw_hw_free,
+ .set_sdw_stream = rt5682_set_sdw_stream,
+ .shutdown = rt5682_sdw_shutdown,
+};
+
+static struct snd_soc_dai_driver rt5682_dai[] = {
+ {
+ .name = "rt5682-aif1",
+ .id = RT5682_AIF1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .ops = &rt5682_aif1_dai_ops,
+ },
+ {
+ .name = "rt5682-aif2",
+ .id = RT5682_AIF2,
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .ops = &rt5682_aif2_dai_ops,
+ },
+ {
+ .name = "rt5682-sdw",
+ .id = RT5682_SDW,
+ .playback = {
+ .stream_name = "SDW Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .capture = {
+ .stream_name = "SDW Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5682_STEREO_RATES,
+ .formats = RT5682_FORMATS,
+ },
+ .ops = &rt5682_sdw_ops,
+ },
+};
+
+static int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
+ struct sdw_slave *slave)
+{
+ struct rt5682_priv *rt5682;
+ int ret;
+
+ rt5682 = devm_kzalloc(dev, sizeof(*rt5682), GFP_KERNEL);
+ if (!rt5682)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, rt5682);
+ rt5682->slave = slave;
+ rt5682->sdw_regmap = regmap;
+ rt5682->is_sdw = true;
+
+ rt5682->regmap = devm_regmap_init(dev, NULL, dev,
+ &rt5682_sdw_indirect_regmap);
+ if (IS_ERR(rt5682->regmap)) {
+ ret = PTR_ERR(rt5682->regmap);
+ dev_err(dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ /*
+ * Mark hw_init to false
+ * HW init will be performed when device reports present
+ */
+ rt5682->hw_init = false;
+ rt5682->first_hw_init = false;
+
+ mutex_init(&rt5682->calibrate_mutex);
+ INIT_DELAYED_WORK(&rt5682->jack_detect_work,
+ rt5682_jack_detect_handler);
+
+ ret = devm_snd_soc_register_component(dev,
+ &rt5682_soc_component_dev,
+ rt5682_dai, ARRAY_SIZE(rt5682_dai));
+ dev_dbg(&slave->dev, "%s\n", __func__);
+
+ return ret;
+}
+
+static int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
+{
+ struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
+ int ret = 0;
+ unsigned int val;
+
+ if (rt5682->hw_init)
+ return 0;
+
+ regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
+ if (val != DEVICE_ID) {
+ dev_err(dev, "Device with ID register %x is not rt5682\n", val);
+ return -ENODEV;
+ }
+
+ /*
+ * PM runtime is only enabled when a Slave reports as Attached
+ */
+ if (!rt5682->first_hw_init) {
+ /* set autosuspend parameters */
+ pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
+ pm_runtime_use_autosuspend(&slave->dev);
+
+ /* update count of parent 'active' children */
+ pm_runtime_set_active(&slave->dev);
+
+ /* make sure the device does not suspend immediately */
+ pm_runtime_mark_last_busy(&slave->dev);
+
+ pm_runtime_enable(&slave->dev);
+ }
+
+ pm_runtime_get_noresume(&slave->dev);
+
+ if (rt5682->first_hw_init) {
+ regcache_cache_only(rt5682->regmap, false);
+ regcache_cache_bypass(rt5682->regmap, true);
+ }
+
+ rt5682_calibrate(rt5682);
+
+ if (rt5682->first_hw_init) {
+ regcache_cache_bypass(rt5682->regmap, false);
+ regcache_mark_dirty(rt5682->regmap);
+ regcache_sync(rt5682->regmap);
+
+ /* volatile registers */
+ regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
+ RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
+
+ goto reinit;
+ }
+
+ rt5682_apply_patch_list(rt5682, dev);
+
+ regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000);
+
+ regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
+ RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK,
+ RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X);
+ regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380);
+ regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000);
+ regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8,
+ RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA);
+ regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1,
+ RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ);
+ regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1,
+ RT5682_PM_HP_MASK, RT5682_PM_HP_HV);
+
+ /* Soundwire */
+ regmap_write(rt5682->regmap, RT5682_PLL2_INTERNAL, 0xa266);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_1, 0x1700);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_2, 0x0006);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_3, 0x2600);
+ regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_4, 0x0c8f);
+ regmap_write(rt5682->regmap, RT5682_PLL_TRACK_2, 0x3000);
+ regmap_write(rt5682->regmap, RT5682_PLL_TRACK_3, 0x4000);
+ regmap_update_bits(rt5682->regmap, RT5682_GLB_CLK,
+ RT5682_SCLK_SRC_MASK | RT5682_PLL2_SRC_MASK,
+ RT5682_SCLK_SRC_PLL2 | RT5682_PLL2_SRC_SDW);
+
+ regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
+ RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
+ regmap_write(rt5682->regmap, RT5682_CBJ_CTRL_1, 0xd042);
+ regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_3,
+ RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN);
+ regmap_update_bits(rt5682->regmap, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN);
+ regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
+ RT5682_POW_IRQ | RT5682_POW_JDH |
+ RT5682_POW_ANA, RT5682_POW_IRQ |
+ RT5682_POW_JDH | RT5682_POW_ANA);
+ regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2,
+ RT5682_PWR_JDH, RT5682_PWR_JDH);
+ regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
+ RT5682_JD1_EN_MASK | RT5682_JD1_IRQ_MASK,
+ RT5682_JD1_EN | RT5682_JD1_IRQ_PUL);
+
+reinit:
+ mod_delayed_work(system_power_efficient_wq,
+ &rt5682->jack_detect_work, msecs_to_jiffies(250));
+
+ /* Mark Slave initialization complete */
+ rt5682->hw_init = true;
+ rt5682->first_hw_init = true;
+
+ pm_runtime_mark_last_busy(&slave->dev);
+ pm_runtime_put_autosuspend(&slave->dev);
+
+ dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
+
+ return ret;
+}
static bool rt5682_sdw_readable_register(struct device *dev, unsigned int reg)
{
@@ -46,7 +501,7 @@ static bool rt5682_sdw_readable_register(struct device *dev, unsigned int reg)
}
}
-const struct regmap_config rt5682_sdw_regmap = {
+static const struct regmap_config rt5682_sdw_regmap = {
.name = "sdw",
.reg_bits = 32,
.val_bits = 8,
diff --git a/sound/soc/codecs/rt5682-sdw.h b/sound/soc/codecs/rt5682-sdw.h
deleted file mode 100644
index 76e6f607066e..000000000000
--- a/sound/soc/codecs/rt5682-sdw.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only
- *
- * rt5682-sdw.h -- RT5682 SDW ALSA SoC audio driver
- *
- * Copyright 2019 Realtek Semiconductor Corp.
- * Author: Oder Chiou <oder_chiou(a)realtek.com>
- */
-
-#ifndef __RT5682_SDW_H__
-#define __RT5682_SDW_H__
-
-#define RT5682_SDW_ADDR_L 0x3000
-#define RT5682_SDW_ADDR_H 0x3001
-#define RT5682_SDW_DATA_L 0x3004
-#define RT5682_SDW_DATA_H 0x3005
-#define RT5682_SDW_CMD 0x3008
-
-#define RT5682_PROBE_TIMEOUT 2000
-
-#endif /* __RT5682_SDW_H__ */
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index 046e6110de73..372833936208 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -12,7 +12,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
-#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/acpi.h>
@@ -31,22 +30,6 @@
#include "rl6231.h"
#include "rt5682.h"
-#include "rt5682-sdw.h"
-
-static const char *rt5682_supply_names[RT5682_NUM_SUPPLIES] = {
- "AVDD",
- "MICVDD",
- "VBAT",
-};
-
-static const struct rt5682_platform_data i2s_default_platform_data = {
- .dmic1_data_pin = RT5682_DMIC1_DATA_GPIO2,
- .dmic1_clk_pin = RT5682_DMIC1_CLK_GPIO3,
- .jd_src = RT5682_JD1,
- .btndet_delay = 16,
- .dai_clk_names[RT5682_DAI_WCLK_IDX] = "rt5682-dai-wclk",
- .dai_clk_names[RT5682_DAI_BCLK_IDX] = "rt5682-dai-bclk",
-};
static const struct reg_sequence patch_list[] = {
{RT5682_HP_IMP_SENS_CTRL_19, 0x1000},
@@ -55,7 +38,18 @@ static const struct reg_sequence patch_list[] = {
{RT5682_PLL2_INTERNAL, 0x8266},
};
-static const struct reg_default rt5682_reg[] = {
+void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev)
+{
+ int ret;
+
+ ret = regmap_multi_reg_write(rt5682->regmap, patch_list,
+ ARRAY_SIZE(patch_list));
+ if (ret)
+ dev_warn(dev, "Failed to apply regmap patch: %d\n", ret);
+}
+EXPORT_SYMBOL_GPL(rt5682_apply_patch_list);
+
+const struct reg_default rt5682_reg[RT5682_REG_NUM] = {
{0x0002, 0x8080},
{0x0003, 0x8000},
{0x0005, 0x0000},
@@ -375,8 +369,9 @@ static const struct reg_default rt5682_reg[] = {
{0x03f2, 0x0800},
{0x03f3, 0x0800},
};
+EXPORT_SYMBOL_GPL(rt5682_reg);
-static bool rt5682_volatile_register(struct device *dev, unsigned int reg)
+bool rt5682_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5682_RESET:
@@ -403,8 +398,9 @@ static bool rt5682_volatile_register(struct device *dev, unsigned int reg)
return false;
}
}
+EXPORT_SYMBOL_GPL(rt5682_volatile_register);
-static bool rt5682_readable_register(struct device *dev, unsigned int reg)
+bool rt5682_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5682_RESET:
@@ -733,6 +729,7 @@ static bool rt5682_readable_register(struct device *dev, unsigned int reg)
return false;
}
}
+EXPORT_SYMBOL_GPL(rt5682_readable_register);
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0);
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0);
@@ -800,12 +797,13 @@ static SOC_ENUM_SINGLE_DECL(rt5682_dacr_enum,
static const struct snd_kcontrol_new rt5682_dac_r_mux =
SOC_DAPM_ENUM("DAC R Mux", rt5682_dacr_enum);
-static void rt5682_reset(struct rt5682_priv *rt5682)
+void rt5682_reset(struct rt5682_priv *rt5682)
{
regmap_write(rt5682->regmap, RT5682_RESET, 0);
if (!rt5682->is_sdw)
regmap_write(rt5682->regmap, RT5682_I2C_MODE, 1);
}
+EXPORT_SYMBOL_GPL(rt5682_reset);
/**
* rt5682_sel_asrc_clk_src - select ASRC clock source for a set of filters
@@ -910,8 +908,7 @@ static void rt5682_enable_push_button_irq(struct snd_soc_component *component,
*
* Returns detect status.
*/
-static int rt5682_headset_detect(struct snd_soc_component *component,
- int jack_insert)
+int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
{
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm = &component->dapm;
@@ -972,35 +969,7 @@ static int rt5682_headset_detect(struct snd_soc_component *component,
dev_dbg(component->dev, "jack_type = %d\n", rt5682->jack_type);
return rt5682->jack_type;
}
-
-static irqreturn_t rt5682_irq(int irq, void *data)
-{
- struct rt5682_priv *rt5682 = data;
-
- mod_delayed_work(system_power_efficient_wq,
- &rt5682->jack_detect_work, msecs_to_jiffies(250));
-
- return IRQ_HANDLED;
-}
-
-static void rt5682_jd_check_handler(struct work_struct *work)
-{
- struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv,
- jd_check_work.work);
-
- if (snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL)
- & RT5682_JDH_RS_MASK) {
- /* jack out */
- rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0);
-
- snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type,
- SND_JACK_HEADSET |
- SND_JACK_BTN_0 | SND_JACK_BTN_1 |
- SND_JACK_BTN_2 | SND_JACK_BTN_3);
- } else {
- schedule_delayed_work(&rt5682->jd_check_work, 500);
- }
-}
+EXPORT_SYMBOL_GPL(rt5682_headset_detect);
static int rt5682_set_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *hs_jack, void *data)
@@ -1077,7 +1046,7 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
return 0;
}
-static void rt5682_jack_detect_handler(struct work_struct *work)
+void rt5682_jack_detect_handler(struct work_struct *work)
{
struct rt5682_priv *rt5682 =
container_of(work, struct rt5682_priv, jack_detect_work.work);
@@ -1160,6 +1129,7 @@ static void rt5682_jack_detect_handler(struct work_struct *work)
mutex_unlock(&rt5682->calibrate_mutex);
}
+EXPORT_SYMBOL_GPL(rt5682_jack_detect_handler);
static const struct snd_kcontrol_new rt5682_snd_controls[] = {
/* DAC Digital Volume */
@@ -2899,7 +2869,8 @@ static int rt5682_resume(struct snd_soc_component *component)
regcache_cache_only(rt5682->regmap, false);
regcache_sync(rt5682->regmap);
- rt5682_irq(0, rt5682);
+ mod_delayed_work(system_power_efficient_wq,
+ &rt5682->jack_detect_work, msecs_to_jiffies(250));
return 0;
}
@@ -2908,270 +2879,22 @@ static int rt5682_resume(struct snd_soc_component *component)
#define rt5682_resume NULL
#endif
-#define RT5682_STEREO_RATES SNDRV_PCM_RATE_8000_192000
-#define RT5682_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
- SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
-
-static const struct snd_soc_dai_ops rt5682_aif1_dai_ops = {
+const struct snd_soc_dai_ops rt5682_aif1_dai_ops = {
.hw_params = rt5682_hw_params,
.set_fmt = rt5682_set_dai_fmt,
.set_tdm_slot = rt5682_set_tdm_slot,
.set_bclk_ratio = rt5682_set_bclk1_ratio,
};
+EXPORT_SYMBOL_GPL(rt5682_aif1_dai_ops);
-static const struct snd_soc_dai_ops rt5682_aif2_dai_ops = {
+const struct snd_soc_dai_ops rt5682_aif2_dai_ops = {
.hw_params = rt5682_hw_params,
.set_fmt = rt5682_set_dai_fmt,
.set_bclk_ratio = rt5682_set_bclk2_ratio,
};
+EXPORT_SYMBOL_GPL(rt5682_aif2_dai_ops);
-#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW)
-struct sdw_stream_data {
- struct sdw_stream_runtime *sdw_stream;
-};
-
-static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
- int direction)
-{
- struct sdw_stream_data *stream;
-
- if (!sdw_stream)
- return 0;
-
- stream = kzalloc(sizeof(*stream), GFP_KERNEL);
- if (!stream)
- return -ENOMEM;
-
- stream->sdw_stream = (struct sdw_stream_runtime *)sdw_stream;
-
- /* Use tx_mask or rx_mask to configure stream tag and set dma_data */
- if (direction == SNDRV_PCM_STREAM_PLAYBACK)
- dai->playback_dma_data = stream;
- else
- dai->capture_dma_data = stream;
-
- return 0;
-}
-
-static void rt5682_sdw_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct sdw_stream_data *stream;
-
- stream = snd_soc_dai_get_dma_data(dai, substream);
- snd_soc_dai_set_dma_data(dai, substream, NULL);
- kfree(stream);
-}
-
-static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_component *component = dai->component;
- struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
- struct sdw_stream_config stream_config;
- struct sdw_port_config port_config;
- enum sdw_data_direction direction;
- struct sdw_stream_data *stream;
- int retval, port, num_channels;
- unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0;
-
- dev_dbg(dai->dev, "%s %s", __func__, dai->name);
-
- stream = snd_soc_dai_get_dma_data(dai, substream);
- if (!stream)
- return -ENOMEM;
-
- if (!rt5682->slave)
- return -EINVAL;
-
- /* SoundWire specific configuration */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- direction = SDW_DATA_DIR_RX;
- port = 1;
- } else {
- direction = SDW_DATA_DIR_TX;
- port = 2;
- }
-
- stream_config.frame_rate = params_rate(params);
- stream_config.ch_count = params_channels(params);
- stream_config.bps = snd_pcm_format_width(params_format(params));
- stream_config.direction = direction;
-
- num_channels = params_channels(params);
- port_config.ch_mask = (1 << (num_channels)) - 1;
- port_config.num = port;
-
- retval = sdw_stream_add_slave(rt5682->slave, &stream_config,
- &port_config, 1, stream->sdw_stream);
- if (retval) {
- dev_err(dai->dev, "Unable to configure port\n");
- return retval;
- }
-
- switch (params_rate(params)) {
- case 48000:
- val_p = RT5682_SDW_REF_1_48K;
- val_c = RT5682_SDW_REF_2_48K;
- break;
- case 96000:
- val_p = RT5682_SDW_REF_1_96K;
- val_c = RT5682_SDW_REF_2_96K;
- break;
- case 192000:
- val_p = RT5682_SDW_REF_1_192K;
- val_c = RT5682_SDW_REF_2_192K;
- break;
- case 32000:
- val_p = RT5682_SDW_REF_1_32K;
- val_c = RT5682_SDW_REF_2_32K;
- break;
- case 24000:
- val_p = RT5682_SDW_REF_1_24K;
- val_c = RT5682_SDW_REF_2_24K;
- break;
- case 16000:
- val_p = RT5682_SDW_REF_1_16K;
- val_c = RT5682_SDW_REF_2_16K;
- break;
- case 12000:
- val_p = RT5682_SDW_REF_1_12K;
- val_c = RT5682_SDW_REF_2_12K;
- break;
- case 8000:
- val_p = RT5682_SDW_REF_1_8K;
- val_c = RT5682_SDW_REF_2_8K;
- break;
- case 44100:
- val_p = RT5682_SDW_REF_1_44K;
- val_c = RT5682_SDW_REF_2_44K;
- break;
- case 88200:
- val_p = RT5682_SDW_REF_1_88K;
- val_c = RT5682_SDW_REF_2_88K;
- break;
- case 176400:
- val_p = RT5682_SDW_REF_1_176K;
- val_c = RT5682_SDW_REF_2_176K;
- break;
- case 22050:
- val_p = RT5682_SDW_REF_1_22K;
- val_c = RT5682_SDW_REF_2_22K;
- break;
- case 11025:
- val_p = RT5682_SDW_REF_1_11K;
- val_c = RT5682_SDW_REF_2_11K;
- break;
- default:
- return -EINVAL;
- }
-
- if (params_rate(params) <= 48000) {
- osr_p = RT5682_DAC_OSR_D_8;
- osr_c = RT5682_ADC_OSR_D_8;
- } else if (params_rate(params) <= 96000) {
- osr_p = RT5682_DAC_OSR_D_4;
- osr_c = RT5682_ADC_OSR_D_4;
- } else {
- osr_p = RT5682_DAC_OSR_D_2;
- osr_c = RT5682_ADC_OSR_D_2;
- }
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
- RT5682_SDW_REF_1_MASK, val_p);
- regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
- RT5682_DAC_OSR_MASK, osr_p);
- } else {
- regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
- RT5682_SDW_REF_2_MASK, val_c);
- regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
- RT5682_ADC_OSR_MASK, osr_c);
- }
-
- return retval;
-}
-
-static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_component *component = dai->component;
- struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
- struct sdw_stream_data *stream =
- snd_soc_dai_get_dma_data(dai, substream);
-
- if (!rt5682->slave)
- return -EINVAL;
-
- sdw_stream_remove_slave(rt5682->slave, stream->sdw_stream);
- return 0;
-}
-
-static struct snd_soc_dai_ops rt5682_sdw_ops = {
- .hw_params = rt5682_sdw_hw_params,
- .hw_free = rt5682_sdw_hw_free,
- .set_sdw_stream = rt5682_set_sdw_stream,
- .shutdown = rt5682_sdw_shutdown,
-};
-#endif
-
-static struct snd_soc_dai_driver rt5682_dai[] = {
- {
- .name = "rt5682-aif1",
- .id = RT5682_AIF1,
- .playback = {
- .stream_name = "AIF1 Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = RT5682_STEREO_RATES,
- .formats = RT5682_FORMATS,
- },
- .capture = {
- .stream_name = "AIF1 Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = RT5682_STEREO_RATES,
- .formats = RT5682_FORMATS,
- },
- .ops = &rt5682_aif1_dai_ops,
- },
- {
- .name = "rt5682-aif2",
- .id = RT5682_AIF2,
- .capture = {
- .stream_name = "AIF2 Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = RT5682_STEREO_RATES,
- .formats = RT5682_FORMATS,
- },
- .ops = &rt5682_aif2_dai_ops,
- },
-#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW)
- {
- .name = "rt5682-sdw",
- .id = RT5682_SDW,
- .playback = {
- .stream_name = "SDW Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = RT5682_STEREO_RATES,
- .formats = RT5682_FORMATS,
- },
- .capture = {
- .stream_name = "SDW Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = RT5682_STEREO_RATES,
- .formats = RT5682_FORMATS,
- },
- .ops = &rt5682_sdw_ops,
- },
-#endif
-};
-
-static const struct snd_soc_component_driver soc_component_dev_rt5682 = {
+const struct snd_soc_component_driver rt5682_soc_component_dev = {
.probe = rt5682_probe,
.remove = rt5682_remove,
.suspend = rt5682_suspend,
@@ -3190,56 +2913,9 @@ static const struct snd_soc_component_driver soc_component_dev_rt5682 = {
.endianness = 1,
.non_legacy_dai_naming = 1,
};
+EXPORT_SYMBOL_GPL(rt5682_soc_component_dev);
-static const struct regmap_config rt5682_regmap = {
- .reg_bits = 16,
- .val_bits = 16,
- .max_register = RT5682_I2C_MODE,
- .volatile_reg = rt5682_volatile_register,
- .readable_reg = rt5682_readable_register,
- .cache_type = REGCACHE_RBTREE,
- .reg_defaults = rt5682_reg,
- .num_reg_defaults = ARRAY_SIZE(rt5682_reg),
- .use_single_read = true,
- .use_single_write = true,
-};
-
-static const struct i2c_device_id rt5682_i2c_id[] = {
- {"rt5682", 0},
- {}
-};
-MODULE_DEVICE_TABLE(i2c, rt5682_i2c_id);
-
-static int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev)
-{
-
- device_property_read_u32(dev, "realtek,dmic1-data-pin",
- &rt5682->pdata.dmic1_data_pin);
- device_property_read_u32(dev, "realtek,dmic1-clk-pin",
- &rt5682->pdata.dmic1_clk_pin);
- device_property_read_u32(dev, "realtek,jd-src",
- &rt5682->pdata.jd_src);
- device_property_read_u32(dev, "realtek,btndet-delay",
- &rt5682->pdata.btndet_delay);
- device_property_read_u32(dev, "realtek,dmic-clk-rate-hz",
- &rt5682->pdata.dmic_clk_rate);
- device_property_read_u32(dev, "realtek,dmic-delay-ms",
- &rt5682->pdata.dmic_delay);
-
- rt5682->pdata.ldo1_en = of_get_named_gpio(dev->of_node,
- "realtek,ldo1-en-gpios", 0);
-
- if (device_property_read_string_array(dev, "clock-output-names",
- rt5682->pdata.dai_clk_names,
- RT5682_DAI_NUM_CLKS) < 0)
- dev_warn(dev, "Using default DAI clk names: %s, %s\n",
- rt5682->pdata.dai_clk_names[RT5682_DAI_WCLK_IDX],
- rt5682->pdata.dai_clk_names[RT5682_DAI_BCLK_IDX]);
-
- return 0;
-}
-
-static void rt5682_calibrate(struct rt5682_priv *rt5682)
+void rt5682_calibrate(struct rt5682_priv *rt5682)
{
int value, count;
@@ -3289,407 +2965,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682)
mutex_unlock(&rt5682->calibrate_mutex);
}
-
-#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW)
-static int rt5682_sdw_read(void *context, unsigned int reg, unsigned int *val)
-{
- struct device *dev = context;
- struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
- unsigned int data_l, data_h;
-
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 0);
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
- regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_H, &data_h);
- regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_L, &data_l);
-
- *val = (data_h << 8) | data_l;
-
- dev_vdbg(dev, "[%s] %04x => %04x\n", __func__, reg, *val);
-
- return 0;
-}
-
-static int rt5682_sdw_write(void *context, unsigned int reg, unsigned int val)
-{
- struct device *dev = context;
- struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
-
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 1);
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_H, (val >> 8) & 0xff);
- regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_L, (val & 0xff));
-
- dev_vdbg(dev, "[%s] %04x <= %04x\n", __func__, reg, val);
-
- return 0;
-}
-
-static const struct regmap_config rt5682_sdw_regmap = {
- .reg_bits = 16,
- .val_bits = 16,
- .max_register = RT5682_I2C_MODE,
- .volatile_reg = rt5682_volatile_register,
- .readable_reg = rt5682_readable_register,
- .cache_type = REGCACHE_RBTREE,
- .reg_defaults = rt5682_reg,
- .num_reg_defaults = ARRAY_SIZE(rt5682_reg),
- .use_single_read = true,
- .use_single_write = true,
- .reg_read = rt5682_sdw_read,
- .reg_write = rt5682_sdw_write,
-};
-
-int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
- struct sdw_slave *slave)
-{
- struct rt5682_priv *rt5682;
- int ret;
-
- rt5682 = devm_kzalloc(dev, sizeof(*rt5682), GFP_KERNEL);
- if (!rt5682)
- return -ENOMEM;
-
- dev_set_drvdata(dev, rt5682);
- rt5682->slave = slave;
- rt5682->sdw_regmap = regmap;
- rt5682->is_sdw = true;
-
- rt5682->regmap = devm_regmap_init(dev, NULL, dev, &rt5682_sdw_regmap);
- if (IS_ERR(rt5682->regmap)) {
- ret = PTR_ERR(rt5682->regmap);
- dev_err(dev, "Failed to allocate register map: %d\n",
- ret);
- return ret;
- }
-
- /*
- * Mark hw_init to false
- * HW init will be performed when device reports present
- */
- rt5682->hw_init = false;
- rt5682->first_hw_init = false;
-
- mutex_init(&rt5682->calibrate_mutex);
- INIT_DELAYED_WORK(&rt5682->jack_detect_work,
- rt5682_jack_detect_handler);
-
- ret = devm_snd_soc_register_component(dev, &soc_component_dev_rt5682,
- rt5682_dai, ARRAY_SIZE(rt5682_dai));
-
- dev_dbg(&slave->dev, "%s\n", __func__);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(rt5682_sdw_init);
-
-int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
-{
- struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
- int ret = 0;
- unsigned int val;
-
- if (rt5682->hw_init)
- return 0;
-
- regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
- if (val != DEVICE_ID) {
- dev_err(dev, "Device with ID register %x is not rt5682\n", val);
- return -ENODEV;
- }
-
- /*
- * PM runtime is only enabled when a Slave reports as Attached
- */
- if (!rt5682->first_hw_init) {
- /* set autosuspend parameters */
- pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
- pm_runtime_use_autosuspend(&slave->dev);
-
- /* update count of parent 'active' children */
- pm_runtime_set_active(&slave->dev);
-
- /* make sure the device does not suspend immediately */
- pm_runtime_mark_last_busy(&slave->dev);
-
- pm_runtime_enable(&slave->dev);
- }
-
- pm_runtime_get_noresume(&slave->dev);
-
- if (rt5682->first_hw_init) {
- regcache_cache_only(rt5682->regmap, false);
- regcache_cache_bypass(rt5682->regmap, true);
- }
-
- rt5682_calibrate(rt5682);
-
- if (rt5682->first_hw_init) {
- regcache_cache_bypass(rt5682->regmap, false);
- regcache_mark_dirty(rt5682->regmap);
- regcache_sync(rt5682->regmap);
-
- /* volatile registers */
- regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
- RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
-
- goto reinit;
- }
-
- ret = regmap_multi_reg_write(rt5682->regmap, patch_list,
- ARRAY_SIZE(patch_list));
- if (ret)
- dev_warn(dev, "Failed to apply regmap patch: %d\n", ret);
-
- regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000);
-
- regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
- RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK,
- RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X);
- regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380);
- regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000);
- regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8,
- RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA);
- regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1,
- RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ);
- regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1,
- RT5682_PM_HP_MASK, RT5682_PM_HP_HV);
-
- /* Soundwire */
- regmap_write(rt5682->regmap, RT5682_PLL2_INTERNAL, 0xa266);
- regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_1, 0x1700);
- regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_2, 0x0006);
- regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_3, 0x2600);
- regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_4, 0x0c8f);
- regmap_write(rt5682->regmap, RT5682_PLL_TRACK_2, 0x3000);
- regmap_write(rt5682->regmap, RT5682_PLL_TRACK_3, 0x4000);
- regmap_update_bits(rt5682->regmap, RT5682_GLB_CLK,
- RT5682_SCLK_SRC_MASK | RT5682_PLL2_SRC_MASK,
- RT5682_SCLK_SRC_PLL2 | RT5682_PLL2_SRC_SDW);
-
- regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
- RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
- regmap_write(rt5682->regmap, RT5682_CBJ_CTRL_1, 0xd042);
- regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_3,
- RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN);
- regmap_update_bits(rt5682->regmap, RT5682_SAR_IL_CMD_1,
- RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN);
- regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
- RT5682_POW_IRQ | RT5682_POW_JDH |
- RT5682_POW_ANA, RT5682_POW_IRQ |
- RT5682_POW_JDH | RT5682_POW_ANA);
- regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2,
- RT5682_PWR_JDH, RT5682_PWR_JDH);
- regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
- RT5682_JD1_EN_MASK | RT5682_JD1_IRQ_MASK,
- RT5682_JD1_EN | RT5682_JD1_IRQ_PUL);
-
-reinit:
- mod_delayed_work(system_power_efficient_wq,
- &rt5682->jack_detect_work, msecs_to_jiffies(250));
-
- /* Mark Slave initialization complete */
- rt5682->hw_init = true;
- rt5682->first_hw_init = true;
-
- pm_runtime_mark_last_busy(&slave->dev);
- pm_runtime_put_autosuspend(&slave->dev);
-
- dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(rt5682_io_init);
-#endif
-
-static int rt5682_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
-{
- struct rt5682_platform_data *pdata = dev_get_platdata(&i2c->dev);
- struct rt5682_priv *rt5682;
- int i, ret;
- unsigned int val;
-
- rt5682 = devm_kzalloc(&i2c->dev, sizeof(struct rt5682_priv),
- GFP_KERNEL);
- if (!rt5682)
- return -ENOMEM;
-
- i2c_set_clientdata(i2c, rt5682);
-
- rt5682->pdata = i2s_default_platform_data;
-
- if (pdata)
- rt5682->pdata = *pdata;
- else
- rt5682_parse_dt(rt5682, &i2c->dev);
-
- rt5682->regmap = devm_regmap_init_i2c(i2c, &rt5682_regmap);
- if (IS_ERR(rt5682->regmap)) {
- ret = PTR_ERR(rt5682->regmap);
- dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
- ret);
- return ret;
- }
-
- for (i = 0; i < ARRAY_SIZE(rt5682->supplies); i++)
- rt5682->supplies[i].supply = rt5682_supply_names[i];
-
- ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5682->supplies),
- rt5682->supplies);
- if (ret) {
- dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
- return ret;
- }
-
- ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies),
- rt5682->supplies);
- if (ret) {
- dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
- return ret;
- }
-
- if (gpio_is_valid(rt5682->pdata.ldo1_en)) {
- if (devm_gpio_request_one(&i2c->dev, rt5682->pdata.ldo1_en,
- GPIOF_OUT_INIT_HIGH, "rt5682"))
- dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n");
- }
-
- /* Sleep for 300 ms miniumum */
- usleep_range(300000, 350000);
-
- regmap_write(rt5682->regmap, RT5682_I2C_MODE, 0x1);
- usleep_range(10000, 15000);
-
- regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
- if (val != DEVICE_ID) {
- dev_err(&i2c->dev,
- "Device with ID register %x is not rt5682\n", val);
- return -ENODEV;
- }
-
- mutex_init(&rt5682->calibrate_mutex);
- rt5682_calibrate(rt5682);
-
- ret = regmap_multi_reg_write(rt5682->regmap, patch_list,
- ARRAY_SIZE(patch_list));
- if (ret)
- dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
-
- regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000);
-
- /* DMIC pin*/
- if (rt5682->pdata.dmic1_data_pin != RT5682_DMIC1_NULL) {
- switch (rt5682->pdata.dmic1_data_pin) {
- case RT5682_DMIC1_DATA_GPIO2: /* share with LRCK2 */
- regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
- RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO2);
- regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
- RT5682_GP2_PIN_MASK, RT5682_GP2_PIN_DMIC_SDA);
- break;
-
- case RT5682_DMIC1_DATA_GPIO5: /* share with DACDAT1 */
- regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
- RT5682_DMIC_1_DP_MASK, RT5682_DMIC_1_DP_GPIO5);
- regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
- RT5682_GP5_PIN_MASK, RT5682_GP5_PIN_DMIC_SDA);
- break;
-
- default:
- dev_warn(&i2c->dev, "invalid DMIC_DAT pin\n");
- break;
- }
-
- switch (rt5682->pdata.dmic1_clk_pin) {
- case RT5682_DMIC1_CLK_GPIO1: /* share with IRQ */
- regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
- RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_DMIC_CLK);
- break;
-
- case RT5682_DMIC1_CLK_GPIO3: /* share with BCLK2 */
- regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
- RT5682_GP3_PIN_MASK, RT5682_GP3_PIN_DMIC_CLK);
- break;
-
- default:
- dev_warn(&i2c->dev, "invalid DMIC_CLK pin\n");
- break;
- }
- }
-
- regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
- RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK,
- RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X);
- regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380);
- regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1,
- RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK,
- RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1);
- regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000);
- regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8,
- RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA);
- regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1,
- RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ);
- regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1,
- RT5682_PM_HP_MASK, RT5682_PM_HP_HV);
- regmap_update_bits(rt5682->regmap, RT5682_DMIC_CTRL_1,
- RT5682_FIFO_CLK_DIV_MASK, RT5682_FIFO_CLK_DIV_2);
-
- INIT_DELAYED_WORK(&rt5682->jack_detect_work,
- rt5682_jack_detect_handler);
- INIT_DELAYED_WORK(&rt5682->jd_check_work,
- rt5682_jd_check_handler);
-
- if (i2c->irq) {
- ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
- rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
- | IRQF_ONESHOT, "rt5682", rt5682);
- if (ret)
- dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
- }
-
- return devm_snd_soc_register_component(&i2c->dev,
- &soc_component_dev_rt5682,
- rt5682_dai, ARRAY_SIZE(rt5682_dai));
-}
-
-static void rt5682_i2c_shutdown(struct i2c_client *client)
-{
- struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
-
- rt5682_reset(rt5682);
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id rt5682_of_match[] = {
- {.compatible = "realtek,rt5682i"},
- {},
-};
-MODULE_DEVICE_TABLE(of, rt5682_of_match);
-#endif
-
-#ifdef CONFIG_ACPI
-static const struct acpi_device_id rt5682_acpi_match[] = {
- {"10EC5682", 0,},
- {},
-};
-MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match);
-#endif
-
-static struct i2c_driver __maybe_unused rt5682_i2c_driver = {
- .driver = {
- .name = "rt5682",
- .of_match_table = of_match_ptr(rt5682_of_match),
- .acpi_match_table = ACPI_PTR(rt5682_acpi_match),
- },
- .probe = rt5682_i2c_probe,
- .shutdown = rt5682_i2c_shutdown,
- .id_table = rt5682_i2c_id,
-};
-
-#ifdef CONFIG_I2C
-module_i2c_driver(rt5682_i2c_driver);
-#endif
+EXPORT_SYMBOL_GPL(rt5682_calibrate);
MODULE_DESCRIPTION("ASoC RT5682 driver");
MODULE_AUTHOR("Bard Liao <bardliao(a)realtek.com>");
diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h
index 0baeece84ec4..65a211ab58f4 100644
--- a/sound/soc/codecs/rt5682.h
+++ b/sound/soc/codecs/rt5682.h
@@ -1337,6 +1337,13 @@
#define RT5682_SAR_SOUR_BTN (0x3f)
#define RT5682_SAR_SOUR_TYPE (0x0)
+/* soundwire timeout */
+#define RT5682_PROBE_TIMEOUT 2000
+
+
+#define RT5682_STEREO_RATES SNDRV_PCM_RATE_8000_192000
+#define RT5682_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
/* System Clock Source */
enum {
@@ -1420,8 +1427,24 @@ struct rt5682_priv {
int rt5682_sel_asrc_clk_src(struct snd_soc_component *component,
unsigned int filter_mask, unsigned int clk_src);
-int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
- struct sdw_slave *slave);
-int rt5682_io_init(struct device *dev, struct sdw_slave *slave);
+
+void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev);
+
+int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert);
+void rt5682_jack_detect_handler(struct work_struct *work);
+
+bool rt5682_volatile_register(struct device *dev, unsigned int reg);
+bool rt5682_readable_register(struct device *dev, unsigned int reg);
+
+int rt5682_register_component(struct device *dev);
+void rt5682_calibrate(struct rt5682_priv *rt5682);
+void rt5682_reset(struct rt5682_priv *rt5682);
+
+#define RT5682_REG_NUM 318
+extern const struct reg_default rt5682_reg[RT5682_REG_NUM];
+
+extern const struct snd_soc_dai_ops rt5682_aif1_dai_ops;
+extern const struct snd_soc_dai_ops rt5682_aif2_dai_ops;
+extern const struct snd_soc_component_driver rt5682_soc_component_dev;
#endif /* __RT5682_H__ */
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index 91ce347b3a45..46073c04364a 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -430,7 +430,7 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
depends on I2C && ACPI && GPIOLIB
depends on MFD_INTEL_LPSS || COMPILE_TEST
depends on SND_HDA_CODEC_HDMI
- select SND_SOC_RT5682
+ select SND_SOC_RT5682_I2C
select SND_SOC_MAX98357A
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
@@ -468,7 +468,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH
depends on SND_HDA_CODEC_HDMI
select SND_SOC_MAX98373
select SND_SOC_RT1015
- select SND_SOC_RT5682
+ select SND_SOC_RT5682_I2C
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
help
@@ -511,7 +511,7 @@ config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH
depends on MFD_INTEL_LPSS || COMPILE_TEST
depends on SND_HDA_CODEC_HDMI
select SND_SOC_RT1011
- select SND_SOC_RT5682
+ select SND_SOC_RT5682_I2C
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
help
--
2.26.2
3
4
27 May '20
This series provides the following updtes to the Intel machine driver
Kconfig:
1. The first patch adds the explicit dependency on GPIOLIB when
SND_SOC_DMIC is selected.
2. SND_SOC_SOF_HDA_AUDIO_CODEC is required for using the legacy
HDA codec driver for HDMI support in SOF. The last 3 three patches
make the required changes to account for this.
Libin Yang (3):
ASoC: intel: add depends on SND_SOC_SOF_HDA_AUDIO_CODEC for common
hdmi
ASoC: sof-sdw: remove CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC condition
ASoC: sof_pcm512x: remove CONFIG_SND_HDA_CODEC_HDMI condition
Pierre-Louis Bossart (1):
ASoC: Intel: boards: add explicit dependency on GPIOLIB when DMIC is
used
sound/soc/intel/boards/Kconfig | 51 ++++++++++++++-------------
sound/soc/intel/boards/sof_pcm512x.c | 9 -----
sound/soc/intel/boards/sof_sdw.c | 8 -----
sound/soc/intel/boards/sof_sdw_hdmi.c | 7 ----
4 files changed, 26 insertions(+), 49 deletions(-)
--
2.17.1
3
9