xref: /linux/sound/soc/hisilicon/hi6210-i2s.c (revision 3d0fe49454652117522f60bfbefb978ba0e5300b)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * linux/sound/soc/m8m/hi6210_i2s.c - I2S IP driver
4  *
5  * Copyright (C) 2015 Linaro, Ltd
6  * Author: Andy Green <andy.green@linaro.org>
7  *
8  * This driver only deals with S2 interface (BT)
9  */
10 
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/device.h>
14 #include <linux/delay.h>
15 #include <linux/clk.h>
16 #include <linux/jiffies.h>
17 #include <linux/io.h>
18 #include <linux/gpio.h>
19 #include <sound/core.h>
20 #include <sound/pcm.h>
21 #include <sound/pcm_params.h>
22 #include <sound/dmaengine_pcm.h>
23 #include <sound/initval.h>
24 #include <sound/soc.h>
25 #include <linux/interrupt.h>
26 #include <linux/reset.h>
27 #include <linux/of_address.h>
28 #include <linux/of_irq.h>
29 #include <linux/mfd/syscon.h>
30 #include <linux/reset-controller.h>
31 
32 #include "hi6210-i2s.h"
33 
34 struct hi6210_i2s {
35 	struct device *dev;
36 	struct reset_control *rc;
37 	struct clk *clk[8];
38 	int clocks;
39 	struct snd_soc_dai_driver dai;
40 	void __iomem *base;
41 	struct regmap *sysctrl;
42 	phys_addr_t base_phys;
43 	struct snd_dmaengine_dai_dma_data dma_data[2];
44 	int clk_rate;
45 	spinlock_t lock;
46 	int rate;
47 	int format;
48 	u8 bits;
49 	u8 channels;
50 	u8 id;
51 	u8 channel_length;
52 	u8 use;
53 	u32 master:1;
54 	u32 status:1;
55 };
56 
57 #define SC_PERIPH_CLKEN1	0x210
58 #define SC_PERIPH_CLKDIS1	0x214
59 
60 #define SC_PERIPH_CLKEN3	0x230
61 #define SC_PERIPH_CLKDIS3	0x234
62 
63 #define SC_PERIPH_CLKEN12	0x270
64 #define SC_PERIPH_CLKDIS12	0x274
65 
66 #define SC_PERIPH_RSTEN1	0x310
67 #define SC_PERIPH_RSTDIS1	0x314
68 #define SC_PERIPH_RSTSTAT1	0x318
69 
70 #define SC_PERIPH_RSTEN2	0x320
71 #define SC_PERIPH_RSTDIS2	0x324
72 #define SC_PERIPH_RSTSTAT2	0x328
73 
74 #define SOC_PMCTRL_BBPPLLALIAS	0x48
75 
76 enum {
77 	CLK_DACODEC,
78 	CLK_I2S_BASE,
79 };
80 
81 static inline void hi6210_write_reg(struct hi6210_i2s *i2s, int reg, u32 val)
82 {
83 	writel(val, i2s->base + reg);
84 }
85 
86 static inline u32 hi6210_read_reg(struct hi6210_i2s *i2s, int reg)
87 {
88 	return readl(i2s->base + reg);
89 }
90 
91 static int hi6210_i2s_startup(struct snd_pcm_substream *substream,
92 			      struct snd_soc_dai *cpu_dai)
93 {
94 	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);
95 	int ret, n;
96 	u32 val;
97 
98 	/* deassert reset on ABB */
99 	regmap_read(i2s->sysctrl, SC_PERIPH_RSTSTAT2, &val);
100 	if (val & BIT(4))
101 		regmap_write(i2s->sysctrl, SC_PERIPH_RSTDIS2, BIT(4));
102 
103 	for (n = 0; n < i2s->clocks; n++) {
104 		ret = clk_prepare_enable(i2s->clk[n]);
105 		if (ret)
106 			goto err_unprepare_clk;
107 	}
108 
109 	ret = clk_set_rate(i2s->clk[CLK_I2S_BASE], 49152000);
110 	if (ret) {
111 		dev_err(i2s->dev, "%s: setting 49.152MHz base rate failed %d\n",
112 			__func__, ret);
113 		goto err_unprepare_clk;
114 	}
115 
116 	/* enable clock before frequency division */
117 	regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN12, BIT(9));
118 
119 	/* enable codec working clock / == "codec bus clock" */
120 	regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN1, BIT(5));
121 
122 	/* deassert reset on codec / interface clock / working clock */
123 	regmap_write(i2s->sysctrl, SC_PERIPH_RSTEN1, BIT(5));
124 	regmap_write(i2s->sysctrl, SC_PERIPH_RSTDIS1, BIT(5));
125 
126 	/* not interested in i2s irqs */
127 	val = hi6210_read_reg(i2s, HII2S_CODEC_IRQ_MASK);
128 	val |= 0x3f;
129 	hi6210_write_reg(i2s, HII2S_CODEC_IRQ_MASK, val);
130 
131 
132 	/* reset the stereo downlink fifo */
133 	val = hi6210_read_reg(i2s, HII2S_APB_AFIFO_CFG_1);
134 	val |= (BIT(5) | BIT(4));
135 	hi6210_write_reg(i2s, HII2S_APB_AFIFO_CFG_1, val);
136 
137 	val = hi6210_read_reg(i2s, HII2S_APB_AFIFO_CFG_1);
138 	val &= ~(BIT(5) | BIT(4));
139 	hi6210_write_reg(i2s, HII2S_APB_AFIFO_CFG_1, val);
140 
141 
142 	val = hi6210_read_reg(i2s, HII2S_SW_RST_N);
143 	val &= ~(HII2S_SW_RST_N__ST_DL_WORDLEN_MASK <<
144 			HII2S_SW_RST_N__ST_DL_WORDLEN_SHIFT);
145 	val |= (HII2S_BITS_16 << HII2S_SW_RST_N__ST_DL_WORDLEN_SHIFT);
146 	hi6210_write_reg(i2s, HII2S_SW_RST_N, val);
147 
148 	val = hi6210_read_reg(i2s, HII2S_MISC_CFG);
149 	/* mux 11/12 = APB not i2s */
150 	val &= ~HII2S_MISC_CFG__ST_DL_TEST_SEL;
151 	/* BT R ch  0 = mixer op of DACR ch */
152 	val &= ~HII2S_MISC_CFG__S2_DOUT_RIGHT_SEL;
153 	val &= ~HII2S_MISC_CFG__S2_DOUT_TEST_SEL;
154 
155 	val |= HII2S_MISC_CFG__S2_DOUT_RIGHT_SEL;
156 	/* BT L ch = 1 = mux 7 = "mixer output of DACL */
157 	val |= HII2S_MISC_CFG__S2_DOUT_TEST_SEL;
158 	hi6210_write_reg(i2s, HII2S_MISC_CFG, val);
159 
160 	val = hi6210_read_reg(i2s, HII2S_SW_RST_N);
161 	val |= HII2S_SW_RST_N__SW_RST_N;
162 	hi6210_write_reg(i2s, HII2S_SW_RST_N, val);
163 
164 	return 0;
165 
166 err_unprepare_clk:
167 	while (n--)
168 		clk_disable_unprepare(i2s->clk[n]);
169 	return ret;
170 }
171 
172 static void hi6210_i2s_shutdown(struct snd_pcm_substream *substream,
173 				struct snd_soc_dai *cpu_dai)
174 {
175 	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);
176 	int n;
177 
178 	for (n = 0; n < i2s->clocks; n++)
179 		clk_disable_unprepare(i2s->clk[n]);
180 
181 	regmap_write(i2s->sysctrl, SC_PERIPH_RSTEN1, BIT(5));
182 }
183 
184 static void hi6210_i2s_txctrl(struct snd_soc_dai *cpu_dai, int on)
185 {
186 	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);
187 	u32 val;
188 
189 	spin_lock(&i2s->lock);
190 	if (on) {
191 		/* enable S2 TX */
192 		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
193 		val |= HII2S_I2S_CFG__S2_IF_TX_EN;
194 		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
195 	} else {
196 		/* disable S2 TX */
197 		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
198 		val &= ~HII2S_I2S_CFG__S2_IF_TX_EN;
199 		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
200 	}
201 	spin_unlock(&i2s->lock);
202 }
203 
204 static void hi6210_i2s_rxctrl(struct snd_soc_dai *cpu_dai, int on)
205 {
206 	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);
207 	u32 val;
208 
209 	spin_lock(&i2s->lock);
210 	if (on) {
211 		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
212 		val |= HII2S_I2S_CFG__S2_IF_RX_EN;
213 		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
214 	} else {
215 		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
216 		val &= ~HII2S_I2S_CFG__S2_IF_RX_EN;
217 		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
218 	}
219 	spin_unlock(&i2s->lock);
220 }
221 
222 static int hi6210_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
223 {
224 	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);
225 
226 	/*
227 	 * We don't actually set the hardware until the hw_params
228 	 * call, but we need to validate the user input here.
229 	 */
230 	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
231 	case SND_SOC_DAIFMT_BC_FC:
232 	case SND_SOC_DAIFMT_BP_FP:
233 		break;
234 	default:
235 		return -EINVAL;
236 	}
237 
238 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
239 	case SND_SOC_DAIFMT_I2S:
240 	case SND_SOC_DAIFMT_LEFT_J:
241 	case SND_SOC_DAIFMT_RIGHT_J:
242 		break;
243 	default:
244 		return -EINVAL;
245 	}
246 
247 	i2s->format = fmt;
248 	i2s->master = (i2s->format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) ==
249 		      SND_SOC_DAIFMT_BP_FP;
250 
251 	return 0;
252 }
253 
254 static int hi6210_i2s_hw_params(struct snd_pcm_substream *substream,
255 			    struct snd_pcm_hw_params *params,
256 			    struct snd_soc_dai *cpu_dai)
257 {
258 	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);
259 	u32 bits = 0, rate = 0, signed_data = 0, fmt = 0;
260 	u32 val;
261 	struct snd_dmaengine_dai_dma_data *dma_data;
262 
263 	switch (params_format(params)) {
264 	case SNDRV_PCM_FORMAT_U16_LE:
265 		signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT;
266 		fallthrough;
267 	case SNDRV_PCM_FORMAT_S16_LE:
268 		bits = HII2S_BITS_16;
269 		break;
270 	case SNDRV_PCM_FORMAT_U24_LE:
271 		signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT;
272 		fallthrough;
273 	case SNDRV_PCM_FORMAT_S24_LE:
274 		bits = HII2S_BITS_24;
275 		break;
276 	default:
277 		dev_err(cpu_dai->dev, "Bad format\n");
278 		return -EINVAL;
279 	}
280 
281 
282 	switch (params_rate(params)) {
283 	case 8000:
284 		rate = HII2S_FS_RATE_8KHZ;
285 		break;
286 	case 16000:
287 		rate = HII2S_FS_RATE_16KHZ;
288 		break;
289 	case 32000:
290 		rate = HII2S_FS_RATE_32KHZ;
291 		break;
292 	case 48000:
293 		rate = HII2S_FS_RATE_48KHZ;
294 		break;
295 	case 96000:
296 		rate = HII2S_FS_RATE_96KHZ;
297 		break;
298 	case 192000:
299 		rate = HII2S_FS_RATE_192KHZ;
300 		break;
301 	default:
302 		dev_err(cpu_dai->dev, "Bad rate: %d\n", params_rate(params));
303 		return -EINVAL;
304 	}
305 
306 	if (!(params_channels(params))) {
307 		dev_err(cpu_dai->dev, "Bad channels\n");
308 		return -EINVAL;
309 	}
310 
311 	dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
312 
313 	switch (bits) {
314 	case HII2S_BITS_24:
315 		i2s->bits = 32;
316 		dma_data->addr_width = 3;
317 		break;
318 	default:
319 		i2s->bits = 16;
320 		dma_data->addr_width = 2;
321 		break;
322 	}
323 	i2s->rate = params_rate(params);
324 	i2s->channels = params_channels(params);
325 	i2s->channel_length = i2s->channels * i2s->bits;
326 
327 	val = hi6210_read_reg(i2s, HII2S_ST_DL_FIFO_TH_CFG);
328 	val &= ~((HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AEMPTY_MASK <<
329 			HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AEMPTY_SHIFT) |
330 		(HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AFULL_MASK <<
331 			HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AFULL_SHIFT) |
332 		(HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AEMPTY_MASK <<
333 			HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AEMPTY_SHIFT) |
334 		(HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AFULL_MASK <<
335 			HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AFULL_SHIFT));
336 	val |= ((16 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AEMPTY_SHIFT) |
337 		(30 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AFULL_SHIFT) |
338 		(16 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AEMPTY_SHIFT) |
339 		(30 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AFULL_SHIFT));
340 	hi6210_write_reg(i2s, HII2S_ST_DL_FIFO_TH_CFG, val);
341 
342 
343 	val = hi6210_read_reg(i2s, HII2S_IF_CLK_EN_CFG);
344 	val |= (BIT(19) | BIT(18) | BIT(17) |
345 		HII2S_IF_CLK_EN_CFG__S2_IF_CLK_EN |
346 		HII2S_IF_CLK_EN_CFG__S2_OL_MIXER_EN |
347 		HII2S_IF_CLK_EN_CFG__S2_OL_SRC_EN |
348 		HII2S_IF_CLK_EN_CFG__ST_DL_R_EN |
349 		HII2S_IF_CLK_EN_CFG__ST_DL_L_EN);
350 	hi6210_write_reg(i2s, HII2S_IF_CLK_EN_CFG, val);
351 
352 
353 	val = hi6210_read_reg(i2s, HII2S_DIG_FILTER_CLK_EN_CFG);
354 	val &= ~(HII2S_DIG_FILTER_CLK_EN_CFG__DACR_SDM_EN |
355 		 HII2S_DIG_FILTER_CLK_EN_CFG__DACR_HBF2I_EN |
356 		 HII2S_DIG_FILTER_CLK_EN_CFG__DACR_AGC_EN |
357 		 HII2S_DIG_FILTER_CLK_EN_CFG__DACL_SDM_EN |
358 		 HII2S_DIG_FILTER_CLK_EN_CFG__DACL_HBF2I_EN |
359 		 HII2S_DIG_FILTER_CLK_EN_CFG__DACL_AGC_EN);
360 	val |= (HII2S_DIG_FILTER_CLK_EN_CFG__DACR_MIXER_EN |
361 		HII2S_DIG_FILTER_CLK_EN_CFG__DACL_MIXER_EN);
362 	hi6210_write_reg(i2s, HII2S_DIG_FILTER_CLK_EN_CFG, val);
363 
364 
365 	val = hi6210_read_reg(i2s, HII2S_DIG_FILTER_MODULE_CFG);
366 	val &= ~(HII2S_DIG_FILTER_MODULE_CFG__DACR_MIXER_IN2_MUTE |
367 		 HII2S_DIG_FILTER_MODULE_CFG__DACL_MIXER_IN2_MUTE);
368 	hi6210_write_reg(i2s, HII2S_DIG_FILTER_MODULE_CFG, val);
369 
370 	val = hi6210_read_reg(i2s, HII2S_MUX_TOP_MODULE_CFG);
371 	val &= ~(HII2S_MUX_TOP_MODULE_CFG__S2_OL_MIXER_IN1_MUTE |
372 		 HII2S_MUX_TOP_MODULE_CFG__S2_OL_MIXER_IN2_MUTE |
373 		 HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_MIXER_IN1_MUTE |
374 		 HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_MIXER_IN2_MUTE);
375 	hi6210_write_reg(i2s, HII2S_MUX_TOP_MODULE_CFG, val);
376 
377 
378 	switch (i2s->format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
379 	case SND_SOC_DAIFMT_BC_FC:
380 		i2s->master = false;
381 		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
382 		val |= HII2S_I2S_CFG__S2_MST_SLV;
383 		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
384 		break;
385 	case SND_SOC_DAIFMT_BP_FP:
386 		i2s->master = true;
387 		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
388 		val &= ~HII2S_I2S_CFG__S2_MST_SLV;
389 		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
390 		break;
391 	default:
392 		WARN_ONCE(1, "Invalid i2s->fmt CLOCK_PROVIDER_MASK. This shouldn't happen\n");
393 		return -EINVAL;
394 	}
395 
396 	switch (i2s->format & SND_SOC_DAIFMT_FORMAT_MASK) {
397 	case SND_SOC_DAIFMT_I2S:
398 		fmt = HII2S_FORMAT_I2S;
399 		break;
400 	case SND_SOC_DAIFMT_LEFT_J:
401 		fmt = HII2S_FORMAT_LEFT_JUST;
402 		break;
403 	case SND_SOC_DAIFMT_RIGHT_J:
404 		fmt = HII2S_FORMAT_RIGHT_JUST;
405 		break;
406 	default:
407 		WARN_ONCE(1, "Invalid i2s->fmt FORMAT_MASK. This shouldn't happen\n");
408 		return -EINVAL;
409 	}
410 
411 	val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
412 	val &= ~(HII2S_I2S_CFG__S2_FUNC_MODE_MASK <<
413 			HII2S_I2S_CFG__S2_FUNC_MODE_SHIFT);
414 	val |= fmt << HII2S_I2S_CFG__S2_FUNC_MODE_SHIFT;
415 	hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
416 
417 
418 	val = hi6210_read_reg(i2s, HII2S_CLK_SEL);
419 	val &= ~(HII2S_CLK_SEL__I2S_BT_FM_SEL | /* BT gets the I2S */
420 			HII2S_CLK_SEL__EXT_12_288MHZ_SEL);
421 	hi6210_write_reg(i2s, HII2S_CLK_SEL, val);
422 
423 	dma_data->maxburst = 2;
424 
425 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
426 		dma_data->addr = i2s->base_phys + HII2S_ST_DL_CHANNEL;
427 	else
428 		dma_data->addr = i2s->base_phys + HII2S_STEREO_UPLINK_CHANNEL;
429 
430 	switch (i2s->channels) {
431 	case 1:
432 		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
433 		val |= HII2S_I2S_CFG__S2_FRAME_MODE;
434 		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
435 		break;
436 	default:
437 		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
438 		val &= ~HII2S_I2S_CFG__S2_FRAME_MODE;
439 		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
440 		break;
441 	}
442 
443 	/* clear loopback, set signed type and word length */
444 	val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
445 	val &= ~HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT;
446 	val &= ~(HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_MASK <<
447 			HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_SHIFT);
448 	val &= ~(HII2S_I2S_CFG__S2_DIRECT_LOOP_MASK <<
449 			HII2S_I2S_CFG__S2_DIRECT_LOOP_SHIFT);
450 	val |= signed_data;
451 	val |= (bits << HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_SHIFT);
452 	hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
453 
454 
455 	if (!i2s->master)
456 		return 0;
457 
458 	/* set DAC and related units to correct rate */
459 	val = hi6210_read_reg(i2s, HII2S_FS_CFG);
460 	val &= ~(HII2S_FS_CFG__FS_S2_MASK << HII2S_FS_CFG__FS_S2_SHIFT);
461 	val &= ~(HII2S_FS_CFG__FS_DACLR_MASK << HII2S_FS_CFG__FS_DACLR_SHIFT);
462 	val &= ~(HII2S_FS_CFG__FS_ST_DL_R_MASK <<
463 					HII2S_FS_CFG__FS_ST_DL_R_SHIFT);
464 	val &= ~(HII2S_FS_CFG__FS_ST_DL_L_MASK <<
465 					HII2S_FS_CFG__FS_ST_DL_L_SHIFT);
466 	val |= (rate << HII2S_FS_CFG__FS_S2_SHIFT);
467 	val |= (rate << HII2S_FS_CFG__FS_DACLR_SHIFT);
468 	val |= (rate << HII2S_FS_CFG__FS_ST_DL_R_SHIFT);
469 	val |= (rate << HII2S_FS_CFG__FS_ST_DL_L_SHIFT);
470 	hi6210_write_reg(i2s, HII2S_FS_CFG, val);
471 
472 	return 0;
473 }
474 
475 static int hi6210_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
476 			  struct snd_soc_dai *cpu_dai)
477 {
478 	pr_debug("%s\n", __func__);
479 	switch (cmd) {
480 	case SNDRV_PCM_TRIGGER_START:
481 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
482 		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
483 			hi6210_i2s_rxctrl(cpu_dai, 1);
484 		else
485 			hi6210_i2s_txctrl(cpu_dai, 1);
486 		break;
487 	case SNDRV_PCM_TRIGGER_STOP:
488 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
489 		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
490 			hi6210_i2s_rxctrl(cpu_dai, 0);
491 		else
492 			hi6210_i2s_txctrl(cpu_dai, 0);
493 		break;
494 	default:
495 		dev_err(cpu_dai->dev, "unknown cmd\n");
496 		return -EINVAL;
497 	}
498 	return 0;
499 }
500 
501 static int hi6210_i2s_dai_probe(struct snd_soc_dai *dai)
502 {
503 	struct hi6210_i2s *i2s = snd_soc_dai_get_drvdata(dai);
504 
505 	snd_soc_dai_init_dma_data(dai,
506 				  &i2s->dma_data[SNDRV_PCM_STREAM_PLAYBACK],
507 				  &i2s->dma_data[SNDRV_PCM_STREAM_CAPTURE]);
508 
509 	return 0;
510 }
511 
512 
513 static const struct snd_soc_dai_ops hi6210_i2s_dai_ops = {
514 	.probe		= hi6210_i2s_dai_probe,
515 	.trigger	= hi6210_i2s_trigger,
516 	.hw_params	= hi6210_i2s_hw_params,
517 	.set_fmt	= hi6210_i2s_set_fmt,
518 	.startup	= hi6210_i2s_startup,
519 	.shutdown	= hi6210_i2s_shutdown,
520 };
521 
522 static const struct snd_soc_dai_driver hi6210_i2s_dai_init = {
523 	.playback = {
524 		.channels_min = 2,
525 		.channels_max = 2,
526 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
527 			   SNDRV_PCM_FMTBIT_U16_LE,
528 		.rates = SNDRV_PCM_RATE_48000,
529 	},
530 	.capture = {
531 		.channels_min = 2,
532 		.channels_max = 2,
533 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
534 			   SNDRV_PCM_FMTBIT_U16_LE,
535 		.rates = SNDRV_PCM_RATE_48000,
536 	},
537 	.ops = &hi6210_i2s_dai_ops,
538 };
539 
540 static const struct snd_soc_component_driver hi6210_i2s_i2s_comp = {
541 	.name = "hi6210_i2s-i2s",
542 	.legacy_dai_naming = 1,
543 };
544 
545 static int hi6210_i2s_probe(struct platform_device *pdev)
546 {
547 	struct device_node *node = pdev->dev.of_node;
548 	struct device *dev = &pdev->dev;
549 	struct hi6210_i2s *i2s;
550 	struct resource *res;
551 	int ret;
552 
553 	i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL);
554 	if (!i2s)
555 		return -ENOMEM;
556 
557 	i2s->dev = dev;
558 	spin_lock_init(&i2s->lock);
559 
560 	i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
561 	if (IS_ERR(i2s->base))
562 		return PTR_ERR(i2s->base);
563 
564 	i2s->base_phys = (phys_addr_t)res->start;
565 	i2s->dai = hi6210_i2s_dai_init;
566 
567 	dev_set_drvdata(dev, i2s);
568 
569 	i2s->sysctrl = syscon_regmap_lookup_by_phandle(node,
570 						"hisilicon,sysctrl-syscon");
571 	if (IS_ERR(i2s->sysctrl))
572 		return PTR_ERR(i2s->sysctrl);
573 
574 	i2s->clk[CLK_DACODEC] = devm_clk_get(dev, "dacodec");
575 	if (IS_ERR(i2s->clk[CLK_DACODEC]))
576 		return PTR_ERR(i2s->clk[CLK_DACODEC]);
577 	i2s->clocks++;
578 
579 	i2s->clk[CLK_I2S_BASE] = devm_clk_get(dev, "i2s-base");
580 	if (IS_ERR(i2s->clk[CLK_I2S_BASE]))
581 		return PTR_ERR(i2s->clk[CLK_I2S_BASE]);
582 	i2s->clocks++;
583 
584 	ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0);
585 	if (ret)
586 		return ret;
587 
588 	ret = devm_snd_soc_register_component(dev, &hi6210_i2s_i2s_comp,
589 					 &i2s->dai, 1);
590 	return ret;
591 }
592 
593 static const struct of_device_id hi6210_i2s_dt_ids[] = {
594 	{ .compatible = "hisilicon,hi6210-i2s" },
595 	{ /* sentinel */ }
596 };
597 
598 MODULE_DEVICE_TABLE(of, hi6210_i2s_dt_ids);
599 
600 static struct platform_driver hi6210_i2s_driver = {
601 	.probe = hi6210_i2s_probe,
602 	.driver = {
603 		.name = "hi6210_i2s",
604 		.of_match_table = hi6210_i2s_dt_ids,
605 	},
606 };
607 
608 module_platform_driver(hi6210_i2s_driver);
609 
610 MODULE_DESCRIPTION("Hisilicon HI6210 I2S driver");
611 MODULE_AUTHOR("Andy Green <andy.green@linaro.org>");
612 MODULE_LICENSE("GPL");
613