1 /* $NetBSD: wm8731_zaudio.c,v 1.3 2019/05/08 13:40:17 isaki Exp $ */
2
3 /*-
4 * Copyright (c) 2013 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by TOYOKURA Atsushi.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * TODO:
34 * - powerhooks (currently only works until first suspend)
35 */
36
37 #include "opt_cputypes.h"
38 #include "opt_zaudio.h"
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: wm8731_zaudio.c,v 1.3 2019/05/08 13:40:17 isaki Exp $");
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/callout.h>
46 #include <sys/device.h>
47 #include <sys/kmem.h>
48 #include <sys/kernel.h>
49 #include <sys/audioio.h>
50 #include <sys/mutex.h>
51 #include <sys/intr.h>
52 #include <sys/bus.h>
53
54 #include <dev/audio/audio_if.h>
55
56 #include <dev/i2c/i2cvar.h>
57
58 #include <arm/xscale/pxa2x0reg.h>
59 #include <arm/xscale/pxa2x0var.h>
60 #include <arm/xscale/pxa2x0_i2c.h>
61 #include <arm/xscale/pxa2x0_i2s.h>
62 #include <arm/xscale/pxa2x0_dmac.h>
63 #include <arm/xscale/pxa2x0_gpio.h>
64
65 #include <zaurus/zaurus/zaurus_var.h>
66 #include <zaurus/dev/zaudiovar.h>
67 #include <zaurus/dev/wm8731reg.h>
68 #include <zaurus/dev/wm8731var.h>
69 #include <zaurus/dev/scoopvar.h>
70
71 #define WM8731_ADDRESS 0x1B
72
73 /* GPIO pins */
74 #define GPIO_HP_IN_C860 4
75
76 #define WM8731_OP_SPKR 0
77 #define WM8731_OP_MIC 1
78 #define WM8731_OP_NUM 2
79
80 static int wm8731_finalize(device_t);
81 static bool wm8731_suspend(device_t, const pmf_qual_t *);
82 static bool wm8731_resume(device_t, const pmf_qual_t *);
83 static void wm8731_volume_up(device_t);
84 static void wm8731_volume_down(device_t);
85 static void wm8731_volume_toggle(device_t);
86
87 static struct audio_device wm8731_device = {
88 "WM8731",
89 "1.0",
90 "wm"
91 };
92
93 static void wm8731_init(struct zaudio_softc *);
94 static int wm8731_jack_intr(void *);
95 static void wm8731_jack(void *);
96 static void wm8731_standby(struct zaudio_softc *);
97 static void wm8731_update_volume(struct zaudio_softc *, int);
98 static void wm8731_update_mutes(struct zaudio_softc *, int);
99 static void wm8731_play_setup(struct zaudio_softc *);
100 /*static*/ void wm8731_record_setup(struct zaudio_softc *);
101 static int wm8731_start_output(void *, void *, int, void (*)(void *), void *);
102 static int wm8731_start_input(void *, void *, int, void (*)(void *), void *);
103 static int wm8731_halt_output(void *);
104 static int wm8731_halt_input(void *);
105 static int wm8731_getdev(void *, struct audio_device *);
106 static int wm8731_set_port(void *, struct mixer_ctrl *);
107 static int wm8731_get_port(void *, struct mixer_ctrl *);
108 static int wm8731_query_devinfo(void *, struct mixer_devinfo *);
109
110 static struct audio_hw_if wm8731_hw_if = {
111 .open = zaudio_open,
112 .close = zaudio_close,
113 .query_format = zaudio_query_format,
114 .set_format = zaudio_set_format,
115 .round_blocksize = zaudio_round_blocksize,
116 .commit_settings = NULL,
117 .init_output = NULL,
118 .init_input = NULL,
119 .start_output = wm8731_start_output,
120 .start_input = wm8731_start_input,
121 .halt_output = wm8731_halt_output,
122 .halt_input = wm8731_halt_input,
123 .speaker_ctl = NULL,
124 .getdev = wm8731_getdev,
125 .set_port = wm8731_set_port,
126 .get_port = wm8731_get_port,
127 .query_devinfo = wm8731_query_devinfo,
128 .allocm = zaudio_allocm,
129 .freem = zaudio_freem,
130 .round_buffersize = zaudio_round_buffersize,
131 .get_props = zaudio_get_props,
132 .trigger_output = NULL,
133 .trigger_input = NULL,
134 .dev_ioctl = NULL,
135 .get_locks = zaudio_get_locks,
136 };
137
138 static const uint16_t playback_regs[][2] = {
139 /* Power Down Control */
140 { WM8731_PD_REG, WM8731_CLKOUTPD | WM8731_OSCPD | WM8731_OUTPD
141 | WM8731_ADCPD | WM8731_MICPD | WM8731_LINEINPD },
142
143 /* Digital Audio Path Control */
144 { WM8731_DAP_REG, 0 },
145
146 /* Analogue Audio Path Control */
147 { WM8731_AAP_REG, WM8731_DACSEL | WM8731_MUTEMIC },
148
149 /* Activating DSP and DAI */
150 { WM8731_AC_REG, WM8731_ACTIVE },
151
152 /* End of list */
153 { 0xffff, 0xffff }
154 };
155
156 static const uint16_t record_regs[][2] = {
157 /* Power Down Control */
158 { WM8731_PD_REG, WM8731_CLKOUTPD | WM8731_OSCPD | WM8731_DACPD
159 | WM8731_LINEINPD },
160
161 /* Digital Audio Path Control */
162 { WM8731_DAP_REG, 0 },
163
164 /* Analogue Audio Path Control */
165 { WM8731_AAP_REG, WM8731_INSEL | WM8731_MICBOOST },
166
167 /* Activating DSP and DAI */
168 { WM8731_AC_REG, WM8731_ACTIVE },
169
170 /* End of list */
171 { 0xffff, 0xffff }
172 };
173
174 static __inline int
wm8731_write(struct zaudio_softc * sc,int reg,int val)175 wm8731_write(struct zaudio_softc *sc, int reg, int val)
176 {
177 uint16_t tmp;
178 uint8_t cmd;
179 uint8_t data;
180
181 tmp = (reg << 9) | (val & 0x1ff);
182 cmd = tmp >> 8;
183 data = tmp;
184 return iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, WM8731_ADDRESS,
185 &cmd, 1, &data, 1, 0);
186 }
187
188 int
wm8731_match(device_t parent,cfdata_t cf,struct i2c_attach_args * ia)189 wm8731_match(device_t parent, cfdata_t cf, struct i2c_attach_args *ia)
190 {
191 int match_result;
192
193 if (ZAURUS_ISC1000 || ZAURUS_ISC3000)
194 return 0;
195
196 if (iic_use_direct_match(ia, cf, NULL, &match_result))
197 return match_result;
198
199 /* indirect config - check typical address */
200 if (ia->ia_addr == WM8731_ADDRESS)
201 return I2C_MATCH_ADDRESS_ONLY;
202
203 return 0;
204 }
205
206 void
wm8731_attach(device_t parent,device_t self,struct i2c_attach_args * ia)207 wm8731_attach(device_t parent, device_t self, struct i2c_attach_args *ia)
208 {
209 struct zaudio_softc *sc = device_private(self);
210 int error;
211
212 aprint_normal(": I2S, WM8731 Audio\n");
213 aprint_naive("\n");
214
215 /* Check for an I2C response from the wm8731 */
216 iic_acquire_bus(sc->sc_i2c, 0);
217 error = wm8731_write(sc, WM8731_RESET_REG, 0);
218 iic_release_bus(sc->sc_i2c, 0);
219 if (error) {
220 aprint_error_dev(self, "codec failed to respond\n");
221 goto fail_i2c;
222 }
223 delay(100);
224
225 /* Allocate memory for volume & mute operations */
226 sc->sc_volume = kmem_zalloc(sizeof(*sc->sc_volume) * WM8731_OP_NUM,
227 KM_SLEEP);
228 sc->sc_unmute = kmem_zalloc(sizeof(*sc->sc_unmute) * WM8731_OP_NUM,
229 KM_SLEEP);
230 sc->sc_unmute_toggle = kmem_zalloc(
231 sizeof(*sc->sc_unmute_toggle) * WM8731_OP_NUM, KM_SLEEP);
232
233 /* Speaker On by default. */
234 sc->sc_volume[WM8731_OP_SPKR].left = 180;
235 sc->sc_volume[WM8731_OP_SPKR].right = 180;
236 sc->sc_jack = FALSE;
237 UNMUTE(sc, WM8731_OP_SPKR, 1);
238 sc->sc_volume[WM8731_OP_MIC].left = 180;
239 UNMUTE(sc, WM8731_OP_MIC, 0);
240
241 /* Configure headphone jack state change handling. */
242 callout_setfunc(&sc->sc_to, wm8731_jack, sc);
243 pxa2x0_gpio_set_function(GPIO_HP_IN_C860, GPIO_IN);
244 (void) pxa2x0_gpio_intr_establish(GPIO_HP_IN_C860, IST_EDGE_BOTH,
245 IPL_BIO, wm8731_jack_intr, sc);
246
247 /* wm8731_init() implicitly depends on ioexp or scoop */
248 config_finalize_register(self, wm8731_finalize);
249
250 audio_attach_mi(&wm8731_hw_if, sc, self);
251
252 if (!pmf_device_register(self, wm8731_suspend, wm8731_resume))
253 aprint_error_dev(self, "couldn't establish power handler\n");
254 if (!pmf_event_register(self, PMFE_AUDIO_VOLUME_UP,
255 wm8731_volume_up, true))
256 aprint_error_dev(self, "couldn't register event handler\n");
257 if (!pmf_event_register(self, PMFE_AUDIO_VOLUME_DOWN,
258 wm8731_volume_down, true))
259 aprint_error_dev(self, "couldn't register event handler\n");
260 if (!pmf_event_register(self, PMFE_AUDIO_VOLUME_TOGGLE,
261 wm8731_volume_toggle, true))
262 aprint_error_dev(self, "couldn't register event handler\n");
263
264 return;
265
266 fail_i2c:
267 pxa2x0_i2s_detach_sub(&sc->sc_i2s);
268 }
269
270 static int
wm8731_finalize(device_t dv)271 wm8731_finalize(device_t dv)
272 {
273 struct zaudio_softc *sc = device_private(dv);
274
275 wm8731_init(sc);
276 return 0;
277 }
278
279 static bool
wm8731_suspend(device_t dv,const pmf_qual_t * qual)280 wm8731_suspend(device_t dv, const pmf_qual_t *qual)
281 {
282 struct zaudio_softc *sc = device_private(dv);
283
284 callout_stop(&sc->sc_to);
285 wm8731_standby(sc);
286
287 return true;
288 }
289
290 static bool
wm8731_resume(device_t dv,const pmf_qual_t * qual)291 wm8731_resume(device_t dv, const pmf_qual_t *qual)
292 {
293 struct zaudio_softc *sc = device_private(dv);
294
295 pxa2x0_i2s_init(&sc->sc_i2s);
296 wm8731_init(sc);
297
298 return true;
299 }
300
301 static __inline uint8_t
vol_sadd(int vol,int stride)302 vol_sadd(int vol, int stride)
303 {
304
305 vol += stride;
306 if (vol > 255)
307 return 255;
308 return (uint8_t)vol;
309 }
310
311 #ifndef ZAUDIO_VOLUME_STRIDE
312 #define ZAUDIO_VOLUME_STRIDE 8
313 #endif
314
315 static void
wm8731_volume_up(device_t dv)316 wm8731_volume_up(device_t dv)
317 {
318 struct zaudio_softc *sc = device_private(dv);
319 int s;
320
321 s = splbio();
322 iic_acquire_bus(sc->sc_i2c, 0);
323
324 sc->sc_volume[WM8731_OP_SPKR].left =
325 vol_sadd(sc->sc_volume[WM8731_OP_SPKR].left, ZAUDIO_VOLUME_STRIDE);
326 sc->sc_volume[WM8731_OP_SPKR].right =
327 vol_sadd(sc->sc_volume[WM8731_OP_SPKR].right, ZAUDIO_VOLUME_STRIDE);
328
329 wm8731_update_volume(sc, WM8731_OP_SPKR);
330
331 iic_release_bus(sc->sc_i2c, 0);
332 splx(s);
333 }
334
335 static __inline uint8_t
vol_ssub(int vol,int stride)336 vol_ssub(int vol, int stride)
337 {
338
339 vol -= stride;
340 if (vol < 0)
341 return 0;
342 return (uint8_t)vol;
343 }
344
345 static void
wm8731_volume_down(device_t dv)346 wm8731_volume_down(device_t dv)
347 {
348 struct zaudio_softc *sc = device_private(dv);
349 int s;
350
351 s = splbio();
352 iic_acquire_bus(sc->sc_i2c, 0);
353
354 sc->sc_volume[WM8731_OP_SPKR].left =
355 vol_ssub(sc->sc_volume[WM8731_OP_SPKR].left, ZAUDIO_VOLUME_STRIDE);
356 sc->sc_volume[WM8731_OP_SPKR].right =
357 vol_ssub(sc->sc_volume[WM8731_OP_SPKR].right, ZAUDIO_VOLUME_STRIDE);
358
359 wm8731_update_volume(sc, WM8731_OP_SPKR);
360
361 iic_release_bus(sc->sc_i2c, 0);
362 splx(s);
363 }
364
365 static void
wm8731_volume_toggle(device_t dv)366 wm8731_volume_toggle(device_t dv)
367 {
368 struct zaudio_softc *sc = device_private(dv);
369 int s;
370
371 s = splbio();
372 iic_acquire_bus(sc->sc_i2c, 0);
373
374 if (!sc->sc_unmute[WM8731_OP_SPKR]) {
375 sc->sc_unmute[WM8731_OP_SPKR] =
376 sc->sc_unmute_toggle[WM8731_OP_SPKR];
377 } else {
378 sc->sc_unmute[WM8731_OP_SPKR] = 0;
379 }
380 wm8731_update_mutes(sc, 1);
381
382 iic_release_bus(sc->sc_i2c, 0);
383 splx(s);
384 }
385
386 static void
wm8731_init(struct zaudio_softc * sc)387 wm8731_init(struct zaudio_softc *sc)
388 {
389
390 iic_acquire_bus(sc->sc_i2c, 0);
391
392 /* Reset the codec */
393 wm8731_write(sc, WM8731_RESET_REG, 0);
394 delay(100);
395
396 /* Switch to standby power only */
397 wm8731_write(sc, WM8731_PD_REG, WM8731_CLKOUTPD | WM8731_OSCPD |
398 WM8731_OUTPD | WM8731_DACPD | WM8731_ADCPD | WM8731_MICPD |
399 WM8731_LINEINPD);
400
401 /* Configure digital interface for I2S */
402 wm8731_write(sc, WM8731_DAI_REG, WM8731_SET_IWL(2) | WM8731_SET_FORMAT(2));
403
404 /* Initialise volume levels */
405 wm8731_update_volume(sc, WM8731_OP_SPKR);
406 wm8731_update_volume(sc, WM8731_OP_MIC);
407
408 scoop_set_headphone(0);
409 scoop_set_speaker(0);
410 scoop_set_mic_bias(0);
411
412 iic_release_bus(sc->sc_i2c, 0);
413
414 /* Assume that the jack state has changed. */
415 wm8731_jack(sc);
416 }
417
418 static int
wm8731_jack_intr(void * v)419 wm8731_jack_intr(void *v)
420 {
421 struct zaudio_softc *sc = v;
422
423 if (!callout_active(&sc->sc_to))
424 wm8731_jack(sc);
425
426 return 1;
427 }
428
429 static void
wm8731_jack(void * v)430 wm8731_jack(void *v)
431 {
432 struct zaudio_softc *sc = v;
433
434 switch (sc->sc_state) {
435 case ZAUDIO_JACK_STATE_OUT:
436 if (pxa2x0_gpio_get_bit(GPIO_HP_IN_C860)) {
437 sc->sc_state = ZAUDIO_JACK_STATE_INS;
438 sc->sc_icount = 0;
439 }
440 break;
441
442 case ZAUDIO_JACK_STATE_INS:
443 if (sc->sc_icount++ > 2) {
444 if (pxa2x0_gpio_get_bit(GPIO_HP_IN_C860)) {
445 sc->sc_state = ZAUDIO_JACK_STATE_IN;
446 sc->sc_jack = TRUE;
447 UNMUTE(sc, WM8731_OP_MIC, 1);
448 goto update_mutes;
449 } else
450 sc->sc_state = ZAUDIO_JACK_STATE_OUT;
451 }
452 break;
453
454 case ZAUDIO_JACK_STATE_IN:
455 if (!pxa2x0_gpio_get_bit(GPIO_HP_IN_C860)) {
456 sc->sc_state = ZAUDIO_JACK_STATE_REM;
457 sc->sc_icount = 0;
458 }
459 break;
460
461 case ZAUDIO_JACK_STATE_REM:
462 if (sc->sc_icount++ > 2) {
463 if (!pxa2x0_gpio_get_bit(GPIO_HP_IN_C860)) {
464 sc->sc_state = ZAUDIO_JACK_STATE_OUT;
465 sc->sc_jack = FALSE;
466 UNMUTE(sc, WM8731_OP_MIC, 0);
467 goto update_mutes;
468 } else
469 sc->sc_state = ZAUDIO_JACK_STATE_IN;
470 }
471 break;
472 }
473
474 callout_schedule(&sc->sc_to, hz/4);
475
476 return;
477
478 update_mutes:
479 callout_stop(&sc->sc_to);
480
481 if (sc->sc_playing || sc->sc_recording) {
482 iic_acquire_bus(sc->sc_i2c, 0);
483 if (sc->sc_playing)
484 wm8731_update_mutes(sc, 1);
485 if (sc->sc_recording)
486 wm8731_update_mutes(sc, 2);
487 iic_release_bus(sc->sc_i2c, 0);
488 }
489 }
490
491 static void
wm8731_standby(struct zaudio_softc * sc)492 wm8731_standby(struct zaudio_softc *sc)
493 {
494
495 iic_acquire_bus(sc->sc_i2c, 0);
496
497 /* Switch to standby power only */
498 wm8731_write(sc, WM8731_PD_REG, WM8731_CLKOUTPD | WM8731_OSCPD |
499 WM8731_OUTPD | WM8731_DACPD | WM8731_ADCPD | WM8731_MICPD |
500 WM8731_LINEINPD);
501
502 scoop_set_headphone(0);
503 scoop_set_speaker(0);
504 scoop_set_mic_bias(0);
505
506 /* Activating DSP and DAI */
507 wm8731_write(sc, WM8731_AC_REG, 0);
508
509 iic_release_bus(sc->sc_i2c, 0);
510 }
511
512 static void
wm8731_update_volume(struct zaudio_softc * sc,int output)513 wm8731_update_volume(struct zaudio_softc *sc, int output)
514 {
515 struct zaudio_volume *volume;
516
517 switch (output) {
518 case WM8731_OP_SPKR:
519 volume = &sc->sc_volume[WM8731_OP_SPKR];
520 wm8731_write(sc, WM8731_LHP_REG,
521 WM8731_SET_LHPVOL(volume->left >> 1));
522 wm8731_write(sc, WM8731_RHP_REG,
523 WM8731_SET_RHPVOL(volume->right >> 1));
524 break;
525
526 case WM8731_OP_MIC:
527 volume = &sc->sc_volume[WM8731_OP_MIC];
528 wm8731_write(sc, WM8731_LIN_REG, WM8731_LRINBOTH |
529 WM8731_SET_LINVOL(volume->left >> 3));
530 break;
531 }
532 }
533
534 static void
wm8731_update_mutes(struct zaudio_softc * sc,int mask)535 wm8731_update_mutes(struct zaudio_softc *sc, int mask)
536 {
537 uint16_t val = WM8731_CLKOUTPD | WM8731_OSCPD | WM8731_LINEINPD;
538
539 /* playback */
540 if (mask & 1) {
541 val |= WM8731_ADCPD | WM8731_MICPD;
542 if (!sc->sc_unmute[WM8731_OP_SPKR]) {
543 val |= WM8731_OUTPD | WM8731_DACPD;
544 }
545 wm8731_write(sc, WM8731_PD_REG, val);
546 scoop_set_headphone(sc->sc_unmute[WM8731_OP_SPKR] & sc->sc_jack);
547 scoop_set_speaker(sc->sc_unmute[WM8731_OP_SPKR] & !sc->sc_jack);
548 }
549
550 /* record */
551 if (mask & 2) {
552 val = WM8731_OUTPD | WM8731_DACPD;
553 if (!sc->sc_unmute[WM8731_OP_MIC]) {
554 val |= WM8731_ADCPD | WM8731_MICPD;
555 }
556 wm8731_write(sc, WM8731_PD_REG, val);
557 scoop_set_mic_bias(sc->sc_unmute[WM8731_OP_MIC]);
558 }
559 }
560
561 static void
wm8731_play_setup(struct zaudio_softc * sc)562 wm8731_play_setup(struct zaudio_softc *sc)
563 {
564 int i;
565
566 iic_acquire_bus(sc->sc_i2c, 0);
567
568 /* Program the codec with playback settings */
569 for (i = 0; playback_regs[i][0] != 0xffff; i++) {
570 wm8731_write(sc, playback_regs[i][0], playback_regs[i][1]);
571 }
572 wm8731_update_mutes(sc, 1);
573
574 iic_release_bus(sc->sc_i2c, 0);
575 }
576
577 /*static*/ void
wm8731_record_setup(struct zaudio_softc * sc)578 wm8731_record_setup(struct zaudio_softc *sc)
579 {
580 int i;
581
582 iic_acquire_bus(sc->sc_i2c, 0);
583
584 /* Program the codec with playback settings */
585 for (i = 0; record_regs[i][0] != 0xffff; i++) {
586 wm8731_write(sc, record_regs[i][0], record_regs[i][1]);
587 }
588 wm8731_update_mutes(sc, 2);
589
590 iic_release_bus(sc->sc_i2c, 0);
591 }
592
593 static int
wm8731_halt_output(void * hdl)594 wm8731_halt_output(void *hdl)
595 {
596 struct zaudio_softc *sc = hdl;
597 int rv;
598
599 rv = pxa2x0_i2s_halt_output(&sc->sc_i2s);
600 if (!sc->sc_recording)
601 wm8731_standby(sc);
602 sc->sc_playing = 0;
603
604 return rv;
605 }
606
607 static int
wm8731_halt_input(void * hdl)608 wm8731_halt_input(void *hdl)
609 {
610 struct zaudio_softc *sc = hdl;
611 int rv;
612
613 rv = pxa2x0_i2s_halt_input(&sc->sc_i2s);
614 if (!sc->sc_playing)
615 wm8731_standby(sc);
616 sc->sc_recording = 0;
617
618 return rv;
619 }
620
621 static int
wm8731_getdev(void * hdl,struct audio_device * ret)622 wm8731_getdev(void *hdl, struct audio_device *ret)
623 {
624
625 *ret = wm8731_device;
626 return 0;
627 }
628
629 #define WM8731_SPKR_LVL 0
630 #define WM8731_SPKR_MUTE 1
631 #define WM8731_MIC_LVL 2
632 #define WM8731_MIC_MUTE 3
633 #define WM8731_RECORD_SOURCE 4
634 #define WM8731_OUTPUT_CLASS 5
635 #define WM8731_INPUT_CLASS 6
636 #define WM8731_RECORD_CLASS 7
637
638 static int
wm8731_set_port(void * hdl,struct mixer_ctrl * mc)639 wm8731_set_port(void *hdl, struct mixer_ctrl *mc)
640 {
641 struct zaudio_softc *sc = hdl;
642 int error = EINVAL;
643 int s;
644
645 s = splbio();
646 iic_acquire_bus(sc->sc_i2c, 0);
647
648 switch (mc->dev) {
649 case WM8731_SPKR_LVL:
650 if (mc->type != AUDIO_MIXER_VALUE)
651 break;
652 if (mc->un.value.num_channels == 1) {
653 sc->sc_volume[WM8731_OP_SPKR].left =
654 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
655 sc->sc_volume[WM8731_OP_SPKR].right =
656 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
657 } else if (mc->un.value.num_channels == 2) {
658 sc->sc_volume[WM8731_OP_SPKR].left =
659 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
660 sc->sc_volume[WM8731_OP_SPKR].right =
661 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
662 }
663 else
664 break;
665 wm8731_update_volume(sc, WM8731_OP_SPKR);
666 error = 0;
667 break;
668
669 case WM8731_SPKR_MUTE:
670 if (mc->type != AUDIO_MIXER_ENUM)
671 break;
672 UNMUTE(sc, WM8731_OP_SPKR, mc->un.ord ? 1 : 0);
673 wm8731_update_mutes(sc, 1);
674 error = 0;
675 break;
676
677 case WM8731_MIC_LVL:
678 if (mc->type != AUDIO_MIXER_VALUE)
679 break;
680 if (mc->un.value.num_channels == 1)
681 sc->sc_volume[WM8731_OP_MIC].left =
682 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
683 else
684 break;
685 wm8731_update_volume(sc, WM8731_OP_MIC);
686 error = 0;
687 break;
688
689 case WM8731_MIC_MUTE:
690 if (mc->type != AUDIO_MIXER_ENUM)
691 break;
692 UNMUTE(sc, WM8731_OP_MIC, mc->un.ord ? 1 : 0);
693 wm8731_update_mutes(sc, 2);
694 error = 0;
695 break;
696
697 case WM8731_RECORD_SOURCE:
698 if (mc->type != AUDIO_MIXER_ENUM)
699 break;
700 if (mc->un.ord != 0)
701 break;
702 /* MIC only */
703 error = 0;
704 break;
705 }
706
707 iic_release_bus(sc->sc_i2c, 0);
708 splx(s);
709
710 return error;
711 }
712
713 static int
wm8731_get_port(void * hdl,struct mixer_ctrl * mc)714 wm8731_get_port(void *hdl, struct mixer_ctrl *mc)
715 {
716 struct zaudio_softc *sc = hdl;
717 int error = EINVAL;
718
719 switch (mc->dev) {
720 case WM8731_SPKR_LVL:
721 if (mc->type != AUDIO_MIXER_VALUE)
722 break;
723 if (mc->un.value.num_channels == 1)
724 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
725 sc->sc_volume[WM8731_OP_SPKR].left;
726 else if (mc->un.value.num_channels == 2) {
727 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
728 sc->sc_volume[WM8731_OP_SPKR].left;
729 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
730 sc->sc_volume[WM8731_OP_SPKR].right;
731 }
732 else
733 break;
734 error = 0;
735 break;
736
737 case WM8731_SPKR_MUTE:
738 if (mc->type != AUDIO_MIXER_ENUM)
739 break;
740 mc->un.ord = sc->sc_unmute[WM8731_OP_SPKR] ? 1 : 0;
741 error = 0;
742 break;
743
744 case WM8731_MIC_LVL:
745 if (mc->type != AUDIO_MIXER_VALUE)
746 break;
747 if (mc->un.value.num_channels == 1)
748 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
749 sc->sc_volume[WM8731_OP_MIC].left;
750 else
751 break;
752 error = 0;
753 break;
754
755 case WM8731_MIC_MUTE:
756 if (mc->type != AUDIO_MIXER_ENUM)
757 break;
758 mc->un.ord = sc->sc_unmute[WM8731_OP_MIC] ? 1 : 0;
759 error = 0;
760 break;
761
762 case WM8731_RECORD_SOURCE:
763 if (mc->type != AUDIO_MIXER_ENUM)
764 break;
765 mc->un.ord = 0; /* MIC only */
766 error = 0;
767 break;
768 }
769
770 return error;
771 }
772
773 /*ARGSUSED*/
774 static int
wm8731_query_devinfo(void * hdl,struct mixer_devinfo * di)775 wm8731_query_devinfo(void *hdl, struct mixer_devinfo *di)
776 {
777
778 switch (di->index) {
779 case WM8731_SPKR_LVL:
780 di->type = AUDIO_MIXER_VALUE;
781 di->mixer_class = WM8731_OUTPUT_CLASS;
782 di->prev = AUDIO_MIXER_LAST;
783 di->next = WM8731_SPKR_MUTE;
784 strlcpy(di->label.name, AudioNspeaker,
785 sizeof(di->label.name));
786 di->un.v.num_channels = 1;
787 strlcpy(di->un.v.units.name, AudioNvolume,
788 sizeof(di->un.v.units.name));
789 break;
790
791 case WM8731_SPKR_MUTE:
792 di->type = AUDIO_MIXER_ENUM;
793 di->mixer_class = WM8731_OUTPUT_CLASS;
794 di->prev = WM8731_SPKR_LVL;
795 di->next = AUDIO_MIXER_LAST;
796 mute:
797 strlcpy(di->label.name, AudioNmute, sizeof(di->label.name));
798 di->un.e.num_mem = 2;
799 strlcpy(di->un.e.member[0].label.name, AudioNon,
800 sizeof(di->un.e.member[0].label.name));
801 di->un.e.member[0].ord = 0;
802 strlcpy(di->un.e.member[1].label.name, AudioNoff,
803 sizeof(di->un.e.member[1].label.name));
804 di->un.e.member[1].ord = 1;
805 break;
806
807 case WM8731_MIC_LVL:
808 di->type = AUDIO_MIXER_VALUE;
809 di->mixer_class = WM8731_INPUT_CLASS;
810 di->prev = AUDIO_MIXER_LAST;
811 di->next = WM8731_MIC_MUTE;
812 strlcpy(di->label.name, AudioNmicrophone,
813 sizeof(di->label.name));
814 strlcpy(di->un.v.units.name, AudioNvolume,
815 sizeof(di->un.v.units.name));
816 di->un.v.num_channels = 1;
817 break;
818
819 case WM8731_MIC_MUTE:
820 di->type = AUDIO_MIXER_ENUM;
821 di->mixer_class = WM8731_INPUT_CLASS;
822 di->prev = WM8731_MIC_LVL;
823 di->next = AUDIO_MIXER_LAST;
824 goto mute;
825
826 case WM8731_RECORD_SOURCE:
827 di->type = AUDIO_MIXER_ENUM;
828 di->mixer_class = WM8731_RECORD_CLASS;
829 di->prev = AUDIO_MIXER_LAST;
830 di->next = AUDIO_MIXER_LAST;
831 strlcpy(di->label.name, AudioNsource, sizeof(di->label.name));
832 di->un.e.num_mem = 1;
833 strlcpy(di->un.e.member[0].label.name, AudioNmicrophone,
834 sizeof(di->un.e.member[0].label.name));
835 di->un.e.member[0].ord = 0;
836 break;
837
838 case WM8731_OUTPUT_CLASS:
839 di->type = AUDIO_MIXER_CLASS;
840 di->mixer_class = WM8731_OUTPUT_CLASS;
841 di->prev = AUDIO_MIXER_LAST;
842 di->next = AUDIO_MIXER_LAST;
843 strlcpy(di->label.name, AudioCoutputs, sizeof(di->label.name));
844 break;
845
846 case WM8731_INPUT_CLASS:
847 di->type = AUDIO_MIXER_CLASS;
848 di->mixer_class = WM8731_INPUT_CLASS;
849 di->prev = AUDIO_MIXER_LAST;
850 di->next = AUDIO_MIXER_LAST;
851 strlcpy(di->label.name, AudioCinputs, sizeof(di->label.name));
852 break;
853
854 case WM8731_RECORD_CLASS:
855 di->type = AUDIO_MIXER_CLASS;
856 di->mixer_class = WM8731_RECORD_CLASS;
857 di->prev = AUDIO_MIXER_LAST;
858 di->next = AUDIO_MIXER_LAST;
859 strlcpy(di->label.name, AudioCinputs, sizeof(di->label.name));
860 break;
861
862 default:
863 return ENXIO;
864 }
865
866 return 0;
867 }
868
869 static int
wm8731_start_output(void * hdl,void * block,int bsize,void (* intr)(void *),void * intrarg)870 wm8731_start_output(void *hdl, void *block, int bsize, void (*intr)(void *),
871 void *intrarg)
872 {
873 struct zaudio_softc *sc = hdl;
874 int rv;
875
876 /* Power up codec if we are not already playing. */
877 if (!sc->sc_playing) {
878 sc->sc_playing = 1;
879 wm8731_play_setup(sc);
880 }
881
882 /* Start DMA via I2S */
883 rv = pxa2x0_i2s_start_output(&sc->sc_i2s, block, bsize, intr, intrarg);
884 if (rv) {
885 if (!sc->sc_recording)
886 wm8731_standby(sc);
887 sc->sc_playing = 0;
888 }
889
890 return rv;
891 }
892
893 static int
wm8731_start_input(void * hdl,void * block,int bsize,void (* intr)(void *),void * intrarg)894 wm8731_start_input(void *hdl, void *block, int bsize, void (*intr)(void *),
895 void *intrarg)
896 {
897 struct zaudio_softc *sc = hdl;
898 int rv;
899
900 /* Power up codec if we are not already recording. */
901 if (!sc->sc_recording) {
902 sc->sc_recording = 1;
903 wm8731_record_setup(sc);
904 }
905
906 /* Start DMA via I2S */
907 rv = pxa2x0_i2s_start_input(&sc->sc_i2s, block, bsize, intr, intrarg);
908 if (rv) {
909 if (!sc->sc_playing)
910 wm8731_standby(sc);
911 sc->sc_recording = 0;
912 }
913 return rv;
914 }
915