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
140int rkiis_match(struct device *, void *, void *);
141void rkiis_attach(struct device *, struct device *, void *);
142
143int rkiis_intr(void *);
144int rkiis_set_format(void *, uint32_t, uint32_t, uint32_t);
145int rkiis_set_sysclk(void *, uint32_t);
146
147int rkiis_open(void *, int);
148int rkiis_set_params(void *, int, int,
149    struct audio_params *, struct audio_params *);
150void *rkiis_allocm(void *, int, size_t, int, int);
151void rkiis_freem(void *, void *, int);
152int rkiis_trigger_output(void *, void *, void *, int,
153    void (*)(void *), void *, struct audio_params *);
154int rkiis_trigger_input(void *, void *, void *, int,
155    void (*)(void *), void *, struct audio_params *);
156int rkiis_halt_output(void *);
157int rkiis_halt_input(void *);
158
159struct 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
166struct rkiis_config rk3399_i2s_config = {
167	.oe_reg = 0xe220,
168	.oe_mask = 0x7,
169	.oe_shift = 11,
170	.oe_val = 0x7,
171};
172
173struct 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
185struct 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
202const 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
213const struct cfattach rkiis_ca = {
214	sizeof (struct rkiis_softc), rkiis_match, rkiis_attach
215};
216
217struct cfdriver rkiis_cd = {
218	NULL, "rkiis", DV_DULL
219};
220
221int
222rkiis_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
229void
230rkiis_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
280unmap:
281	bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
282}
283
284int
285rkiis_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
339int
340rkiis_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
411int
412rkiis_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
427int
428rkiis_open(void *cookie, int flags)
429{
430	if ((flags & (FWRITE | FREAD)) == (FWRITE | FREAD))
431		return ENXIO;
432
433	return 0;
434}
435
436int
437rkiis_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
513void *
514rkiis_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
520void
521rkiis_freem(void *cookie, void *addr, int size)
522{
523	free(addr, M_DEVBUF, size);
524}
525
526int
527rkiis_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
558int
559rkiis_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
565int
566rkiis_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
596int
597rkiis_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