xref: /linux/sound/soc/sophgo/cv1800b-tdm.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/clk.h>
4 #include <linux/delay.h>
5 #include <linux/io.h>
6 #include <linux/module.h>
7 #include <linux/of.h>
8 #include <linux/platform_device.h>
9 #include <sound/dmaengine_pcm.h>
10 #include <sound/pcm_params.h>
11 #include <sound/soc.h>
12 #include <linux/string.h>
13 #include <linux/dev_printk.h>
14 
15 #include <linux/bitfield.h>
16 #include <linux/bits.h>
17 #include <linux/limits.h>
18 #include <linux/overflow.h>
19 
20 #define TX_FIFO_SIZE (1024)
21 #define RX_FIFO_SIZE (1024)
22 #define TX_MAX_BURST (8)
23 #define RX_MAX_BURST (8)
24 
25 #define CV1800B_DEF_FREQ          24576000
26 #define CV1800B_DEF_MCLK_FS_RATIO 256
27 
28 /* tdm registers */
29 #define CV1800B_BLK_MODE_SETTING  0x000
30 #define CV1800B_FRAME_SETTING     0x004
31 #define CV1800B_SLOT_SETTING1     0x008
32 #define CV1800B_SLOT_SETTING2     0x00C
33 #define CV1800B_DATA_FORMAT       0x010
34 #define CV1800B_BLK_CFG           0x014
35 #define CV1800B_I2S_ENABLE        0x018
36 #define CV1800B_I2S_RESET         0x01C
37 #define CV1800B_I2S_INT_EN        0x020
38 #define CV1800B_I2S_INT           0x024
39 #define CV1800B_FIFO_THRESHOLD    0x028
40 #define CV1800B_LRCK_MASTER       0x02C /* special clock only mode */
41 #define CV1800B_FIFO_RESET        0x030
42 #define CV1800B_RX_STATUS         0x040
43 #define CV1800B_TX_STATUS         0x048
44 #define CV1800B_CLK_CTRL0         0x060
45 #define CV1800B_CLK_CTRL1         0x064
46 #define CV1800B_PCM_SYNTH         0x068
47 #define CV1800B_RX_RD_PORT        0x080
48 #define CV1800B_TX_WR_PORT        0x0C0
49 
50 /* CV1800B_BLK_MODE_SETTING (0x000) */
51 #define BLK_TX_MODE_MASK                   GENMASK(0, 0)
52 #define BLK_MASTER_MODE_MASK               GENMASK(1, 1)
53 #define BLK_DMA_MODE_MASK                  GENMASK(7, 7)
54 
55 /* CV1800B_CLK_CTRL1 (0x064) */
56 #define CLK_MCLK_DIV_MASK                  GENMASK(15, 0)
57 #define CLK_BCLK_DIV_MASK                  GENMASK(31, 16)
58 
59 /* CV1800B_CLK_CTRL0 (0x060) */
60 #define CLK_AUD_CLK_SEL_MASK               GENMASK(0, 0)
61 #define CLK_BCLK_OUT_CLK_FORCE_EN_MASK     GENMASK(6, 6)
62 #define CLK_MCLK_OUT_EN_MASK               GENMASK(7, 7)
63 #define CLK_AUD_EN_MASK                    GENMASK(8, 8)
64 
65 /* CV1800B_I2S_RESET (0x01C) */
66 #define RST_I2S_RESET_RX_MASK              GENMASK(0, 0)
67 #define RST_I2S_RESET_TX_MASK              GENMASK(1, 1)
68 
69 /* CV1800B_FIFO_RESET (0x030) */
70 #define FIFO_RX_RESET_MASK                 GENMASK(0, 0)
71 #define FIFO_TX_RESET_MASK                 GENMASK(16, 16)
72 
73 /* CV1800B_I2S_ENABLE (0x018) */
74 #define I2S_ENABLE_MASK                    GENMASK(0, 0)
75 
76 /* CV1800B_BLK_CFG (0x014) */
77 #define BLK_AUTO_DISABLE_WITH_CH_EN_MASK   GENMASK(4, 4)
78 #define BLK_RX_BLK_CLK_FORCE_EN_MASK       GENMASK(8, 8)
79 #define BLK_RX_FIFO_DMA_CLK_FORCE_EN_MASK  GENMASK(9, 9)
80 #define BLK_TX_BLK_CLK_FORCE_EN_MASK       GENMASK(16, 16)
81 #define BLK_TX_FIFO_DMA_CLK_FORCE_EN_MASK  GENMASK(17, 17)
82 
83 /* CV1800B_FRAME_SETTING (0x004) */
84 #define FRAME_LENGTH_MASK                  GENMASK(8, 0)
85 #define FS_ACTIVE_LENGTH_MASK              GENMASK(23, 16)
86 
87 /* CV1800B_I2S_INT_EN (0x020) */
88 #define INT_I2S_INT_EN_MASK                GENMASK(8, 8)
89 
90 /* CV1800B_SLOT_SETTING2 (0x00C) */
91 #define SLOT_EN_MASK                       GENMASK(15, 0)
92 
93 /* CV1800B_LRCK_MASTER (0x02C) */
94 #define LRCK_MASTER_ENABLE_MASK            GENMASK(0, 0)
95 
96 /* CV1800B_DATA_FORMAT (0x010) */
97 #define DF_WORD_LENGTH_MASK	           GENMASK(2, 1)
98 #define DF_TX_SOURCE_LEFT_ALIGN_MASK       GENMASK(6, 6)
99 
100 /* CV1800B_FIFO_THRESHOLD (0x028) */
101 #define FIFO_RX_THRESHOLD_MASK	           GENMASK(4, 0)
102 #define FIFO_TX_THRESHOLD_MASK	           GENMASK(20, 16)
103 #define FIFO_TX_HIGH_THRESHOLD_MASK        GENMASK(28, 24)
104 
105 /* CV1800B_SLOT_SETTING1 (0x008) */
106 #define SLOT_NUM_MASK                      GENMASK(3, 0)
107 #define SLOT_SIZE_MASK                     GENMASK(13, 8)
108 #define DATA_SIZE_MASK                     GENMASK(20, 16)
109 #define FB_OFFSET_MASK                     GENMASK(28, 24)
110 
111 enum cv1800b_tdm_word_length {
112 	CV1800B_WORD_LENGTH_8_BIT = 0,
113 	CV1800B_WORD_LENGTH_16_BIT = 1,
114 	CV1800B_WORD_LENGTH_32_BIT = 2,
115 };
116 
117 struct cv1800b_i2s {
118 	void __iomem *base;
119 	struct clk *clk;
120 	struct clk *sysclk;
121 	struct device *dev;
122 	struct snd_dmaengine_dai_dma_data playback_dma;
123 	struct snd_dmaengine_dai_dma_data capture_dma;
124 	u32 mclk_rate;
125 	bool bclk_ratio_fixed;
126 	u32 bclk_ratio;
127 
128 };
129 
130 static void cv1800b_setup_dma_struct(struct cv1800b_i2s *i2s,
131 				     phys_addr_t phys_base)
132 {
133 	i2s->playback_dma.addr = phys_base + CV1800B_TX_WR_PORT;
134 	i2s->playback_dma.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
135 	i2s->playback_dma.fifo_size = TX_FIFO_SIZE;
136 	i2s->playback_dma.maxburst = TX_MAX_BURST;
137 
138 	i2s->capture_dma.addr = phys_base + CV1800B_RX_RD_PORT;
139 	i2s->capture_dma.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
140 	i2s->capture_dma.fifo_size = RX_FIFO_SIZE;
141 	i2s->capture_dma.maxburst = RX_MAX_BURST;
142 }
143 
144 static const struct snd_dmaengine_pcm_config cv1800b_i2s_pcm_config = {
145 	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
146 };
147 
148 static void cv1800b_reset_fifo(struct cv1800b_i2s *i2s)
149 {
150 	u32 val;
151 
152 	val = readl(i2s->base + CV1800B_FIFO_RESET);
153 	val = u32_replace_bits(val, 1, FIFO_RX_RESET_MASK);
154 	val = u32_replace_bits(val, 1, FIFO_TX_RESET_MASK);
155 	writel(val, i2s->base + CV1800B_FIFO_RESET);
156 
157 	usleep_range(10, 20);
158 
159 	val = readl(i2s->base + CV1800B_FIFO_RESET);
160 	val = u32_replace_bits(val, 0, FIFO_RX_RESET_MASK);
161 	val = u32_replace_bits(val, 0, FIFO_TX_RESET_MASK);
162 	writel(val, i2s->base + CV1800B_FIFO_RESET);
163 }
164 
165 static void cv1800b_reset_i2s(struct cv1800b_i2s *i2s)
166 {
167 	u32 val;
168 
169 	val = readl(i2s->base + CV1800B_I2S_RESET);
170 	val = u32_replace_bits(val, 1, RST_I2S_RESET_RX_MASK);
171 	val = u32_replace_bits(val, 1, RST_I2S_RESET_TX_MASK);
172 	writel(val, i2s->base + CV1800B_I2S_RESET);
173 
174 	usleep_range(10, 20);
175 
176 	val = readl(i2s->base + CV1800B_I2S_RESET);
177 	val = u32_replace_bits(val, 0, RST_I2S_RESET_RX_MASK);
178 	val = u32_replace_bits(val, 0, RST_I2S_RESET_TX_MASK);
179 	writel(val, i2s->base + CV1800B_I2S_RESET);
180 }
181 
182 static void cv1800b_set_mclk_div(struct cv1800b_i2s *i2s, u32 mclk_div)
183 {
184 	u32 val;
185 
186 	val = readl(i2s->base + CV1800B_CLK_CTRL1);
187 	val = u32_replace_bits(val, mclk_div, CLK_MCLK_DIV_MASK);
188 	writel(val, i2s->base + CV1800B_CLK_CTRL1);
189 	dev_dbg(i2s->dev, "mclk_div is set to %u\n", mclk_div);
190 }
191 
192 static void cv1800b_set_tx_mode(struct cv1800b_i2s *i2s, bool is_tx)
193 {
194 	u32 val;
195 
196 	val = readl(i2s->base + CV1800B_BLK_MODE_SETTING);
197 	val = u32_replace_bits(val, is_tx, BLK_TX_MODE_MASK);
198 	writel(val, i2s->base + CV1800B_BLK_MODE_SETTING);
199 	dev_dbg(i2s->dev, "tx_mode is set to %u\n", is_tx);
200 }
201 
202 static int cv1800b_set_bclk_div(struct cv1800b_i2s *i2s, u32 bclk_div)
203 {
204 	u32 val;
205 
206 	if (bclk_div == 0 || bclk_div > 0xFFFF)
207 		return -EINVAL;
208 
209 	val = readl(i2s->base + CV1800B_CLK_CTRL1);
210 	val = u32_replace_bits(val, bclk_div, CLK_BCLK_DIV_MASK);
211 	writel(val, i2s->base + CV1800B_CLK_CTRL1);
212 	dev_dbg(i2s->dev, "bclk_div is set to %u\n", bclk_div);
213 	return 0;
214 }
215 
216 /* set memory width of audio data , reg word_length */
217 static int cv1800b_set_word_length(struct cv1800b_i2s *i2s,
218 				   unsigned int physical_width)
219 {
220 	u8 word_length_val;
221 	u32 val;
222 
223 	switch (physical_width) {
224 	case 8:
225 		word_length_val = CV1800B_WORD_LENGTH_8_BIT;
226 		break;
227 	case 16:
228 		word_length_val = CV1800B_WORD_LENGTH_16_BIT;
229 		break;
230 	case 32:
231 		word_length_val = CV1800B_WORD_LENGTH_32_BIT;
232 		break;
233 	default:
234 		dev_dbg(i2s->dev, "can't set word_length field\n");
235 		return -EINVAL;
236 	}
237 
238 	val = readl(i2s->base + CV1800B_DATA_FORMAT);
239 	val = u32_replace_bits(val, word_length_val, DF_WORD_LENGTH_MASK);
240 	writel(val, i2s->base + CV1800B_DATA_FORMAT);
241 	return 0;
242 }
243 
244 static void cv1800b_enable_clocks(struct cv1800b_i2s *i2s, bool enabled)
245 {
246 	u32 val;
247 
248 	val = readl(i2s->base + CV1800B_CLK_CTRL0);
249 	val = u32_replace_bits(val, enabled, CLK_AUD_EN_MASK);
250 	writel(val, i2s->base + CV1800B_CLK_CTRL0);
251 }
252 
253 static int cv1800b_set_slot_settings(struct cv1800b_i2s *i2s, u32 slots,
254 				     u32 physical_width, u32 data_size)
255 {
256 	u32 slot_num;
257 	u32 slot_size;
258 	u32 frame_length;
259 	u32 frame_active_length;
260 	u32 val;
261 
262 	if (!slots || !physical_width || !data_size) {
263 		dev_err(i2s->dev, "frame or slot settings are not valid\n");
264 		return -EINVAL;
265 	}
266 	if (slots > 16 || physical_width > 64 || data_size > 32) {
267 		dev_err(i2s->dev, "frame or slot settings are not valid\n");
268 		return -EINVAL;
269 	}
270 
271 	slot_num = slots - 1;
272 	slot_size = physical_width - 1;
273 	frame_length = (physical_width * slots) - 1;
274 	frame_active_length = physical_width - 1;
275 
276 	if (frame_length > 511 || frame_active_length > 255) {
277 		dev_err(i2s->dev, "frame or slot settings are not valid\n");
278 		return -EINVAL;
279 	}
280 
281 	val = readl(i2s->base + CV1800B_SLOT_SETTING1);
282 	val = u32_replace_bits(val, slot_size, SLOT_SIZE_MASK);
283 	val = u32_replace_bits(val, data_size - 1, DATA_SIZE_MASK);
284 	val = u32_replace_bits(val, slot_num, SLOT_NUM_MASK);
285 	writel(val, i2s->base + CV1800B_SLOT_SETTING1);
286 
287 	val = readl(i2s->base + CV1800B_FRAME_SETTING);
288 	val = u32_replace_bits(val, frame_length, FRAME_LENGTH_MASK);
289 	val = u32_replace_bits(val, frame_active_length, FS_ACTIVE_LENGTH_MASK);
290 	writel(val, i2s->base + CV1800B_FRAME_SETTING);
291 
292 	dev_dbg(i2s->dev, "slot settings num: %u width: %u\n", slots, physical_width);
293 	return 0;
294 }
295 
296 /*
297  * calculate mclk_div.
298  * if requested value is bigger than optimal
299  * leave mclk_div as 1. cff clock is capable
300  * to handle it
301  */
302 static int cv1800b_calc_mclk_div(unsigned int target_mclk, u32 *mclk_div)
303 {
304 	*mclk_div = 1;
305 
306 	if (target_mclk == 0)
307 		return -EINVAL;
308 
309 	/* optimal parent frequency is close to CV1800B_DEF_FREQ */
310 	if (target_mclk < CV1800B_DEF_FREQ) {
311 		*mclk_div = DIV_ROUND_CLOSEST(CV1800B_DEF_FREQ, target_mclk);
312 		if (!*mclk_div || *mclk_div > 0xFFFF)
313 			return -EINVAL;
314 	}
315 	return 0;
316 }
317 
318 /*
319  * set CCF clock and divider for this clock
320  * mclk_clock = ccf_clock / mclk_div
321  */
322 static int cv1800b_i2s_set_rate_for_mclk(struct cv1800b_i2s *i2s,
323 					 unsigned int target_mclk)
324 {
325 	u32 mclk_div = 1;
326 	u64 tmp;
327 	int ret;
328 	unsigned long clk_rate;
329 	unsigned long actual;
330 
331 	ret = cv1800b_calc_mclk_div(target_mclk, &mclk_div);
332 	if (ret) {
333 		dev_dbg(i2s->dev, "can't calc mclk_div for freq %u\n",
334 			target_mclk);
335 		return ret;
336 	}
337 
338 	tmp = (u64)target_mclk * mclk_div;
339 	if (tmp > ULONG_MAX) {
340 		dev_err(i2s->dev, "clk_rate overflow: freq=%u div=%u\n",
341 			target_mclk, mclk_div);
342 		return -ERANGE;
343 	}
344 
345 	clk_rate = (unsigned long)tmp;
346 
347 	cv1800b_enable_clocks(i2s, false);
348 
349 	ret = clk_set_rate(i2s->sysclk, clk_rate);
350 	if (ret)
351 		return ret;
352 
353 	actual = clk_get_rate(i2s->sysclk);
354 	if (clk_rate != actual) {
355 		dev_err_ratelimited(i2s->dev,
356 				    "clk_set_rate failed %lu, actual is %lu\n",
357 				    clk_rate, actual);
358 	}
359 
360 	cv1800b_set_mclk_div(i2s, mclk_div);
361 	cv1800b_enable_clocks(i2s, true);
362 
363 	return 0;
364 }
365 
366 static int cv1800b_i2s_hw_params(struct snd_pcm_substream *substream,
367 				 struct snd_pcm_hw_params *params,
368 				 struct snd_soc_dai *dai)
369 {
370 	struct cv1800b_i2s *i2s = snd_soc_dai_get_drvdata(dai);
371 	unsigned int rate = params_rate(params);
372 	unsigned int channels = params_channels(params);
373 	unsigned int physical_width = params_physical_width(params);
374 	int data_width = params_width(params);
375 	bool tx_mode = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 1 : 0;
376 	int ret;
377 	u32 bclk_div;
378 	u32 bclk_ratio;
379 	u32 mclk_rate;
380 	u32 tmp;
381 
382 	if (data_width < 0)
383 		return data_width;
384 
385 	if (!channels || !rate || !physical_width)
386 		return -EINVAL;
387 
388 	ret = cv1800b_set_slot_settings(i2s, channels, physical_width, data_width);
389 	if (ret)
390 		return ret;
391 
392 	if (i2s->mclk_rate) {
393 		mclk_rate = i2s->mclk_rate;
394 	} else {
395 		dev_dbg(i2s->dev, "mclk is not set by machine driver\n");
396 		ret = cv1800b_i2s_set_rate_for_mclk(i2s,
397 						    rate * CV1800B_DEF_MCLK_FS_RATIO);
398 		if (ret)
399 			return ret;
400 		mclk_rate = rate * CV1800B_DEF_MCLK_FS_RATIO;
401 	}
402 
403 	bclk_ratio = (i2s->bclk_ratio_fixed) ? i2s->bclk_ratio :
404 					       (physical_width * channels);
405 
406 	if (check_mul_overflow(rate, bclk_ratio, &tmp))
407 		return -EOVERFLOW;
408 
409 	if (!tmp)
410 		return -EINVAL;
411 	if (mclk_rate % tmp)
412 		dev_warn(i2s->dev, "mclk rate is not aligned to bclk or rate\n");
413 
414 	bclk_div = DIV_ROUND_CLOSEST(mclk_rate, tmp);
415 
416 	ret = cv1800b_set_bclk_div(i2s, bclk_div);
417 	if (ret)
418 		return ret;
419 
420 	ret = cv1800b_set_word_length(i2s, physical_width);
421 	if (ret)
422 		return ret;
423 
424 	cv1800b_set_tx_mode(i2s, tx_mode);
425 
426 	cv1800b_reset_fifo(i2s);
427 	cv1800b_reset_i2s(i2s);
428 	return 0;
429 }
430 
431 static int cv1800b_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
432 			       struct snd_soc_dai *dai)
433 {
434 	struct cv1800b_i2s *i2s = snd_soc_dai_get_drvdata(dai);
435 	u32 val;
436 
437 	val = readl(i2s->base + CV1800B_I2S_ENABLE);
438 
439 	switch (cmd) {
440 	case SNDRV_PCM_TRIGGER_START:
441 	case SNDRV_PCM_TRIGGER_RESUME:
442 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
443 		val = u32_replace_bits(val, 1, I2S_ENABLE_MASK);
444 		break;
445 
446 	case SNDRV_PCM_TRIGGER_STOP:
447 	case SNDRV_PCM_TRIGGER_SUSPEND:
448 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
449 		val = u32_replace_bits(val, 0, I2S_ENABLE_MASK);
450 		break;
451 	default:
452 		return -EINVAL;
453 	}
454 	writel(val, i2s->base + CV1800B_I2S_ENABLE);
455 	return 0;
456 }
457 
458 static int cv1800b_i2s_startup(struct snd_pcm_substream *substream,
459 			       struct snd_soc_dai *dai)
460 {
461 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
462 	struct cv1800b_i2s *i2s = snd_soc_dai_get_drvdata(dai);
463 	struct snd_soc_dai_link *dai_link = rtd->dai_link;
464 
465 	dev_dbg(i2s->dev, "%s: dai=%s substream=%d\n", __func__, dai->name,
466 		substream->stream);
467 	/**
468 	 * Ensure DMA is stopped before DAI
469 	 * shutdown (prevents DW AXI DMAC stop/busy on next open).
470 	 */
471 	dai_link->trigger_stop = SND_SOC_TRIGGER_ORDER_LDC;
472 	return 0;
473 }
474 
475 static int cv1800b_i2s_dai_probe(struct snd_soc_dai *dai)
476 {
477 	struct cv1800b_i2s *i2s = snd_soc_dai_get_drvdata(dai);
478 
479 	if (!i2s) {
480 		dev_err(dai->dev, "no drvdata in DAI probe\n");
481 		return -ENODEV;
482 	}
483 
484 	snd_soc_dai_init_dma_data(dai, &i2s->playback_dma, &i2s->capture_dma);
485 	return 0;
486 }
487 
488 static int cv1800b_i2s_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
489 {
490 	struct cv1800b_i2s *i2s = snd_soc_dai_get_drvdata(dai);
491 	u32 val;
492 	u32 master;
493 
494 	/* only i2s format is supported */
495 	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S)
496 		return -EINVAL;
497 
498 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
499 	case SND_SOC_DAIFMT_CBP_CFP:
500 		dev_dbg(i2s->dev, "set to master mode\n");
501 		master = 1;
502 		break;
503 
504 	case SND_SOC_DAIFMT_CBC_CFC:
505 		dev_dbg(i2s->dev, "set to slave mode\n");
506 		master = 0;
507 		break;
508 	default:
509 		return -EINVAL;
510 	}
511 
512 	val = readl(i2s->base + CV1800B_BLK_MODE_SETTING);
513 	val = u32_replace_bits(val, master, BLK_MASTER_MODE_MASK);
514 	writel(val, i2s->base + CV1800B_BLK_MODE_SETTING);
515 	return 0;
516 }
517 
518 static int cv1800b_i2s_dai_set_bclk_ratio(struct snd_soc_dai *dai,
519 					  unsigned int ratio)
520 {
521 	struct cv1800b_i2s *i2s = snd_soc_dai_get_drvdata(dai);
522 
523 	if (ratio == 0)
524 		return -EINVAL;
525 	i2s->bclk_ratio = ratio;
526 	i2s->bclk_ratio_fixed = true;
527 	return 0;
528 }
529 
530 static int cv1800b_i2s_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
531 				      unsigned int freq, int dir)
532 {
533 	struct cv1800b_i2s *i2s = snd_soc_dai_get_drvdata(dai);
534 	int ret;
535 	u32 val;
536 	bool output_enable = (dir == SND_SOC_CLOCK_OUT) ? true : false;
537 
538 	dev_dbg(i2s->dev, "%s called with %u\n", __func__, freq);
539 	ret = cv1800b_i2s_set_rate_for_mclk(i2s, freq);
540 	if (ret)
541 		return ret;
542 
543 	val = readl(i2s->base + CV1800B_CLK_CTRL0);
544 	val = u32_replace_bits(val, output_enable, CLK_MCLK_OUT_EN_MASK);
545 	writel(val, i2s->base + CV1800B_CLK_CTRL0);
546 
547 	i2s->mclk_rate = freq;
548 	return 0;
549 }
550 
551 static const struct snd_soc_dai_ops cv1800b_i2s_dai_ops = {
552 	.probe = cv1800b_i2s_dai_probe,
553 	.startup = cv1800b_i2s_startup,
554 	.hw_params = cv1800b_i2s_hw_params,
555 	.trigger = cv1800b_i2s_trigger,
556 	.set_fmt = cv1800b_i2s_dai_set_fmt,
557 	.set_bclk_ratio = cv1800b_i2s_dai_set_bclk_ratio,
558 	.set_sysclk = cv1800b_i2s_dai_set_sysclk,
559 };
560 
561 static const struct snd_soc_dai_driver cv1800b_i2s_dai_template = {
562 	.name = "cv1800b-i2s",
563 	.playback = {
564 		.stream_name = "Playback",
565 		.channels_min = 1,
566 		.channels_max = 2,
567 		.rates = SNDRV_PCM_RATE_8000_192000,
568 		.formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
569 	},
570 	.capture = {
571 		.stream_name = "Capture",
572 		.channels_min = 1,
573 		.channels_max = 2,
574 		.rates = SNDRV_PCM_RATE_8000_192000,
575 		.formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
576 	},
577 	.ops = &cv1800b_i2s_dai_ops,
578 };
579 
580 static const struct snd_soc_component_driver cv1800b_i2s_component = {
581 	.name = "cv1800b-i2s",
582 };
583 
584 static void cv1800b_i2s_hw_disable(struct cv1800b_i2s *i2s)
585 {
586 	u32 val;
587 
588 	val = readl(i2s->base + CV1800B_I2S_ENABLE);
589 	val = u32_replace_bits(val, 0, I2S_ENABLE_MASK);
590 	writel(val, i2s->base + CV1800B_I2S_ENABLE);
591 
592 	val = readl(i2s->base + CV1800B_CLK_CTRL0);
593 	val = u32_replace_bits(val, 0, CLK_AUD_EN_MASK);
594 	val = u32_replace_bits(val, 0, CLK_MCLK_OUT_EN_MASK);
595 	writel(val, i2s->base + CV1800B_CLK_CTRL0);
596 
597 	val = readl(i2s->base + CV1800B_I2S_RESET);
598 	val = u32_replace_bits(val, 1, RST_I2S_RESET_RX_MASK);
599 	val = u32_replace_bits(val, 1, RST_I2S_RESET_TX_MASK);
600 	writel(val, i2s->base + CV1800B_I2S_RESET);
601 
602 	val = readl(i2s->base + CV1800B_FIFO_RESET);
603 	val = u32_replace_bits(val, 1, FIFO_RX_RESET_MASK);
604 	val = u32_replace_bits(val, 1, FIFO_TX_RESET_MASK);
605 	writel(val, i2s->base + CV1800B_FIFO_RESET);
606 }
607 
608 static void cv1800b_i2s_setup_tdm(struct cv1800b_i2s *i2s)
609 {
610 	u32 val;
611 
612 	val = readl(i2s->base + CV1800B_BLK_MODE_SETTING);
613 	val = u32_replace_bits(val, 1, BLK_DMA_MODE_MASK);
614 	writel(val, i2s->base + CV1800B_BLK_MODE_SETTING);
615 
616 	val = readl(i2s->base + CV1800B_CLK_CTRL0);
617 	val = u32_replace_bits(val, 0, CLK_AUD_CLK_SEL_MASK);
618 	val = u32_replace_bits(val, 0, CLK_MCLK_OUT_EN_MASK);
619 	val = u32_replace_bits(val, 0, CLK_AUD_EN_MASK);
620 	writel(val, i2s->base + CV1800B_CLK_CTRL0);
621 
622 	val = readl(i2s->base + CV1800B_FIFO_THRESHOLD);
623 	val = u32_replace_bits(val, 4, FIFO_RX_THRESHOLD_MASK);
624 	val = u32_replace_bits(val, 4, FIFO_TX_THRESHOLD_MASK);
625 	val = u32_replace_bits(val, 4, FIFO_TX_HIGH_THRESHOLD_MASK);
626 	writel(val, i2s->base + CV1800B_FIFO_THRESHOLD);
627 
628 	val = readl(i2s->base + CV1800B_I2S_ENABLE);
629 	val = u32_replace_bits(val, 0, I2S_ENABLE_MASK);
630 	writel(val, i2s->base + CV1800B_I2S_ENABLE);
631 }
632 
633 static int cv1800b_i2s_probe(struct platform_device *pdev)
634 {
635 	struct device *dev = &pdev->dev;
636 	struct cv1800b_i2s *i2s;
637 	struct resource *res;
638 	void __iomem *regs;
639 	struct snd_soc_dai_driver *dai;
640 	int ret;
641 
642 	i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL);
643 	if (!i2s)
644 		return -ENOMEM;
645 
646 	regs = devm_platform_ioremap_resource(pdev, 0);
647 	if (IS_ERR(regs))
648 		return PTR_ERR(regs);
649 	i2s->dev = &pdev->dev;
650 	i2s->base = regs;
651 
652 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
653 	if (!res)
654 		return -ENODEV;
655 	cv1800b_setup_dma_struct(i2s, res->start);
656 
657 	i2s->clk = devm_clk_get_enabled(dev, "i2s");
658 	if (IS_ERR(i2s->clk))
659 		return dev_err_probe(dev, PTR_ERR(i2s->clk),
660 				     "failed to get+enable i2s\n");
661 	i2s->sysclk = devm_clk_get_enabled(dev, "mclk");
662 	if (IS_ERR(i2s->sysclk))
663 		return dev_err_probe(dev, PTR_ERR(i2s->sysclk),
664 				     "failed to get+enable mclk\n");
665 
666 	platform_set_drvdata(pdev, i2s);
667 	cv1800b_i2s_setup_tdm(i2s);
668 
669 	dai = devm_kmemdup(dev, &cv1800b_i2s_dai_template, sizeof(*dai),
670 			   GFP_KERNEL);
671 	if (!dai)
672 		return -ENOMEM;
673 
674 	ret = devm_snd_soc_register_component(dev, &cv1800b_i2s_component, dai,
675 					      1);
676 	if (ret)
677 		return ret;
678 
679 	ret = devm_snd_dmaengine_pcm_register(dev, &cv1800b_i2s_pcm_config, 0);
680 	if (ret) {
681 		dev_err(dev, "dmaengine_pcm_register failed: %d\n", ret);
682 		return ret;
683 	}
684 
685 	return 0;
686 }
687 
688 static void cv1800b_i2s_remove(struct platform_device *pdev)
689 {
690 	struct cv1800b_i2s *i2s = platform_get_drvdata(pdev);
691 
692 	if (!i2s)
693 		return;
694 	cv1800b_i2s_hw_disable(i2s);
695 }
696 
697 static const struct of_device_id cv1800b_i2s_of_match[] = {
698 	{ .compatible = "sophgo,cv1800b-i2s" },
699 	{ /* sentinel */ }
700 };
701 
702 MODULE_DEVICE_TABLE(of, cv1800b_i2s_of_match);
703 
704 static struct platform_driver cv1800b_i2s_driver = {
705 	.probe = cv1800b_i2s_probe,
706 	.remove = cv1800b_i2s_remove,
707 	.driver = {
708 		.name = "cv1800b-i2s",
709 		.of_match_table = cv1800b_i2s_of_match,
710 	},
711 };
712 module_platform_driver(cv1800b_i2s_driver);
713 
714 MODULE_DESCRIPTION("Sophgo cv1800b I2S/TDM driver");
715 MODULE_AUTHOR("Anton D. Stavinsky <stavinsky@gmail.com>");
716 MODULE_LICENSE("GPL");
717