Unverified Commit a50067d4 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Mark Brown
Browse files

ASoC: rt5682: split i2c driver into separate module



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: 6b8e4e7d ("ASoC: amd: Add machine driver for Raven based platform")
Fixes: fd443a20 ("ASoC: rt5682: fix I2C/Soundwire dependencies")
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20200528091851.2889754-1-arnd@arndb.de


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 2b1878af
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+6 −5
Original line number Diff line number Diff line
@@ -168,7 +168,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
@@ -1143,14 +1143,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

+2 −0
Original line number Diff line number Diff line
@@ -179,6 +179,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
@@ -481,6 +482,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
+306 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
//
// rt5682.c  --  RT5682 ALSA SoC audio component driver
//
// Copyright 2018 Realtek Semiconductor Corp.
// Author: Bard Liao <bardliao@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@realtek.com>");
MODULE_LICENSE("GPL v2");
+457 −2
Original line number Diff line number Diff line
@@ -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,
Loading