zaudio.c revision 1.1 1 1.1 ober /* $NetBSD: zaudio.c,v 1.1 2006/12/16 05:21:04 ober Exp $ */
2 1.1 ober /* $OpenBSD: zaurus_audio.c,v 1.8 2005/08/18 13:23:02 robert Exp $ */
3 1.1 ober
4 1.1 ober /*
5 1.1 ober * Copyright (c) 2005 Christopher Pascoe <pascoe (at) openbsd.org>
6 1.1 ober *
7 1.1 ober * Permission to use, copy, modify, and distribute this software for any
8 1.1 ober * purpose with or without fee is hereby granted, provided that the above
9 1.1 ober * copyright notice and this permission notice appear in all copies.
10 1.1 ober *
11 1.1 ober * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 1.1 ober * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 1.1 ober * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 1.1 ober * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 1.1 ober * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 1.1 ober * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 1.1 ober * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 1.1 ober */
19 1.1 ober
20 1.1 ober /*
21 1.1 ober * TODO:
22 1.1 ober * - powerhooks (currently only works until first suspend)
23 1.1 ober * - record support
24 1.1 ober */
25 1.1 ober
26 1.1 ober #include <sys/cdefs.h>
27 1.1 ober __KERNEL_RCSID(0, "$NetBSD");
28 1.1 ober
29 1.1 ober #include <sys/param.h>
30 1.1 ober #include <sys/systm.h>
31 1.1 ober #include <sys/callout.h>
32 1.1 ober #include <sys/device.h>
33 1.1 ober #include <sys/malloc.h>
34 1.1 ober #include <sys/kernel.h>
35 1.1 ober #include <sys/audioio.h>
36 1.1 ober
37 1.1 ober #include <machine/intr.h>
38 1.1 ober #include <machine/bus.h>
39 1.1 ober
40 1.1 ober #include <arm/xscale/pxa2x0reg.h>
41 1.1 ober #include <arm/xscale/pxa2x0var.h>
42 1.1 ober #include <arm/xscale/pxa2x0_i2c.h>
43 1.1 ober #include <arm/xscale/pxa2x0_i2s.h>
44 1.1 ober #include <arm/xscale/pxa2x0_dmac.h>
45 1.1 ober #include <arm/xscale/pxa2x0_gpio.h>
46 1.1 ober
47 1.1 ober #include <dev/audio_if.h>
48 1.1 ober #include <dev/mulaw.h>
49 1.1 ober #include <dev/auconv.h>
50 1.1 ober
51 1.1 ober #include <zaurus/dev/wm8750reg.h>
52 1.1 ober #include <zaurus/dev/scoopvar.h>
53 1.1 ober
54 1.1 ober #define WM8750_ADDRESS 0x1B
55 1.1 ober #define SPKR_VOLUME 112
56 1.1 ober
57 1.1 ober #define wm8750_write(sc, reg, val) \
58 1.1 ober pxa2x0_i2c_write_2(&sc->sc_i2c, WM8750_ADDRESS, \
59 1.1 ober (((reg) << 9) | ((val) & 0x1ff)))
60 1.1 ober
61 1.1 ober static int zaudio_match(struct device *, struct cfdata *, void *);
62 1.1 ober static void zaudio_attach(struct device *, struct device *, void *);
63 1.1 ober static int zaudio_detach(struct device *, int);
64 1.1 ober static void zaudio_power(int, void *);
65 1.1 ober
66 1.1 ober #define ZAUDIO_OP_SPKR 0
67 1.1 ober #define ZAUDIO_OP_HP 1
68 1.1 ober
69 1.1 ober #define ZAUDIO_JACK_STATE_OUT 0
70 1.1 ober #define ZAUDIO_JACK_STATE_IN 1
71 1.1 ober #define ZAUDIO_JACK_STATE_INS 2
72 1.1 ober #define ZAUDIO_JACK_STATE_REM 3
73 1.1 ober
74 1.1 ober /* GPIO pins */
75 1.1 ober #define GPIO_HP_IN_C3000 116
76 1.1 ober
77 1.1 ober struct zaudio_volume {
78 1.1 ober u_int8_t left;
79 1.1 ober u_int8_t right;
80 1.1 ober };
81 1.1 ober
82 1.1 ober struct zaudio_softc {
83 1.1 ober struct device sc_dev;
84 1.1 ober
85 1.1 ober /* i2s device softc */
86 1.1 ober /* NB: pxa2x0_i2s requires this to be the second struct member */
87 1.1 ober struct pxa2x0_i2s_softc sc_i2s;
88 1.1 ober
89 1.1 ober /* i2c device softc */
90 1.1 ober struct pxa2x0_i2c_softc sc_i2c;
91 1.1 ober
92 1.1 ober void *sc_powerhook;
93 1.1 ober int sc_playing;
94 1.1 ober
95 1.1 ober struct zaudio_volume sc_volume[2];
96 1.1 ober char sc_unmute[2];
97 1.1 ober
98 1.1 ober int sc_state;
99 1.1 ober int sc_icount;
100 1.1 ober struct callout sc_to;
101 1.1 ober };
102 1.1 ober
103 1.1 ober CFATTACH_DECL(zaudio, sizeof(struct zaudio_softc),
104 1.1 ober zaudio_match, zaudio_attach, zaudio_detach, NULL);
105 1.1 ober
106 1.1 ober struct audio_device wm8750_device = {
107 1.1 ober "WM8750",
108 1.1 ober "1.0",
109 1.1 ober "wm"
110 1.1 ober };
111 1.1 ober
112 1.1 ober void zaudio_init(struct zaudio_softc *);
113 1.1 ober int zaudio_jack_intr(void *);
114 1.1 ober void zaudio_jack(void *);
115 1.1 ober void zaudio_standby(struct zaudio_softc *);
116 1.1 ober void zaudio_update_volume(struct zaudio_softc *, int);
117 1.1 ober void zaudio_update_mutes(struct zaudio_softc *);
118 1.1 ober void zaudio_play_setup(struct zaudio_softc *);
119 1.1 ober int zaudio_open(void *, int);
120 1.1 ober void zaudio_close(void *);
121 1.1 ober int zaudio_query_encoding(void *, struct audio_encoding *);
122 1.1 ober int zaudio_set_params(void *, int, int, struct audio_params *,
123 1.1 ober struct audio_params *);
124 1.1 ober int zaudio_halt_output(void *);
125 1.1 ober int zaudio_halt_input(void *);
126 1.1 ober int zaudio_getdev(void *, struct audio_device *);
127 1.1 ober int zaudio_set_port(void *, struct mixer_ctrl *);
128 1.1 ober int zaudio_get_port(void *, struct mixer_ctrl *);
129 1.1 ober int zaudio_query_devinfo(void *, struct mixer_devinfo *);
130 1.1 ober int zaudio_get_props(void *);
131 1.1 ober int zaudio_start_output(void *, void *, int, void (*)(void *), void *);
132 1.1 ober int zaudio_start_input(void *, void *, int, void (*)(void *), void *);
133 1.1 ober
134 1.1 ober struct audio_hw_if wm8750_hw_if = {
135 1.1 ober zaudio_open,
136 1.1 ober zaudio_close,
137 1.1 ober NULL /* zaudio_drain */,
138 1.1 ober zaudio_query_encoding,
139 1.1 ober zaudio_set_params,
140 1.1 ober pxa2x0_i2s_round_blocksize,
141 1.1 ober NULL /* zaudio_commit_settings */,
142 1.1 ober NULL /* zaudio_init_output */,
143 1.1 ober NULL /* zaudio_init_input */,
144 1.1 ober zaudio_start_output,
145 1.1 ober zaudio_start_input,
146 1.1 ober zaudio_halt_output,
147 1.1 ober zaudio_halt_input,
148 1.1 ober NULL /* zaudio_speaker_ctl */,
149 1.1 ober zaudio_getdev,
150 1.1 ober NULL /* zaudio_setfd */,
151 1.1 ober zaudio_set_port,
152 1.1 ober zaudio_get_port,
153 1.1 ober zaudio_query_devinfo,
154 1.1 ober pxa2x0_i2s_allocm,
155 1.1 ober pxa2x0_i2s_freem,
156 1.1 ober pxa2x0_i2s_round_buffersize,
157 1.1 ober pxa2x0_i2s_mappage,
158 1.1 ober zaudio_get_props,
159 1.1 ober NULL /* zaudio_trigger_output */,
160 1.1 ober NULL /* zaudio_trigger_input */
161 1.1 ober };
162 1.1 ober
163 1.1 ober static const unsigned short playback_registers[][2] = {
164 1.1 ober /* Unmute DAC */
165 1.1 ober { ADCDACCTL_REG, 0x000 },
166 1.1 ober
167 1.1 ober /* 16 bit audio words */
168 1.1 ober { AUDINT_REG, AUDINT_SET_FORMAT(2) },
169 1.1 ober
170 1.1 ober /* Enable thermal protection, power */
171 1.1 ober { ADCTL1_REG, ADCTL1_TSDEN | ADCTL1_SET_VSEL(3) },
172 1.1 ober
173 1.1 ober /* Enable speaker driver, DAC oversampling */
174 1.1 ober { ADCTL2_REG, ADCTL2_ROUT2INV | ADCTL2_DACOSR },
175 1.1 ober
176 1.1 ober /* Set DAC voltage references */
177 1.1 ober { PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(1) | PWRMGMT1_VREF },
178 1.1 ober
179 1.1 ober /* Direct DACs to output mixers */
180 1.1 ober { LOUTMIX1_REG, LOUTMIX1_LD2LO },
181 1.1 ober { ROUTMIX2_REG, ROUTMIX2_RD2RO },
182 1.1 ober
183 1.1 ober /* End of list */
184 1.1 ober { 0xffff, 0xffff }
185 1.1 ober };
186 1.1 ober
187 1.1 ober static int
188 1.1 ober zaudio_match(struct device *parent, struct cfdata *cf, void *aux)
189 1.1 ober {
190 1.1 ober
191 1.1 ober return 1;
192 1.1 ober }
193 1.1 ober
194 1.1 ober static void
195 1.1 ober zaudio_attach(struct device *parent, struct device *self, void *aux)
196 1.1 ober {
197 1.1 ober struct zaudio_softc *sc = (struct zaudio_softc *)self;
198 1.1 ober struct pxaip_attach_args *pxa = aux;
199 1.1 ober int err;
200 1.1 ober
201 1.1 ober sc->sc_powerhook = powerhook_establish(zaudio_power, sc);
202 1.1 ober if (sc->sc_powerhook == NULL) {
203 1.1 ober printf(": unable to establish powerhook\n");
204 1.1 ober return;
205 1.1 ober }
206 1.1 ober
207 1.1 ober sc->sc_i2s.sc_iot = pxa->pxa_iot;
208 1.1 ober sc->sc_i2s.sc_dmat = pxa->pxa_dmat;
209 1.1 ober sc->sc_i2s.sc_size = PXA2X0_I2S_SIZE;
210 1.1 ober if (pxa2x0_i2s_attach_sub(&sc->sc_i2s)) {
211 1.1 ober printf(": unable to attach I2S\n");
212 1.1 ober goto fail_i2s;
213 1.1 ober }
214 1.1 ober
215 1.1 ober sc->sc_i2c.sc_iot = pxa->pxa_iot;
216 1.1 ober sc->sc_i2c.sc_size = PXA2X0_I2C_SIZE;
217 1.1 ober if (pxa2x0_i2c_attach_sub(&sc->sc_i2c)) {
218 1.1 ober printf(": unable to attach I2C\n");
219 1.1 ober goto fail_i2c;
220 1.1 ober }
221 1.1 ober
222 1.1 ober /* Check for an I2C response from the wm8750 */
223 1.1 ober pxa2x0_i2c_open(&sc->sc_i2c);
224 1.1 ober err = wm8750_write(sc, RESET_REG, 0);
225 1.1 ober pxa2x0_i2c_close(&sc->sc_i2c);
226 1.1 ober
227 1.1 ober if (err) {
228 1.1 ober printf(": codec failed to respond\n");
229 1.1 ober goto fail_probe;
230 1.1 ober }
231 1.1 ober delay(100);
232 1.1 ober
233 1.1 ober /* Speaker on, headphones off by default. */
234 1.1 ober sc->sc_volume[ZAUDIO_OP_SPKR].left = 240;
235 1.1 ober sc->sc_unmute[ZAUDIO_OP_SPKR] = 1;
236 1.1 ober sc->sc_volume[ZAUDIO_OP_HP].left = 180;
237 1.1 ober sc->sc_volume[ZAUDIO_OP_HP].right = 180;
238 1.1 ober sc->sc_unmute[ZAUDIO_OP_HP] = 0;
239 1.1 ober
240 1.1 ober /* Configure headphone jack state change handling. */
241 1.1 ober callout_init(&sc->sc_to);
242 1.1 ober callout_setfunc(&sc->sc_to, zaudio_jack, sc);
243 1.1 ober pxa2x0_gpio_set_function(GPIO_HP_IN_C3000, GPIO_IN);
244 1.1 ober (void)pxa2x0_gpio_intr_establish(GPIO_HP_IN_C3000,
245 1.1 ober IST_EDGE_BOTH, IPL_BIO, zaudio_jack_intr, sc, "hpjk");
246 1.1 ober
247 1.1 ober zaudio_init(sc);
248 1.1 ober
249 1.1 ober printf(": I2C, I2S, WM8750 Audio\n");
250 1.1 ober
251 1.1 ober audio_attach_mi(&wm8750_hw_if, sc, &sc->sc_dev);
252 1.1 ober
253 1.1 ober return;
254 1.1 ober
255 1.1 ober fail_probe:
256 1.1 ober pxa2x0_i2c_detach_sub(&sc->sc_i2c);
257 1.1 ober fail_i2c:
258 1.1 ober pxa2x0_i2s_detach_sub(&sc->sc_i2s);
259 1.1 ober fail_i2s:
260 1.1 ober powerhook_disestablish(sc->sc_powerhook);
261 1.1 ober }
262 1.1 ober
263 1.1 ober int
264 1.1 ober zaudio_detach(struct device *self, int flags)
265 1.1 ober {
266 1.1 ober struct zaudio_softc *sc = (struct zaudio_softc *)self;
267 1.1 ober
268 1.1 ober if (sc->sc_powerhook != NULL) {
269 1.1 ober powerhook_disestablish(sc->sc_powerhook);
270 1.1 ober sc->sc_powerhook = NULL;
271 1.1 ober }
272 1.1 ober
273 1.1 ober pxa2x0_i2c_detach_sub(&sc->sc_i2c);
274 1.1 ober pxa2x0_i2s_detach_sub(&sc->sc_i2s);
275 1.1 ober
276 1.1 ober return 0;
277 1.1 ober }
278 1.1 ober
279 1.1 ober static void
280 1.1 ober zaudio_power(int why, void *arg)
281 1.1 ober {
282 1.1 ober struct zaudio_softc *sc = arg;
283 1.1 ober
284 1.1 ober switch (why) {
285 1.1 ober case PWR_STANDBY:
286 1.1 ober case PWR_SUSPEND:
287 1.1 ober callout_stop(&sc->sc_to);
288 1.1 ober zaudio_standby(sc);
289 1.1 ober break;
290 1.1 ober
291 1.1 ober case PWR_RESUME:
292 1.1 ober pxa2x0_i2s_init(&sc->sc_i2s);
293 1.1 ober pxa2x0_i2c_init(&sc->sc_i2c);
294 1.1 ober zaudio_init(sc);
295 1.1 ober break;
296 1.1 ober }
297 1.1 ober }
298 1.1 ober
299 1.1 ober void
300 1.1 ober zaudio_init(struct zaudio_softc *sc)
301 1.1 ober {
302 1.1 ober pxa2x0_i2c_open(&sc->sc_i2c);
303 1.1 ober
304 1.1 ober /* Reset the codec */
305 1.1 ober wm8750_write(sc, RESET_REG, 0);
306 1.1 ober delay(100);
307 1.1 ober
308 1.1 ober /* Switch to standby power only */
309 1.1 ober wm8750_write(sc, PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(2));
310 1.1 ober wm8750_write(sc, PWRMGMT2_REG, 0);
311 1.1 ober
312 1.1 ober /* Configure digital interface for I2S */
313 1.1 ober wm8750_write(sc, AUDINT_REG, AUDINT_SET_FORMAT(2));
314 1.1 ober
315 1.1 ober /* Initialise volume levels */
316 1.1 ober zaudio_update_volume(sc, ZAUDIO_OP_SPKR);
317 1.1 ober zaudio_update_volume(sc, ZAUDIO_OP_HP);
318 1.1 ober scoop_set_headphone(0);
319 1.1 ober
320 1.1 ober pxa2x0_i2c_close(&sc->sc_i2c);
321 1.1 ober
322 1.1 ober /* Assume that the jack state has changed. */
323 1.1 ober zaudio_jack(sc);
324 1.1 ober
325 1.1 ober }
326 1.1 ober
327 1.1 ober int
328 1.1 ober zaudio_jack_intr(void *v)
329 1.1 ober {
330 1.1 ober struct zaudio_softc *sc = v;
331 1.1 ober
332 1.1 ober if (!callout_active(&sc->sc_to))
333 1.1 ober zaudio_jack(sc);
334 1.1 ober
335 1.1 ober return (1);
336 1.1 ober }
337 1.1 ober
338 1.1 ober void
339 1.1 ober zaudio_jack(void *v)
340 1.1 ober {
341 1.1 ober struct zaudio_softc *sc = v;
342 1.1 ober
343 1.1 ober switch (sc->sc_state) {
344 1.1 ober case ZAUDIO_JACK_STATE_OUT:
345 1.1 ober if (pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
346 1.1 ober sc->sc_state = ZAUDIO_JACK_STATE_INS;
347 1.1 ober sc->sc_icount = 0;
348 1.1 ober }
349 1.1 ober break;
350 1.1 ober case ZAUDIO_JACK_STATE_INS:
351 1.1 ober if (sc->sc_icount++ > 2) {
352 1.1 ober if (pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
353 1.1 ober sc->sc_state = ZAUDIO_JACK_STATE_IN;
354 1.1 ober sc->sc_unmute[ZAUDIO_OP_SPKR] = 0;
355 1.1 ober sc->sc_unmute[ZAUDIO_OP_HP] = 1;
356 1.1 ober goto update_mutes;
357 1.1 ober } else
358 1.1 ober sc->sc_state = ZAUDIO_JACK_STATE_OUT;
359 1.1 ober }
360 1.1 ober break;
361 1.1 ober case ZAUDIO_JACK_STATE_IN:
362 1.1 ober if (!pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
363 1.1 ober sc->sc_state = ZAUDIO_JACK_STATE_REM;
364 1.1 ober sc->sc_icount = 0;
365 1.1 ober }
366 1.1 ober break;
367 1.1 ober case ZAUDIO_JACK_STATE_REM:
368 1.1 ober if (sc->sc_icount++ > 2) {
369 1.1 ober if (!pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
370 1.1 ober sc->sc_state = ZAUDIO_JACK_STATE_OUT;
371 1.1 ober sc->sc_unmute[ZAUDIO_OP_SPKR] = 1;
372 1.1 ober sc->sc_unmute[ZAUDIO_OP_HP] = 0;
373 1.1 ober goto update_mutes;
374 1.1 ober } else
375 1.1 ober sc->sc_state = ZAUDIO_JACK_STATE_IN;
376 1.1 ober }
377 1.1 ober break;
378 1.1 ober }
379 1.1 ober
380 1.1 ober callout_schedule(&sc->sc_to, hz/4);
381 1.1 ober return;
382 1.1 ober
383 1.1 ober update_mutes:
384 1.1 ober callout_stop(&sc->sc_to);
385 1.1 ober
386 1.1 ober if (sc->sc_playing) {
387 1.1 ober pxa2x0_i2c_open(&sc->sc_i2c);
388 1.1 ober zaudio_update_mutes(sc);
389 1.1 ober pxa2x0_i2c_close(&sc->sc_i2c);
390 1.1 ober }
391 1.1 ober }
392 1.1 ober
393 1.1 ober void
394 1.1 ober zaudio_standby(struct zaudio_softc *sc)
395 1.1 ober {
396 1.1 ober pxa2x0_i2c_open(&sc->sc_i2c);
397 1.1 ober
398 1.1 ober /* Switch codec to standby power only */
399 1.1 ober wm8750_write(sc, PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(2));
400 1.1 ober wm8750_write(sc, PWRMGMT2_REG, 0);
401 1.1 ober
402 1.1 ober scoop_set_headphone(0);
403 1.1 ober
404 1.1 ober pxa2x0_i2c_close(&sc->sc_i2c);
405 1.1 ober }
406 1.1 ober
407 1.1 ober void
408 1.1 ober zaudio_update_volume(struct zaudio_softc *sc, int output)
409 1.1 ober {
410 1.1 ober switch(output) {
411 1.1 ober case ZAUDIO_OP_SPKR:
412 1.1 ober wm8750_write(sc, LOUT2VOL_REG, LOUT2VOL_LO2VU | LOUT2VOL_LO2ZC |
413 1.1 ober LOUT2VOL_SET_LOUT2VOL(sc->sc_volume[ZAUDIO_OP_SPKR
414 1.1 ober ].left >> 1));
415 1.1 ober wm8750_write(sc, ROUT2VOL_REG, ROUT2VOL_RO2VU | ROUT2VOL_RO2ZC |
416 1.1 ober ROUT2VOL_SET_ROUT2VOL(sc->sc_volume[ZAUDIO_OP_SPKR
417 1.1 ober ].left >> 1));
418 1.1 ober break;
419 1.1 ober case ZAUDIO_OP_HP:
420 1.1 ober wm8750_write(sc, LOUT1VOL_REG, LOUT1VOL_LO1VU | LOUT1VOL_LO1ZC |
421 1.1 ober LOUT1VOL_SET_LOUT1VOL(sc->sc_volume[ZAUDIO_OP_HP
422 1.1 ober ].left >> 1));
423 1.1 ober wm8750_write(sc, ROUT1VOL_REG, ROUT1VOL_RO1VU | ROUT1VOL_RO1ZC |
424 1.1 ober ROUT1VOL_SET_ROUT1VOL(sc->sc_volume[ZAUDIO_OP_HP
425 1.1 ober ].right >> 1));
426 1.1 ober break;
427 1.1 ober }
428 1.1 ober }
429 1.1 ober
430 1.1 ober void
431 1.1 ober zaudio_update_mutes(struct zaudio_softc *sc)
432 1.1 ober {
433 1.1 ober unsigned short val;
434 1.1 ober
435 1.1 ober val = PWRMGMT2_DACL | PWRMGMT2_DACR;
436 1.1 ober
437 1.1 ober if (sc->sc_unmute[ZAUDIO_OP_SPKR])
438 1.1 ober val |= PWRMGMT2_LOUT2 | PWRMGMT2_ROUT2;
439 1.1 ober
440 1.1 ober if (sc->sc_unmute[ZAUDIO_OP_HP])
441 1.1 ober val |= PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1;
442 1.1 ober
443 1.1 ober wm8750_write(sc, PWRMGMT2_REG, val);
444 1.1 ober
445 1.1 ober scoop_set_headphone(sc->sc_unmute[ZAUDIO_OP_HP]);
446 1.1 ober }
447 1.1 ober
448 1.1 ober void
449 1.1 ober zaudio_play_setup(struct zaudio_softc *sc)
450 1.1 ober {
451 1.1 ober int i = 0;
452 1.1 ober
453 1.1 ober pxa2x0_i2c_open(&sc->sc_i2c);
454 1.1 ober
455 1.1 ober /* Program the codec with playback settings */
456 1.1 ober while (playback_registers[i][0] != 0xffff) {
457 1.1 ober wm8750_write(sc, playback_registers[i][0],
458 1.1 ober playback_registers[i][1]);
459 1.1 ober i++;
460 1.1 ober }
461 1.1 ober zaudio_update_mutes(sc);
462 1.1 ober
463 1.1 ober pxa2x0_i2c_close(&sc->sc_i2c);
464 1.1 ober }
465 1.1 ober
466 1.1 ober int
467 1.1 ober zaudio_open(void *hdl, int flags)
468 1.1 ober {
469 1.1 ober struct zaudio_softc *sc = hdl;
470 1.1 ober
471 1.1 ober /* Power on the I2S bus and codec */
472 1.1 ober pxa2x0_i2s_open(&sc->sc_i2s);
473 1.1 ober
474 1.1 ober return 0;
475 1.1 ober }
476 1.1 ober
477 1.1 ober void
478 1.1 ober zaudio_close(void *hdl)
479 1.1 ober {
480 1.1 ober struct zaudio_softc *sc = hdl;
481 1.1 ober
482 1.1 ober /* Power off the I2S bus and codec */
483 1.1 ober pxa2x0_i2s_close(&sc->sc_i2s);
484 1.1 ober }
485 1.1 ober
486 1.1 ober int
487 1.1 ober zaudio_query_encoding(void *hdl, struct audio_encoding *aep)
488 1.1 ober {
489 1.1 ober switch (aep->index) {
490 1.1 ober case 0:
491 1.1 ober strlcpy(aep->name, AudioEulinear, sizeof(aep->name));
492 1.1 ober aep->encoding = AUDIO_ENCODING_ULINEAR;
493 1.1 ober aep->precision = 8;
494 1.1 ober aep->flags = 0;
495 1.1 ober return (0);
496 1.1 ober case 1:
497 1.1 ober strlcpy(aep->name, AudioEmulaw, sizeof(aep->name));
498 1.1 ober aep->encoding = AUDIO_ENCODING_ULAW;
499 1.1 ober aep->precision = 8;
500 1.1 ober aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
501 1.1 ober return (0);
502 1.1 ober case 2:
503 1.1 ober strlcpy(aep->name, AudioEalaw, sizeof(aep->name));
504 1.1 ober aep->encoding = AUDIO_ENCODING_ALAW;
505 1.1 ober aep->precision = 8;
506 1.1 ober aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
507 1.1 ober return (0);
508 1.1 ober case 3:
509 1.1 ober strlcpy(aep->name, AudioEslinear, sizeof(aep->name));
510 1.1 ober aep->encoding = AUDIO_ENCODING_SLINEAR;
511 1.1 ober aep->precision = 8;
512 1.1 ober aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
513 1.1 ober return (0);
514 1.1 ober case 4:
515 1.1 ober strlcpy(aep->name, AudioEslinear_le, sizeof(aep->name));
516 1.1 ober aep->encoding = AUDIO_ENCODING_SLINEAR_LE;
517 1.1 ober aep->precision = 16;
518 1.1 ober aep->flags = 0;
519 1.1 ober return (0);
520 1.1 ober case 5:
521 1.1 ober strlcpy(aep->name, AudioEulinear_le, sizeof(aep->name));
522 1.1 ober aep->encoding = AUDIO_ENCODING_ULINEAR_LE;
523 1.1 ober aep->precision = 16;
524 1.1 ober aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
525 1.1 ober return (0);
526 1.1 ober case 6:
527 1.1 ober strlcpy(aep->name, AudioEslinear_be, sizeof(aep->name));
528 1.1 ober aep->encoding = AUDIO_ENCODING_SLINEAR_BE;
529 1.1 ober aep->precision = 16;
530 1.1 ober aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
531 1.1 ober return (0);
532 1.1 ober case 7:
533 1.1 ober strlcpy(aep->name, AudioEulinear_be, sizeof(aep->name));
534 1.1 ober aep->encoding = AUDIO_ENCODING_ULINEAR_BE;
535 1.1 ober aep->precision = 16;
536 1.1 ober aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
537 1.1 ober return (0);
538 1.1 ober default:
539 1.1 ober return (EINVAL);
540 1.1 ober }
541 1.1 ober }
542 1.1 ober
543 1.1 ober int
544 1.1 ober zaudio_set_params(void *hdl, int setmode, int usemode,
545 1.1 ober struct audio_params *play, struct audio_params *rec)
546 1.1 ober {
547 1.1 ober struct zaudio_softc *sc = hdl;
548 1.1 ober
549 1.1 ober if (setmode & AUMODE_PLAY) {
550 1.1 ober play->factor = 1;
551 1.1 ober play->sw_code = NULL;
552 1.1 ober switch(play->encoding) {
553 1.1 ober case AUDIO_ENCODING_ULAW:
554 1.1 ober switch (play->channels) {
555 1.1 ober case 1:
556 1.1 ober play->factor = 4;
557 1.1 ober play->sw_code = mulaw_to_slinear16_mts;
558 1.1 ober break;
559 1.1 ober case 2:
560 1.1 ober play->factor = 2;
561 1.1 ober play->sw_code = mulaw_to_slinear16;
562 1.1 ober break;
563 1.1 ober default:
564 1.1 ober return (EINVAL);
565 1.1 ober }
566 1.1 ober break;
567 1.1 ober case AUDIO_ENCODING_SLINEAR_LE:
568 1.1 ober switch (play->precision) {
569 1.1 ober case 8:
570 1.1 ober switch (play->channels) {
571 1.1 ober case 1:
572 1.1 ober play->factor = 4;
573 1.1 ober play->sw_code = linear8_to_linear16_mts;
574 1.1 ober break;
575 1.1 ober case 2:
576 1.1 ober play->factor = 2;
577 1.1 ober play->sw_code = linear8_to_linear16;
578 1.1 ober break;
579 1.1 ober default:
580 1.1 ober return (EINVAL);
581 1.1 ober }
582 1.1 ober break;
583 1.1 ober case 16:
584 1.1 ober switch (play->channels) {
585 1.1 ober case 1:
586 1.1 ober play->factor = 2;
587 1.1 ober play->sw_code = noswap_bytes_mts;
588 1.1 ober break;
589 1.1 ober case 2:
590 1.1 ober break;
591 1.1 ober default:
592 1.1 ober return (EINVAL);
593 1.1 ober }
594 1.1 ober break;
595 1.1 ober default:
596 1.1 ober return (EINVAL);
597 1.1 ober }
598 1.1 ober break;
599 1.1 ober case AUDIO_ENCODING_ULINEAR_LE:
600 1.1 ober switch (play->precision) {
601 1.1 ober case 8:
602 1.1 ober switch (play->channels) {
603 1.1 ober case 1:
604 1.1 ober play->factor = 4;
605 1.1 ober play->sw_code =
606 1.1 ober ulinear8_to_linear16_mts;
607 1.1 ober break;
608 1.1 ober case 2:
609 1.1 ober play->factor = 2;
610 1.1 ober play->sw_code = ulinear8_to_linear16;
611 1.1 ober break;
612 1.1 ober default:
613 1.1 ober return (EINVAL);
614 1.1 ober }
615 1.1 ober break;
616 1.1 ober case 16:
617 1.1 ober switch (play->channels) {
618 1.1 ober case 1:
619 1.1 ober play->factor = 2;
620 1.1 ober play->sw_code = change_sign16_mts;
621 1.1 ober break;
622 1.1 ober case 2:
623 1.1 ober play->sw_code = change_sign16;
624 1.1 ober break;
625 1.1 ober default:
626 1.1 ober return (EINVAL);
627 1.1 ober }
628 1.1 ober break;
629 1.1 ober default:
630 1.1 ober return (EINVAL);
631 1.1 ober }
632 1.1 ober break;
633 1.1 ober case AUDIO_ENCODING_ALAW:
634 1.1 ober switch (play->channels) {
635 1.1 ober case 1:
636 1.1 ober play->factor = 4;
637 1.1 ober play->sw_code = alaw_to_slinear16_mts;
638 1.1 ober case 2:
639 1.1 ober play->factor = 2;
640 1.1 ober play->sw_code = alaw_to_slinear16;
641 1.1 ober default:
642 1.1 ober return (EINVAL);
643 1.1 ober }
644 1.1 ober break;
645 1.1 ober case AUDIO_ENCODING_SLINEAR_BE:
646 1.1 ober switch (play->precision) {
647 1.1 ober case 8:
648 1.1 ober switch (play->channels) {
649 1.1 ober case 1:
650 1.1 ober play->factor = 4;
651 1.1 ober play->sw_code =
652 1.1 ober linear8_to_linear16_mts;
653 1.1 ober break;
654 1.1 ober case 2:
655 1.1 ober play->factor = 2;
656 1.1 ober play->sw_code = linear8_to_linear16;
657 1.1 ober break;
658 1.1 ober default:
659 1.1 ober return (EINVAL);
660 1.1 ober }
661 1.1 ober break;
662 1.1 ober case 16:
663 1.1 ober switch (play->channels) {
664 1.1 ober case 1:
665 1.1 ober play->factor = 2;
666 1.1 ober play->sw_code = swap_bytes_mts;
667 1.1 ober break;
668 1.1 ober case 2:
669 1.1 ober play->sw_code = swap_bytes;
670 1.1 ober break;
671 1.1 ober default:
672 1.1 ober return (EINVAL);
673 1.1 ober }
674 1.1 ober break;
675 1.1 ober default:
676 1.1 ober return (EINVAL);
677 1.1 ober }
678 1.1 ober break;
679 1.1 ober case AUDIO_ENCODING_ULINEAR_BE:
680 1.1 ober switch (play->precision) {
681 1.1 ober case 8:
682 1.1 ober switch (play->channels) {
683 1.1 ober case 1:
684 1.1 ober play->factor = 4;
685 1.1 ober play->sw_code =
686 1.1 ober ulinear8_to_linear16_mts;
687 1.1 ober break;
688 1.1 ober case 2:
689 1.1 ober play->factor = 2;
690 1.1 ober play->sw_code = ulinear8_to_linear16;
691 1.1 ober break;
692 1.1 ober default:
693 1.1 ober return (EINVAL);
694 1.1 ober }
695 1.1 ober break;
696 1.1 ober case 16:
697 1.1 ober switch (play->channels) {
698 1.1 ober case 1:
699 1.1 ober play->factor = 2;
700 1.1 ober play->sw_code =
701 1.1 ober change_sign16_swap_bytes_mts;
702 1.1 ober break;
703 1.1 ober case 2:
704 1.1 ober play->sw_code =
705 1.1 ober change_sign16_swap_bytes;
706 1.1 ober break;
707 1.1 ober default:
708 1.1 ober return (EINVAL);
709 1.1 ober }
710 1.1 ober break;
711 1.1 ober default:
712 1.1 ober return (EINVAL);
713 1.1 ober }
714 1.1 ober break;
715 1.1 ober default:
716 1.1 ober return (EINVAL);
717 1.1 ober }
718 1.1 ober
719 1.1 ober pxa2x0_i2s_setspeed(&sc->sc_i2s, &play->sample_rate);
720 1.1 ober }
721 1.1 ober
722 1.1 ober #if RECORD_XXX_NOT_YET
723 1.1 ober if (setmode & AUMODE_RECORD) {
724 1.1 ober rec->factor = 1;
725 1.1 ober rec->sw_code = NULL;
726 1.1 ober switch(rec->encoding) {
727 1.1 ober case AUDIO_ENCODING_ULAW:
728 1.1 ober rec->sw_code = ulinear8_to_mulaw;
729 1.1 ober break;
730 1.1 ober case AUDIO_ENCODING_SLINEAR_LE:
731 1.1 ober if (rec->precision == 8)
732 1.1 ober rec->sw_code = change_sign8;
733 1.1 ober break;
734 1.1 ober case AUDIO_ENCODING_ULINEAR_LE:
735 1.1 ober if (rec->precision == 16)
736 1.1 ober rec->sw_code = change_sign16;
737 1.1 ober break;
738 1.1 ober case AUDIO_ENCODING_ALAW:
739 1.1 ober rec->sw_code = ulinear8_to_alaw;
740 1.1 ober break;
741 1.1 ober case AUDIO_ENCODING_SLINEAR_BE:
742 1.1 ober if (rec->precision == 16)
743 1.1 ober rec->sw_code = swap_bytes;
744 1.1 ober else
745 1.1 ober rec->sw_code = change_sign8;
746 1.1 ober break;
747 1.1 ober case AUDIO_ENCODING_ULINEAR_BE:
748 1.1 ober if (rec->precision == 16)
749 1.1 ober rec->sw_code = swap_bytes_change_sign16;
750 1.1 ober break;
751 1.1 ober default:
752 1.1 ober return (EINVAL);
753 1.1 ober }
754 1.1 ober
755 1.1 ober pxa2x0_i2s_setspeed(sc, &rec->sample_rate);
756 1.1 ober }
757 1.1 ober #endif
758 1.1 ober
759 1.1 ober return (0);
760 1.1 ober }
761 1.1 ober
762 1.1 ober int
763 1.1 ober zaudio_halt_output(void *hdl)
764 1.1 ober {
765 1.1 ober struct zaudio_softc *sc = hdl;
766 1.1 ober
767 1.1 ober /* XXX forcibly stop output DMA? */
768 1.1 ober
769 1.1 ober zaudio_standby(sc);
770 1.1 ober sc->sc_playing = 0;
771 1.1 ober
772 1.1 ober return 0;
773 1.1 ober }
774 1.1 ober
775 1.1 ober int
776 1.1 ober zaudio_halt_input(void *hdl)
777 1.1 ober {
778 1.1 ober /* struct zaudio_softc *sc = hdl; */
779 1.1 ober
780 1.1 ober return 0;
781 1.1 ober }
782 1.1 ober
783 1.1 ober int
784 1.1 ober zaudio_getdev(void *hdl, struct audio_device *ret)
785 1.1 ober {
786 1.1 ober /* struct zaudio_softc *sc = hdl; */
787 1.1 ober
788 1.1 ober *ret = wm8750_device;
789 1.1 ober return 0;
790 1.1 ober }
791 1.1 ober
792 1.1 ober #define ZAUDIO_SPKR_LVL 0
793 1.1 ober #define ZAUDIO_SPKR_MUTE 1
794 1.1 ober #define ZAUDIO_HP_LVL 2
795 1.1 ober #define ZAUDIO_HP_MUTE 3
796 1.1 ober #define ZAUDIO_OUTPUT_CLASS 4
797 1.1 ober
798 1.1 ober int
799 1.1 ober zaudio_set_port(void *hdl, struct mixer_ctrl *mc)
800 1.1 ober {
801 1.1 ober struct zaudio_softc *sc = hdl;
802 1.1 ober int error = EINVAL, s;
803 1.1 ober
804 1.1 ober s = splbio();
805 1.1 ober pxa2x0_i2c_open(&sc->sc_i2c);
806 1.1 ober
807 1.1 ober switch (mc->dev) {
808 1.1 ober case ZAUDIO_SPKR_LVL:
809 1.1 ober if (mc->type != AUDIO_MIXER_VALUE)
810 1.1 ober break;
811 1.1 ober if (mc->un.value.num_channels == 1)
812 1.1 ober sc->sc_volume[ZAUDIO_OP_SPKR].left =
813 1.1 ober mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
814 1.1 ober else
815 1.1 ober break;
816 1.1 ober zaudio_update_volume(sc, ZAUDIO_OP_SPKR);
817 1.1 ober error = 0;
818 1.1 ober break;
819 1.1 ober case ZAUDIO_SPKR_MUTE:
820 1.1 ober if (mc->type != AUDIO_MIXER_ENUM)
821 1.1 ober break;
822 1.1 ober sc->sc_unmute[ZAUDIO_OP_SPKR] = mc->un.ord ? 1 : 0;
823 1.1 ober zaudio_update_mutes(sc);
824 1.1 ober error = 0;
825 1.1 ober break;
826 1.1 ober case ZAUDIO_HP_LVL:
827 1.1 ober if (mc->type != AUDIO_MIXER_VALUE)
828 1.1 ober break;
829 1.1 ober if (mc->un.value.num_channels == 1) {
830 1.1 ober sc->sc_volume[ZAUDIO_OP_HP].left =
831 1.1 ober mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
832 1.1 ober sc->sc_volume[ZAUDIO_OP_HP].right =
833 1.1 ober mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
834 1.1 ober } else if (mc->un.value.num_channels == 2) {
835 1.1 ober sc->sc_volume[ZAUDIO_OP_HP].left =
836 1.1 ober mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
837 1.1 ober sc->sc_volume[ZAUDIO_OP_HP].right =
838 1.1 ober mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
839 1.1 ober }
840 1.1 ober else
841 1.1 ober break;
842 1.1 ober zaudio_update_volume(sc, ZAUDIO_OP_HP);
843 1.1 ober error = 0;
844 1.1 ober break;
845 1.1 ober case ZAUDIO_HP_MUTE:
846 1.1 ober if (mc->type != AUDIO_MIXER_ENUM)
847 1.1 ober break;
848 1.1 ober sc->sc_unmute[ZAUDIO_OP_HP] = mc->un.ord ? 1 : 0;
849 1.1 ober zaudio_update_mutes(sc);
850 1.1 ober error = 0;
851 1.1 ober break;
852 1.1 ober }
853 1.1 ober
854 1.1 ober pxa2x0_i2c_close(&sc->sc_i2c);
855 1.1 ober splx(s);
856 1.1 ober
857 1.1 ober return error;
858 1.1 ober }
859 1.1 ober
860 1.1 ober int
861 1.1 ober zaudio_get_port(void *hdl, struct mixer_ctrl *mc)
862 1.1 ober {
863 1.1 ober struct zaudio_softc *sc = hdl;
864 1.1 ober int error = EINVAL;
865 1.1 ober
866 1.1 ober switch (mc->dev) {
867 1.1 ober case ZAUDIO_SPKR_LVL:
868 1.1 ober if (mc->type != AUDIO_MIXER_VALUE)
869 1.1 ober break;
870 1.1 ober if (mc->un.value.num_channels == 1)
871 1.1 ober mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
872 1.1 ober sc->sc_volume[ZAUDIO_OP_SPKR].left;
873 1.1 ober else
874 1.1 ober break;
875 1.1 ober error = 0;
876 1.1 ober break;
877 1.1 ober case ZAUDIO_SPKR_MUTE:
878 1.1 ober if (mc->type != AUDIO_MIXER_ENUM)
879 1.1 ober break;
880 1.1 ober mc->un.ord = sc->sc_unmute[ZAUDIO_OP_SPKR] ? 1 : 0;
881 1.1 ober error = 0;
882 1.1 ober break;
883 1.1 ober case ZAUDIO_HP_LVL:
884 1.1 ober if (mc->type != AUDIO_MIXER_VALUE)
885 1.1 ober break;
886 1.1 ober if (mc->un.value.num_channels == 1)
887 1.1 ober mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
888 1.1 ober sc->sc_volume[ZAUDIO_OP_HP].left;
889 1.1 ober else if (mc->un.value.num_channels == 2) {
890 1.1 ober mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
891 1.1 ober sc->sc_volume[ZAUDIO_OP_HP].left;
892 1.1 ober mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
893 1.1 ober sc->sc_volume[ZAUDIO_OP_HP].right;
894 1.1 ober }
895 1.1 ober else
896 1.1 ober break;
897 1.1 ober error = 0;
898 1.1 ober break;
899 1.1 ober case ZAUDIO_HP_MUTE:
900 1.1 ober if (mc->type != AUDIO_MIXER_ENUM)
901 1.1 ober break;
902 1.1 ober mc->un.ord = sc->sc_unmute[ZAUDIO_OP_HP] ? 1 : 0;
903 1.1 ober error = 0;
904 1.1 ober break;
905 1.1 ober }
906 1.1 ober
907 1.1 ober return error;
908 1.1 ober }
909 1.1 ober
910 1.1 ober int
911 1.1 ober zaudio_query_devinfo(void *hdl, struct mixer_devinfo *di)
912 1.1 ober {
913 1.1 ober /* struct zaudio_softc *sc = hdl; */
914 1.1 ober
915 1.1 ober switch (di->index) {
916 1.1 ober case ZAUDIO_SPKR_LVL:
917 1.1 ober di->type = AUDIO_MIXER_VALUE;
918 1.1 ober di->mixer_class = ZAUDIO_OUTPUT_CLASS;
919 1.1 ober di->prev = AUDIO_MIXER_LAST;
920 1.1 ober di->next = ZAUDIO_SPKR_MUTE;
921 1.1 ober strlcpy(di->label.name, AudioNspeaker,
922 1.1 ober sizeof(di->label.name));
923 1.1 ober strlcpy(di->un.v.units.name, AudioNvolume,
924 1.1 ober sizeof(di->un.v.units.name));
925 1.1 ober di->un.v.num_channels = 1;
926 1.1 ober break;
927 1.1 ober case ZAUDIO_SPKR_MUTE:
928 1.1 ober di->type = AUDIO_MIXER_ENUM;
929 1.1 ober di->mixer_class = ZAUDIO_OUTPUT_CLASS;
930 1.1 ober di->prev = ZAUDIO_SPKR_LVL;
931 1.1 ober di->next = AUDIO_MIXER_LAST;
932 1.1 ober goto mute;
933 1.1 ober case ZAUDIO_HP_LVL:
934 1.1 ober di->type = AUDIO_MIXER_VALUE;
935 1.1 ober di->mixer_class = ZAUDIO_OUTPUT_CLASS;
936 1.1 ober di->prev = AUDIO_MIXER_LAST;
937 1.1 ober di->next = ZAUDIO_HP_MUTE;
938 1.1 ober strlcpy(di->label.name, AudioNheadphone,
939 1.1 ober sizeof(di->label.name));
940 1.1 ober di->un.v.num_channels = 1;
941 1.1 ober strlcpy(di->un.v.units.name, AudioNvolume,
942 1.1 ober sizeof(di->un.v.units.name));
943 1.1 ober break;
944 1.1 ober case ZAUDIO_HP_MUTE:
945 1.1 ober di->type = AUDIO_MIXER_ENUM;
946 1.1 ober di->mixer_class = ZAUDIO_OUTPUT_CLASS;
947 1.1 ober di->prev = ZAUDIO_HP_LVL;
948 1.1 ober di->next = AUDIO_MIXER_LAST;
949 1.1 ober mute:
950 1.1 ober strlcpy(di->label.name, AudioNmute, sizeof(di->label.name));
951 1.1 ober di->un.e.num_mem = 2;
952 1.1 ober strlcpy(di->un.e.member[0].label.name, AudioNon,
953 1.1 ober sizeof(di->un.e.member[0].label.name));
954 1.1 ober di->un.e.member[0].ord = 0;
955 1.1 ober strlcpy(di->un.e.member[1].label.name, AudioNoff,
956 1.1 ober sizeof(di->un.e.member[1].label.name));
957 1.1 ober di->un.e.member[1].ord = 1;
958 1.1 ober break;
959 1.1 ober case ZAUDIO_OUTPUT_CLASS:
960 1.1 ober di->type = AUDIO_MIXER_CLASS;
961 1.1 ober di->mixer_class = ZAUDIO_OUTPUT_CLASS;
962 1.1 ober di->prev = AUDIO_MIXER_LAST;
963 1.1 ober di->next = AUDIO_MIXER_LAST;
964 1.1 ober strlcpy(di->label.name, AudioCoutputs,
965 1.1 ober sizeof(di->label.name));
966 1.1 ober break;
967 1.1 ober default:
968 1.1 ober return ENXIO;
969 1.1 ober }
970 1.1 ober
971 1.1 ober return 0;
972 1.1 ober }
973 1.1 ober
974 1.1 ober int
975 1.1 ober zaudio_get_props(void *hdl)
976 1.1 ober {
977 1.1 ober return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
978 1.1 ober }
979 1.1 ober
980 1.1 ober int
981 1.1 ober zaudio_start_output(void *hdl, void *block, int bsize, void (*intr)(void *),
982 1.1 ober void *intrarg)
983 1.1 ober {
984 1.1 ober struct zaudio_softc *sc = hdl;
985 1.1 ober int err;
986 1.1 ober
987 1.1 ober /* Power up codec if we are not already playing. */
988 1.1 ober if (!sc->sc_playing) {
989 1.1 ober sc->sc_playing = 1;
990 1.1 ober zaudio_play_setup(sc);
991 1.1 ober }
992 1.1 ober
993 1.1 ober /* Start DMA via I2S */
994 1.1 ober err = pxa2x0_i2s_start_output(&sc->sc_i2s, block, bsize, intr, intrarg);
995 1.1 ober if (err) {
996 1.1 ober zaudio_standby(sc);
997 1.1 ober sc->sc_playing = 0;
998 1.1 ober }
999 1.1 ober return err;
1000 1.1 ober }
1001 1.1 ober
1002 1.1 ober int
1003 1.1 ober zaudio_start_input(void *hdl, void *block, int bsize, void (*intr)(void *),
1004 1.1 ober void *intrarg)
1005 1.1 ober {
1006 1.1 ober return ENXIO;
1007 1.1 ober }
1008