xref: /openbsd/sys/dev/fdt/rkiis.c (revision 7eff0e4e)
1 /* $OpenBSD: rkiis.c,v 1.4 2022/10/28 15:09:45 kn Exp $ */
2 /* $NetBSD: rk_i2s.c,v 1.3 2020/02/29 05:51:10 isaki Exp $ */
3 /*-
4  * Copyright (c) 2019 Jared McNeill <jmcneill@invisible.ca>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/device.h>
32 #include <sys/malloc.h>
33 #include <sys/fcntl.h>
34 
35 #include <machine/intr.h>
36 #include <machine/bus.h>
37 #include <machine/fdt.h>
38 
39 #include <dev/ofw/openfirm.h>
40 #include <dev/ofw/ofw_clock.h>
41 #include <dev/ofw/ofw_misc.h>
42 #include <dev/ofw/ofw_pinctrl.h>
43 #include <dev/ofw/fdt.h>
44 
45 #include <sys/audioio.h>
46 #include <dev/audio_if.h>
47 #include <dev/midi_if.h>
48 
49 #define	RK_I2S_FIFO_DEPTH	32
50 #define	RK_I2S_SAMPLE_RATE	48000
51 
52 #define	I2S_TXCR		0x00
53 #define	 TXCR_RCNT_MASK			(0x3f << 17)
54 #define	 TXCR_RCNT_SHIFT		17
55 #define	 TXCR_TCSR_MASK			(0x3 << 15)
56 #define	 TXCR_TCSR_SHIFT		15
57 #define	 TXCR_HWT			(1 << 14)
58 #define	 TXCR_SJM			(1 << 12)
59 #define	 TXCR_FBM			(1 << 11)
60 #define	 TXCR_IBM_MASK			(0x3 << 9)
61 #define	 TXCR_IBM_SHIFT			9
62 #define	 TXCR_PBM_MASK			(0x3 << 7)
63 #define	 TXCR_PBM_SHIFT			7
64 #define	 TXCR_TFS			(1 << 5)
65 #define	 TXCR_VDW_MASK			(0x1f << 0)
66 #define	 TXCR_VDW_SHIFT			0
67 #define	I2S_RXCR		0x04
68 #define	 RXCR_RCSR_MASK			(0x3 << 15)
69 #define	 RXCR_RCSR_SHIFT		15
70 #define	 RXCR_HWT			(1 << 14)
71 #define	 RXCR_SJM			(1 << 12)
72 #define	 RXCR_FBM			(1 << 11)
73 #define	 RXCR_IBM_MASK			(0x3 << 9)
74 #define	 RXCR_IBM_SHIFT			9
75 #define	 RXCR_PBM_MASK			(0x3 << 7)
76 #define	 RXCR_PBM_SHIFT			7
77 #define	 RXCR_TFS			(1 << 5)
78 #define	 RXCR_VDW_MASK			(0x1f << 0)
79 #define	 RXCR_VDW_SHIFT			0
80 #define	I2S_CKR			0x08
81 #define	 CKR_TRCM_MASK			(0x3 << 28)
82 #define	 CKR_TRCM_SHIFT			28
83 #define	 CKR_MSS			(1 << 27)
84 #define	 CKR_CKP			(1 << 26)
85 #define	 CKR_RLP			(1 << 25)
86 #define	 CKR_TLP			(1 << 24)
87 #define	 CKR_MDIV_MASK			(0xff << 16)
88 #define	 CKR_MDIV_SHIFT			16
89 #define	 CKR_RSD_MASK			(0xff << 8)
90 #define	 CKR_RSD_SHIFT			8
91 #define	 CKR_TSD_MASK			(0xff << 0)
92 #define	 CKR_TSD_SHIFT			0
93 #define	I2S_TXFIFOLR		0x0c
94 #define	 TXFIFOLR_TFL_MASK(n)		(0x3f << ((n) * 6))
95 #define	 TXFIFOLR_TFL_SHIFT(n)		((n) * 6)
96 #define	I2S_DMACR		0x10
97 #define	 DMACR_RDE			(1 << 24)
98 #define	 DMACR_RDL_MASK			(0x1f << 16)
99 #define	 DMACR_RDL_SHIFT		16
100 #define	 DMACR_TDE			(1 << 8)
101 #define	 DMACR_TDL_MASK			(0x1f << 0)
102 #define	 DMACR_TDL_SHIFT		0
103 #define	I2S_INTCR		0x14
104 #define	 INTCR_RFT_MASK			(0x1f << 20)
105 #define	 INTCR_RFT_SHIFT		20
106 #define	 INTCR_RXOIC			(1 << 18)
107 #define	 INTCR_RXOIE			(1 << 17)
108 #define	 INTCR_RXFIE			(1 << 16)
109 #define	 INTCR_TFT_MASK			(0x1f << 4)
110 #define	 INTCR_TFT_SHIFT		4
111 #define	 INTCR_TXUIC			(1 << 2)
112 #define	 INTCR_TXUIE			(1 << 1)
113 #define	 INTCR_TXEIE			(1 << 0)
114 #define	I2S_INTSR		0x18
115 #define	 INTSR_RXOI			(1 << 17)
116 #define	 INTSR_RXFI			(1 << 16)
117 #define	 INTSR_TXUI			(1 << 1)
118 #define	 INTSR_TXEI			(1 << 0)
119 #define	I2S_XFER		0x1c
120 #define	 XFER_RXS			(1 << 1)
121 #define	 XFER_TXS			(1 << 0)
122 #define	I2S_CLR			0x20
123 #define	 CLR_RXC			(1 << 1)
124 #define	 CLR_TXC			(1 << 0)
125 #define	I2S_TXDR		0x24
126 #define	I2S_RXDR		0x28
127 #define	I2S_RXFIFOLR		0x2c
128 #define	 RXFIFOLR_RFL_MASK(n)		(0x3f << ((n) * 6))
129 #define	 RXFIFOLR_RFL_SHIFT(n)		((n) * 6)
130 
131 #define HREAD4(sc, reg)							\
132 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
133 #define HWRITE4(sc, reg, val)						\
134 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
135 #define HSET4(sc, reg, bits)						\
136 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
137 #define HCLR4(sc, reg, bits)						\
138 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
139 
140 int rkiis_match(struct device *, void *, void *);
141 void rkiis_attach(struct device *, struct device *, void *);
142 
143 int rkiis_intr(void *);
144 int rkiis_set_format(void *, uint32_t, uint32_t, uint32_t);
145 int rkiis_set_sysclk(void *, uint32_t);
146 
147 int rkiis_open(void *, int);
148 int rkiis_set_params(void *, int, int,
149     struct audio_params *, struct audio_params *);
150 void *rkiis_allocm(void *, int, size_t, int, int);
151 void rkiis_freem(void *, void *, int);
152 int rkiis_trigger_output(void *, void *, void *, int,
153     void (*)(void *), void *, struct audio_params *);
154 int rkiis_trigger_input(void *, void *, void *, int,
155     void (*)(void *), void *, struct audio_params *);
156 int rkiis_halt_output(void *);
157 int rkiis_halt_input(void *);
158 
159 struct rkiis_config {
160 	bus_size_t		oe_reg;
161 	uint32_t		oe_mask;
162 	uint32_t		oe_shift;
163 	uint32_t		oe_val;
164 };
165 
166 struct rkiis_config rk3399_i2s_config = {
167 	.oe_reg = 0xe220,
168 	.oe_mask = 0x7,
169 	.oe_shift = 11,
170 	.oe_val = 0x7,
171 };
172 
173 struct rkiis_chan {
174 	uint32_t		*ch_start;
175 	uint32_t		*ch_end;
176 	uint32_t		*ch_cur;
177 
178 	int			ch_blksize;
179 	int			ch_resid;
180 
181 	void			(*ch_intr)(void *);
182 	void			*ch_intrarg;
183 };
184 
185 struct rkiis_softc {
186 	struct device		sc_dev;
187 	bus_space_tag_t		sc_iot;
188 	bus_space_handle_t	sc_ioh;
189 	void			*sc_ih;
190 
191 	int			sc_node;
192 	struct rkiis_config	*sc_conf;
193 
194 	struct rkiis_chan	sc_pchan;
195 	struct rkiis_chan	sc_rchan;
196 
197 	uint32_t		sc_active;
198 
199 	struct dai_device	sc_dai;
200 };
201 
202 const struct audio_hw_if rkiis_hw_if = {
203 	.open = rkiis_open,
204 	.set_params = rkiis_set_params,
205 	.allocm = rkiis_allocm,
206 	.freem = rkiis_freem,
207 	.trigger_output = rkiis_trigger_output,
208 	.trigger_input = rkiis_trigger_input,
209 	.halt_output = rkiis_halt_output,
210 	.halt_input = rkiis_halt_input,
211 };
212 
213 const struct cfattach rkiis_ca = {
214 	sizeof (struct rkiis_softc), rkiis_match, rkiis_attach
215 };
216 
217 struct cfdriver rkiis_cd = {
218 	NULL, "rkiis", DV_DULL
219 };
220 
221 int
rkiis_match(struct device * parent,void * match,void * aux)222 rkiis_match(struct device *parent, void *match, void *aux)
223 {
224 	struct fdt_attach_args *faa = aux;
225 
226 	return OF_is_compatible(faa->fa_node, "rockchip,rk3399-i2s");
227 }
228 
229 void
rkiis_attach(struct device * parent,struct device * self,void * aux)230 rkiis_attach(struct device *parent, struct device *self, void *aux)
231 {
232 	struct rkiis_softc *sc = (struct rkiis_softc *)self;
233 	struct fdt_attach_args *faa = aux;
234 	struct regmap *rm;
235 	uint32_t grf, val;
236 
237 	if (faa->fa_nreg < 1) {
238 		printf(": no registers\n");
239 		return;
240 	}
241 
242 	sc->sc_iot = faa->fa_iot;
243 	sc->sc_node = faa->fa_node;
244 	sc->sc_conf = &rk3399_i2s_config;
245 
246 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
247 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
248 		printf(": can't map registers\n");
249 		return;
250 	}
251 
252 	pinctrl_byname(sc->sc_node, "default");
253 	clock_enable_all(sc->sc_node);
254 
255 	grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
256 	rm = regmap_byphandle(grf);
257 	if (rm && sc->sc_conf->oe_mask) {
258 		val = sc->sc_conf->oe_val << sc->sc_conf->oe_shift;
259 		val |= (sc->sc_conf->oe_mask << sc->sc_conf->oe_shift) << 16;
260 		regmap_write_4(rm, sc->sc_conf->oe_reg, val);
261 	}
262 
263 	sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_AUDIO | IPL_MPSAFE,
264 	    rkiis_intr, sc, sc->sc_dev.dv_xname);
265 	if (sc->sc_ih == NULL) {
266 		printf(": can't establish interrupt\n");
267 		goto unmap;
268 	}
269 
270 	printf("\n");
271 
272 	sc->sc_dai.dd_node = faa->fa_node;
273 	sc->sc_dai.dd_cookie = sc;
274 	sc->sc_dai.dd_hw_if = &rkiis_hw_if;
275 	sc->sc_dai.dd_set_format = rkiis_set_format;
276 	sc->sc_dai.dd_set_sysclk = rkiis_set_sysclk;
277 	dai_register(&sc->sc_dai);
278 	return;
279 
280 unmap:
281 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
282 }
283 
284 int
rkiis_intr(void * cookie)285 rkiis_intr(void *cookie)
286 {
287 	struct rkiis_softc *sc = cookie;
288 	struct rkiis_chan *pch = &sc->sc_pchan;
289 #if notyet
290 	struct rkiis_chan *rch = &sc->sc_rchan;
291 #endif
292 	uint32_t sr, val;
293 	int fifolr;
294 
295 	mtx_enter(&audio_lock);
296 
297 	sr = HREAD4(sc, I2S_INTSR);
298 
299 	if ((sr & INTSR_RXFI) != 0) {
300 #if notyet
301 		val = HREAD4(sc, I2S_RXFIFOLR);
302 		fifolr = val & RXFIFOLR_RFL_MASK(0);
303 		fifolr >>= RXFIFOLR_RFL_SHIFT(0);
304 		while (fifolr > 0) {
305 			*rch->ch_data = HREAD4(sc, I2S_RXDR);
306 			rch->ch_data++;
307 			rch->ch_resid -= 4;
308 			if (rch->ch_resid == 0)
309 				rch->ch_intr(rch->ch_intrarg);
310 			--fifolr;
311 		}
312 #endif
313 	}
314 
315 	if ((sr & INTSR_TXEI) != 0) {
316 		val = HREAD4(sc, I2S_TXFIFOLR);
317 		fifolr = val & TXFIFOLR_TFL_MASK(0);
318 		fifolr >>= TXFIFOLR_TFL_SHIFT(0);
319 		fifolr = min(fifolr, RK_I2S_FIFO_DEPTH);
320 		while (fifolr < RK_I2S_FIFO_DEPTH - 1) {
321 			HWRITE4(sc, I2S_TXDR, *pch->ch_cur);
322 			pch->ch_cur++;
323 			if (pch->ch_cur == pch->ch_end)
324 				pch->ch_cur = pch->ch_start;
325 			pch->ch_resid -= 4;
326 			if (pch->ch_resid == 0) {
327 				pch->ch_intr(pch->ch_intrarg);
328 				pch->ch_resid = pch->ch_blksize;
329 			}
330 			++fifolr;
331 		}
332 	}
333 
334 	mtx_leave(&audio_lock);
335 
336 	return 1;
337 }
338 
339 int
rkiis_set_format(void * cookie,uint32_t fmt,uint32_t pol,uint32_t clk)340 rkiis_set_format(void *cookie, uint32_t fmt, uint32_t pol,
341     uint32_t clk)
342 {
343 	struct rkiis_softc *sc = cookie;
344 	uint32_t txcr, rxcr, ckr;
345 
346 	txcr = HREAD4(sc, I2S_TXCR);
347 	rxcr = HREAD4(sc, I2S_RXCR);
348 	ckr = HREAD4(sc, I2S_CKR);
349 
350 	txcr &= ~(TXCR_IBM_MASK|TXCR_PBM_MASK|TXCR_TFS);
351 	rxcr &= ~(RXCR_IBM_MASK|RXCR_PBM_MASK|RXCR_TFS);
352 	switch (fmt) {
353 	case DAI_FORMAT_I2S:
354 		txcr |= 0 << TXCR_IBM_SHIFT;
355 		rxcr |= 0 << RXCR_IBM_SHIFT;
356 		break;
357 	case DAI_FORMAT_LJ:
358 		txcr |= 1 << TXCR_IBM_SHIFT;
359 		rxcr |= 1 << RXCR_IBM_SHIFT;
360 		break;
361 	case DAI_FORMAT_RJ:
362 		txcr |= 2 << TXCR_IBM_SHIFT;
363 		rxcr |= 2 << RXCR_IBM_SHIFT;
364 		break;
365 	case DAI_FORMAT_DSPA:
366 		txcr |= 0 << TXCR_PBM_SHIFT;
367 		txcr |= TXCR_TFS;
368 		rxcr |= 0 << RXCR_PBM_SHIFT;
369 		txcr |= RXCR_TFS;
370 		break;
371 	case DAI_FORMAT_DSPB:
372 		txcr |= 1 << TXCR_PBM_SHIFT;
373 		txcr |= TXCR_TFS;
374 		rxcr |= 1 << RXCR_PBM_SHIFT;
375 		txcr |= RXCR_TFS;
376 		break;
377 	default:
378 		return EINVAL;
379 	}
380 
381 	HWRITE4(sc, I2S_TXCR, txcr);
382 	HWRITE4(sc, I2S_RXCR, rxcr);
383 
384 	switch (pol) {
385 	case DAI_POLARITY_IB|DAI_POLARITY_NF:
386 		ckr |= CKR_CKP;
387 		break;
388 	case DAI_POLARITY_NB|DAI_POLARITY_NF:
389 		ckr &= ~CKR_CKP;
390 		break;
391 	default:
392 		return EINVAL;
393 	}
394 
395 	switch (clk) {
396 	case DAI_CLOCK_CBM|DAI_CLOCK_CFM:
397 		ckr |= CKR_MSS;		/* sclk input */
398 		break;
399 	case DAI_CLOCK_CBS|DAI_CLOCK_CFS:
400 		ckr &= ~CKR_MSS;	/* sclk output */
401 		break;
402 	default:
403 		return EINVAL;
404 	}
405 
406 	HWRITE4(sc, I2S_CKR, ckr);
407 
408 	return 0;
409 }
410 
411 int
rkiis_set_sysclk(void * cookie,uint32_t rate)412 rkiis_set_sysclk(void *cookie, uint32_t rate)
413 {
414 	struct rkiis_softc *sc = cookie;
415 	int error;
416 
417 	error = clock_set_frequency(sc->sc_node, "i2s_clk", rate);
418 	if (error != 0) {
419 		printf("%s: can't set sysclk to %u Hz\n",
420 		    sc->sc_dev.dv_xname, rate);
421 		return error;
422 	}
423 
424 	return 0;
425 }
426 
427 int
rkiis_open(void * cookie,int flags)428 rkiis_open(void *cookie, int flags)
429 {
430 	if ((flags & (FWRITE | FREAD)) == (FWRITE | FREAD))
431 		return ENXIO;
432 
433 	return 0;
434 }
435 
436 int
rkiis_set_params(void * cookie,int setmode,int usemode,struct audio_params * play,struct audio_params * rec)437 rkiis_set_params(void *cookie, int setmode, int usemode,
438     struct audio_params *play, struct audio_params *rec)
439 {
440 	struct rkiis_softc *sc = cookie;
441 	uint32_t mclk_rate, bclk_rate;
442 	uint32_t bclk_div, lrck_div;
443 	uint32_t ckr, txcr, rxcr;
444 	int i;
445 
446 	ckr = HREAD4(sc, I2S_CKR);
447 	if ((ckr & CKR_MSS) == 0) {
448 		mclk_rate = clock_get_frequency(sc->sc_node, "i2s_clk");
449 		bclk_rate = 2 * 32 * RK_I2S_SAMPLE_RATE;
450 		bclk_div = mclk_rate / bclk_rate;
451 		lrck_div = bclk_rate / RK_I2S_SAMPLE_RATE;
452 
453 		ckr &= ~CKR_MDIV_MASK;
454 		ckr |= (bclk_div - 1) << CKR_MDIV_SHIFT;
455 		ckr &= ~CKR_TSD_MASK;
456 		ckr |= (lrck_div - 1) << CKR_TSD_SHIFT;
457 		ckr &= ~CKR_RSD_MASK;
458 		ckr |= (lrck_div - 1) << CKR_RSD_SHIFT;
459 	}
460 
461 	ckr &= ~CKR_TRCM_MASK;
462 	HWRITE4(sc, I2S_CKR, ckr);
463 
464 	for (i = 0; i < 2; i++) {
465 		struct audio_params *p;
466 		int mode;
467 
468 		switch (i) {
469 		case 0:
470 			mode = AUMODE_PLAY;
471 			p = play;
472 			break;
473 		case 1:
474 			mode = AUMODE_RECORD;
475 			p = rec;
476 			break;
477 		default:
478 			return EINVAL;
479 		}
480 
481 		if (!(setmode & mode))
482 			continue;
483 
484 		if (p->channels & 1)
485 			return EINVAL;
486 
487 		if (setmode & AUMODE_PLAY) {
488 			txcr = HREAD4(sc, I2S_TXCR);
489 			txcr &= ~TXCR_VDW_MASK;
490 			txcr |= (16 - 1) << TXCR_VDW_SHIFT;
491 			txcr &= ~TXCR_TCSR_MASK;
492 			txcr |= (p->channels / 2 - 1) << TXCR_TCSR_SHIFT;
493 			HWRITE4(sc, I2S_TXCR, txcr);
494 		} else {
495 			rxcr = HREAD4(sc, I2S_RXCR);
496 			rxcr &= ~RXCR_VDW_MASK;
497 			rxcr |= (16 - 1) << RXCR_VDW_SHIFT;
498 			rxcr &= ~RXCR_RCSR_MASK;
499 			rxcr |= (p->channels / 2 - 1) << RXCR_RCSR_SHIFT;
500 			HWRITE4(sc, I2S_RXCR, rxcr);
501 		}
502 
503 		p->encoding = AUDIO_ENCODING_SLINEAR_LE;
504 		p->precision = 16;
505 		p->bps = AUDIO_BPS(p->precision);
506 		p->msb = 1;
507 		p->sample_rate = RK_I2S_SAMPLE_RATE;
508 	}
509 
510 	return 0;
511 }
512 
513 void *
rkiis_allocm(void * cookie,int direction,size_t size,int type,int flags)514 rkiis_allocm(void *cookie, int direction, size_t size, int type,
515     int flags)
516 {
517 	return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
518 }
519 
520 void
rkiis_freem(void * cookie,void * addr,int size)521 rkiis_freem(void *cookie, void *addr, int size)
522 {
523 	free(addr, M_DEVBUF, size);
524 }
525 
526 int
rkiis_trigger_output(void * cookie,void * start,void * end,int blksize,void (* intr)(void *),void * intrarg,struct audio_params * params)527 rkiis_trigger_output(void *cookie, void *start, void *end, int blksize,
528     void (*intr)(void *), void *intrarg, struct audio_params *params)
529 {
530 	struct rkiis_softc *sc = cookie;
531 	struct rkiis_chan *ch = &sc->sc_pchan;
532 	uint32_t val;
533 
534 	if (sc->sc_active == 0) {
535 		val = HREAD4(sc, I2S_XFER);
536 		val |= (XFER_TXS | XFER_RXS);
537 		HWRITE4(sc, I2S_XFER, val);
538 	}
539 
540 	sc->sc_active |= XFER_TXS;
541 
542 	val = HREAD4(sc, I2S_INTCR);
543 	val |= INTCR_TXEIE;
544 	val &= ~INTCR_TFT_MASK;
545 	val |= (RK_I2S_FIFO_DEPTH / 2) << INTCR_TFT_SHIFT;
546 	HWRITE4(sc, I2S_INTCR, val);
547 
548 	ch->ch_intr = intr;
549 	ch->ch_intrarg = intrarg;
550 	ch->ch_start = ch->ch_cur = start;
551 	ch->ch_end = end;
552 	ch->ch_blksize = blksize;
553 	ch->ch_resid = blksize;
554 
555 	return 0;
556 }
557 
558 int
rkiis_trigger_input(void * cookie,void * start,void * end,int blksize,void (* intr)(void *),void * intrarg,struct audio_params * params)559 rkiis_trigger_input(void *cookie, void *start, void *end, int blksize,
560     void (*intr)(void *), void *intrarg, struct audio_params *params)
561 {
562 	return EIO;
563 }
564 
565 int
rkiis_halt_output(void * cookie)566 rkiis_halt_output(void *cookie)
567 {
568 	struct rkiis_softc *sc = cookie;
569 	struct rkiis_chan *ch = &sc->sc_pchan;
570 	uint32_t val;
571 
572 	sc->sc_active &= ~XFER_TXS;
573 	if (sc->sc_active == 0) {
574 		val = HREAD4(sc, I2S_XFER);
575 		val &= ~(XFER_TXS|XFER_RXS);
576 		HWRITE4(sc, I2S_XFER, val);
577 	}
578 
579 	val = HREAD4(sc, I2S_INTCR);
580 	val &= ~INTCR_TXEIE;
581 	HWRITE4(sc, I2S_INTCR, val);
582 
583 	val = HREAD4(sc, I2S_CLR);
584 	val |= CLR_TXC;
585 	HWRITE4(sc, I2S_CLR, val);
586 
587 	while ((HREAD4(sc, I2S_CLR) & CLR_TXC) != 0)
588 		delay(1);
589 
590 	ch->ch_intr = NULL;
591 	ch->ch_intrarg = NULL;
592 
593 	return 0;
594 }
595 
596 int
rkiis_halt_input(void * cookie)597 rkiis_halt_input(void *cookie)
598 {
599 	struct rkiis_softc *sc = cookie;
600 	struct rkiis_chan *ch = &sc->sc_rchan;
601 	uint32_t val;
602 
603 	sc->sc_active &= ~XFER_RXS;
604 	if (sc->sc_active == 0) {
605 		val = HREAD4(sc, I2S_XFER);
606 		val &= ~(XFER_TXS|XFER_RXS);
607 		HWRITE4(sc, I2S_XFER, val);
608 	}
609 
610 	val = HREAD4(sc, I2S_INTCR);
611 	val &= ~INTCR_RXFIE;
612 	HWRITE4(sc, I2S_INTCR, val);
613 
614 	ch->ch_intr = NULL;
615 	ch->ch_intrarg = NULL;
616 
617 	return 0;
618 }
619