xref: /openbmc/linux/sound/soc/codecs/rt5682-sdw.c (revision 3f3d66ba998fb079c1239430e96e3b138bc63166)
103f6fc6dSOder Chiou // SPDX-License-Identifier: GPL-2.0-only
203f6fc6dSOder Chiou //
303f6fc6dSOder Chiou // rt5682-sdw.c  --  RT5682 ALSA SoC audio component driver
403f6fc6dSOder Chiou //
503f6fc6dSOder Chiou // Copyright 2019 Realtek Semiconductor Corp.
603f6fc6dSOder Chiou // Author: Oder Chiou <oder_chiou@realtek.com>
703f6fc6dSOder Chiou //
803f6fc6dSOder Chiou 
903f6fc6dSOder Chiou #include <linux/module.h>
1003f6fc6dSOder Chiou #include <linux/moduleparam.h>
1103f6fc6dSOder Chiou #include <linux/init.h>
1203f6fc6dSOder Chiou #include <linux/delay.h>
1303f6fc6dSOder Chiou #include <linux/pm.h>
1403f6fc6dSOder Chiou #include <linux/acpi.h>
1503f6fc6dSOder Chiou #include <linux/gpio.h>
1603f6fc6dSOder Chiou #include <linux/of_gpio.h>
17a50067d4SArnd Bergmann #include <linux/pm_runtime.h>
1803f6fc6dSOder Chiou #include <linux/regulator/consumer.h>
1903f6fc6dSOder Chiou #include <linux/mutex.h>
2003f6fc6dSOder Chiou #include <linux/soundwire/sdw.h>
2103f6fc6dSOder Chiou #include <linux/soundwire/sdw_type.h>
222acd30b9SPierre-Louis Bossart #include <linux/soundwire/sdw_registers.h>
2303f6fc6dSOder Chiou #include <sound/core.h>
2403f6fc6dSOder Chiou #include <sound/pcm.h>
2503f6fc6dSOder Chiou #include <sound/pcm_params.h>
2603f6fc6dSOder Chiou #include <sound/jack.h>
275b75bc7fSCharles Keepax #include <sound/sdw.h>
2803f6fc6dSOder Chiou #include <sound/soc.h>
2903f6fc6dSOder Chiou #include <sound/soc-dapm.h>
3003f6fc6dSOder Chiou #include <sound/initval.h>
3103f6fc6dSOder Chiou #include <sound/tlv.h>
3203f6fc6dSOder Chiou 
3303f6fc6dSOder Chiou #include "rt5682.h"
34a50067d4SArnd Bergmann 
35a50067d4SArnd Bergmann #define RT5682_SDW_ADDR_L			0x3000
36a50067d4SArnd Bergmann #define RT5682_SDW_ADDR_H			0x3001
37a50067d4SArnd Bergmann #define RT5682_SDW_DATA_L			0x3004
38a50067d4SArnd Bergmann #define RT5682_SDW_DATA_H			0x3005
39a50067d4SArnd Bergmann #define RT5682_SDW_CMD				0x3008
40a50067d4SArnd Bergmann 
41a50067d4SArnd Bergmann static int rt5682_sdw_read(void *context, unsigned int reg, unsigned int *val)
42a50067d4SArnd Bergmann {
43a50067d4SArnd Bergmann 	struct device *dev = context;
44a50067d4SArnd Bergmann 	struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
45a50067d4SArnd Bergmann 	unsigned int data_l, data_h;
46a50067d4SArnd Bergmann 
47a50067d4SArnd Bergmann 	regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 0);
48a50067d4SArnd Bergmann 	regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
49a50067d4SArnd Bergmann 	regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
50a50067d4SArnd Bergmann 	regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_H, &data_h);
51a50067d4SArnd Bergmann 	regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_L, &data_l);
52a50067d4SArnd Bergmann 
53a50067d4SArnd Bergmann 	*val = (data_h << 8) | data_l;
54a50067d4SArnd Bergmann 
55a50067d4SArnd Bergmann 	dev_vdbg(dev, "[%s] %04x => %04x\n", __func__, reg, *val);
56a50067d4SArnd Bergmann 
57a50067d4SArnd Bergmann 	return 0;
58a50067d4SArnd Bergmann }
59a50067d4SArnd Bergmann 
60a50067d4SArnd Bergmann static int rt5682_sdw_write(void *context, unsigned int reg, unsigned int val)
61a50067d4SArnd Bergmann {
62a50067d4SArnd Bergmann 	struct device *dev = context;
63a50067d4SArnd Bergmann 	struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
64a50067d4SArnd Bergmann 
65a50067d4SArnd Bergmann 	regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 1);
66a50067d4SArnd Bergmann 	regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff);
67a50067d4SArnd Bergmann 	regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff));
68a50067d4SArnd Bergmann 	regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_H, (val >> 8) & 0xff);
69a50067d4SArnd Bergmann 	regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_L, (val & 0xff));
70a50067d4SArnd Bergmann 
71a50067d4SArnd Bergmann 	dev_vdbg(dev, "[%s] %04x <= %04x\n", __func__, reg, val);
72a50067d4SArnd Bergmann 
73a50067d4SArnd Bergmann 	return 0;
74a50067d4SArnd Bergmann }
75a50067d4SArnd Bergmann 
76a50067d4SArnd Bergmann static const struct regmap_config rt5682_sdw_indirect_regmap = {
77a50067d4SArnd Bergmann 	.reg_bits = 16,
78a50067d4SArnd Bergmann 	.val_bits = 16,
79a50067d4SArnd Bergmann 	.max_register = RT5682_I2C_MODE,
80a50067d4SArnd Bergmann 	.volatile_reg = rt5682_volatile_register,
81a50067d4SArnd Bergmann 	.readable_reg = rt5682_readable_register,
82582ed316SMark Brown 	.cache_type = REGCACHE_MAPLE,
83a50067d4SArnd Bergmann 	.reg_defaults = rt5682_reg,
84a50067d4SArnd Bergmann 	.num_reg_defaults = RT5682_REG_NUM,
85a50067d4SArnd Bergmann 	.use_single_read = true,
86a50067d4SArnd Bergmann 	.use_single_write = true,
87a50067d4SArnd Bergmann 	.reg_read = rt5682_sdw_read,
88a50067d4SArnd Bergmann 	.reg_write = rt5682_sdw_write,
89a50067d4SArnd Bergmann };
90a50067d4SArnd Bergmann 
91a50067d4SArnd Bergmann static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
92a50067d4SArnd Bergmann 				 int direction)
93a50067d4SArnd Bergmann {
94b3a2e00eSPierre-Louis Bossart 	snd_soc_dai_dma_data_set(dai, direction, sdw_stream);
95a50067d4SArnd Bergmann 
96a50067d4SArnd Bergmann 	return 0;
97a50067d4SArnd Bergmann }
98a50067d4SArnd Bergmann 
99a50067d4SArnd Bergmann static void rt5682_sdw_shutdown(struct snd_pcm_substream *substream,
100a50067d4SArnd Bergmann 				struct snd_soc_dai *dai)
101a50067d4SArnd Bergmann {
102a50067d4SArnd Bergmann 	snd_soc_dai_set_dma_data(dai, substream, NULL);
103a50067d4SArnd Bergmann }
104a50067d4SArnd Bergmann 
105a50067d4SArnd Bergmann static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream,
106a50067d4SArnd Bergmann 				struct snd_pcm_hw_params *params,
107a50067d4SArnd Bergmann 				struct snd_soc_dai *dai)
108a50067d4SArnd Bergmann {
109a50067d4SArnd Bergmann 	struct snd_soc_component *component = dai->component;
110a50067d4SArnd Bergmann 	struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
1115b75bc7fSCharles Keepax 	struct sdw_stream_config stream_config = {0};
1125b75bc7fSCharles Keepax 	struct sdw_port_config port_config = {0};
113b3a2e00eSPierre-Louis Bossart 	struct sdw_stream_runtime *sdw_stream;
1145b75bc7fSCharles Keepax 	int retval;
115a50067d4SArnd Bergmann 	unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0;
116a50067d4SArnd Bergmann 
117a50067d4SArnd Bergmann 	dev_dbg(dai->dev, "%s %s", __func__, dai->name);
118a50067d4SArnd Bergmann 
119b3a2e00eSPierre-Louis Bossart 	sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
120b3a2e00eSPierre-Louis Bossart 	if (!sdw_stream)
121a50067d4SArnd Bergmann 		return -ENOMEM;
122a50067d4SArnd Bergmann 
123a50067d4SArnd Bergmann 	if (!rt5682->slave)
124a50067d4SArnd Bergmann 		return -EINVAL;
125a50067d4SArnd Bergmann 
126a50067d4SArnd Bergmann 	/* SoundWire specific configuration */
1275b75bc7fSCharles Keepax 	snd_sdw_params_to_config(substream, params, &stream_config, &port_config);
128a50067d4SArnd Bergmann 
1295b75bc7fSCharles Keepax 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1305b75bc7fSCharles Keepax 		port_config.num = 1;
1315b75bc7fSCharles Keepax 	else
1325b75bc7fSCharles Keepax 		port_config.num = 2;
133a50067d4SArnd Bergmann 
134a50067d4SArnd Bergmann 	retval = sdw_stream_add_slave(rt5682->slave, &stream_config,
135b3a2e00eSPierre-Louis Bossart 				      &port_config, 1, sdw_stream);
136a50067d4SArnd Bergmann 	if (retval) {
137a50067d4SArnd Bergmann 		dev_err(dai->dev, "Unable to configure port\n");
138a50067d4SArnd Bergmann 		return retval;
139a50067d4SArnd Bergmann 	}
140a50067d4SArnd Bergmann 
141a50067d4SArnd Bergmann 	switch (params_rate(params)) {
142a50067d4SArnd Bergmann 	case 48000:
143a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_48K;
144a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_48K;
145a50067d4SArnd Bergmann 		break;
146a50067d4SArnd Bergmann 	case 96000:
147a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_96K;
148a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_96K;
149a50067d4SArnd Bergmann 		break;
150a50067d4SArnd Bergmann 	case 192000:
151a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_192K;
152a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_192K;
153a50067d4SArnd Bergmann 		break;
154a50067d4SArnd Bergmann 	case 32000:
155a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_32K;
156a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_32K;
157a50067d4SArnd Bergmann 		break;
158a50067d4SArnd Bergmann 	case 24000:
159a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_24K;
160a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_24K;
161a50067d4SArnd Bergmann 		break;
162a50067d4SArnd Bergmann 	case 16000:
163a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_16K;
164a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_16K;
165a50067d4SArnd Bergmann 		break;
166a50067d4SArnd Bergmann 	case 12000:
167a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_12K;
168a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_12K;
169a50067d4SArnd Bergmann 		break;
170a50067d4SArnd Bergmann 	case 8000:
171a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_8K;
172a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_8K;
173a50067d4SArnd Bergmann 		break;
174a50067d4SArnd Bergmann 	case 44100:
175a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_44K;
176a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_44K;
177a50067d4SArnd Bergmann 		break;
178a50067d4SArnd Bergmann 	case 88200:
179a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_88K;
180a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_88K;
181a50067d4SArnd Bergmann 		break;
182a50067d4SArnd Bergmann 	case 176400:
183a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_176K;
184a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_176K;
185a50067d4SArnd Bergmann 		break;
186a50067d4SArnd Bergmann 	case 22050:
187a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_22K;
188a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_22K;
189a50067d4SArnd Bergmann 		break;
190a50067d4SArnd Bergmann 	case 11025:
191a50067d4SArnd Bergmann 		val_p = RT5682_SDW_REF_1_11K;
192a50067d4SArnd Bergmann 		val_c = RT5682_SDW_REF_2_11K;
193a50067d4SArnd Bergmann 		break;
194a50067d4SArnd Bergmann 	default:
195a50067d4SArnd Bergmann 		return -EINVAL;
196a50067d4SArnd Bergmann 	}
197a50067d4SArnd Bergmann 
198a50067d4SArnd Bergmann 	if (params_rate(params) <= 48000) {
199a50067d4SArnd Bergmann 		osr_p = RT5682_DAC_OSR_D_8;
200a50067d4SArnd Bergmann 		osr_c = RT5682_ADC_OSR_D_8;
201a50067d4SArnd Bergmann 	} else if (params_rate(params) <= 96000) {
202a50067d4SArnd Bergmann 		osr_p = RT5682_DAC_OSR_D_4;
203a50067d4SArnd Bergmann 		osr_c = RT5682_ADC_OSR_D_4;
204a50067d4SArnd Bergmann 	} else {
205a50067d4SArnd Bergmann 		osr_p = RT5682_DAC_OSR_D_2;
206a50067d4SArnd Bergmann 		osr_c = RT5682_ADC_OSR_D_2;
207a50067d4SArnd Bergmann 	}
208a50067d4SArnd Bergmann 
209a50067d4SArnd Bergmann 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
210a50067d4SArnd Bergmann 		regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
211a50067d4SArnd Bergmann 			RT5682_SDW_REF_1_MASK, val_p);
212a50067d4SArnd Bergmann 		regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
213a50067d4SArnd Bergmann 			RT5682_DAC_OSR_MASK, osr_p);
214a50067d4SArnd Bergmann 	} else {
215a50067d4SArnd Bergmann 		regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK,
216a50067d4SArnd Bergmann 			RT5682_SDW_REF_2_MASK, val_c);
217a50067d4SArnd Bergmann 		regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1,
218a50067d4SArnd Bergmann 			RT5682_ADC_OSR_MASK, osr_c);
219a50067d4SArnd Bergmann 	}
220a50067d4SArnd Bergmann 
221a50067d4SArnd Bergmann 	return retval;
222a50067d4SArnd Bergmann }
223a50067d4SArnd Bergmann 
224a50067d4SArnd Bergmann static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream,
225a50067d4SArnd Bergmann 			      struct snd_soc_dai *dai)
226a50067d4SArnd Bergmann {
227a50067d4SArnd Bergmann 	struct snd_soc_component *component = dai->component;
228a50067d4SArnd Bergmann 	struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
229b3a2e00eSPierre-Louis Bossart 	struct sdw_stream_runtime *sdw_stream =
230a50067d4SArnd Bergmann 		snd_soc_dai_get_dma_data(dai, substream);
231a50067d4SArnd Bergmann 
232a50067d4SArnd Bergmann 	if (!rt5682->slave)
233a50067d4SArnd Bergmann 		return -EINVAL;
234a50067d4SArnd Bergmann 
235b3a2e00eSPierre-Louis Bossart 	sdw_stream_remove_slave(rt5682->slave, sdw_stream);
236a50067d4SArnd Bergmann 	return 0;
237a50067d4SArnd Bergmann }
238a50067d4SArnd Bergmann 
239f9e56a34SRikard Falkeborn static const struct snd_soc_dai_ops rt5682_sdw_ops = {
240a50067d4SArnd Bergmann 	.hw_params	= rt5682_sdw_hw_params,
241a50067d4SArnd Bergmann 	.hw_free	= rt5682_sdw_hw_free,
242e8444560SPierre-Louis Bossart 	.set_stream	= rt5682_set_sdw_stream,
243a50067d4SArnd Bergmann 	.shutdown	= rt5682_sdw_shutdown,
244a50067d4SArnd Bergmann };
245a50067d4SArnd Bergmann 
246a50067d4SArnd Bergmann static struct snd_soc_dai_driver rt5682_dai[] = {
247a50067d4SArnd Bergmann 	{
248a50067d4SArnd Bergmann 		.name = "rt5682-aif1",
249a50067d4SArnd Bergmann 		.id = RT5682_AIF1,
250a50067d4SArnd Bergmann 		.playback = {
251a50067d4SArnd Bergmann 			.stream_name = "AIF1 Playback",
252a50067d4SArnd Bergmann 			.channels_min = 1,
253a50067d4SArnd Bergmann 			.channels_max = 2,
254a50067d4SArnd Bergmann 			.rates = RT5682_STEREO_RATES,
255a50067d4SArnd Bergmann 			.formats = RT5682_FORMATS,
256a50067d4SArnd Bergmann 		},
257a50067d4SArnd Bergmann 		.capture = {
258a50067d4SArnd Bergmann 			.stream_name = "AIF1 Capture",
259a50067d4SArnd Bergmann 			.channels_min = 1,
260a50067d4SArnd Bergmann 			.channels_max = 2,
261a50067d4SArnd Bergmann 			.rates = RT5682_STEREO_RATES,
262a50067d4SArnd Bergmann 			.formats = RT5682_FORMATS,
263a50067d4SArnd Bergmann 		},
264a50067d4SArnd Bergmann 		.ops = &rt5682_aif1_dai_ops,
265a50067d4SArnd Bergmann 	},
266a50067d4SArnd Bergmann 	{
267a50067d4SArnd Bergmann 		.name = "rt5682-aif2",
268a50067d4SArnd Bergmann 		.id = RT5682_AIF2,
269a50067d4SArnd Bergmann 		.capture = {
270a50067d4SArnd Bergmann 			.stream_name = "AIF2 Capture",
271a50067d4SArnd Bergmann 			.channels_min = 1,
272a50067d4SArnd Bergmann 			.channels_max = 2,
273a50067d4SArnd Bergmann 			.rates = RT5682_STEREO_RATES,
274a50067d4SArnd Bergmann 			.formats = RT5682_FORMATS,
275a50067d4SArnd Bergmann 		},
276a50067d4SArnd Bergmann 		.ops = &rt5682_aif2_dai_ops,
277a50067d4SArnd Bergmann 	},
278a50067d4SArnd Bergmann 	{
279a50067d4SArnd Bergmann 		.name = "rt5682-sdw",
280a50067d4SArnd Bergmann 		.id = RT5682_SDW,
281a50067d4SArnd Bergmann 		.playback = {
282a50067d4SArnd Bergmann 			.stream_name = "SDW Playback",
283a50067d4SArnd Bergmann 			.channels_min = 1,
284a50067d4SArnd Bergmann 			.channels_max = 2,
285a50067d4SArnd Bergmann 			.rates = RT5682_STEREO_RATES,
286a50067d4SArnd Bergmann 			.formats = RT5682_FORMATS,
287a50067d4SArnd Bergmann 		},
288a50067d4SArnd Bergmann 		.capture = {
289a50067d4SArnd Bergmann 			.stream_name = "SDW Capture",
290a50067d4SArnd Bergmann 			.channels_min = 1,
291a50067d4SArnd Bergmann 			.channels_max = 2,
292a50067d4SArnd Bergmann 			.rates = RT5682_STEREO_RATES,
293a50067d4SArnd Bergmann 			.formats = RT5682_FORMATS,
294a50067d4SArnd Bergmann 		},
295a50067d4SArnd Bergmann 		.ops = &rt5682_sdw_ops,
296a50067d4SArnd Bergmann 	},
297a50067d4SArnd Bergmann };
298a50067d4SArnd Bergmann 
299a50067d4SArnd Bergmann static int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
300a50067d4SArnd Bergmann 			   struct sdw_slave *slave)
301a50067d4SArnd Bergmann {
302a50067d4SArnd Bergmann 	struct rt5682_priv *rt5682;
303a50067d4SArnd Bergmann 	int ret;
304a50067d4SArnd Bergmann 
305a50067d4SArnd Bergmann 	rt5682 = devm_kzalloc(dev, sizeof(*rt5682), GFP_KERNEL);
306a50067d4SArnd Bergmann 	if (!rt5682)
307a50067d4SArnd Bergmann 		return -ENOMEM;
308a50067d4SArnd Bergmann 
309a50067d4SArnd Bergmann 	dev_set_drvdata(dev, rt5682);
310a50067d4SArnd Bergmann 	rt5682->slave = slave;
311a50067d4SArnd Bergmann 	rt5682->sdw_regmap = regmap;
312a50067d4SArnd Bergmann 	rt5682->is_sdw = true;
313a50067d4SArnd Bergmann 
31414f4946dSPierre-Louis Bossart 	mutex_init(&rt5682->disable_irq_lock);
31514f4946dSPierre-Louis Bossart 
316a50067d4SArnd Bergmann 	rt5682->regmap = devm_regmap_init(dev, NULL, dev,
317a50067d4SArnd Bergmann 					  &rt5682_sdw_indirect_regmap);
318a50067d4SArnd Bergmann 	if (IS_ERR(rt5682->regmap)) {
319a50067d4SArnd Bergmann 		ret = PTR_ERR(rt5682->regmap);
320a50067d4SArnd Bergmann 		dev_err(dev, "Failed to allocate register map: %d\n",
321a50067d4SArnd Bergmann 			ret);
322a50067d4SArnd Bergmann 		return ret;
323a50067d4SArnd Bergmann 	}
324a50067d4SArnd Bergmann 
325a50067d4SArnd Bergmann 	/*
326a50067d4SArnd Bergmann 	 * Mark hw_init to false
327a50067d4SArnd Bergmann 	 * HW init will be performed when device reports present
328a50067d4SArnd Bergmann 	 */
329a50067d4SArnd Bergmann 	rt5682->hw_init = false;
330a50067d4SArnd Bergmann 	rt5682->first_hw_init = false;
331a50067d4SArnd Bergmann 
332a50067d4SArnd Bergmann 	mutex_init(&rt5682->calibrate_mutex);
333a50067d4SArnd Bergmann 	INIT_DELAYED_WORK(&rt5682->jack_detect_work,
334a50067d4SArnd Bergmann 		rt5682_jack_detect_handler);
335a50067d4SArnd Bergmann 
336a50067d4SArnd Bergmann 	ret = devm_snd_soc_register_component(dev,
337a50067d4SArnd Bergmann 					      &rt5682_soc_component_dev,
338a50067d4SArnd Bergmann 					      rt5682_dai, ARRAY_SIZE(rt5682_dai));
339a50067d4SArnd Bergmann 	dev_dbg(&slave->dev, "%s\n", __func__);
340a50067d4SArnd Bergmann 
341a50067d4SArnd Bergmann 	return ret;
342a50067d4SArnd Bergmann }
343a50067d4SArnd Bergmann 
344a50067d4SArnd Bergmann static int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
345a50067d4SArnd Bergmann {
346a50067d4SArnd Bergmann 	struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
347867f8d18SShuming Fan 	int ret = 0, loop = 10;
348a50067d4SArnd Bergmann 	unsigned int val;
349a50067d4SArnd Bergmann 
35014f4946dSPierre-Louis Bossart 	rt5682->disable_irq = false;
35114f4946dSPierre-Louis Bossart 
352a50067d4SArnd Bergmann 	if (rt5682->hw_init)
353a50067d4SArnd Bergmann 		return 0;
354a50067d4SArnd Bergmann 
355a50067d4SArnd Bergmann 	/*
356a50067d4SArnd Bergmann 	 * PM runtime is only enabled when a Slave reports as Attached
357a50067d4SArnd Bergmann 	 */
358a50067d4SArnd Bergmann 	if (!rt5682->first_hw_init) {
359a50067d4SArnd Bergmann 		/* set autosuspend parameters */
360a50067d4SArnd Bergmann 		pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
361a50067d4SArnd Bergmann 		pm_runtime_use_autosuspend(&slave->dev);
362a50067d4SArnd Bergmann 
363a50067d4SArnd Bergmann 		/* update count of parent 'active' children */
364a50067d4SArnd Bergmann 		pm_runtime_set_active(&slave->dev);
365a50067d4SArnd Bergmann 
366a50067d4SArnd Bergmann 		/* make sure the device does not suspend immediately */
367a50067d4SArnd Bergmann 		pm_runtime_mark_last_busy(&slave->dev);
368a50067d4SArnd Bergmann 
369a50067d4SArnd Bergmann 		pm_runtime_enable(&slave->dev);
370a50067d4SArnd Bergmann 	}
371a50067d4SArnd Bergmann 
372a50067d4SArnd Bergmann 	pm_runtime_get_noresume(&slave->dev);
373a50067d4SArnd Bergmann 
374c0372bc8SBard Liao 	if (rt5682->first_hw_init) {
375c0372bc8SBard Liao 		regcache_cache_only(rt5682->regmap, false);
376c0372bc8SBard Liao 		regcache_cache_bypass(rt5682->regmap, true);
377c0372bc8SBard Liao 	}
378c0372bc8SBard Liao 
379867f8d18SShuming Fan 	while (loop > 0) {
380867f8d18SShuming Fan 		regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
381867f8d18SShuming Fan 		if (val == DEVICE_ID)
382867f8d18SShuming Fan 			break;
383867f8d18SShuming Fan 		dev_warn(dev, "Device with ID register %x is not rt5682\n", val);
384867f8d18SShuming Fan 		usleep_range(30000, 30005);
385867f8d18SShuming Fan 		loop--;
386867f8d18SShuming Fan 	}
3879266d954SOder Chiou 
388867f8d18SShuming Fan 	if (val != DEVICE_ID) {
389867f8d18SShuming Fan 		dev_err(dev, "Device with ID register %x is not rt5682\n", val);
3909266d954SOder Chiou 		ret = -ENODEV;
3919266d954SOder Chiou 		goto err_nodev;
392867f8d18SShuming Fan 	}
393867f8d18SShuming Fan 
394a50067d4SArnd Bergmann 	rt5682_calibrate(rt5682);
395a50067d4SArnd Bergmann 
396a50067d4SArnd Bergmann 	if (rt5682->first_hw_init) {
397a50067d4SArnd Bergmann 		regcache_cache_bypass(rt5682->regmap, false);
398a50067d4SArnd Bergmann 		regcache_mark_dirty(rt5682->regmap);
399a50067d4SArnd Bergmann 		regcache_sync(rt5682->regmap);
400a50067d4SArnd Bergmann 
401a50067d4SArnd Bergmann 		/* volatile registers */
402a50067d4SArnd Bergmann 		regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
403a50067d4SArnd Bergmann 			RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
404a50067d4SArnd Bergmann 
405a50067d4SArnd Bergmann 		goto reinit;
406a50067d4SArnd Bergmann 	}
407a50067d4SArnd Bergmann 
408a50067d4SArnd Bergmann 	rt5682_apply_patch_list(rt5682, dev);
409a50067d4SArnd Bergmann 
410a50067d4SArnd Bergmann 	regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000);
411a50067d4SArnd Bergmann 
412a50067d4SArnd Bergmann 	regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
413a50067d4SArnd Bergmann 		RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK,
414a50067d4SArnd Bergmann 		RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X);
4156301adf9SShuming Fan 	regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0080);
416a50067d4SArnd Bergmann 	regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000);
417a50067d4SArnd Bergmann 	regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8,
418a50067d4SArnd Bergmann 		RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA);
419a50067d4SArnd Bergmann 	regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1,
420a50067d4SArnd Bergmann 		RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ);
421a50067d4SArnd Bergmann 	regmap_update_bits(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1,
422a50067d4SArnd Bergmann 		RT5682_PM_HP_MASK, RT5682_PM_HP_HV);
423a50067d4SArnd Bergmann 
424a50067d4SArnd Bergmann 	/* Soundwire */
425a50067d4SArnd Bergmann 	regmap_write(rt5682->regmap, RT5682_PLL2_INTERNAL, 0xa266);
426a50067d4SArnd Bergmann 	regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_1, 0x1700);
427a50067d4SArnd Bergmann 	regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_2, 0x0006);
428a50067d4SArnd Bergmann 	regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_3, 0x2600);
429a50067d4SArnd Bergmann 	regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_4, 0x0c8f);
430a50067d4SArnd Bergmann 	regmap_write(rt5682->regmap, RT5682_PLL_TRACK_2, 0x3000);
431a50067d4SArnd Bergmann 	regmap_write(rt5682->regmap, RT5682_PLL_TRACK_3, 0x4000);
432a50067d4SArnd Bergmann 	regmap_update_bits(rt5682->regmap, RT5682_GLB_CLK,
433a50067d4SArnd Bergmann 		RT5682_SCLK_SRC_MASK | RT5682_PLL2_SRC_MASK,
434a50067d4SArnd Bergmann 		RT5682_SCLK_SRC_PLL2 | RT5682_PLL2_SRC_SDW);
435a50067d4SArnd Bergmann 
436a50067d4SArnd Bergmann 	regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2,
437a50067d4SArnd Bergmann 		RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL);
43849783c6fSOder Chiou 	regmap_write(rt5682->regmap, RT5682_CBJ_CTRL_1, 0xd142);
43949783c6fSOder Chiou 	regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_5, 0x0700, 0x0600);
440a50067d4SArnd Bergmann 	regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_3,
441a50067d4SArnd Bergmann 		RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN);
442a50067d4SArnd Bergmann 	regmap_update_bits(rt5682->regmap, RT5682_SAR_IL_CMD_1,
443a50067d4SArnd Bergmann 		RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN);
444a50067d4SArnd Bergmann 	regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
445a50067d4SArnd Bergmann 		RT5682_POW_IRQ | RT5682_POW_JDH |
446a50067d4SArnd Bergmann 		RT5682_POW_ANA, RT5682_POW_IRQ |
447a50067d4SArnd Bergmann 		RT5682_POW_JDH | RT5682_POW_ANA);
448a50067d4SArnd Bergmann 	regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2,
449a50067d4SArnd Bergmann 		RT5682_PWR_JDH, RT5682_PWR_JDH);
450a50067d4SArnd Bergmann 	regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
451a50067d4SArnd Bergmann 		RT5682_JD1_EN_MASK | RT5682_JD1_IRQ_MASK,
452a50067d4SArnd Bergmann 		RT5682_JD1_EN | RT5682_JD1_IRQ_PUL);
453a50067d4SArnd Bergmann 
454a50067d4SArnd Bergmann reinit:
455a50067d4SArnd Bergmann 	mod_delayed_work(system_power_efficient_wq,
456a50067d4SArnd Bergmann 		&rt5682->jack_detect_work, msecs_to_jiffies(250));
457a50067d4SArnd Bergmann 
458a50067d4SArnd Bergmann 	/* Mark Slave initialization complete */
459a50067d4SArnd Bergmann 	rt5682->hw_init = true;
460a50067d4SArnd Bergmann 	rt5682->first_hw_init = true;
461a50067d4SArnd Bergmann 
4629266d954SOder Chiou err_nodev:
463a50067d4SArnd Bergmann 	pm_runtime_mark_last_busy(&slave->dev);
464a50067d4SArnd Bergmann 	pm_runtime_put_autosuspend(&slave->dev);
465a50067d4SArnd Bergmann 
4669266d954SOder Chiou 	dev_dbg(&slave->dev, "%s hw_init complete: %d\n", __func__, ret);
467a50067d4SArnd Bergmann 
468a50067d4SArnd Bergmann 	return ret;
469a50067d4SArnd Bergmann }
47003f6fc6dSOder Chiou 
47103f6fc6dSOder Chiou static bool rt5682_sdw_readable_register(struct device *dev, unsigned int reg)
47203f6fc6dSOder Chiou {
47303f6fc6dSOder Chiou 	switch (reg) {
47403f6fc6dSOder Chiou 	case 0x00e0:
47503f6fc6dSOder Chiou 	case 0x00f0:
47603f6fc6dSOder Chiou 	case 0x3000:
47703f6fc6dSOder Chiou 	case 0x3001:
47803f6fc6dSOder Chiou 	case 0x3004:
47903f6fc6dSOder Chiou 	case 0x3005:
48003f6fc6dSOder Chiou 	case 0x3008:
48103f6fc6dSOder Chiou 		return true;
48203f6fc6dSOder Chiou 	default:
48303f6fc6dSOder Chiou 		return false;
48403f6fc6dSOder Chiou 	}
48503f6fc6dSOder Chiou }
48603f6fc6dSOder Chiou 
487a50067d4SArnd Bergmann static const struct regmap_config rt5682_sdw_regmap = {
48803f6fc6dSOder Chiou 	.name = "sdw",
48903f6fc6dSOder Chiou 	.reg_bits = 32,
49003f6fc6dSOder Chiou 	.val_bits = 8,
49103f6fc6dSOder Chiou 	.max_register = RT5682_I2C_MODE,
49203f6fc6dSOder Chiou 	.readable_reg = rt5682_sdw_readable_register,
49303f6fc6dSOder Chiou 	.cache_type = REGCACHE_NONE,
49403f6fc6dSOder Chiou 	.use_single_read = true,
49503f6fc6dSOder Chiou 	.use_single_write = true,
49603f6fc6dSOder Chiou };
49703f6fc6dSOder Chiou 
49803f6fc6dSOder Chiou static int rt5682_update_status(struct sdw_slave *slave,
49903f6fc6dSOder Chiou 					enum sdw_slave_status status)
50003f6fc6dSOder Chiou {
50103f6fc6dSOder Chiou 	struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
50203f6fc6dSOder Chiou 
50303f6fc6dSOder Chiou 	if (status == SDW_SLAVE_UNATTACHED)
50403f6fc6dSOder Chiou 		rt5682->hw_init = false;
50503f6fc6dSOder Chiou 
50603f6fc6dSOder Chiou 	/*
50703f6fc6dSOder Chiou 	 * Perform initialization only if slave status is present and
50803f6fc6dSOder Chiou 	 * hw_init flag is false
50903f6fc6dSOder Chiou 	 */
510758665b1SKrzysztof Kozlowski 	if (rt5682->hw_init || status != SDW_SLAVE_ATTACHED)
51103f6fc6dSOder Chiou 		return 0;
51203f6fc6dSOder Chiou 
51303f6fc6dSOder Chiou 	/* perform I/O transfers required for Slave initialization */
51403f6fc6dSOder Chiou 	return rt5682_io_init(&slave->dev, slave);
51503f6fc6dSOder Chiou }
51603f6fc6dSOder Chiou 
51703f6fc6dSOder Chiou static int rt5682_read_prop(struct sdw_slave *slave)
51803f6fc6dSOder Chiou {
51903f6fc6dSOder Chiou 	struct sdw_slave_prop *prop = &slave->prop;
520d0bbcb4eSPierre-Louis Bossart 	int nval, i;
52103f6fc6dSOder Chiou 	u32 bit;
52203f6fc6dSOder Chiou 	unsigned long addr;
52303f6fc6dSOder Chiou 	struct sdw_dpn_prop *dpn;
52403f6fc6dSOder Chiou 
5252acd30b9SPierre-Louis Bossart 	prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH |
5262acd30b9SPierre-Louis Bossart 		SDW_SCP_INT1_PARITY;
52738edbfaeSPierre-Louis Bossart 	prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY;
5282acd30b9SPierre-Louis Bossart 
52903f6fc6dSOder Chiou 	prop->paging_support = false;
53003f6fc6dSOder Chiou 
53103f6fc6dSOder Chiou 	/* first we need to allocate memory for set bits in port lists */
53203f6fc6dSOder Chiou 	prop->source_ports = 0x4;	/* BITMAP: 00000100 */
53303f6fc6dSOder Chiou 	prop->sink_ports = 0x2;		/* BITMAP: 00000010 */
53403f6fc6dSOder Chiou 
53503f6fc6dSOder Chiou 	nval = hweight32(prop->source_ports);
53603f6fc6dSOder Chiou 	prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
53703f6fc6dSOder Chiou 					  sizeof(*prop->src_dpn_prop),
53803f6fc6dSOder Chiou 					  GFP_KERNEL);
53903f6fc6dSOder Chiou 	if (!prop->src_dpn_prop)
54003f6fc6dSOder Chiou 		return -ENOMEM;
54103f6fc6dSOder Chiou 
54203f6fc6dSOder Chiou 	i = 0;
54303f6fc6dSOder Chiou 	dpn = prop->src_dpn_prop;
54403f6fc6dSOder Chiou 	addr = prop->source_ports;
54503f6fc6dSOder Chiou 	for_each_set_bit(bit, &addr, 32) {
54603f6fc6dSOder Chiou 		dpn[i].num = bit;
54703f6fc6dSOder Chiou 		dpn[i].type = SDW_DPN_FULL;
54803f6fc6dSOder Chiou 		dpn[i].simple_ch_prep_sm = true;
54903f6fc6dSOder Chiou 		dpn[i].ch_prep_timeout = 10;
55003f6fc6dSOder Chiou 		i++;
55103f6fc6dSOder Chiou 	}
55203f6fc6dSOder Chiou 
55303f6fc6dSOder Chiou 	/* do this again for sink now */
55403f6fc6dSOder Chiou 	nval = hweight32(prop->sink_ports);
55503f6fc6dSOder Chiou 	prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
55603f6fc6dSOder Chiou 					   sizeof(*prop->sink_dpn_prop),
55703f6fc6dSOder Chiou 					   GFP_KERNEL);
55803f6fc6dSOder Chiou 	if (!prop->sink_dpn_prop)
55903f6fc6dSOder Chiou 		return -ENOMEM;
56003f6fc6dSOder Chiou 
56103f6fc6dSOder Chiou 	i = 0;
56203f6fc6dSOder Chiou 	dpn = prop->sink_dpn_prop;
56303f6fc6dSOder Chiou 	addr = prop->sink_ports;
56403f6fc6dSOder Chiou 	for_each_set_bit(bit, &addr, 32) {
56503f6fc6dSOder Chiou 		dpn[i].num = bit;
56603f6fc6dSOder Chiou 		dpn[i].type = SDW_DPN_FULL;
56703f6fc6dSOder Chiou 		dpn[i].simple_ch_prep_sm = true;
56803f6fc6dSOder Chiou 		dpn[i].ch_prep_timeout = 10;
56903f6fc6dSOder Chiou 		i++;
57003f6fc6dSOder Chiou 	}
57103f6fc6dSOder Chiou 
57203f6fc6dSOder Chiou 	/* set the timeout values */
57303f6fc6dSOder Chiou 	prop->clk_stop_timeout = 20;
57403f6fc6dSOder Chiou 
57503f6fc6dSOder Chiou 	/* wake-up event */
57603f6fc6dSOder Chiou 	prop->wake_capable = 1;
57703f6fc6dSOder Chiou 
57803f6fc6dSOder Chiou 	return 0;
57903f6fc6dSOder Chiou }
58003f6fc6dSOder Chiou 
58103f6fc6dSOder Chiou /* Bus clock frequency */
58203f6fc6dSOder Chiou #define RT5682_CLK_FREQ_9600000HZ 9600000
58303f6fc6dSOder Chiou #define RT5682_CLK_FREQ_12000000HZ 12000000
58403f6fc6dSOder Chiou #define RT5682_CLK_FREQ_6000000HZ 6000000
58503f6fc6dSOder Chiou #define RT5682_CLK_FREQ_4800000HZ 4800000
58603f6fc6dSOder Chiou #define RT5682_CLK_FREQ_2400000HZ 2400000
58703f6fc6dSOder Chiou #define RT5682_CLK_FREQ_12288000HZ 12288000
58803f6fc6dSOder Chiou 
589a3c2e894SYueHaibing static int rt5682_clock_config(struct device *dev)
59003f6fc6dSOder Chiou {
59103f6fc6dSOder Chiou 	struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
59203f6fc6dSOder Chiou 	unsigned int clk_freq, value;
59303f6fc6dSOder Chiou 
59403f6fc6dSOder Chiou 	clk_freq = (rt5682->params.curr_dr_freq >> 1);
59503f6fc6dSOder Chiou 
59603f6fc6dSOder Chiou 	switch (clk_freq) {
59703f6fc6dSOder Chiou 	case RT5682_CLK_FREQ_12000000HZ:
59803f6fc6dSOder Chiou 		value = 0x0;
59903f6fc6dSOder Chiou 		break;
60003f6fc6dSOder Chiou 	case RT5682_CLK_FREQ_6000000HZ:
60103f6fc6dSOder Chiou 		value = 0x1;
60203f6fc6dSOder Chiou 		break;
60303f6fc6dSOder Chiou 	case RT5682_CLK_FREQ_9600000HZ:
60403f6fc6dSOder Chiou 		value = 0x2;
60503f6fc6dSOder Chiou 		break;
60603f6fc6dSOder Chiou 	case RT5682_CLK_FREQ_4800000HZ:
60703f6fc6dSOder Chiou 		value = 0x3;
60803f6fc6dSOder Chiou 		break;
60903f6fc6dSOder Chiou 	case RT5682_CLK_FREQ_2400000HZ:
61003f6fc6dSOder Chiou 		value = 0x4;
61103f6fc6dSOder Chiou 		break;
61203f6fc6dSOder Chiou 	case RT5682_CLK_FREQ_12288000HZ:
61303f6fc6dSOder Chiou 		value = 0x5;
61403f6fc6dSOder Chiou 		break;
61503f6fc6dSOder Chiou 	default:
61603f6fc6dSOder Chiou 		return -EINVAL;
61703f6fc6dSOder Chiou 	}
61803f6fc6dSOder Chiou 
61903f6fc6dSOder Chiou 	regmap_write(rt5682->sdw_regmap, 0xe0, value);
62003f6fc6dSOder Chiou 	regmap_write(rt5682->sdw_regmap, 0xf0, value);
62103f6fc6dSOder Chiou 
62203f6fc6dSOder Chiou 	dev_dbg(dev, "%s complete, clk_freq=%d\n", __func__, clk_freq);
62303f6fc6dSOder Chiou 
62403f6fc6dSOder Chiou 	return 0;
62503f6fc6dSOder Chiou }
62603f6fc6dSOder Chiou 
62703f6fc6dSOder Chiou static int rt5682_bus_config(struct sdw_slave *slave,
62803f6fc6dSOder Chiou 					struct sdw_bus_params *params)
62903f6fc6dSOder Chiou {
63003f6fc6dSOder Chiou 	struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
63103f6fc6dSOder Chiou 	int ret;
63203f6fc6dSOder Chiou 
63303f6fc6dSOder Chiou 	memcpy(&rt5682->params, params, sizeof(*params));
63403f6fc6dSOder Chiou 
63503f6fc6dSOder Chiou 	ret = rt5682_clock_config(&slave->dev);
63603f6fc6dSOder Chiou 	if (ret < 0)
63703f6fc6dSOder Chiou 		dev_err(&slave->dev, "Invalid clk config");
63803f6fc6dSOder Chiou 
63903f6fc6dSOder Chiou 	return ret;
64003f6fc6dSOder Chiou }
64103f6fc6dSOder Chiou 
64203f6fc6dSOder Chiou static int rt5682_interrupt_callback(struct sdw_slave *slave,
64303f6fc6dSOder Chiou 					struct sdw_slave_intr_status *status)
64403f6fc6dSOder Chiou {
64503f6fc6dSOder Chiou 	struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
64603f6fc6dSOder Chiou 
64703f6fc6dSOder Chiou 	dev_dbg(&slave->dev,
64803f6fc6dSOder Chiou 		"%s control_port_stat=%x", __func__, status->control_port);
64903f6fc6dSOder Chiou 
65014f4946dSPierre-Louis Bossart 	mutex_lock(&rt5682->disable_irq_lock);
65114f4946dSPierre-Louis Bossart 	if (status->control_port & 0x4 && !rt5682->disable_irq) {
65203f6fc6dSOder Chiou 		mod_delayed_work(system_power_efficient_wq,
65354271282SShuming Fan 			&rt5682->jack_detect_work, msecs_to_jiffies(rt5682->irq_work_delay_time));
65403f6fc6dSOder Chiou 	}
65514f4946dSPierre-Louis Bossart 	mutex_unlock(&rt5682->disable_irq_lock);
65603f6fc6dSOder Chiou 
65703f6fc6dSOder Chiou 	return 0;
65803f6fc6dSOder Chiou }
65903f6fc6dSOder Chiou 
660628fc9d9SRikard Falkeborn static const struct sdw_slave_ops rt5682_slave_ops = {
66103f6fc6dSOder Chiou 	.read_prop = rt5682_read_prop,
66203f6fc6dSOder Chiou 	.interrupt_callback = rt5682_interrupt_callback,
66303f6fc6dSOder Chiou 	.update_status = rt5682_update_status,
66403f6fc6dSOder Chiou 	.bus_config = rt5682_bus_config,
66503f6fc6dSOder Chiou };
66603f6fc6dSOder Chiou 
66703f6fc6dSOder Chiou static int rt5682_sdw_probe(struct sdw_slave *slave,
66803f6fc6dSOder Chiou 			   const struct sdw_device_id *id)
66903f6fc6dSOder Chiou {
67003f6fc6dSOder Chiou 	struct regmap *regmap;
67103f6fc6dSOder Chiou 
67203f6fc6dSOder Chiou 	/* Regmap Initialization */
67303f6fc6dSOder Chiou 	regmap = devm_regmap_init_sdw(slave, &rt5682_sdw_regmap);
67403f6fc6dSOder Chiou 	if (IS_ERR(regmap))
67503f6fc6dSOder Chiou 		return -EINVAL;
67603f6fc6dSOder Chiou 
677*3f3d66baSPierre-Louis Bossart 	return rt5682_sdw_init(&slave->dev, regmap, slave);
67803f6fc6dSOder Chiou }
67903f6fc6dSOder Chiou 
68003f6fc6dSOder Chiou static int rt5682_sdw_remove(struct sdw_slave *slave)
68103f6fc6dSOder Chiou {
68203f6fc6dSOder Chiou 	struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
68303f6fc6dSOder Chiou 
684ac63716dSPierre-Louis Bossart 	if (rt5682->hw_init)
685c792c369SPierre-Louis Bossart 		cancel_delayed_work_sync(&rt5682->jack_detect_work);
68603f6fc6dSOder Chiou 
687ac63716dSPierre-Louis Bossart 	if (rt5682->first_hw_init)
688ac63716dSPierre-Louis Bossart 		pm_runtime_disable(&slave->dev);
689ac63716dSPierre-Louis Bossart 
69003f6fc6dSOder Chiou 	return 0;
69103f6fc6dSOder Chiou }
69203f6fc6dSOder Chiou 
69303f6fc6dSOder Chiou static const struct sdw_device_id rt5682_id[] = {
6949e473058SPierre-Louis Bossart 	SDW_SLAVE_ENTRY_EXT(0x025d, 0x5682, 0x2, 0, 0),
69503f6fc6dSOder Chiou 	{},
69603f6fc6dSOder Chiou };
69703f6fc6dSOder Chiou MODULE_DEVICE_TABLE(sdw, rt5682_id);
69803f6fc6dSOder Chiou 
699724cc62fSPierre-Louis Bossart static int __maybe_unused rt5682_dev_suspend(struct device *dev)
70003f6fc6dSOder Chiou {
70103f6fc6dSOder Chiou 	struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
70203f6fc6dSOder Chiou 
70303f6fc6dSOder Chiou 	if (!rt5682->hw_init)
70403f6fc6dSOder Chiou 		return 0;
70503f6fc6dSOder Chiou 
706c792c369SPierre-Louis Bossart 	cancel_delayed_work_sync(&rt5682->jack_detect_work);
707c792c369SPierre-Louis Bossart 
70803f6fc6dSOder Chiou 	regcache_cache_only(rt5682->regmap, true);
70903f6fc6dSOder Chiou 	regcache_mark_dirty(rt5682->regmap);
71003f6fc6dSOder Chiou 
71103f6fc6dSOder Chiou 	return 0;
71203f6fc6dSOder Chiou }
71303f6fc6dSOder Chiou 
71414f4946dSPierre-Louis Bossart static int __maybe_unused rt5682_dev_system_suspend(struct device *dev)
71514f4946dSPierre-Louis Bossart {
71614f4946dSPierre-Louis Bossart 	struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
71714f4946dSPierre-Louis Bossart 	struct sdw_slave *slave = dev_to_sdw_dev(dev);
71814f4946dSPierre-Louis Bossart 	int ret;
71914f4946dSPierre-Louis Bossart 
72014f4946dSPierre-Louis Bossart 	if (!rt5682->hw_init)
72114f4946dSPierre-Louis Bossart 		return 0;
72214f4946dSPierre-Louis Bossart 
72314f4946dSPierre-Louis Bossart 	/*
72414f4946dSPierre-Louis Bossart 	 * prevent new interrupts from being handled after the
72514f4946dSPierre-Louis Bossart 	 * deferred work completes and before the parent disables
72614f4946dSPierre-Louis Bossart 	 * interrupts on the link
72714f4946dSPierre-Louis Bossart 	 */
72814f4946dSPierre-Louis Bossart 	mutex_lock(&rt5682->disable_irq_lock);
72914f4946dSPierre-Louis Bossart 	rt5682->disable_irq = true;
73014f4946dSPierre-Louis Bossart 	ret = sdw_update_no_pm(slave, SDW_SCP_INTMASK1,
73114f4946dSPierre-Louis Bossart 			       SDW_SCP_INT1_IMPL_DEF, 0);
73214f4946dSPierre-Louis Bossart 	mutex_unlock(&rt5682->disable_irq_lock);
73314f4946dSPierre-Louis Bossart 
73414f4946dSPierre-Louis Bossart 	if (ret < 0) {
73514f4946dSPierre-Louis Bossart 		/* log but don't prevent suspend from happening */
73614f4946dSPierre-Louis Bossart 		dev_dbg(&slave->dev, "%s: could not disable imp-def interrupts\n:", __func__);
73714f4946dSPierre-Louis Bossart 	}
73814f4946dSPierre-Louis Bossart 
73914f4946dSPierre-Louis Bossart 	return rt5682_dev_suspend(dev);
74014f4946dSPierre-Louis Bossart }
74114f4946dSPierre-Louis Bossart 
742724cc62fSPierre-Louis Bossart static int __maybe_unused rt5682_dev_resume(struct device *dev)
74303f6fc6dSOder Chiou {
74403f6fc6dSOder Chiou 	struct sdw_slave *slave = dev_to_sdw_dev(dev);
74503f6fc6dSOder Chiou 	struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
74603f6fc6dSOder Chiou 	unsigned long time;
74703f6fc6dSOder Chiou 
7485361a421SPierre-Louis Bossart 	if (!rt5682->first_hw_init)
74903f6fc6dSOder Chiou 		return 0;
75003f6fc6dSOder Chiou 
75102fb23d7SShuming Fan 	if (!slave->unattach_request) {
75202fb23d7SShuming Fan 		if (rt5682->disable_irq == true) {
75302fb23d7SShuming Fan 			mutex_lock(&rt5682->disable_irq_lock);
75402fb23d7SShuming Fan 			sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
75502fb23d7SShuming Fan 			rt5682->disable_irq = false;
75602fb23d7SShuming Fan 			mutex_unlock(&rt5682->disable_irq_lock);
75702fb23d7SShuming Fan 		}
75803f6fc6dSOder Chiou 		goto regmap_sync;
75902fb23d7SShuming Fan 	}
76003f6fc6dSOder Chiou 
76103f6fc6dSOder Chiou 	time = wait_for_completion_timeout(&slave->initialization_complete,
76203f6fc6dSOder Chiou 				msecs_to_jiffies(RT5682_PROBE_TIMEOUT));
76303f6fc6dSOder Chiou 	if (!time) {
76403f6fc6dSOder Chiou 		dev_err(&slave->dev, "Initialization not complete, timed out\n");
765917df025SPierre-Louis Bossart 		sdw_show_ping_status(slave->bus, true);
766917df025SPierre-Louis Bossart 
76703f6fc6dSOder Chiou 		return -ETIMEDOUT;
76803f6fc6dSOder Chiou 	}
76903f6fc6dSOder Chiou 
77003f6fc6dSOder Chiou regmap_sync:
77103f6fc6dSOder Chiou 	slave->unattach_request = 0;
77203f6fc6dSOder Chiou 	regcache_cache_only(rt5682->regmap, false);
77303f6fc6dSOder Chiou 	regcache_sync(rt5682->regmap);
77403f6fc6dSOder Chiou 
77503f6fc6dSOder Chiou 	return 0;
77603f6fc6dSOder Chiou }
77703f6fc6dSOder Chiou 
77803f6fc6dSOder Chiou static const struct dev_pm_ops rt5682_pm = {
77914f4946dSPierre-Louis Bossart 	SET_SYSTEM_SLEEP_PM_OPS(rt5682_dev_system_suspend, rt5682_dev_resume)
78003f6fc6dSOder Chiou 	SET_RUNTIME_PM_OPS(rt5682_dev_suspend, rt5682_dev_resume, NULL)
78103f6fc6dSOder Chiou };
78203f6fc6dSOder Chiou 
78303f6fc6dSOder Chiou static struct sdw_driver rt5682_sdw_driver = {
78403f6fc6dSOder Chiou 	.driver = {
78503f6fc6dSOder Chiou 		.name = "rt5682",
78603f6fc6dSOder Chiou 		.owner = THIS_MODULE,
78703f6fc6dSOder Chiou 		.pm = &rt5682_pm,
78803f6fc6dSOder Chiou 	},
78903f6fc6dSOder Chiou 	.probe = rt5682_sdw_probe,
79003f6fc6dSOder Chiou 	.remove = rt5682_sdw_remove,
79103f6fc6dSOder Chiou 	.ops = &rt5682_slave_ops,
79203f6fc6dSOder Chiou 	.id_table = rt5682_id,
79303f6fc6dSOder Chiou };
79403f6fc6dSOder Chiou module_sdw_driver(rt5682_sdw_driver);
79503f6fc6dSOder Chiou 
79603f6fc6dSOder Chiou MODULE_DESCRIPTION("ASoC RT5682 driver SDW");
79703f6fc6dSOder Chiou MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
79803f6fc6dSOder Chiou MODULE_LICENSE("GPL v2");
799