1 /* $NetBSD: wm8750_zaudio.c,v 1.4 2024/05/01 19:11:45 andvar Exp $ */
2 /* $OpenBSD: zaurus_audio.c,v 1.8 2005/08/18 13:23:02 robert Exp $ */
3
4 /*
5 * Copyright (c) 2005 Christopher Pascoe <pascoe@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*-
21 * Copyright (C) 2009 NONAKA Kimihiro <nonaka@netbsd.org>
22 * All rights reserved.
23 *
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
26 * are met:
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
29 * 2. Redistributions in binary form must reproduce the above copyright
30 * notice, this list of conditions and the following disclaimer in the
31 * documentation and/or other materials provided with the distribution.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
34 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
37 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
38 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
39 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
40 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
42 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 */
44
45 /*
46 * TODO:
47 * - powerhooks (currently only works until first suspend)
48 */
49
50 #include "opt_cputypes.h"
51 #include "opt_zaudio.h"
52
53 #include <sys/cdefs.h>
54 __KERNEL_RCSID(0, "$NetBSD: wm8750_zaudio.c,v 1.4 2024/05/01 19:11:45 andvar Exp $");
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/callout.h>
59 #include <sys/device.h>
60 #include <sys/kmem.h>
61 #include <sys/kernel.h>
62 #include <sys/audioio.h>
63 #include <sys/mutex.h>
64 #include <sys/intr.h>
65 #include <sys/bus.h>
66
67 #include <dev/audio/audio_if.h>
68
69 #include <dev/i2c/i2cvar.h>
70
71 #include <arm/xscale/pxa2x0reg.h>
72 #include <arm/xscale/pxa2x0var.h>
73 #include <arm/xscale/pxa2x0_i2c.h>
74 #include <arm/xscale/pxa2x0_i2s.h>
75 #include <arm/xscale/pxa2x0_dmac.h>
76 #include <arm/xscale/pxa2x0_gpio.h>
77
78 #include <zaurus/zaurus/zaurus_var.h>
79 #include <zaurus/dev/zaudiovar.h>
80 #include <zaurus/dev/wm8750reg.h>
81 #include <zaurus/dev/wm8750var.h>
82 #include <zaurus/dev/scoopvar.h>
83 #include <zaurus/dev/ioexpvar.h>
84
85 #define WM8750_ADDRESS 0x1B
86
87 /* GPIO pins */
88 #define GPIO_HP_IN_C3000 116
89
90 #define WM8750_OP_SPKR 0
91 #define WM8750_OP_HP 1
92 #define WM8750_OP_MIC 2
93 #define WM8750_OP_NUM 3
94
95 #define ZAUDIO_JACK_STATE_OUT 0
96 #define ZAUDIO_JACK_STATE_IN 1
97 #define ZAUDIO_JACK_STATE_INS 2
98 #define ZAUDIO_JACK_STATE_REM 3
99
100 static int wm8750_finalize(device_t);
101 static bool wm8750_suspend(device_t, const pmf_qual_t *);
102 static bool wm8750_resume(device_t, const pmf_qual_t *);
103 static void wm8750_volume_up(device_t);
104 static void wm8750_volume_down(device_t);
105 static void wm8750_volume_toggle(device_t);
106
107 static struct audio_device wm8750_device = {
108 "WM8750",
109 "1.0",
110 "wm"
111 };
112
113 static void wm8750_init(struct zaudio_softc *);
114 static int wm8750_jack_intr(void *);
115 static void wm8750_jack(void *);
116 static void wm8750_standby(struct zaudio_softc *);
117 static void wm8750_update_volume(struct zaudio_softc *, int);
118 static void wm8750_update_mutes(struct zaudio_softc *, int);
119 static void wm8750_play_setup(struct zaudio_softc *);
120 /*static*/ void wm8750_record_setup(struct zaudio_softc *);
121 static int wm8750_start_output(void *, void *, int, void (*)(void *), void *);
122 static int wm8750_start_input(void *, void *, int, void (*)(void *), void *);
123 static int wm8750_halt_output(void *);
124 static int wm8750_halt_input(void *);
125 static int wm8750_getdev(void *, struct audio_device *);
126 static int wm8750_set_port(void *, struct mixer_ctrl *);
127 static int wm8750_get_port(void *, struct mixer_ctrl *);
128 static int wm8750_query_devinfo(void *, struct mixer_devinfo *);
129
130 static struct audio_hw_if wm8750_hw_if = {
131 .open = zaudio_open,
132 .close = zaudio_close,
133 .query_format = zaudio_query_format,
134 .set_format = zaudio_set_format,
135 .round_blocksize = zaudio_round_blocksize,
136 .commit_settings = NULL,
137 .init_output = NULL,
138 .init_input = NULL,
139 .start_output = wm8750_start_output,
140 .start_input = wm8750_start_input,
141 .halt_output = wm8750_halt_output,
142 .halt_input = wm8750_halt_input,
143 .speaker_ctl = NULL,
144 .getdev = wm8750_getdev,
145 .set_port = wm8750_set_port,
146 .get_port = wm8750_get_port,
147 .query_devinfo = wm8750_query_devinfo,
148 .allocm = zaudio_allocm,
149 .freem = zaudio_freem,
150 .round_buffersize = zaudio_round_buffersize,
151 .get_props = zaudio_get_props,
152 .trigger_output = NULL,
153 .trigger_input = NULL,
154 .dev_ioctl = NULL,
155 .get_locks = zaudio_get_locks,
156 };
157
158 static const uint16_t playback_regs[][2] = {
159 /* Unmute DAC */
160 { ADCDACCTL_REG, 0x000 },
161
162 /* 16 bit audio words */
163 { AUDINT_REG, AUDINT_SET_FORMAT(2) },
164
165 /* Enable thermal protection, power */
166 { ADCTL1_REG, ADCTL1_TSDEN | ADCTL1_SET_VSEL(3) },
167
168 /* Enable speaker driver, DAC oversampling */
169 { ADCTL2_REG, ADCTL2_ROUT2INV | ADCTL2_DACOSR },
170
171 /* Set DAC voltage references */
172 { PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(1) | PWRMGMT1_VREF },
173
174 /* Direct DACs to output mixers */
175 { LOUTMIX1_REG, LOUTMIX1_LD2LO },
176 { LOUTMIX2_REG, 0x000 },
177 { ROUTMIX1_REG, 0x000 },
178 { ROUTMIX2_REG, ROUTMIX2_RD2RO },
179
180 /* End of list */
181 { 0xffff, 0xffff }
182 };
183
184 static const uint16_t record_regs[][2] = {
185 /* Unmute DAC */
186 { ADCDACCTL_REG, 0x000 },
187
188 /* 16 bit audio words */
189 { AUDINT_REG, AUDINT_SET_FORMAT(2) },
190
191 /* Enable thermal protection, power, left DAC for both channel */
192 { ADCTL1_REG, ADCTL1_TSDEN | ADCTL1_SET_VSEL(3)
193 | ADCTL1_SET_DATSEL(1) },
194
195 /* Differential input select: LINPUT1-RINPUT1, stereo */
196 { ADCINPMODE_REG, 0x000 },
197
198 /* L-R differential, micboost 20dB */
199 { ADCLSPATH_REG, ADCLSPATH_SET_LINSEL(3) | ADCLSPATH_SET_LMICBOOST(2) },
200 { ADCRSPATH_REG, ADCRSPATH_SET_RINSEL(3) | ADCRSPATH_SET_RMICBOOST(2) },
201
202 /* End of list */
203 { 0xffff, 0xffff }
204 };
205
206 static __inline int
wm8750_write(struct zaudio_softc * sc,int reg,int val)207 wm8750_write(struct zaudio_softc *sc, int reg, int val)
208 {
209 uint16_t tmp;
210 uint8_t cmd;
211 uint8_t data;
212
213 tmp = (reg << 9) | (val & 0x1ff);
214 cmd = tmp >> 8;
215 data = tmp;
216 return iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, WM8750_ADDRESS,
217 &cmd, 1, &data, 1, 0);
218 }
219
220 int
wm8750_match(device_t parent,cfdata_t cf,struct i2c_attach_args * ia)221 wm8750_match(device_t parent, cfdata_t cf, struct i2c_attach_args *ia)
222 {
223 int match_result;
224
225 if (ZAURUS_ISC860)
226 return 0;
227
228 if (iic_use_direct_match(ia, cf, NULL, &match_result))
229 return match_result;
230
231 /* indirect config - check typical address */
232 if (ia->ia_addr == WM8750_ADDRESS)
233 return I2C_MATCH_ADDRESS_ONLY;
234
235 return 0;
236 }
237
238 void
wm8750_attach(device_t parent,device_t self,struct i2c_attach_args * ia)239 wm8750_attach(device_t parent, device_t self, struct i2c_attach_args *ia)
240 {
241 struct zaudio_softc *sc = device_private(self);
242 int error;
243
244 aprint_normal(": I2S, WM8750 Audio\n");
245 aprint_naive("\n");
246
247 /* Check for an I2C response from the wm8750 */
248 iic_acquire_bus(sc->sc_i2c, 0);
249 error = wm8750_write(sc, RESET_REG, 0);
250 iic_release_bus(sc->sc_i2c, 0);
251 if (error) {
252 aprint_error_dev(self, "codec failed to respond\n");
253 goto fail_i2c;
254 }
255 delay(100);
256
257 /* Allocate memory for volume & mute operations */
258 sc->sc_volume = kmem_zalloc(sizeof(*sc->sc_volume) * WM8750_OP_NUM,
259 KM_SLEEP);
260 sc->sc_unmute = kmem_zalloc(sizeof(*sc->sc_unmute) * WM8750_OP_NUM,
261 KM_SLEEP);
262 sc->sc_unmute_toggle = kmem_zalloc(
263 sizeof(*sc->sc_unmute_toggle) * WM8750_OP_NUM, KM_SLEEP);
264
265 /* Speaker on, headphones off by default. */
266 sc->sc_volume[WM8750_OP_SPKR].left = 180;
267 sc->sc_jack = FALSE;
268 UNMUTE(sc, WM8750_OP_SPKR, 1);
269 sc->sc_volume[WM8750_OP_HP].left = 180;
270 sc->sc_volume[WM8750_OP_HP].right = 180;
271 UNMUTE(sc, WM8750_OP_HP, 0);
272 sc->sc_volume[WM8750_OP_MIC].left = 180;
273 UNMUTE(sc, WM8750_OP_MIC, 0);
274
275 /* Configure headphone jack state change handling. */
276 callout_setfunc(&sc->sc_to, wm8750_jack, sc);
277 pxa2x0_gpio_set_function(GPIO_HP_IN_C3000, GPIO_IN);
278 (void) pxa2x0_gpio_intr_establish(GPIO_HP_IN_C3000, IST_EDGE_BOTH,
279 IPL_BIO, wm8750_jack_intr, sc);
280
281 /* wm8750_init() implicitly depends on ioexp or scoop */
282 config_finalize_register(self, wm8750_finalize);
283
284 audio_attach_mi(&wm8750_hw_if, sc, self);
285
286 if (!pmf_device_register(self, wm8750_suspend, wm8750_resume))
287 aprint_error_dev(self, "couldn't establish power handler\n");
288 if (!pmf_event_register(self, PMFE_AUDIO_VOLUME_UP,
289 wm8750_volume_up, true))
290 aprint_error_dev(self, "couldn't register event handler\n");
291 if (!pmf_event_register(self, PMFE_AUDIO_VOLUME_DOWN,
292 wm8750_volume_down, true))
293 aprint_error_dev(self, "couldn't register event handler\n");
294 if (!pmf_event_register(self, PMFE_AUDIO_VOLUME_TOGGLE,
295 wm8750_volume_toggle, true))
296 aprint_error_dev(self, "couldn't register event handler\n");
297
298 return;
299
300 fail_i2c:
301 pxa2x0_i2s_detach_sub(&sc->sc_i2s);
302 }
303
304 static int
wm8750_finalize(device_t dv)305 wm8750_finalize(device_t dv)
306 {
307 struct zaudio_softc *sc = device_private(dv);
308
309 wm8750_init(sc);
310 return 0;
311 }
312
313 static bool
wm8750_suspend(device_t dv,const pmf_qual_t * qual)314 wm8750_suspend(device_t dv, const pmf_qual_t *qual)
315 {
316 struct zaudio_softc *sc = device_private(dv);
317
318 callout_stop(&sc->sc_to);
319 wm8750_standby(sc);
320
321 return true;
322 }
323
324 static bool
wm8750_resume(device_t dv,const pmf_qual_t * qual)325 wm8750_resume(device_t dv, const pmf_qual_t *qual)
326 {
327 struct zaudio_softc *sc = device_private(dv);
328
329 pxa2x0_i2s_init(&sc->sc_i2s);
330 wm8750_init(sc);
331
332 return true;
333 }
334
335 static __inline uint8_t
vol_sadd(int vol,int stride)336 vol_sadd(int vol, int stride)
337 {
338
339 vol += stride;
340 if (vol > 255)
341 return 255;
342 return (uint8_t)vol;
343 }
344
345 #ifndef ZAUDIO_VOLUME_STRIDE
346 #define ZAUDIO_VOLUME_STRIDE 8
347 #endif
348
349 static void
wm8750_volume_up(device_t dv)350 wm8750_volume_up(device_t dv)
351 {
352 struct zaudio_softc *sc = device_private(dv);
353 int s;
354
355 s = splbio();
356 iic_acquire_bus(sc->sc_i2c, 0);
357
358 sc->sc_volume[WM8750_OP_SPKR].left =
359 vol_sadd(sc->sc_volume[WM8750_OP_SPKR].left, ZAUDIO_VOLUME_STRIDE);
360 sc->sc_volume[WM8750_OP_HP].left =
361 vol_sadd(sc->sc_volume[WM8750_OP_HP].left, ZAUDIO_VOLUME_STRIDE);
362 sc->sc_volume[WM8750_OP_HP].right =
363 vol_sadd(sc->sc_volume[WM8750_OP_HP].right, ZAUDIO_VOLUME_STRIDE);
364
365 wm8750_update_volume(sc, WM8750_OP_SPKR);
366 wm8750_update_volume(sc, WM8750_OP_HP);
367
368 iic_release_bus(sc->sc_i2c, 0);
369 splx(s);
370 }
371
372 static __inline uint8_t
vol_ssub(int vol,int stride)373 vol_ssub(int vol, int stride)
374 {
375
376 vol -= stride;
377 if (vol < 0)
378 return 0;
379 return (uint8_t)vol;
380 }
381
382 static void
wm8750_volume_down(device_t dv)383 wm8750_volume_down(device_t dv)
384 {
385 struct zaudio_softc *sc = device_private(dv);
386 int s;
387
388 s = splbio();
389 iic_acquire_bus(sc->sc_i2c, 0);
390
391 sc->sc_volume[WM8750_OP_SPKR].left =
392 vol_ssub(sc->sc_volume[WM8750_OP_SPKR].left, ZAUDIO_VOLUME_STRIDE);
393 sc->sc_volume[WM8750_OP_HP].left =
394 vol_ssub(sc->sc_volume[WM8750_OP_HP].left, ZAUDIO_VOLUME_STRIDE);
395 sc->sc_volume[WM8750_OP_HP].right =
396 vol_ssub(sc->sc_volume[WM8750_OP_HP].right, ZAUDIO_VOLUME_STRIDE);
397
398 wm8750_update_volume(sc, WM8750_OP_SPKR);
399 wm8750_update_volume(sc, WM8750_OP_HP);
400
401 iic_release_bus(sc->sc_i2c, 0);
402 splx(s);
403 }
404
405 static void
wm8750_volume_toggle(device_t dv)406 wm8750_volume_toggle(device_t dv)
407 {
408 struct zaudio_softc *sc = device_private(dv);
409 int s;
410
411 s = splbio();
412 iic_acquire_bus(sc->sc_i2c, 0);
413
414 if (!sc->sc_unmute[WM8750_OP_SPKR] && !sc->sc_unmute[WM8750_OP_HP]) {
415 sc->sc_unmute[WM8750_OP_SPKR] =
416 sc->sc_unmute_toggle[WM8750_OP_SPKR];
417 sc->sc_unmute[WM8750_OP_HP] =
418 sc->sc_unmute_toggle[WM8750_OP_HP];
419 } else {
420 sc->sc_unmute[WM8750_OP_SPKR] = 0;
421 sc->sc_unmute[WM8750_OP_HP] = 0;
422 }
423 wm8750_update_mutes(sc, 1);
424
425 iic_release_bus(sc->sc_i2c, 0);
426 splx(s);
427 }
428
429 static void
wm8750_init(struct zaudio_softc * sc)430 wm8750_init(struct zaudio_softc *sc)
431 {
432
433 iic_acquire_bus(sc->sc_i2c, 0);
434
435 /* Reset the codec */
436 wm8750_write(sc, RESET_REG, 0);
437 delay(100);
438
439 /* Switch to standby power only */
440 wm8750_write(sc, PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(2));
441 wm8750_write(sc, PWRMGMT2_REG, 0);
442
443 /* Configure digital interface for I2S */
444 wm8750_write(sc, AUDINT_REG, AUDINT_SET_FORMAT(2));
445
446 /* Initialise volume levels */
447 wm8750_update_volume(sc, WM8750_OP_SPKR);
448 wm8750_update_volume(sc, WM8750_OP_HP);
449 wm8750_update_volume(sc, WM8750_OP_MIC);
450
451 scoop_set_headphone(0);
452 if (ZAURUS_ISC1000)
453 ioexp_set_mic_bias(0);
454 else
455 scoop_set_mic_bias(0);
456
457 iic_release_bus(sc->sc_i2c, 0);
458
459 /* Assume that the jack state has changed. */
460 wm8750_jack(sc);
461 }
462
463 static int
wm8750_jack_intr(void * v)464 wm8750_jack_intr(void *v)
465 {
466 struct zaudio_softc *sc = v;
467
468 if (!callout_active(&sc->sc_to))
469 wm8750_jack(sc);
470
471 return 1;
472 }
473
474 static void
wm8750_jack(void * v)475 wm8750_jack(void *v)
476 {
477 struct zaudio_softc *sc = v;
478
479 switch (sc->sc_state) {
480 case ZAUDIO_JACK_STATE_OUT:
481 if (pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
482 sc->sc_state = ZAUDIO_JACK_STATE_INS;
483 sc->sc_icount = 0;
484 }
485 break;
486
487 case ZAUDIO_JACK_STATE_INS:
488 if (sc->sc_icount++ > 2) {
489 if (pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
490 sc->sc_state = ZAUDIO_JACK_STATE_IN;
491 sc->sc_jack = TRUE;
492 UNMUTE(sc, WM8750_OP_SPKR, 0);
493 UNMUTE(sc, WM8750_OP_HP, 1);
494 UNMUTE(sc, WM8750_OP_MIC, 1);
495 goto update_mutes;
496 } else
497 sc->sc_state = ZAUDIO_JACK_STATE_OUT;
498 }
499 break;
500
501 case ZAUDIO_JACK_STATE_IN:
502 if (!pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
503 sc->sc_state = ZAUDIO_JACK_STATE_REM;
504 sc->sc_icount = 0;
505 }
506 break;
507
508 case ZAUDIO_JACK_STATE_REM:
509 if (sc->sc_icount++ > 2) {
510 if (!pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
511 sc->sc_state = ZAUDIO_JACK_STATE_OUT;
512 sc->sc_jack = FALSE;
513 UNMUTE(sc, WM8750_OP_SPKR, 1);
514 UNMUTE(sc, WM8750_OP_HP, 0);
515 UNMUTE(sc, WM8750_OP_MIC, 0);
516 goto update_mutes;
517 } else
518 sc->sc_state = ZAUDIO_JACK_STATE_IN;
519 }
520 break;
521 }
522
523 callout_schedule(&sc->sc_to, hz/4);
524
525 return;
526
527 update_mutes:
528 callout_stop(&sc->sc_to);
529
530 if (sc->sc_playing || sc->sc_recording) {
531 iic_acquire_bus(sc->sc_i2c, 0);
532 if (sc->sc_playing)
533 wm8750_update_mutes(sc, 1);
534 if (sc->sc_recording)
535 wm8750_update_mutes(sc, 2);
536 iic_release_bus(sc->sc_i2c, 0);
537 }
538 }
539
540 static void
wm8750_standby(struct zaudio_softc * sc)541 wm8750_standby(struct zaudio_softc *sc)
542 {
543
544 iic_acquire_bus(sc->sc_i2c, 0);
545
546 /* Switch codec to standby power only */
547 wm8750_write(sc, PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(2));
548 wm8750_write(sc, PWRMGMT2_REG, 0);
549
550 scoop_set_headphone(0);
551 if (ZAURUS_ISC1000)
552 ioexp_set_mic_bias(0);
553 else
554 scoop_set_mic_bias(0);
555
556 iic_release_bus(sc->sc_i2c, 0);
557 }
558
559 static void
wm8750_update_volume(struct zaudio_softc * sc,int output)560 wm8750_update_volume(struct zaudio_softc *sc, int output)
561 {
562
563 switch (output) {
564 case WM8750_OP_SPKR:
565 wm8750_write(sc, LOUT2VOL_REG, LOUT2VOL_LO2VU | LOUT2VOL_LO2ZC |
566 LOUT2VOL_SET_LOUT2VOL(sc->sc_volume[WM8750_OP_SPKR].left >> 1));
567 wm8750_write(sc, ROUT2VOL_REG, ROUT2VOL_RO2VU | ROUT2VOL_RO2ZC |
568 ROUT2VOL_SET_ROUT2VOL(sc->sc_volume[WM8750_OP_SPKR].left >> 1));
569 break;
570
571 case WM8750_OP_HP:
572 wm8750_write(sc, LOUT1VOL_REG, LOUT1VOL_LO1VU | LOUT1VOL_LO1ZC |
573 LOUT1VOL_SET_LOUT1VOL(sc->sc_volume[WM8750_OP_HP].left >> 1));
574 wm8750_write(sc, ROUT1VOL_REG, ROUT1VOL_RO1VU | ROUT1VOL_RO1ZC |
575 ROUT1VOL_SET_ROUT1VOL(sc->sc_volume[WM8750_OP_HP].right >> 1));
576 break;
577
578 case WM8750_OP_MIC:
579 wm8750_write(sc, LINVOL_REG, LINVOL_LIVU |
580 LINVOL_SET_LINVOL(sc->sc_volume[WM8750_OP_MIC].left >> 2));
581 wm8750_write(sc, RINVOL_REG, RINVOL_RIVU |
582 RINVOL_SET_RINVOL(sc->sc_volume[WM8750_OP_MIC].left >> 2));
583 break;
584 }
585 }
586
587 static void
wm8750_update_mutes(struct zaudio_softc * sc,int mask)588 wm8750_update_mutes(struct zaudio_softc *sc, int mask)
589 {
590 uint16_t val;
591
592 /* playback */
593 if (mask & 1) {
594 val = PWRMGMT2_DACL | PWRMGMT2_DACR;
595 if (sc->sc_unmute[WM8750_OP_SPKR])
596 val |= PWRMGMT2_LOUT2 | PWRMGMT2_ROUT2;
597 if (sc->sc_unmute[WM8750_OP_HP])
598 val |= PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1;
599 wm8750_write(sc, PWRMGMT2_REG, val);
600 scoop_set_headphone(sc->sc_unmute[WM8750_OP_HP]);
601 }
602
603 /* record */
604 if (mask & 2) {
605 val = PWRMGMT1_SET_VMIDSEL(1) | PWRMGMT1_VREF;
606 if (sc->sc_unmute[WM8750_OP_MIC]) {
607 val |= PWRMGMT1_AINL | PWRMGMT1_AINR
608 | PWRMGMT1_ADCL | PWRMGMT1_ADCR | PWRMGMT1_MICB;
609 }
610 wm8750_write(sc, PWRMGMT1_REG, val);
611 if (ZAURUS_ISC1000)
612 ioexp_set_mic_bias(sc->sc_unmute[WM8750_OP_MIC]);
613 else
614 scoop_set_mic_bias(sc->sc_unmute[WM8750_OP_MIC]);
615 }
616 }
617
618 static void
wm8750_play_setup(struct zaudio_softc * sc)619 wm8750_play_setup(struct zaudio_softc *sc)
620 {
621 int i;
622
623 iic_acquire_bus(sc->sc_i2c, 0);
624
625 /* Program the codec with playback settings */
626 for (i = 0; playback_regs[i][0] != 0xffff; i++) {
627 wm8750_write(sc, playback_regs[i][0], playback_regs[i][1]);
628 }
629 wm8750_update_mutes(sc, 1);
630
631 iic_release_bus(sc->sc_i2c, 0);
632 }
633
634 /*static*/ void
wm8750_record_setup(struct zaudio_softc * sc)635 wm8750_record_setup(struct zaudio_softc *sc)
636 {
637 int i;
638
639 iic_acquire_bus(sc->sc_i2c, 0);
640
641 /* Program the codec with playback settings */
642 for (i = 0; record_regs[i][0] != 0xffff; i++) {
643 wm8750_write(sc, record_regs[i][0], record_regs[i][1]);
644 }
645 wm8750_update_mutes(sc, 2);
646
647 iic_release_bus(sc->sc_i2c, 0);
648 }
649
650 static int
wm8750_halt_output(void * hdl)651 wm8750_halt_output(void *hdl)
652 {
653 struct zaudio_softc *sc = hdl;
654 int rv;
655
656 rv = pxa2x0_i2s_halt_output(&sc->sc_i2s);
657 if (!sc->sc_recording)
658 wm8750_standby(sc);
659 sc->sc_playing = 0;
660
661 return rv;
662 }
663
664 static int
wm8750_halt_input(void * hdl)665 wm8750_halt_input(void *hdl)
666 {
667 struct zaudio_softc *sc = hdl;
668 int rv;
669
670 rv = pxa2x0_i2s_halt_input(&sc->sc_i2s);
671 if (!sc->sc_playing)
672 wm8750_standby(sc);
673 sc->sc_recording = 0;
674
675 return rv;
676 }
677
678 static int
wm8750_getdev(void * hdl,struct audio_device * ret)679 wm8750_getdev(void *hdl, struct audio_device *ret)
680 {
681
682 *ret = wm8750_device;
683 return 0;
684 }
685
686 #define WM8750_SPKR_LVL 0
687 #define WM8750_SPKR_MUTE 1
688 #define WM8750_HP_LVL 2
689 #define WM8750_HP_MUTE 3
690 #define WM8750_MIC_LVL 4
691 #define WM8750_MIC_MUTE 5
692 #define WM8750_RECORD_SOURCE 6
693 #define WM8750_OUTPUT_CLASS 7
694 #define WM8750_INPUT_CLASS 8
695 #define WM8750_RECORD_CLASS 9
696
697 static int
wm8750_set_port(void * hdl,struct mixer_ctrl * mc)698 wm8750_set_port(void *hdl, struct mixer_ctrl *mc)
699 {
700 struct zaudio_softc *sc = hdl;
701 int error = EINVAL;
702 int s;
703
704 s = splbio();
705 iic_acquire_bus(sc->sc_i2c, 0);
706
707 switch (mc->dev) {
708 case WM8750_SPKR_LVL:
709 if (mc->type != AUDIO_MIXER_VALUE)
710 break;
711 if (mc->un.value.num_channels == 1)
712 sc->sc_volume[WM8750_OP_SPKR].left =
713 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
714 else
715 break;
716 wm8750_update_volume(sc, WM8750_OP_SPKR);
717 error = 0;
718 break;
719
720 case WM8750_SPKR_MUTE:
721 if (mc->type != AUDIO_MIXER_ENUM)
722 break;
723 UNMUTE(sc, WM8750_OP_SPKR, mc->un.ord ? 1 : 0);
724 wm8750_update_mutes(sc, 1);
725 error = 0;
726 break;
727
728 case WM8750_HP_LVL:
729 if (mc->type != AUDIO_MIXER_VALUE)
730 break;
731 if (mc->un.value.num_channels == 1) {
732 sc->sc_volume[WM8750_OP_HP].left =
733 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
734 sc->sc_volume[WM8750_OP_HP].right =
735 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
736 } else if (mc->un.value.num_channels == 2) {
737 sc->sc_volume[WM8750_OP_HP].left =
738 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
739 sc->sc_volume[WM8750_OP_HP].right =
740 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
741 }
742 else
743 break;
744 wm8750_update_volume(sc, WM8750_OP_HP);
745 error = 0;
746 break;
747
748 case WM8750_HP_MUTE:
749 if (mc->type != AUDIO_MIXER_ENUM)
750 break;
751 UNMUTE(sc, WM8750_OP_HP, mc->un.ord ? 1 : 0);
752 wm8750_update_mutes(sc, 1);
753 error = 0;
754 break;
755
756 case WM8750_MIC_LVL:
757 if (mc->type != AUDIO_MIXER_VALUE)
758 break;
759 if (mc->un.value.num_channels == 1)
760 sc->sc_volume[WM8750_OP_MIC].left =
761 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
762 else
763 break;
764 wm8750_update_volume(sc, WM8750_OP_MIC);
765 error = 0;
766 break;
767
768 case WM8750_MIC_MUTE:
769 if (mc->type != AUDIO_MIXER_ENUM)
770 break;
771 UNMUTE(sc, WM8750_OP_MIC, mc->un.ord ? 1 : 0);
772 wm8750_update_mutes(sc, 2);
773 error = 0;
774 break;
775
776 case WM8750_RECORD_SOURCE:
777 if (mc->type != AUDIO_MIXER_ENUM)
778 break;
779 if (mc->un.ord != 0)
780 break;
781 /* MIC only */
782 error = 0;
783 break;
784 }
785
786 iic_release_bus(sc->sc_i2c, 0);
787 splx(s);
788
789 return error;
790 }
791
792 static int
wm8750_get_port(void * hdl,struct mixer_ctrl * mc)793 wm8750_get_port(void *hdl, struct mixer_ctrl *mc)
794 {
795 struct zaudio_softc *sc = hdl;
796 int error = EINVAL;
797
798 switch (mc->dev) {
799 case WM8750_SPKR_LVL:
800 if (mc->type != AUDIO_MIXER_VALUE)
801 break;
802 if (mc->un.value.num_channels == 1)
803 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
804 sc->sc_volume[WM8750_OP_SPKR].left;
805 else
806 break;
807 error = 0;
808 break;
809
810 case WM8750_SPKR_MUTE:
811 if (mc->type != AUDIO_MIXER_ENUM)
812 break;
813 mc->un.ord = sc->sc_unmute[WM8750_OP_SPKR] ? 1 : 0;
814 error = 0;
815 break;
816
817 case WM8750_HP_LVL:
818 if (mc->type != AUDIO_MIXER_VALUE)
819 break;
820 if (mc->un.value.num_channels == 1)
821 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
822 sc->sc_volume[WM8750_OP_HP].left;
823 else if (mc->un.value.num_channels == 2) {
824 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
825 sc->sc_volume[WM8750_OP_HP].left;
826 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
827 sc->sc_volume[WM8750_OP_HP].right;
828 }
829 else
830 break;
831 error = 0;
832 break;
833
834 case WM8750_HP_MUTE:
835 if (mc->type != AUDIO_MIXER_ENUM)
836 break;
837 mc->un.ord = sc->sc_unmute[WM8750_OP_HP] ? 1 : 0;
838 error = 0;
839 break;
840
841 case WM8750_MIC_LVL:
842 if (mc->type != AUDIO_MIXER_VALUE)
843 break;
844 if (mc->un.value.num_channels == 1)
845 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
846 sc->sc_volume[WM8750_OP_MIC].left;
847 else
848 break;
849 error = 0;
850 break;
851
852 case WM8750_MIC_MUTE:
853 if (mc->type != AUDIO_MIXER_ENUM)
854 break;
855 mc->un.ord = sc->sc_unmute[WM8750_OP_MIC] ? 1 : 0;
856 error = 0;
857 break;
858
859 case WM8750_RECORD_SOURCE:
860 if (mc->type != AUDIO_MIXER_ENUM)
861 break;
862 mc->un.ord = 0; /* MIC only */
863 error = 0;
864 break;
865 }
866
867 return error;
868 }
869
870 /*ARGSUSED*/
871 static int
wm8750_query_devinfo(void * hdl,struct mixer_devinfo * di)872 wm8750_query_devinfo(void *hdl, struct mixer_devinfo *di)
873 {
874
875 switch (di->index) {
876 case WM8750_SPKR_LVL:
877 di->type = AUDIO_MIXER_VALUE;
878 di->mixer_class = WM8750_OUTPUT_CLASS;
879 di->prev = AUDIO_MIXER_LAST;
880 di->next = WM8750_SPKR_MUTE;
881 strlcpy(di->label.name, AudioNspeaker, sizeof(di->label.name));
882 strlcpy(di->un.v.units.name, AudioNvolume,
883 sizeof(di->un.v.units.name));
884 di->un.v.num_channels = 1;
885 break;
886
887 case WM8750_SPKR_MUTE:
888 di->type = AUDIO_MIXER_ENUM;
889 di->mixer_class = WM8750_OUTPUT_CLASS;
890 di->prev = WM8750_SPKR_LVL;
891 di->next = AUDIO_MIXER_LAST;
892 goto mute;
893
894 case WM8750_HP_LVL:
895 di->type = AUDIO_MIXER_VALUE;
896 di->mixer_class = WM8750_OUTPUT_CLASS;
897 di->prev = AUDIO_MIXER_LAST;
898 di->next = WM8750_HP_MUTE;
899 strlcpy(di->label.name, AudioNheadphone,
900 sizeof(di->label.name));
901 di->un.v.num_channels = 1;
902 strlcpy(di->un.v.units.name, AudioNvolume,
903 sizeof(di->un.v.units.name));
904 break;
905
906 case WM8750_HP_MUTE:
907 di->type = AUDIO_MIXER_ENUM;
908 di->mixer_class = WM8750_OUTPUT_CLASS;
909 di->prev = WM8750_HP_LVL;
910 di->next = AUDIO_MIXER_LAST;
911 mute:
912 strlcpy(di->label.name, AudioNmute, sizeof(di->label.name));
913 di->un.e.num_mem = 2;
914 strlcpy(di->un.e.member[0].label.name, AudioNon,
915 sizeof(di->un.e.member[0].label.name));
916 di->un.e.member[0].ord = 0;
917 strlcpy(di->un.e.member[1].label.name, AudioNoff,
918 sizeof(di->un.e.member[1].label.name));
919 di->un.e.member[1].ord = 1;
920 break;
921
922 case WM8750_MIC_LVL:
923 di->type = AUDIO_MIXER_VALUE;
924 di->mixer_class = WM8750_INPUT_CLASS;
925 di->prev = AUDIO_MIXER_LAST;
926 di->next = WM8750_MIC_MUTE;
927 strlcpy(di->label.name, AudioNmicrophone,
928 sizeof(di->label.name));
929 strlcpy(di->un.v.units.name, AudioNvolume,
930 sizeof(di->un.v.units.name));
931 di->un.v.num_channels = 1;
932 break;
933
934 case WM8750_MIC_MUTE:
935 di->type = AUDIO_MIXER_ENUM;
936 di->mixer_class = WM8750_INPUT_CLASS;
937 di->prev = WM8750_MIC_LVL;
938 di->next = AUDIO_MIXER_LAST;
939 goto mute;
940
941 case WM8750_RECORD_SOURCE:
942 di->type = AUDIO_MIXER_ENUM;
943 di->mixer_class = WM8750_RECORD_CLASS;
944 di->prev = AUDIO_MIXER_LAST;
945 di->next = AUDIO_MIXER_LAST;
946 strlcpy(di->label.name, AudioNsource, sizeof(di->label.name));
947 di->un.e.num_mem = 1;
948 strlcpy(di->un.e.member[0].label.name, AudioNmicrophone,
949 sizeof(di->un.e.member[0].label.name));
950 di->un.e.member[0].ord = 0;
951 break;
952
953 case WM8750_OUTPUT_CLASS:
954 di->type = AUDIO_MIXER_CLASS;
955 di->mixer_class = WM8750_OUTPUT_CLASS;
956 di->prev = AUDIO_MIXER_LAST;
957 di->next = AUDIO_MIXER_LAST;
958 strlcpy(di->label.name, AudioCoutputs, sizeof(di->label.name));
959 break;
960
961 case WM8750_INPUT_CLASS:
962 di->type = AUDIO_MIXER_CLASS;
963 di->mixer_class = WM8750_INPUT_CLASS;
964 di->prev = AUDIO_MIXER_LAST;
965 di->next = AUDIO_MIXER_LAST;
966 strlcpy(di->label.name, AudioCinputs, sizeof(di->label.name));
967 break;
968
969 case WM8750_RECORD_CLASS:
970 di->type = AUDIO_MIXER_CLASS;
971 di->mixer_class = WM8750_RECORD_CLASS;
972 di->prev = AUDIO_MIXER_LAST;
973 di->next = AUDIO_MIXER_LAST;
974 strlcpy(di->label.name, AudioCinputs, sizeof(di->label.name));
975 break;
976
977 default:
978 return ENXIO;
979 }
980
981 return 0;
982 }
983
984 static int
wm8750_start_output(void * hdl,void * block,int bsize,void (* intr)(void *),void * intrarg)985 wm8750_start_output(void *hdl, void *block, int bsize, void (*intr)(void *),
986 void *intrarg)
987 {
988 struct zaudio_softc *sc = hdl;
989 int rv;
990
991 /* Power up codec if we are not already playing. */
992 if (!sc->sc_playing) {
993 sc->sc_playing = 1;
994 wm8750_play_setup(sc);
995 }
996
997 /* Start DMA via I2S */
998 rv = pxa2x0_i2s_start_output(&sc->sc_i2s, block, bsize, intr, intrarg);
999 if (rv) {
1000 if (!sc->sc_recording)
1001 wm8750_standby(sc);
1002 sc->sc_playing = 0;
1003 }
1004
1005 return rv;
1006 }
1007
1008 static int
wm8750_start_input(void * hdl,void * block,int bsize,void (* intr)(void *),void * intrarg)1009 wm8750_start_input(void *hdl, void *block, int bsize, void (*intr)(void *),
1010 void *intrarg)
1011 {
1012 struct zaudio_softc *sc = hdl;
1013 int rv;
1014
1015 /* Power up codec if we are not already recording. */
1016 if (!sc->sc_recording) {
1017 sc->sc_recording = 1;
1018 wm8750_record_setup(sc);
1019 }
1020
1021 /* Start DMA via I2S */
1022 rv = pxa2x0_i2s_start_input(&sc->sc_i2s, block, bsize, intr, intrarg);
1023 if (rv) {
1024 if (!sc->sc_playing)
1025 wm8750_standby(sc);
1026 sc->sc_recording = 0;
1027 }
1028 return rv;
1029 }
1030