xref: /OK3568_Linux_fs/kernel/sound/soc/codecs/rt5677-spi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * rt5677-spi.c  --  RT5677 ALSA SoC audio codec driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright 2013 Realtek Semiconductor Corp.
6*4882a593Smuzhiyun  * Author: Oder Chiou <oder_chiou@realtek.com>
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/input.h>
11*4882a593Smuzhiyun #include <linux/spi/spi.h>
12*4882a593Smuzhiyun #include <linux/device.h>
13*4882a593Smuzhiyun #include <linux/init.h>
14*4882a593Smuzhiyun #include <linux/delay.h>
15*4882a593Smuzhiyun #include <linux/interrupt.h>
16*4882a593Smuzhiyun #include <linux/irq.h>
17*4882a593Smuzhiyun #include <linux/slab.h>
18*4882a593Smuzhiyun #include <linux/sched.h>
19*4882a593Smuzhiyun #include <linux/uaccess.h>
20*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
21*4882a593Smuzhiyun #include <linux/pm_qos.h>
22*4882a593Smuzhiyun #include <linux/sysfs.h>
23*4882a593Smuzhiyun #include <linux/clk.h>
24*4882a593Smuzhiyun #include <linux/firmware.h>
25*4882a593Smuzhiyun #include <linux/acpi.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include <sound/soc.h>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include "rt5677.h"
30*4882a593Smuzhiyun #include "rt5677-spi.h"
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #define DRV_NAME "rt5677spi"
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define RT5677_SPI_BURST_LEN	240
35*4882a593Smuzhiyun #define RT5677_SPI_HEADER	5
36*4882a593Smuzhiyun #define RT5677_SPI_FREQ		6000000
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun /* The AddressPhase and DataPhase of SPI commands are MSB first on the wire.
39*4882a593Smuzhiyun  * DataPhase word size of 16-bit commands is 2 bytes.
40*4882a593Smuzhiyun  * DataPhase word size of 32-bit commands is 4 bytes.
41*4882a593Smuzhiyun  * DataPhase word size of burst commands is 8 bytes.
42*4882a593Smuzhiyun  * The DSP CPU is little-endian.
43*4882a593Smuzhiyun  */
44*4882a593Smuzhiyun #define RT5677_SPI_WRITE_BURST	0x5
45*4882a593Smuzhiyun #define RT5677_SPI_READ_BURST	0x4
46*4882a593Smuzhiyun #define RT5677_SPI_WRITE_32	0x3
47*4882a593Smuzhiyun #define RT5677_SPI_READ_32	0x2
48*4882a593Smuzhiyun #define RT5677_SPI_WRITE_16	0x1
49*4882a593Smuzhiyun #define RT5677_SPI_READ_16	0x0
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #define RT5677_BUF_BYTES_TOTAL		0x20000
52*4882a593Smuzhiyun #define RT5677_MIC_BUF_ADDR		0x60030000
53*4882a593Smuzhiyun #define RT5677_MODEL_ADDR		0x5FFC9800
54*4882a593Smuzhiyun #define RT5677_MIC_BUF_BYTES		((u32)(RT5677_BUF_BYTES_TOTAL - \
55*4882a593Smuzhiyun 					sizeof(u32)))
56*4882a593Smuzhiyun #define RT5677_MIC_BUF_FIRST_READ_SIZE	0x10000
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun static struct spi_device *g_spi;
59*4882a593Smuzhiyun static DEFINE_MUTEX(spi_mutex);
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun struct rt5677_dsp {
62*4882a593Smuzhiyun 	struct device *dev;
63*4882a593Smuzhiyun 	struct delayed_work copy_work;
64*4882a593Smuzhiyun 	struct mutex dma_lock;
65*4882a593Smuzhiyun 	struct snd_pcm_substream *substream;
66*4882a593Smuzhiyun 	size_t dma_offset;	/* zero-based offset into runtime->dma_area */
67*4882a593Smuzhiyun 	size_t avail_bytes;	/* number of new bytes since last period */
68*4882a593Smuzhiyun 	u32 mic_read_offset;	/* zero-based offset into DSP's mic buffer */
69*4882a593Smuzhiyun 	bool new_hotword;	/* a new hotword is fired */
70*4882a593Smuzhiyun };
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun static const struct snd_pcm_hardware rt5677_spi_pcm_hardware = {
73*4882a593Smuzhiyun 	.info			= SNDRV_PCM_INFO_MMAP |
74*4882a593Smuzhiyun 				  SNDRV_PCM_INFO_MMAP_VALID |
75*4882a593Smuzhiyun 				  SNDRV_PCM_INFO_INTERLEAVED,
76*4882a593Smuzhiyun 	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
77*4882a593Smuzhiyun 	.period_bytes_min	= PAGE_SIZE,
78*4882a593Smuzhiyun 	.period_bytes_max	= RT5677_BUF_BYTES_TOTAL / 8,
79*4882a593Smuzhiyun 	.periods_min		= 8,
80*4882a593Smuzhiyun 	.periods_max		= 8,
81*4882a593Smuzhiyun 	.channels_min		= 1,
82*4882a593Smuzhiyun 	.channels_max		= 1,
83*4882a593Smuzhiyun 	.buffer_bytes_max	= RT5677_BUF_BYTES_TOTAL,
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun static struct snd_soc_dai_driver rt5677_spi_dai = {
87*4882a593Smuzhiyun 	/* The DAI name "rt5677-dsp-cpu-dai" is not used. The actual DAI name
88*4882a593Smuzhiyun 	 * registered with ASoC is the name of the device "spi-RT5677AA:00",
89*4882a593Smuzhiyun 	 * because we only have one DAI. See snd_soc_register_dais().
90*4882a593Smuzhiyun 	 */
91*4882a593Smuzhiyun 	.name = "rt5677-dsp-cpu-dai",
92*4882a593Smuzhiyun 	.id = 0,
93*4882a593Smuzhiyun 	.capture = {
94*4882a593Smuzhiyun 		.stream_name = "DSP Capture",
95*4882a593Smuzhiyun 		.channels_min = 1,
96*4882a593Smuzhiyun 		.channels_max = 1,
97*4882a593Smuzhiyun 		.rates = SNDRV_PCM_RATE_16000,
98*4882a593Smuzhiyun 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
99*4882a593Smuzhiyun 	},
100*4882a593Smuzhiyun };
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun /* PCM for streaming audio from the DSP buffer */
rt5677_spi_pcm_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)103*4882a593Smuzhiyun static int rt5677_spi_pcm_open(
104*4882a593Smuzhiyun 		struct snd_soc_component *component,
105*4882a593Smuzhiyun 		struct snd_pcm_substream *substream)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	snd_soc_set_runtime_hwparams(substream, &rt5677_spi_pcm_hardware);
108*4882a593Smuzhiyun 	return 0;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
rt5677_spi_pcm_close(struct snd_soc_component * component,struct snd_pcm_substream * substream)111*4882a593Smuzhiyun static int rt5677_spi_pcm_close(
112*4882a593Smuzhiyun 		struct snd_soc_component *component,
113*4882a593Smuzhiyun 		struct snd_pcm_substream *substream)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
116*4882a593Smuzhiyun 	struct snd_soc_component *codec_component =
117*4882a593Smuzhiyun 			snd_soc_rtdcom_lookup(rtd, "rt5677");
118*4882a593Smuzhiyun 	struct rt5677_priv *rt5677 =
119*4882a593Smuzhiyun 			snd_soc_component_get_drvdata(codec_component);
120*4882a593Smuzhiyun 	struct rt5677_dsp *rt5677_dsp =
121*4882a593Smuzhiyun 			snd_soc_component_get_drvdata(component);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	cancel_delayed_work_sync(&rt5677_dsp->copy_work);
124*4882a593Smuzhiyun 	rt5677->set_dsp_vad(codec_component, false);
125*4882a593Smuzhiyun 	return 0;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun 
rt5677_spi_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params)128*4882a593Smuzhiyun static int rt5677_spi_hw_params(
129*4882a593Smuzhiyun 		struct snd_soc_component *component,
130*4882a593Smuzhiyun 		struct snd_pcm_substream *substream,
131*4882a593Smuzhiyun 		struct snd_pcm_hw_params *hw_params)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	struct rt5677_dsp *rt5677_dsp =
134*4882a593Smuzhiyun 			snd_soc_component_get_drvdata(component);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	mutex_lock(&rt5677_dsp->dma_lock);
137*4882a593Smuzhiyun 	rt5677_dsp->substream = substream;
138*4882a593Smuzhiyun 	mutex_unlock(&rt5677_dsp->dma_lock);
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	return 0;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
rt5677_spi_hw_free(struct snd_soc_component * component,struct snd_pcm_substream * substream)143*4882a593Smuzhiyun static int rt5677_spi_hw_free(
144*4882a593Smuzhiyun 		struct snd_soc_component *component,
145*4882a593Smuzhiyun 		struct snd_pcm_substream *substream)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun 	struct rt5677_dsp *rt5677_dsp =
148*4882a593Smuzhiyun 			snd_soc_component_get_drvdata(component);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	mutex_lock(&rt5677_dsp->dma_lock);
151*4882a593Smuzhiyun 	rt5677_dsp->substream = NULL;
152*4882a593Smuzhiyun 	mutex_unlock(&rt5677_dsp->dma_lock);
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	return 0;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
rt5677_spi_prepare(struct snd_soc_component * component,struct snd_pcm_substream * substream)157*4882a593Smuzhiyun static int rt5677_spi_prepare(
158*4882a593Smuzhiyun 		struct snd_soc_component *component,
159*4882a593Smuzhiyun 		struct snd_pcm_substream *substream)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
162*4882a593Smuzhiyun 	struct snd_soc_component *rt5677_component =
163*4882a593Smuzhiyun 			snd_soc_rtdcom_lookup(rtd, "rt5677");
164*4882a593Smuzhiyun 	struct rt5677_priv *rt5677 =
165*4882a593Smuzhiyun 			snd_soc_component_get_drvdata(rt5677_component);
166*4882a593Smuzhiyun 	struct rt5677_dsp *rt5677_dsp =
167*4882a593Smuzhiyun 			snd_soc_component_get_drvdata(component);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	rt5677->set_dsp_vad(rt5677_component, true);
170*4882a593Smuzhiyun 	rt5677_dsp->dma_offset = 0;
171*4882a593Smuzhiyun 	rt5677_dsp->avail_bytes = 0;
172*4882a593Smuzhiyun 	return 0;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
rt5677_spi_pcm_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)175*4882a593Smuzhiyun static snd_pcm_uframes_t rt5677_spi_pcm_pointer(
176*4882a593Smuzhiyun 		struct snd_soc_component *component,
177*4882a593Smuzhiyun 		struct snd_pcm_substream *substream)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	struct snd_pcm_runtime *runtime = substream->runtime;
180*4882a593Smuzhiyun 	struct rt5677_dsp *rt5677_dsp =
181*4882a593Smuzhiyun 			snd_soc_component_get_drvdata(component);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	return bytes_to_frames(runtime, rt5677_dsp->dma_offset);
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
rt5677_spi_mic_write_offset(u32 * mic_write_offset)186*4882a593Smuzhiyun static int rt5677_spi_mic_write_offset(u32 *mic_write_offset)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	int ret;
189*4882a593Smuzhiyun 	/* Grab the first 4 bytes that hold the write pointer on the
190*4882a593Smuzhiyun 	 * dsp, and check to make sure that it points somewhere inside the
191*4882a593Smuzhiyun 	 * buffer.
192*4882a593Smuzhiyun 	 */
193*4882a593Smuzhiyun 	ret = rt5677_spi_read(RT5677_MIC_BUF_ADDR, mic_write_offset,
194*4882a593Smuzhiyun 			sizeof(u32));
195*4882a593Smuzhiyun 	if (ret)
196*4882a593Smuzhiyun 		return ret;
197*4882a593Smuzhiyun 	/* Adjust the offset so that it's zero-based */
198*4882a593Smuzhiyun 	*mic_write_offset = *mic_write_offset - sizeof(u32);
199*4882a593Smuzhiyun 	return *mic_write_offset < RT5677_MIC_BUF_BYTES ? 0 : -EFAULT;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun /*
203*4882a593Smuzhiyun  * Copy one contiguous block of audio samples from the DSP mic buffer to the
204*4882a593Smuzhiyun  * dma_area of the pcm runtime. The receiving buffer may wrap around.
205*4882a593Smuzhiyun  * @begin: start offset of the block to copy, in bytes.
206*4882a593Smuzhiyun  * @end:   offset of the first byte after the block to copy, must be greater
207*4882a593Smuzhiyun  *         than or equal to begin.
208*4882a593Smuzhiyun  *
209*4882a593Smuzhiyun  * Return: Zero if successful, or a negative error code on failure.
210*4882a593Smuzhiyun  */
rt5677_spi_copy_block(struct rt5677_dsp * rt5677_dsp,u32 begin,u32 end)211*4882a593Smuzhiyun static int rt5677_spi_copy_block(struct rt5677_dsp *rt5677_dsp,
212*4882a593Smuzhiyun 		u32 begin, u32 end)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	struct snd_pcm_runtime *runtime = rt5677_dsp->substream->runtime;
215*4882a593Smuzhiyun 	size_t bytes_per_frame = frames_to_bytes(runtime, 1);
216*4882a593Smuzhiyun 	size_t first_chunk_len, second_chunk_len;
217*4882a593Smuzhiyun 	int ret;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	if (begin > end || runtime->dma_bytes < 2 * bytes_per_frame) {
220*4882a593Smuzhiyun 		dev_err(rt5677_dsp->dev,
221*4882a593Smuzhiyun 			"Invalid copy from (%u, %u), dma_area size %zu\n",
222*4882a593Smuzhiyun 			begin, end, runtime->dma_bytes);
223*4882a593Smuzhiyun 		return -EINVAL;
224*4882a593Smuzhiyun 	}
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	/* The block to copy is empty */
227*4882a593Smuzhiyun 	if (begin == end)
228*4882a593Smuzhiyun 		return 0;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	/* If the incoming chunk is too big for the receiving buffer, only the
231*4882a593Smuzhiyun 	 * last "receiving buffer size - one frame" bytes are copied.
232*4882a593Smuzhiyun 	 */
233*4882a593Smuzhiyun 	if (end - begin > runtime->dma_bytes - bytes_per_frame)
234*4882a593Smuzhiyun 		begin = end - (runtime->dma_bytes - bytes_per_frame);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	/* May need to split to two chunks, calculate the size of each */
237*4882a593Smuzhiyun 	first_chunk_len = end - begin;
238*4882a593Smuzhiyun 	second_chunk_len = 0;
239*4882a593Smuzhiyun 	if (rt5677_dsp->dma_offset + first_chunk_len > runtime->dma_bytes) {
240*4882a593Smuzhiyun 		/* Receiving buffer wrapped around */
241*4882a593Smuzhiyun 		second_chunk_len = first_chunk_len;
242*4882a593Smuzhiyun 		first_chunk_len = runtime->dma_bytes - rt5677_dsp->dma_offset;
243*4882a593Smuzhiyun 		second_chunk_len -= first_chunk_len;
244*4882a593Smuzhiyun 	}
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	/* Copy first chunk */
247*4882a593Smuzhiyun 	ret = rt5677_spi_read(RT5677_MIC_BUF_ADDR + sizeof(u32) + begin,
248*4882a593Smuzhiyun 			runtime->dma_area + rt5677_dsp->dma_offset,
249*4882a593Smuzhiyun 			first_chunk_len);
250*4882a593Smuzhiyun 	if (ret)
251*4882a593Smuzhiyun 		return ret;
252*4882a593Smuzhiyun 	rt5677_dsp->dma_offset += first_chunk_len;
253*4882a593Smuzhiyun 	if (rt5677_dsp->dma_offset == runtime->dma_bytes)
254*4882a593Smuzhiyun 		rt5677_dsp->dma_offset = 0;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	/* Copy second chunk */
257*4882a593Smuzhiyun 	if (second_chunk_len) {
258*4882a593Smuzhiyun 		ret = rt5677_spi_read(RT5677_MIC_BUF_ADDR + sizeof(u32) +
259*4882a593Smuzhiyun 				begin + first_chunk_len, runtime->dma_area,
260*4882a593Smuzhiyun 				second_chunk_len);
261*4882a593Smuzhiyun 		if (!ret)
262*4882a593Smuzhiyun 			rt5677_dsp->dma_offset = second_chunk_len;
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 	return ret;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun /*
268*4882a593Smuzhiyun  * Copy a given amount of audio samples from the DSP mic buffer starting at
269*4882a593Smuzhiyun  * mic_read_offset, to the dma_area of the pcm runtime. The source buffer may
270*4882a593Smuzhiyun  * wrap around. mic_read_offset is updated after successful copy.
271*4882a593Smuzhiyun  * @amount: amount of samples to copy, in bytes.
272*4882a593Smuzhiyun  *
273*4882a593Smuzhiyun  * Return: Zero if successful, or a negative error code on failure.
274*4882a593Smuzhiyun  */
rt5677_spi_copy(struct rt5677_dsp * rt5677_dsp,u32 amount)275*4882a593Smuzhiyun static int rt5677_spi_copy(struct rt5677_dsp *rt5677_dsp, u32 amount)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun 	int ret = 0;
278*4882a593Smuzhiyun 	u32 target;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	if (amount == 0)
281*4882a593Smuzhiyun 		return ret;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	target = rt5677_dsp->mic_read_offset + amount;
284*4882a593Smuzhiyun 	/* Copy the first chunk in DSP's mic buffer */
285*4882a593Smuzhiyun 	ret |= rt5677_spi_copy_block(rt5677_dsp, rt5677_dsp->mic_read_offset,
286*4882a593Smuzhiyun 			min(target, RT5677_MIC_BUF_BYTES));
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	if (target >= RT5677_MIC_BUF_BYTES) {
289*4882a593Smuzhiyun 		/* Wrap around, copy the second chunk */
290*4882a593Smuzhiyun 		target -= RT5677_MIC_BUF_BYTES;
291*4882a593Smuzhiyun 		ret |= rt5677_spi_copy_block(rt5677_dsp, 0, target);
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	if (!ret)
295*4882a593Smuzhiyun 		rt5677_dsp->mic_read_offset = target;
296*4882a593Smuzhiyun 	return ret;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun /*
300*4882a593Smuzhiyun  * A delayed work that streams audio samples from the DSP mic buffer to the
301*4882a593Smuzhiyun  * dma_area of the pcm runtime via SPI.
302*4882a593Smuzhiyun  */
rt5677_spi_copy_work(struct work_struct * work)303*4882a593Smuzhiyun static void rt5677_spi_copy_work(struct work_struct *work)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun 	struct rt5677_dsp *rt5677_dsp =
306*4882a593Smuzhiyun 		container_of(work, struct rt5677_dsp, copy_work.work);
307*4882a593Smuzhiyun 	struct snd_pcm_runtime *runtime;
308*4882a593Smuzhiyun 	u32 mic_write_offset;
309*4882a593Smuzhiyun 	size_t new_bytes, copy_bytes, period_bytes;
310*4882a593Smuzhiyun 	unsigned int delay;
311*4882a593Smuzhiyun 	int ret = 0;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	/* Ensure runtime->dma_area buffer does not go away while copying. */
314*4882a593Smuzhiyun 	mutex_lock(&rt5677_dsp->dma_lock);
315*4882a593Smuzhiyun 	if (!rt5677_dsp->substream) {
316*4882a593Smuzhiyun 		dev_err(rt5677_dsp->dev, "No pcm substream\n");
317*4882a593Smuzhiyun 		goto done;
318*4882a593Smuzhiyun 	}
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	runtime = rt5677_dsp->substream->runtime;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	if (rt5677_spi_mic_write_offset(&mic_write_offset)) {
323*4882a593Smuzhiyun 		dev_err(rt5677_dsp->dev, "No mic_write_offset\n");
324*4882a593Smuzhiyun 		goto done;
325*4882a593Smuzhiyun 	}
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	/* If this is the first time that we've asked for streaming data after
328*4882a593Smuzhiyun 	 * a hotword is fired, we should start reading from the previous 2
329*4882a593Smuzhiyun 	 * seconds of audio from wherever the mic_write_offset is currently.
330*4882a593Smuzhiyun 	 */
331*4882a593Smuzhiyun 	if (rt5677_dsp->new_hotword) {
332*4882a593Smuzhiyun 		rt5677_dsp->new_hotword = false;
333*4882a593Smuzhiyun 		/* See if buffer wraparound happens */
334*4882a593Smuzhiyun 		if (mic_write_offset < RT5677_MIC_BUF_FIRST_READ_SIZE)
335*4882a593Smuzhiyun 			rt5677_dsp->mic_read_offset = RT5677_MIC_BUF_BYTES -
336*4882a593Smuzhiyun 					(RT5677_MIC_BUF_FIRST_READ_SIZE -
337*4882a593Smuzhiyun 					mic_write_offset);
338*4882a593Smuzhiyun 		else
339*4882a593Smuzhiyun 			rt5677_dsp->mic_read_offset = mic_write_offset -
340*4882a593Smuzhiyun 					RT5677_MIC_BUF_FIRST_READ_SIZE;
341*4882a593Smuzhiyun 	}
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	/* Calculate the amount of new samples in bytes */
344*4882a593Smuzhiyun 	if (rt5677_dsp->mic_read_offset <= mic_write_offset)
345*4882a593Smuzhiyun 		new_bytes = mic_write_offset - rt5677_dsp->mic_read_offset;
346*4882a593Smuzhiyun 	else
347*4882a593Smuzhiyun 		new_bytes = RT5677_MIC_BUF_BYTES + mic_write_offset
348*4882a593Smuzhiyun 				- rt5677_dsp->mic_read_offset;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	/* Copy all new samples from DSP mic buffer, one period at a time */
351*4882a593Smuzhiyun 	period_bytes = snd_pcm_lib_period_bytes(rt5677_dsp->substream);
352*4882a593Smuzhiyun 	while (new_bytes) {
353*4882a593Smuzhiyun 		copy_bytes = min(new_bytes, period_bytes
354*4882a593Smuzhiyun 				- rt5677_dsp->avail_bytes);
355*4882a593Smuzhiyun 		ret = rt5677_spi_copy(rt5677_dsp, copy_bytes);
356*4882a593Smuzhiyun 		if (ret) {
357*4882a593Smuzhiyun 			dev_err(rt5677_dsp->dev, "Copy failed %d\n", ret);
358*4882a593Smuzhiyun 			goto done;
359*4882a593Smuzhiyun 		}
360*4882a593Smuzhiyun 		rt5677_dsp->avail_bytes += copy_bytes;
361*4882a593Smuzhiyun 		if (rt5677_dsp->avail_bytes >= period_bytes) {
362*4882a593Smuzhiyun 			snd_pcm_period_elapsed(rt5677_dsp->substream);
363*4882a593Smuzhiyun 			rt5677_dsp->avail_bytes = 0;
364*4882a593Smuzhiyun 		}
365*4882a593Smuzhiyun 		new_bytes -= copy_bytes;
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	delay = bytes_to_frames(runtime, period_bytes) / (runtime->rate / 1000);
369*4882a593Smuzhiyun 	schedule_delayed_work(&rt5677_dsp->copy_work, msecs_to_jiffies(delay));
370*4882a593Smuzhiyun done:
371*4882a593Smuzhiyun 	mutex_unlock(&rt5677_dsp->dma_lock);
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun 
rt5677_spi_pcm_new(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)374*4882a593Smuzhiyun static int rt5677_spi_pcm_new(struct snd_soc_component *component,
375*4882a593Smuzhiyun 			      struct snd_soc_pcm_runtime *rtd)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun 	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_VMALLOC,
378*4882a593Smuzhiyun 				       NULL, 0, 0);
379*4882a593Smuzhiyun 	return 0;
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun 
rt5677_spi_pcm_probe(struct snd_soc_component * component)382*4882a593Smuzhiyun static int rt5677_spi_pcm_probe(struct snd_soc_component *component)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun 	struct rt5677_dsp *rt5677_dsp;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	rt5677_dsp = devm_kzalloc(component->dev, sizeof(*rt5677_dsp),
387*4882a593Smuzhiyun 			GFP_KERNEL);
388*4882a593Smuzhiyun 	if (!rt5677_dsp)
389*4882a593Smuzhiyun 		return -ENOMEM;
390*4882a593Smuzhiyun 	rt5677_dsp->dev = &g_spi->dev;
391*4882a593Smuzhiyun 	mutex_init(&rt5677_dsp->dma_lock);
392*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&rt5677_dsp->copy_work, rt5677_spi_copy_work);
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	snd_soc_component_set_drvdata(component, rt5677_dsp);
395*4882a593Smuzhiyun 	return 0;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun static const struct snd_soc_component_driver rt5677_spi_dai_component = {
399*4882a593Smuzhiyun 	.name		= DRV_NAME,
400*4882a593Smuzhiyun 	.probe		= rt5677_spi_pcm_probe,
401*4882a593Smuzhiyun 	.open		= rt5677_spi_pcm_open,
402*4882a593Smuzhiyun 	.close		= rt5677_spi_pcm_close,
403*4882a593Smuzhiyun 	.hw_params	= rt5677_spi_hw_params,
404*4882a593Smuzhiyun 	.hw_free	= rt5677_spi_hw_free,
405*4882a593Smuzhiyun 	.prepare	= rt5677_spi_prepare,
406*4882a593Smuzhiyun 	.pointer	= rt5677_spi_pcm_pointer,
407*4882a593Smuzhiyun 	.pcm_construct	= rt5677_spi_pcm_new,
408*4882a593Smuzhiyun };
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun /* Select a suitable transfer command for the next transfer to ensure
411*4882a593Smuzhiyun  * the transfer address is always naturally aligned while minimizing
412*4882a593Smuzhiyun  * the total number of transfers required.
413*4882a593Smuzhiyun  *
414*4882a593Smuzhiyun  * 3 transfer commands are available:
415*4882a593Smuzhiyun  * RT5677_SPI_READ/WRITE_16:	Transfer 2 bytes
416*4882a593Smuzhiyun  * RT5677_SPI_READ/WRITE_32:	Transfer 4 bytes
417*4882a593Smuzhiyun  * RT5677_SPI_READ/WRITE_BURST:	Transfer any multiples of 8 bytes
418*4882a593Smuzhiyun  *
419*4882a593Smuzhiyun  * Note:
420*4882a593Smuzhiyun  * 16 Bit writes and reads are restricted to the address range
421*4882a593Smuzhiyun  * 0x18020000 ~ 0x18021000
422*4882a593Smuzhiyun  *
423*4882a593Smuzhiyun  * For example, reading 256 bytes at 0x60030004 uses the following commands:
424*4882a593Smuzhiyun  * 0x60030004 RT5677_SPI_READ_32	4 bytes
425*4882a593Smuzhiyun  * 0x60030008 RT5677_SPI_READ_BURST	240 bytes
426*4882a593Smuzhiyun  * 0x600300F8 RT5677_SPI_READ_BURST	8 bytes
427*4882a593Smuzhiyun  * 0x60030100 RT5677_SPI_READ_32	4 bytes
428*4882a593Smuzhiyun  *
429*4882a593Smuzhiyun  * Input:
430*4882a593Smuzhiyun  * @read: true for read commands; false for write commands
431*4882a593Smuzhiyun  * @align: alignment of the next transfer address
432*4882a593Smuzhiyun  * @remain: number of bytes remaining to transfer
433*4882a593Smuzhiyun  *
434*4882a593Smuzhiyun  * Output:
435*4882a593Smuzhiyun  * @len: number of bytes to transfer with the selected command
436*4882a593Smuzhiyun  * Returns the selected command
437*4882a593Smuzhiyun  */
rt5677_spi_select_cmd(bool read,u32 align,u32 remain,u32 * len)438*4882a593Smuzhiyun static u8 rt5677_spi_select_cmd(bool read, u32 align, u32 remain, u32 *len)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun 	u8 cmd;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	if (align == 4 || remain <= 4) {
443*4882a593Smuzhiyun 		cmd = RT5677_SPI_READ_32;
444*4882a593Smuzhiyun 		*len = 4;
445*4882a593Smuzhiyun 	} else {
446*4882a593Smuzhiyun 		cmd = RT5677_SPI_READ_BURST;
447*4882a593Smuzhiyun 		*len = (((remain - 1) >> 3) + 1) << 3;
448*4882a593Smuzhiyun 		*len = min_t(u32, *len, RT5677_SPI_BURST_LEN);
449*4882a593Smuzhiyun 	}
450*4882a593Smuzhiyun 	return read ? cmd : cmd + 1;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun /* Copy dstlen bytes from src to dst, while reversing byte order for each word.
454*4882a593Smuzhiyun  * If srclen < dstlen, zeros are padded.
455*4882a593Smuzhiyun  */
rt5677_spi_reverse(u8 * dst,u32 dstlen,const u8 * src,u32 srclen)456*4882a593Smuzhiyun static void rt5677_spi_reverse(u8 *dst, u32 dstlen, const u8 *src, u32 srclen)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	u32 w, i, si;
459*4882a593Smuzhiyun 	u32 word_size = min_t(u32, dstlen, 8);
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	for (w = 0; w < dstlen; w += word_size) {
462*4882a593Smuzhiyun 		for (i = 0; i < word_size && i + w < dstlen; i++) {
463*4882a593Smuzhiyun 			si = w + word_size - i - 1;
464*4882a593Smuzhiyun 			dst[w + i] = si < srclen ? src[si] : 0;
465*4882a593Smuzhiyun 		}
466*4882a593Smuzhiyun 	}
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun /* Read DSP address space using SPI. addr and len have to be 4-byte aligned. */
rt5677_spi_read(u32 addr,void * rxbuf,size_t len)470*4882a593Smuzhiyun int rt5677_spi_read(u32 addr, void *rxbuf, size_t len)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun 	u32 offset;
473*4882a593Smuzhiyun 	int status = 0;
474*4882a593Smuzhiyun 	struct spi_transfer t[2];
475*4882a593Smuzhiyun 	struct spi_message m;
476*4882a593Smuzhiyun 	/* +4 bytes is for the DummyPhase following the AddressPhase */
477*4882a593Smuzhiyun 	u8 header[RT5677_SPI_HEADER + 4];
478*4882a593Smuzhiyun 	u8 body[RT5677_SPI_BURST_LEN];
479*4882a593Smuzhiyun 	u8 spi_cmd;
480*4882a593Smuzhiyun 	u8 *cb = rxbuf;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	if (!g_spi)
483*4882a593Smuzhiyun 		return -ENODEV;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	if ((addr & 3) || (len & 3)) {
486*4882a593Smuzhiyun 		dev_err(&g_spi->dev, "Bad read align 0x%x(%zu)\n", addr, len);
487*4882a593Smuzhiyun 		return -EACCES;
488*4882a593Smuzhiyun 	}
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	memset(t, 0, sizeof(t));
491*4882a593Smuzhiyun 	t[0].tx_buf = header;
492*4882a593Smuzhiyun 	t[0].len = sizeof(header);
493*4882a593Smuzhiyun 	t[0].speed_hz = RT5677_SPI_FREQ;
494*4882a593Smuzhiyun 	t[1].rx_buf = body;
495*4882a593Smuzhiyun 	t[1].speed_hz = RT5677_SPI_FREQ;
496*4882a593Smuzhiyun 	spi_message_init_with_transfers(&m, t, ARRAY_SIZE(t));
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	for (offset = 0; offset < len; offset += t[1].len) {
499*4882a593Smuzhiyun 		spi_cmd = rt5677_spi_select_cmd(true, (addr + offset) & 7,
500*4882a593Smuzhiyun 				len - offset, &t[1].len);
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 		/* Construct SPI message header */
503*4882a593Smuzhiyun 		header[0] = spi_cmd;
504*4882a593Smuzhiyun 		header[1] = ((addr + offset) & 0xff000000) >> 24;
505*4882a593Smuzhiyun 		header[2] = ((addr + offset) & 0x00ff0000) >> 16;
506*4882a593Smuzhiyun 		header[3] = ((addr + offset) & 0x0000ff00) >> 8;
507*4882a593Smuzhiyun 		header[4] = ((addr + offset) & 0x000000ff) >> 0;
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 		mutex_lock(&spi_mutex);
510*4882a593Smuzhiyun 		status |= spi_sync(g_spi, &m);
511*4882a593Smuzhiyun 		mutex_unlock(&spi_mutex);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 		/* Copy data back to caller buffer */
515*4882a593Smuzhiyun 		rt5677_spi_reverse(cb + offset, len - offset, body, t[1].len);
516*4882a593Smuzhiyun 	}
517*4882a593Smuzhiyun 	return status;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rt5677_spi_read);
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun /* Write DSP address space using SPI. addr has to be 4-byte aligned.
522*4882a593Smuzhiyun  * If len is not 4-byte aligned, then extra zeros are written at the end
523*4882a593Smuzhiyun  * as padding.
524*4882a593Smuzhiyun  */
rt5677_spi_write(u32 addr,const void * txbuf,size_t len)525*4882a593Smuzhiyun int rt5677_spi_write(u32 addr, const void *txbuf, size_t len)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun 	u32 offset;
528*4882a593Smuzhiyun 	int status = 0;
529*4882a593Smuzhiyun 	struct spi_transfer t;
530*4882a593Smuzhiyun 	struct spi_message m;
531*4882a593Smuzhiyun 	/* +1 byte is for the DummyPhase following the DataPhase */
532*4882a593Smuzhiyun 	u8 buf[RT5677_SPI_HEADER + RT5677_SPI_BURST_LEN + 1];
533*4882a593Smuzhiyun 	u8 *body = buf + RT5677_SPI_HEADER;
534*4882a593Smuzhiyun 	u8 spi_cmd;
535*4882a593Smuzhiyun 	const u8 *cb = txbuf;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	if (!g_spi)
538*4882a593Smuzhiyun 		return -ENODEV;
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	if (addr & 3) {
541*4882a593Smuzhiyun 		dev_err(&g_spi->dev, "Bad write align 0x%x(%zu)\n", addr, len);
542*4882a593Smuzhiyun 		return -EACCES;
543*4882a593Smuzhiyun 	}
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	memset(&t, 0, sizeof(t));
546*4882a593Smuzhiyun 	t.tx_buf = buf;
547*4882a593Smuzhiyun 	t.speed_hz = RT5677_SPI_FREQ;
548*4882a593Smuzhiyun 	spi_message_init_with_transfers(&m, &t, 1);
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	for (offset = 0; offset < len;) {
551*4882a593Smuzhiyun 		spi_cmd = rt5677_spi_select_cmd(false, (addr + offset) & 7,
552*4882a593Smuzhiyun 				len - offset, &t.len);
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 		/* Construct SPI message header */
555*4882a593Smuzhiyun 		buf[0] = spi_cmd;
556*4882a593Smuzhiyun 		buf[1] = ((addr + offset) & 0xff000000) >> 24;
557*4882a593Smuzhiyun 		buf[2] = ((addr + offset) & 0x00ff0000) >> 16;
558*4882a593Smuzhiyun 		buf[3] = ((addr + offset) & 0x0000ff00) >> 8;
559*4882a593Smuzhiyun 		buf[4] = ((addr + offset) & 0x000000ff) >> 0;
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 		/* Fetch data from caller buffer */
562*4882a593Smuzhiyun 		rt5677_spi_reverse(body, t.len, cb + offset, len - offset);
563*4882a593Smuzhiyun 		offset += t.len;
564*4882a593Smuzhiyun 		t.len += RT5677_SPI_HEADER + 1;
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 		mutex_lock(&spi_mutex);
567*4882a593Smuzhiyun 		status |= spi_sync(g_spi, &m);
568*4882a593Smuzhiyun 		mutex_unlock(&spi_mutex);
569*4882a593Smuzhiyun 	}
570*4882a593Smuzhiyun 	return status;
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rt5677_spi_write);
573*4882a593Smuzhiyun 
rt5677_spi_write_firmware(u32 addr,const struct firmware * fw)574*4882a593Smuzhiyun int rt5677_spi_write_firmware(u32 addr, const struct firmware *fw)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun 	return rt5677_spi_write(addr, fw->data, fw->size);
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rt5677_spi_write_firmware);
579*4882a593Smuzhiyun 
rt5677_spi_hotword_detected(void)580*4882a593Smuzhiyun void rt5677_spi_hotword_detected(void)
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun 	struct rt5677_dsp *rt5677_dsp;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	if (!g_spi)
585*4882a593Smuzhiyun 		return;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	rt5677_dsp = dev_get_drvdata(&g_spi->dev);
588*4882a593Smuzhiyun 	if (!rt5677_dsp) {
589*4882a593Smuzhiyun 		dev_err(&g_spi->dev, "Can't get rt5677_dsp\n");
590*4882a593Smuzhiyun 		return;
591*4882a593Smuzhiyun 	}
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	mutex_lock(&rt5677_dsp->dma_lock);
594*4882a593Smuzhiyun 	dev_info(rt5677_dsp->dev, "Hotword detected\n");
595*4882a593Smuzhiyun 	rt5677_dsp->new_hotword = true;
596*4882a593Smuzhiyun 	mutex_unlock(&rt5677_dsp->dma_lock);
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	schedule_delayed_work(&rt5677_dsp->copy_work, 0);
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rt5677_spi_hotword_detected);
601*4882a593Smuzhiyun 
rt5677_spi_probe(struct spi_device * spi)602*4882a593Smuzhiyun static int rt5677_spi_probe(struct spi_device *spi)
603*4882a593Smuzhiyun {
604*4882a593Smuzhiyun 	int ret;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	g_spi = spi;
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	ret = devm_snd_soc_register_component(&spi->dev,
609*4882a593Smuzhiyun 					      &rt5677_spi_dai_component,
610*4882a593Smuzhiyun 					      &rt5677_spi_dai, 1);
611*4882a593Smuzhiyun 	if (ret < 0)
612*4882a593Smuzhiyun 		dev_err(&spi->dev, "Failed to register component.\n");
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 	return ret;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun #ifdef CONFIG_ACPI
618*4882a593Smuzhiyun static const struct acpi_device_id rt5677_spi_acpi_id[] = {
619*4882a593Smuzhiyun 	{ "RT5677AA", 0 },
620*4882a593Smuzhiyun 	{ }
621*4882a593Smuzhiyun };
622*4882a593Smuzhiyun MODULE_DEVICE_TABLE(acpi, rt5677_spi_acpi_id);
623*4882a593Smuzhiyun #endif
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun static struct spi_driver rt5677_spi_driver = {
626*4882a593Smuzhiyun 	.driver = {
627*4882a593Smuzhiyun 		.name = DRV_NAME,
628*4882a593Smuzhiyun 		.acpi_match_table = ACPI_PTR(rt5677_spi_acpi_id),
629*4882a593Smuzhiyun 	},
630*4882a593Smuzhiyun 	.probe = rt5677_spi_probe,
631*4882a593Smuzhiyun };
632*4882a593Smuzhiyun module_spi_driver(rt5677_spi_driver);
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC RT5677 SPI driver");
635*4882a593Smuzhiyun MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
636*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
637