1/*	$NetBSD: cs4231_ebus.c,v 1.39 2019/05/08 13:40:17 isaki Exp $ */
2
3/*
4 * Copyright (c) 2002 Valeriy E. Ushakov
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 * 3. The name of the author may not be used to endorse or promote products
16 *    derived from this software without specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: cs4231_ebus.c,v 1.39 2019/05/08 13:40:17 isaki Exp $");
32
33#ifdef _KERNEL_OPT
34#include "opt_sparc_arch.h"
35#endif
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/errno.h>
40#include <sys/device.h>
41#include <sys/cpu.h>
42#include <sys/kmem.h>
43#include <sys/malloc.h>
44
45#include <machine/autoconf.h>
46
47#include <dev/ebus/ebusreg.h>
48#include <dev/ebus/ebusvar.h>
49
50#include <sys/audioio.h>
51#include <dev/audio/audio_if.h>
52
53#include <dev/ic/ad1848reg.h>
54#include <dev/ic/cs4231reg.h>
55#include <dev/ic/ad1848var.h>
56#include <dev/ic/cs4231var.h>
57
58#ifdef AUDIO_DEBUG
59int cs4231_ebus_debug = 0;
60#define DPRINTF(x)	if (cs4231_ebus_debug) printf x
61#else
62#define DPRINTF(x)
63#endif
64
65
66struct cs4231_ebus_softc {
67	struct cs4231_softc sc_cs4231;
68
69	void *sc_pint;
70	void *sc_rint;
71	bus_space_tag_t sc_bt;
72	bus_space_handle_t sc_pdmareg; /* playback DMA */
73	bus_space_handle_t sc_cdmareg; /* record DMA */
74};
75
76
77void	cs4231_ebus_attach(device_t, device_t, void *);
78int	cs4231_ebus_match(device_t, cfdata_t, void *);
79
80static int	cs4231_ebus_pint(void *);
81static int	cs4231_ebus_rint(void *);
82
83CFATTACH_DECL_NEW(audiocs_ebus, sizeof(struct cs4231_ebus_softc),
84    cs4231_ebus_match, cs4231_ebus_attach, NULL, NULL);
85
86/* audio_hw_if methods specific to ebus DMA */
87static int	cs4231_ebus_round_blocksize(void *, int, int,
88					    const audio_params_t *);
89static int	cs4231_ebus_trigger_output(void *, void *, void *, int,
90					   void (*)(void *), void *,
91					   const audio_params_t *);
92static int	cs4231_ebus_trigger_input(void *, void *, void *, int,
93					  void (*)(void *), void *,
94					  const audio_params_t *);
95static int	cs4231_ebus_halt_output(void *);
96static int	cs4231_ebus_halt_input(void *);
97
98const struct audio_hw_if audiocs_ebus_hw_if = {
99	.open			= cs4231_open,
100	.close			= cs4231_close,
101	.query_format		= ad1848_query_format,
102	.set_format		= ad1848_set_format,
103	.round_blocksize	= cs4231_ebus_round_blocksize,
104	.commit_settings	= ad1848_commit_settings,
105	.halt_output		= cs4231_ebus_halt_output,
106	.halt_input		= cs4231_ebus_halt_input,
107	.getdev			= cs4231_getdev,
108	.set_port		= cs4231_set_port,
109	.get_port		= cs4231_get_port,
110	.query_devinfo		= cs4231_query_devinfo,
111	.allocm			= cs4231_malloc,
112	.freem			= cs4231_free,
113	.get_props		= cs4231_get_props,
114	.trigger_output		= cs4231_ebus_trigger_output,
115	.trigger_input		= cs4231_ebus_trigger_input,
116	.get_locks		= ad1848_get_locks,
117};
118
119#ifdef AUDIO_DEBUG
120static void	cs4231_ebus_regdump(const char *, struct cs4231_ebus_softc *);
121#endif
122
123static int	cs4231_ebus_dma_reset(bus_space_tag_t, bus_space_handle_t);
124static int	cs4231_ebus_trigger_transfer(struct cs4231_softc *,
125			struct cs_transfer *,
126			bus_space_tag_t, bus_space_handle_t,
127			int, void *, void *, int, void (*)(void *), void *,
128			const audio_params_t *);
129static void	cs4231_ebus_dma_advance(struct cs_transfer *,
130					bus_space_tag_t, bus_space_handle_t);
131static int	cs4231_ebus_dma_intr(struct cs_transfer *,
132				     bus_space_tag_t, bus_space_handle_t,
133				     void *);
134static int	cs4231_ebus_intr(void *);
135
136
137int
138cs4231_ebus_match(device_t parent, cfdata_t cf, void *aux)
139{
140	struct ebus_attach_args *ea;
141	char *compat;
142	int len, total_size;
143
144	ea = aux;
145	if (strcmp(ea->ea_name, AUDIOCS_PROM_NAME) == 0)
146		return 1;
147
148	compat = NULL;
149	if (prom_getprop(ea->ea_node, "compatible", 1, &total_size, &compat) == 0) {
150		do {
151			if (strcmp(compat, AUDIOCS_PROM_NAME) == 0)
152				return 1;
153#ifdef __sparc__
154			/* on KRUPS compatible lists: "cs4231", "ad1848",
155			 * "mwave", and "pnpPNP,b007" */
156			if (strcmp(compat, "cs4231") == 0)
157				return 1;
158#endif
159			len = strlen(compat) + 1;
160			total_size -= len;
161			compat += len;
162		} while (total_size > 0);
163	}
164
165	return 0;
166}
167
168
169void
170cs4231_ebus_attach(device_t parent, device_t self, void *aux)
171{
172	struct cs4231_ebus_softc *ebsc;
173	struct cs4231_softc *sc;
174	struct ebus_attach_args *ea;
175	bus_space_handle_t bh;
176	int i;
177
178	ebsc = device_private(self);
179	sc = &ebsc->sc_cs4231;
180	ea = aux;
181	sc->sc_bustag = ebsc->sc_bt = ea->ea_bustag;
182	sc->sc_dmatag = ea->ea_dmatag;
183
184	ebsc->sc_pint = sparc_softintr_establish(IPL_VM,
185	    (void *)cs4231_ebus_pint, sc);
186	ebsc->sc_rint = sparc_softintr_establish(IPL_VM,
187	    (void *)cs4231_ebus_rint, sc);
188
189	/*
190	 * These are the register we get from the prom:
191	 *	- CS4231 registers
192	 *	- Playback EBus DMA controller
193	 *	- Capture EBus DMA controller
194	 *	- AUXIO audio register (codec powerdown)
195	 *
196	 * Map my registers in, if they aren't already in virtual
197	 * address space.
198	 */
199	if (bus_space_map(ea->ea_bustag, EBUS_ADDR_FROM_REG(&ea->ea_reg[0]),
200		ea->ea_reg[0].size, 0, &bh) != 0) {
201		printf(": unable to map registers\n");
202		return;
203	}
204
205	if (bus_space_map(ea->ea_bustag,
206#ifdef MSIIEP		/* XXX: Krups */
207			  /*
208			   * XXX: map playback DMA registers
209			   * (we just know where they are)
210			   */
211			  BUS_ADDR(0x14, 0x702000), /* XXX: magic num */
212			  EBUS_DMAC_SIZE,
213#else
214			  EBUS_ADDR_FROM_REG(&ea->ea_reg[1]),
215			  ea->ea_reg[1].size,
216#endif
217			  0, &ebsc->sc_pdmareg) != 0)
218	{
219		printf(": unable to map playback DMA registers\n");
220		return;
221	}
222
223	if (bus_space_map(ea->ea_bustag,
224#ifdef MSIIEP		/* XXX: Krups */
225			  /*
226			   * XXX: map capture DMA registers
227			   * (we just know where they are)
228			   */
229			  BUS_ADDR(0x14, 0x704000), /* XXX: magic num */
230			  EBUS_DMAC_SIZE,
231#else
232			  EBUS_ADDR_FROM_REG(&ea->ea_reg[2]),
233			  ea->ea_reg[2].size,
234#endif
235			  0, &ebsc->sc_cdmareg) != 0)
236	{
237		printf(": unable to map capture DMA registers\n");
238		return;
239	}
240
241	ad1848_init_locks(&sc->sc_ad1848, IPL_SCHED);
242
243	/* establish interrupt channels */
244	for (i = 0; i < ea->ea_nintr; ++i)
245		bus_intr_establish(ea->ea_bustag,
246				   ea->ea_intr[i], IPL_SCHED,
247				   cs4231_ebus_intr, ebsc);
248
249	cs4231_common_attach(sc, self, bh);
250	printf("\n");
251
252	/* XXX: todo: move to cs4231_common_attach, pass hw_if as arg? */
253	audio_attach_mi(&audiocs_ebus_hw_if, sc, sc->sc_ad1848.sc_dev);
254}
255
256
257static int
258cs4231_ebus_round_blocksize(void *addr, int blk, int mode,
259			    const audio_params_t *param)
260{
261	int sz;
262
263	/* we want to use DMA burst size of 16 words */
264	sz = blk & -64;
265	if (sz == 0)
266		sz = 64;	/* zero is not a good blocksize */
267	return sz;
268}
269
270
271#ifdef AUDIO_DEBUG
272static void
273cs4231_ebus_regdump(const char *label, struct cs4231_ebus_softc *ebsc)
274{
275	/* char bits[128]; */
276
277	printf("cs4231regdump(%s): regs:", label);
278	/* XXX: dump ebus DMA and aux registers */
279	ad1848_dump_regs(&ebsc->sc_cs4231.sc_ad1848);
280}
281#endif /* AUDIO_DEBUG */
282
283
284/* XXX: nothing CS4231-specific in this code... */
285static int
286cs4231_ebus_dma_reset(bus_space_tag_t dt, bus_space_handle_t dh)
287{
288	u_int32_t csr;
289	int timo;
290
291	/* reset, also clear TC, just in case */
292	bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, EBDMA_RESET | EBDMA_TC);
293
294	for (timo = 50000; timo != 0; --timo) {
295		csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR);
296		if ((csr & (EBDMA_CYC_PEND | EBDMA_DRAIN)) == 0)
297			break;
298	}
299
300	if (timo == 0) {
301		char bits[128];
302		snprintb(bits, sizeof(bits), EBUS_DCSR_BITS, csr);
303		printf("cs4231_ebus_dma_reset: timed out: csr=%s\n", bits);
304		return ETIMEDOUT;
305	}
306
307	bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, csr & ~EBDMA_RESET);
308	return 0;
309}
310
311
312static void
313cs4231_ebus_dma_advance(struct cs_transfer *t, bus_space_tag_t dt,
314			bus_space_handle_t dh)
315{
316	bus_addr_t dmaaddr;
317	bus_size_t dmasize;
318
319	cs4231_transfer_advance(t, &dmaaddr, &dmasize);
320
321	bus_space_write_4(dt, dh, EBUS_DMAC_DNBR, (u_int32_t)dmasize);
322	bus_space_write_4(dt, dh, EBUS_DMAC_DNAR, (u_int32_t)dmaaddr);
323}
324
325
326/*
327 * Trigger transfer "t" using DMA controller at "dt"/"dh".
328 * "iswrite" defines direction of the transfer.
329 */
330static int
331cs4231_ebus_trigger_transfer(
332	struct cs4231_softc *sc,
333	struct cs_transfer *t,
334	bus_space_tag_t dt,
335	bus_space_handle_t dh,
336	int iswrite,
337	void *start, void *end,
338	int blksize,
339	void (*intr)(void *),
340	void *arg,
341	const audio_params_t *param)
342{
343	uint32_t csr;
344	bus_addr_t dmaaddr;
345	bus_size_t dmasize;
346	int ret;
347
348	ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize,
349				   start, end, blksize, intr, arg);
350	if (ret != 0)
351		return ret;
352
353	ret = cs4231_ebus_dma_reset(dt, dh);
354	if (ret != 0)
355		return ret;
356
357	csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR);
358	bus_space_write_4(dt, dh, EBUS_DMAC_DCSR,
359			  csr | EBDMA_EN_NEXT | (iswrite ? EBDMA_WRITE : 0)
360			  | EBDMA_EN_DMA | EBDMA_EN_CNT | EBDMA_INT_EN
361			  | EBDMA_BURST_SIZE_16);
362
363	/* first load: propagated to DACR/DBCR */
364	bus_space_write_4(dt, dh, EBUS_DMAC_DNBR, (uint32_t)dmasize);
365	bus_space_write_4(dt, dh, EBUS_DMAC_DNAR, (uint32_t)dmaaddr);
366
367	/* next load: goes to DNAR/DNBR */
368	cs4231_ebus_dma_advance(t, dt, dh);
369
370	return 0;
371}
372
373
374static int
375cs4231_ebus_trigger_output(void *addr, void *start, void *end, int blksize,
376			   void (*intr)(void *), void *arg,
377			   const audio_params_t *param)
378{
379	struct cs4231_ebus_softc *ebsc;
380	struct cs4231_softc *sc;
381	int cfg, ret;
382
383	ebsc = addr;
384	sc = &ebsc->sc_cs4231;
385	ret = cs4231_ebus_trigger_transfer(sc, &sc->sc_playback,
386					   ebsc->sc_bt, ebsc->sc_pdmareg,
387					   0, /* iswrite */
388					   start, end, blksize,
389					   intr, arg, param);
390	if (ret != 0)
391		return ret;
392
393	ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff);
394	ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff);
395
396	cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
397	ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, cfg | PLAYBACK_ENABLE);
398
399	return 0;
400}
401
402
403static int
404cs4231_ebus_trigger_input(void *addr, void *start, void *end, int blksize,
405			  void (*intr)(void *), void *arg,
406			  const audio_params_t *param)
407{
408	struct cs4231_ebus_softc *ebsc;
409	struct cs4231_softc *sc;
410	int cfg, ret;
411
412	ebsc = addr;
413	sc = &ebsc->sc_cs4231;
414	ret = cs4231_ebus_trigger_transfer(sc, &sc->sc_capture,
415					   ebsc->sc_bt, ebsc->sc_cdmareg,
416					   1, /* iswrite */
417					   start, end, blksize,
418					   intr, arg, param);
419	if (ret != 0)
420		return ret;
421
422	ad_write(&sc->sc_ad1848, CS_LOWER_REC_CNT, 0xff);
423	ad_write(&sc->sc_ad1848, CS_UPPER_REC_CNT, 0xff);
424
425	cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
426	ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, cfg | CAPTURE_ENABLE);
427
428	return 0;
429}
430
431
432static int
433cs4231_ebus_halt_output(void *addr)
434{
435	struct cs4231_ebus_softc *ebsc;
436	struct cs4231_softc *sc;
437	u_int32_t csr;
438	int cfg;
439
440	ebsc = addr;
441	sc = &ebsc->sc_cs4231;
442	sc->sc_playback.t_active = 0;
443
444	csr = bus_space_read_4(ebsc->sc_bt, ebsc->sc_pdmareg, EBUS_DMAC_DCSR);
445	bus_space_write_4(ebsc->sc_bt, ebsc->sc_pdmareg, EBUS_DMAC_DCSR,
446			  csr & ~EBDMA_EN_DMA);
447
448	cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
449	ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,
450		 cfg & ~PLAYBACK_ENABLE);
451
452	return 0;
453}
454
455
456static int
457cs4231_ebus_halt_input(void *addr)
458{
459	struct cs4231_ebus_softc *ebsc;
460	struct cs4231_softc *sc;
461	uint32_t csr;
462	int cfg;
463
464	ebsc = addr;
465	sc = &ebsc->sc_cs4231;
466	sc->sc_capture.t_active = 0;
467
468	csr = bus_space_read_4(ebsc->sc_bt, ebsc->sc_cdmareg, EBUS_DMAC_DCSR);
469	bus_space_write_4(ebsc->sc_bt, ebsc->sc_cdmareg, EBUS_DMAC_DCSR,
470			  csr & ~EBDMA_EN_DMA);
471
472	cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
473	ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,
474		 cfg & ~CAPTURE_ENABLE);
475
476	return 0;
477}
478
479
480static int
481cs4231_ebus_dma_intr(struct cs_transfer *t, bus_space_tag_t dt,
482		     bus_space_handle_t dh, void *sih)
483{
484	uint32_t csr;
485#ifdef AUDIO_DEBUG
486	char bits[128];
487#endif
488
489	/* read DMA status, clear TC bit by writing it back */
490	csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR);
491	bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, csr);
492#ifdef AUDIO_DEBUG
493	snprintb(bits, sizeof(bits), EBUS_DCSR_BITS, csr);
494	DPRINTF(("audiocs: %s dcsr=%s\n", t->t_name, bits));
495#endif
496
497	if (csr & EBDMA_ERR_PEND) {
498		++t->t_ierrcnt.ev_count;
499		printf("audiocs: %s DMA error, resetting\n", t->t_name);
500		cs4231_ebus_dma_reset(dt, dh);
501		/* how to notify audio(9)??? */
502		return 1;
503	}
504
505	if ((csr & EBDMA_INT_PEND) == 0)
506		return 0;
507
508	++t->t_intrcnt.ev_count;
509
510	if ((csr & EBDMA_TC) == 0) { /* can this happen? */
511		printf("audiocs: %s INT_PEND but !TC\n", t->t_name);
512		return 1;
513	}
514
515	if (!t->t_active)
516		return 1;
517
518	cs4231_ebus_dma_advance(t, dt, dh);
519
520	/* call audio(9) framework while DMA is chugging along */
521	if (t->t_intr != NULL)
522		sparc_softintr_schedule(sih);
523	return 1;
524}
525
526
527static int
528cs4231_ebus_intr(void *arg)
529{
530	struct cs4231_ebus_softc *ebsc;
531	struct cs4231_softc *sc;
532	int status;
533	int ret;
534#ifdef AUDIO_DEBUG
535	char bits[128];
536#endif
537
538	ebsc = arg;
539	sc = &ebsc->sc_cs4231;
540	mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock);
541
542	status = ADREAD(&sc->sc_ad1848, AD1848_STATUS);
543
544#ifdef AUDIO_DEBUG
545	if (cs4231_ebus_debug > 1)
546		cs4231_ebus_regdump("audiointr", ebsc);
547
548	snprintb(bits, sizeof(bits), AD_R2_BITS, status);
549	DPRINTF(("%s: status: %s\n", device_xname(sc->sc_ad1848.sc_dev),
550	    bits));
551#endif
552
553	if (status & INTERRUPT_STATUS) {
554#ifdef AUDIO_DEBUG
555		int reason;
556
557		reason = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS);
558	        snprintb(bits, sizeof(bits), CS_I24_BITS, reason);
559		DPRINTF(("%s: i24: %s\n", device_xname(sc->sc_ad1848.sc_dev),
560		    bits));
561#endif
562		/* clear interrupt from ad1848 */
563		ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0);
564	}
565
566	ret = 0;
567
568	if (cs4231_ebus_dma_intr(&sc->sc_capture, ebsc->sc_bt,
569	    ebsc->sc_cdmareg, ebsc->sc_rint) != 0)
570	{
571		++sc->sc_intrcnt.ev_count;
572		ret = 1;
573	}
574
575	if (cs4231_ebus_dma_intr(&sc->sc_playback, ebsc->sc_bt,
576	    ebsc->sc_pdmareg, ebsc->sc_pint) != 0)
577	{
578		++sc->sc_intrcnt.ev_count;
579		ret = 1;
580	}
581
582	mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock);
583
584	return ret;
585}
586
587static int
588cs4231_ebus_pint(void *cookie)
589{
590	struct cs4231_softc *sc = cookie;
591	struct cs_transfer *t = &sc->sc_playback;
592
593	mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock);
594	if (t->t_intr != NULL)
595		(*t->t_intr)(t->t_arg);
596	mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock);
597	return 0;
598}
599
600static int
601cs4231_ebus_rint(void *cookie)
602{
603	struct cs4231_softc *sc = cookie;
604	struct cs_transfer *t = &sc->sc_capture;
605
606	mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock);
607	if (t->t_intr != NULL)
608		(*t->t_intr)(t->t_arg);
609	mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock);
610	return 0;
611}
612