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 80static int wm8731_finalize(device_t); 81static bool wm8731_suspend(device_t, const pmf_qual_t *); 82static bool wm8731_resume(device_t, const pmf_qual_t *); 83static void wm8731_volume_up(device_t); 84static void wm8731_volume_down(device_t); 85static void wm8731_volume_toggle(device_t); 86 87static struct audio_device wm8731_device = { 88 "WM8731", 89 "1.0", 90 "wm" 91}; 92 93static void wm8731_init(struct zaudio_softc *); 94static int wm8731_jack_intr(void *); 95static void wm8731_jack(void *); 96static void wm8731_standby(struct zaudio_softc *); 97static void wm8731_update_volume(struct zaudio_softc *, int); 98static void wm8731_update_mutes(struct zaudio_softc *, int); 99static void wm8731_play_setup(struct zaudio_softc *); 100/*static*/ void wm8731_record_setup(struct zaudio_softc *); 101static int wm8731_start_output(void *, void *, int, void (*)(void *), void *); 102static int wm8731_start_input(void *, void *, int, void (*)(void *), void *); 103static int wm8731_halt_output(void *); 104static int wm8731_halt_input(void *); 105static int wm8731_getdev(void *, struct audio_device *); 106static int wm8731_set_port(void *, struct mixer_ctrl *); 107static int wm8731_get_port(void *, struct mixer_ctrl *); 108static int wm8731_query_devinfo(void *, struct mixer_devinfo *); 109 110static 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 138static 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 156static 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 174static __inline int 175wm8731_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 188int 189wm8731_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 206void 207wm8731_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 266fail_i2c: 267 pxa2x0_i2s_detach_sub(&sc->sc_i2s); 268} 269 270static int 271wm8731_finalize(device_t dv) 272{ 273 struct zaudio_softc *sc = device_private(dv); 274 275 wm8731_init(sc); 276 return 0; 277} 278 279static bool 280wm8731_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 290static bool 291wm8731_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 301static __inline uint8_t 302vol_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 315static void 316wm8731_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 335static __inline uint8_t 336vol_ssub(int vol, int stride) 337{ 338 339 vol -= stride; 340 if (vol < 0) 341 return 0; 342 return (uint8_t)vol; 343} 344 345static void 346wm8731_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 365static void 366wm8731_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 386static void 387wm8731_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 418static int 419wm8731_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 429static void 430wm8731_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 478update_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 491static void 492wm8731_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 512static void 513wm8731_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 534static void 535wm8731_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 561static void 562wm8731_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 578wm8731_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 593static int 594wm8731_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 607static int 608wm8731_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 621static int 622wm8731_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 638static int 639wm8731_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 713static int 714wm8731_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*/ 774static int 775wm8731_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; 796mute: 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 869static int 870wm8731_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 893static int 894wm8731_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