xref: /netbsd-src/sys/arch/zaurus/dev/zaudio.c (revision ede47d01be4803885c8045b421d15d6f54b4a255)
1*ede47d01Sisaki /*	$NetBSD: zaudio.c,v 1.23 2019/06/08 08:02:37 isaki Exp $	*/
2953d3b5bSober /*	$OpenBSD: zaurus_audio.c,v 1.8 2005/08/18 13:23:02 robert Exp $	*/
3953d3b5bSober 
4953d3b5bSober /*
5953d3b5bSober  * Copyright (c) 2005 Christopher Pascoe <pascoe@openbsd.org>
6953d3b5bSober  *
7953d3b5bSober  * Permission to use, copy, modify, and distribute this software for any
8953d3b5bSober  * purpose with or without fee is hereby granted, provided that the above
9953d3b5bSober  * copyright notice and this permission notice appear in all copies.
10953d3b5bSober  *
11953d3b5bSober  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12953d3b5bSober  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13953d3b5bSober  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14953d3b5bSober  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15953d3b5bSober  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16953d3b5bSober  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17953d3b5bSober  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18953d3b5bSober  */
19953d3b5bSober 
2053f7d89dSnonaka /*-
217e1e52beSnonaka  * Copyright (C) 2009 NONAKA Kimihiro <nonaka@netbsd.org>
2253f7d89dSnonaka  * All rights reserved.
2353f7d89dSnonaka  *
2453f7d89dSnonaka  * Redistribution and use in source and binary forms, with or without
2553f7d89dSnonaka  * modification, are permitted provided that the following conditions
2653f7d89dSnonaka  * are met:
2753f7d89dSnonaka  * 1. Redistributions of source code must retain the above copyright
2853f7d89dSnonaka  *    notice, this list of conditions and the following disclaimer.
2953f7d89dSnonaka  * 2. Redistributions in binary form must reproduce the above copyright
3053f7d89dSnonaka  *    notice, this list of conditions and the following disclaimer in the
3153f7d89dSnonaka  *    documentation and/or other materials provided with the distribution.
3253f7d89dSnonaka  *
337e1e52beSnonaka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
347e1e52beSnonaka  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
357e1e52beSnonaka  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
367e1e52beSnonaka  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
377e1e52beSnonaka  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
387e1e52beSnonaka  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
397e1e52beSnonaka  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
407e1e52beSnonaka  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
417e1e52beSnonaka  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
427e1e52beSnonaka  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4353f7d89dSnonaka  */
4453f7d89dSnonaka 
45953d3b5bSober /*
46953d3b5bSober  * TODO:
47953d3b5bSober  *	- powerhooks (currently only works until first suspend)
48953d3b5bSober  */
49953d3b5bSober 
5094ff29c8Snonaka #include "opt_cputypes.h"
51003bdf4cSnonaka 
52953d3b5bSober #include <sys/cdefs.h>
53*ede47d01Sisaki __KERNEL_RCSID(0, "$NetBSD: zaudio.c,v 1.23 2019/06/08 08:02:37 isaki Exp $");
54953d3b5bSober 
55953d3b5bSober #include <sys/param.h>
56953d3b5bSober #include <sys/systm.h>
5794ff29c8Snonaka #include <sys/audioio.h>
58953d3b5bSober #include <sys/callout.h>
59953d3b5bSober #include <sys/device.h>
60003bdf4cSnonaka #include <sys/mutex.h>
61953d3b5bSober 
62e622eac4Sisaki #include <dev/audio/audio_if.h>
63003bdf4cSnonaka 
64003bdf4cSnonaka #include <dev/i2c/i2cvar.h>
65953d3b5bSober 
66953d3b5bSober #include <arm/xscale/pxa2x0reg.h>
67953d3b5bSober #include <arm/xscale/pxa2x0var.h>
68953d3b5bSober #include <arm/xscale/pxa2x0_i2s.h>
69953d3b5bSober 
70003bdf4cSnonaka #include <zaurus/zaurus/zaurus_var.h>
7194ff29c8Snonaka #include <zaurus/dev/zaudiovar.h>
7294ff29c8Snonaka #if defined(CPU_XSCALE_PXA270)
7394ff29c8Snonaka #include <zaurus/dev/wm8750var.h>
7494ff29c8Snonaka #endif
7594ff29c8Snonaka #if defined(CPU_XSCALE_PXA250)
7694ff29c8Snonaka #include <zaurus/dev/wm8731var.h>
7794ff29c8Snonaka #endif
78003bdf4cSnonaka 
79003bdf4cSnonaka static int	zaudio_match(device_t, cfdata_t, void *);
80003bdf4cSnonaka static void	zaudio_attach(device_t, device_t, void *);
81003bdf4cSnonaka 
821a686006Snonaka CFATTACH_DECL_NEW(zaudio, sizeof(struct zaudio_softc),
83664df27bSnonaka     zaudio_match, zaudio_attach, NULL, NULL);
84953d3b5bSober 
85e622eac4Sisaki static const struct audio_format zaudio_formats[] = {
86e622eac4Sisaki 	{
87e622eac4Sisaki 		.mode		= AUMODE_PLAY | AUMODE_RECORD,
88e622eac4Sisaki 		.encoding	= AUDIO_ENCODING_SLINEAR_LE,
89e622eac4Sisaki 		.validbits	= 16,
90e622eac4Sisaki 		.precision	= 16,
91e622eac4Sisaki 		.channels	= 2,
92e622eac4Sisaki 		.channel_mask	= AUFMT_STEREO,
93e622eac4Sisaki 		.frequency_type	= 6,
94e622eac4Sisaki 		.frequency	= { 8000, 11025, 16000, 22050, 44100, 48000 },
95e622eac4Sisaki 	}
96e622eac4Sisaki };
97e622eac4Sisaki #define ZAUDIO_NFORMATS	__arraycount(zaudio_formats)
98e622eac4Sisaki 
99953d3b5bSober static int
zaudio_match(device_t parent,cfdata_t cf,void * aux)1001a686006Snonaka zaudio_match(device_t parent, cfdata_t cf, void *aux)
101953d3b5bSober {
102003bdf4cSnonaka 	struct i2c_attach_args *ia = aux;
103953d3b5bSober 
10494ff29c8Snonaka 	if (ZAURUS_ISC1000 || ZAURUS_ISC3000) {
10594ff29c8Snonaka #if defined(CPU_XSCALE_PXA270)
10694ff29c8Snonaka 		return wm8750_match(parent, cf, ia);
10794ff29c8Snonaka #endif
10894ff29c8Snonaka 	} else if (ZAURUS_ISC860) {
10994ff29c8Snonaka #if defined(CPU_XSCALE_PXA250)
11094ff29c8Snonaka 		return wm8731_match(parent, cf, ia);
11194ff29c8Snonaka #endif
112003bdf4cSnonaka 	}
113003bdf4cSnonaka 	return 0;
114953d3b5bSober }
115953d3b5bSober 
116953d3b5bSober static void
zaudio_attach(device_t parent,device_t self,void * aux)1171a686006Snonaka zaudio_attach(device_t parent, device_t self, void *aux)
118953d3b5bSober {
1191a686006Snonaka 	struct zaudio_softc *sc = device_private(self);
120003bdf4cSnonaka 	struct i2c_attach_args *ia = aux;
121953d3b5bSober 
12294ff29c8Snonaka 	sc->sc_dev = self;
123003bdf4cSnonaka 	sc->sc_i2c = ia->ia_tag;
12494ff29c8Snonaka 
1258a962f23Sjmcneill 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
1268a962f23Sjmcneill 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
12794ff29c8Snonaka 	callout_init(&sc->sc_to, 0);
1281a686006Snonaka 
129003bdf4cSnonaka 	sc->sc_i2s.sc_iot = &pxa2x0_bs_tag;
130003bdf4cSnonaka 	sc->sc_i2s.sc_dmat = &pxa2x0_bus_dma_tag;
131953d3b5bSober 	sc->sc_i2s.sc_size = PXA2X0_I2S_SIZE;
1328a962f23Sjmcneill 	sc->sc_i2s.sc_intr_lock = &sc->sc_intr_lock;
133953d3b5bSober 	if (pxa2x0_i2s_attach_sub(&sc->sc_i2s)) {
134003bdf4cSnonaka 		aprint_error_dev(self, "unable to attach I2S\n");
135953d3b5bSober 		return;
136953d3b5bSober 	}
137953d3b5bSober 
13894ff29c8Snonaka 	if (ZAURUS_ISC1000 || ZAURUS_ISC3000) {
13994ff29c8Snonaka #if defined(CPU_XSCALE_PXA270)
14094ff29c8Snonaka 		wm8750_attach(parent, self, ia);
141003bdf4cSnonaka #endif
14294ff29c8Snonaka 	} else if (ZAURUS_ISC860) {
14394ff29c8Snonaka #if defined(CPU_XSCALE_PXA250)
14494ff29c8Snonaka 		wm8731_attach(parent, self, ia);
14594ff29c8Snonaka #endif
146003bdf4cSnonaka 	}
147003bdf4cSnonaka 
148953d3b5bSober 	return;
149953d3b5bSober }
150953d3b5bSober 
151f19ed1a8Speter /*
152f19ed1a8Speter  * audio operation functions.
153f19ed1a8Speter  */
15494ff29c8Snonaka int
zaudio_open(void * hdl,int flags)155953d3b5bSober zaudio_open(void *hdl, int flags)
156953d3b5bSober {
157953d3b5bSober 	struct zaudio_softc *sc = hdl;
158953d3b5bSober 
159953d3b5bSober 	/* Power on the I2S bus and codec */
160953d3b5bSober 	pxa2x0_i2s_open(&sc->sc_i2s);
161953d3b5bSober 
162953d3b5bSober 	return 0;
163953d3b5bSober }
164953d3b5bSober 
16594ff29c8Snonaka void
zaudio_close(void * hdl)166953d3b5bSober zaudio_close(void *hdl)
167953d3b5bSober {
168953d3b5bSober 	struct zaudio_softc *sc = hdl;
169953d3b5bSober 
170953d3b5bSober 	/* Power off the I2S bus and codec */
171953d3b5bSober 	pxa2x0_i2s_close(&sc->sc_i2s);
172953d3b5bSober }
173953d3b5bSober 
17494ff29c8Snonaka int
zaudio_query_format(void * hdl,audio_format_query_t * afp)175e622eac4Sisaki zaudio_query_format(void *hdl, audio_format_query_t *afp)
176e622eac4Sisaki {
177e622eac4Sisaki 
178e622eac4Sisaki 	return audio_query_format(zaudio_formats, ZAUDIO_NFORMATS, afp);
179e622eac4Sisaki }
180e622eac4Sisaki 
181e622eac4Sisaki int
zaudio_set_format(void * hdl,int setmode,const audio_params_t * play,const audio_params_t * rec,audio_filter_reg_t * pfil,audio_filter_reg_t * rfil)182e622eac4Sisaki zaudio_set_format(void *hdl, int setmode,
183e622eac4Sisaki     const audio_params_t *play, const audio_params_t *rec,
184e622eac4Sisaki     audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
185e622eac4Sisaki {
186e622eac4Sisaki 	struct zaudio_softc *sc = hdl;
187e622eac4Sisaki 
188e622eac4Sisaki 	/* *play and *rec are the identical because !AUDIO_PROP_INDEPENDENT. */
189e622eac4Sisaki 
190e622eac4Sisaki 	if (setmode == AUMODE_RECORD)
191e622eac4Sisaki 		pxa2x0_i2s_setspeed(&sc->sc_i2s, rec->sample_rate);
192e622eac4Sisaki 	else
193e622eac4Sisaki 		pxa2x0_i2s_setspeed(&sc->sc_i2s, play->sample_rate);
194e622eac4Sisaki 
195e622eac4Sisaki 	return 0;
196e622eac4Sisaki }
197e622eac4Sisaki 
198e622eac4Sisaki int
zaudio_round_blocksize(void * hdl,int bs,int mode,const audio_params_t * param)199f19ed1a8Speter zaudio_round_blocksize(void *hdl, int bs, int mode, const audio_params_t *param)
200953d3b5bSober {
201953d3b5bSober 	struct zaudio_softc *sc = hdl;
202953d3b5bSober 
203f19ed1a8Speter 	return pxa2x0_i2s_round_blocksize(&sc->sc_i2s, bs, mode, param);
204953d3b5bSober }
205953d3b5bSober 
20694ff29c8Snonaka void *
zaudio_allocm(void * hdl,int direction,size_t size)2078a962f23Sjmcneill zaudio_allocm(void *hdl, int direction, size_t size)
208f19ed1a8Speter {
209f19ed1a8Speter 	struct zaudio_softc *sc = hdl;
210f19ed1a8Speter 
2118a962f23Sjmcneill 	return pxa2x0_i2s_allocm(&sc->sc_i2s, direction, size);
212f19ed1a8Speter }
213f19ed1a8Speter 
21494ff29c8Snonaka void
zaudio_freem(void * hdl,void * ptr,size_t size)2158a962f23Sjmcneill zaudio_freem(void *hdl, void *ptr, size_t size)
216f19ed1a8Speter {
217f19ed1a8Speter 	struct zaudio_softc *sc = hdl;
218f19ed1a8Speter 
2198a962f23Sjmcneill 	return pxa2x0_i2s_freem(&sc->sc_i2s, ptr, size);
220f19ed1a8Speter }
221f19ed1a8Speter 
22294ff29c8Snonaka size_t
zaudio_round_buffersize(void * hdl,int direction,size_t bufsize)223f19ed1a8Speter zaudio_round_buffersize(void *hdl, int direction, size_t bufsize)
224f19ed1a8Speter {
225f19ed1a8Speter 	struct zaudio_softc *sc = hdl;
226f19ed1a8Speter 
227f19ed1a8Speter 	return pxa2x0_i2s_round_buffersize(&sc->sc_i2s, direction, bufsize);
228f19ed1a8Speter }
229f19ed1a8Speter 
23094ff29c8Snonaka int
zaudio_get_props(void * hdl)231953d3b5bSober zaudio_get_props(void *hdl)
232953d3b5bSober {
233f19ed1a8Speter 
234*ede47d01Sisaki 	return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE;
235953d3b5bSober }
236953d3b5bSober 
23794ff29c8Snonaka void
zaudio_get_locks(void * hdl,kmutex_t ** intr,kmutex_t ** thread)2388a962f23Sjmcneill zaudio_get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread)
2398a962f23Sjmcneill {
2408a962f23Sjmcneill 	struct zaudio_softc *sc = hdl;
2418a962f23Sjmcneill 
2428a962f23Sjmcneill 	*intr = &sc->sc_intr_lock;
2438a962f23Sjmcneill 	*thread = &sc->sc_lock;
2448a962f23Sjmcneill }
245