xref: /netbsd-src/sys/arch/zaurus/dev/wm8750_zaudio.c (revision 9cc6f62bd5eeaa18a29cbfe77b0075d638eff80e)
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