1 /* $NetBSD: mavb.c,v 1.7 2011/07/01 18:53:47 dyoung Exp $ */ 2 /* $OpenBSD: mavb.c,v 1.6 2005/04/15 13:05:14 mickey Exp $ */ 3 4 /* 5 * Copyright (c) 2005 Mark Kettenis 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 #include <sys/param.h> 21 #include <sys/systm.h> 22 #include <sys/device.h> 23 #include <sys/kernel.h> 24 #include <sys/malloc.h> 25 #include <sys/callout.h> 26 27 #include <sys/bus.h> 28 #include <machine/intr.h> 29 #include <machine/autoconf.h> 30 31 #include <sys/audioio.h> 32 #include <dev/auconv.h> 33 #include <dev/audio_if.h> 34 35 #include <arch/sgimips/mace/macevar.h> 36 #include <arch/sgimips/mace/macereg.h> 37 #include <arch/sgimips/mace/mavbreg.h> 38 39 #include <dev/ic/ad1843reg.h> 40 41 #undef MAVB_DEBUG 42 43 #ifdef MAVB_DEBUG 44 #define DPRINTF(l,x) do { if (mavb_debug & (l)) printf x; } while (0) 45 #define MAVB_DEBUG_INTR 0x0100 46 int mavb_debug = ~MAVB_DEBUG_INTR; 47 #else 48 #define DPRINTF(l,x) /* nothing */ 49 #endif 50 51 /* Repeat delays for volume buttons. */ 52 #define MAVB_VOLUME_BUTTON_REPEAT_DEL1 400 /* 400ms to start repeating */ 53 #define MAVB_VOLUME_BUTTON_REPEAT_DELN 100 /* 100ms between repeats */ 54 55 /* XXX We need access to some of the MACE ISA registers. */ 56 #define MAVB_ISA_NREGS 0x20 57 58 /* 59 * AD1843 Mixer. 60 */ 61 62 enum { 63 AD1843_RECORD_CLASS, 64 AD1843_ADC_SOURCE, /* ADC Source Select */ 65 AD1843_ADC_GAIN, /* ADC Input Gain */ 66 67 AD1843_INPUT_CLASS, 68 AD1843_DAC1_GAIN, /* DAC1 Analog/Digital Gain/Attenuation */ 69 AD1843_DAC1_MUTE, /* DAC1 Analog Mute */ 70 AD1843_DAC2_GAIN, /* DAC2 Mix Gain */ 71 AD1843_AUX1_GAIN, /* Auxilliary 1 Mix Gain */ 72 AD1843_AUX2_GAIN, /* Auxilliary 2 Mix Gain */ 73 AD1843_AUX3_GAIN, /* Auxilliary 3 Mix Gain */ 74 AD1843_MIC_GAIN, /* Microphone Mix Gain */ 75 AD1843_MONO_GAIN, /* Mono Mix Gain */ 76 AD1843_DAC2_MUTE, /* DAC2 Mix Mute */ 77 AD1843_AUX1_MUTE, /* Auxilliary 1 Mix Mute */ 78 AD1843_AUX2_MUTE, /* Auxilliary 2 Mix Mute */ 79 AD1843_AUX3_MUTE, /* Auxilliary 3 Mix Mute */ 80 AD1843_MIC_MUTE, /* Microphone Mix Mute */ 81 AD1843_MONO_MUTE, /* Mono Mix Mute */ 82 AD1843_SUM_MUTE, /* Sum Mute */ 83 84 AD1843_OUTPUT_CLASS, 85 AD1843_MNO_MUTE, /* Mono Output Mute */ 86 AD1843_HPO_MUTE /* Headphone Output Mute */ 87 }; 88 89 /* ADC Source Select. The order matches the hardware bits. */ 90 const char *ad1843_source[] = { 91 AudioNline, 92 AudioNmicrophone, 93 AudioNaux "1", 94 AudioNaux "2", 95 AudioNaux "3", 96 AudioNmono, 97 AudioNdac "1", 98 AudioNdac "2" 99 }; 100 101 /* Mix Control. The order matches the hardware register numbering. */ 102 const char *ad1843_input[] = { 103 AudioNdac "2", /* AD1843_DAC2__TO_MIXER */ 104 AudioNaux "1", 105 AudioNaux "2", 106 AudioNaux "3", 107 AudioNmicrophone, 108 AudioNmono /* AD1843_MISC_SETTINGS */ 109 }; 110 111 #define MAVB_NFORMATS 2 112 static const struct audio_format mavb_formats[MAVB_NFORMATS] = { 113 { NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_BE, 16, 16, 114 1, AUFMT_MONAURAL, 0, { 8000, 48000 } }, 115 { NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_BE, 16, 16, 116 2, AUFMT_STEREO, 0, { 8000, 48000 } }, 117 }; 118 119 struct mavb_softc { 120 struct device sc_dev; 121 bus_space_tag_t sc_st; 122 bus_space_handle_t sc_sh; 123 bus_dma_tag_t sc_dmat; 124 bus_dmamap_t sc_dmamap; 125 126 /* XXX We need access to some of the MACE ISA registers. */ 127 bus_space_handle_t sc_isash; 128 129 #define MAVB_ISA_RING_SIZE 0x1000 130 uint8_t *sc_ring; 131 132 uint8_t *sc_start, *sc_end; 133 int sc_blksize; 134 void (*sc_intr)(void *); 135 void *sc_intrarg; 136 137 void *sc_get; 138 int sc_count; 139 140 u_long sc_play_rate; 141 u_int sc_play_format; 142 143 struct callout sc_volume_button_ch; 144 145 struct audio_format sc_formats[MAVB_NFORMATS]; 146 struct audio_encoding_set *sc_encodings; 147 }; 148 149 struct mavb_codecvar { 150 stream_filter_t base; 151 }; 152 153 static stream_filter_t *mavb_factory 154 (int (*)(stream_fetcher_t *, audio_stream_t *, int)); 155 static void mavb_dtor(stream_filter_t *); 156 157 /* XXX I'm going to complain every time I have to copy this macro */ 158 #define DEFINE_FILTER(name) \ 159 static int \ 160 name##_fetch_to(stream_fetcher_t *, audio_stream_t *, int); \ 161 stream_filter_t *name(struct audio_softc *, \ 162 const audio_params_t *, const audio_params_t *); \ 163 stream_filter_t * \ 164 name(struct audio_softc *sc, const audio_params_t *from, \ 165 const audio_params_t *to) \ 166 { \ 167 return mavb_factory(name##_fetch_to); \ 168 } \ 169 static int \ 170 name##_fetch_to(stream_fetcher_t *self, audio_stream_t *dst, \ 171 int max_used) 172 173 DEFINE_FILTER(mavb_16to24) 174 { 175 stream_filter_t *this; 176 int m, err; 177 178 this = (stream_filter_t *)self; 179 max_used = (max_used + 1) & ~1; 180 if ((err = this->prev->fetch_to(this->prev, this->src, max_used))) 181 return err; 182 m = (dst->end - dst->start) & ~1; 183 m = min(m, max_used); 184 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 4, m) { 185 d[3] = 0; 186 d[2] = s[1]; 187 d[1] = s[0]; 188 d[0] = (s[0] & 0x80) ? 0xff : 0; 189 } FILTER_LOOP_EPILOGUE(this->src, dst); 190 191 return 0; 192 } 193 194 DEFINE_FILTER(mavb_mts) 195 { 196 stream_filter_t *this; 197 int m, err; 198 199 this = (stream_filter_t *)self; 200 max_used = (max_used + 1) & ~1; 201 if ((err = this->prev->fetch_to(this->prev, this->src, max_used))) 202 return err; 203 m = (dst->end - dst->start) & ~1; 204 m = min(m, max_used); 205 FILTER_LOOP_PROLOGUE(this->src, 4, dst, 8, m) { 206 d[3] = d[7] = s[3]; 207 d[2] = d[6] = s[2]; 208 d[1] = d[5] = s[1]; 209 d[0] = d[4] = s[0]; 210 } FILTER_LOOP_EPILOGUE(this->src, dst); 211 212 return 0; 213 } 214 215 static stream_filter_t * 216 mavb_factory(int (*fetch_to)(stream_fetcher_t *, audio_stream_t *, int)) 217 { 218 struct mavb_codecvar *this; 219 220 this = malloc(sizeof(*this), M_DEVBUF, M_WAITOK | M_ZERO); 221 this->base.base.fetch_to = fetch_to; 222 this->base.dtor = mavb_dtor; 223 this->base.set_fetcher = stream_filter_set_fetcher; 224 this->base.set_inputbuffer = stream_filter_set_inputbuffer; 225 226 return &this->base; 227 } 228 229 static void 230 mavb_dtor(stream_filter_t *this) 231 { 232 233 if (this != NULL) 234 free(this, M_DEVBUF); 235 } 236 237 typedef uint64_t ad1843_addr_t; 238 239 uint16_t ad1843_reg_read(struct mavb_softc *, ad1843_addr_t); 240 uint16_t ad1843_reg_write(struct mavb_softc *, ad1843_addr_t, uint16_t); 241 void ad1843_dump_regs(struct mavb_softc *); 242 243 int mavb_match(struct device *, struct cfdata *, void *); 244 void mavb_attach(struct device *, struct device *, void *); 245 246 CFATTACH_DECL(mavb, sizeof(struct mavb_softc), 247 mavb_match, mavb_attach, NULL, NULL); 248 249 int mavb_open(void *, int); 250 void mavb_close(void *); 251 int mavb_query_encoding(void *, struct audio_encoding *); 252 int mavb_set_params(void *, int, int, struct audio_params *, 253 struct audio_params *, stream_filter_list_t *, 254 stream_filter_list_t *); 255 int mavb_round_blocksize(void *hdl, int, int, const audio_params_t *); 256 int mavb_halt_output(void *); 257 int mavb_halt_input(void *); 258 int mavb_getdev(void *, struct audio_device *); 259 int mavb_set_port(void *, struct mixer_ctrl *); 260 int mavb_get_port(void *, struct mixer_ctrl *); 261 int mavb_query_devinfo(void *, struct mixer_devinfo *); 262 size_t mavb_round_buffersize(void *, int, size_t); 263 int mavb_get_props(void *); 264 int mavb_trigger_output(void *, void *, void *, int, void (*)(void *), 265 void *, const audio_params_t *); 266 int mavb_trigger_input(void *, void *, void *, int, void (*)(void *), 267 void *, const audio_params_t *); 268 269 struct audio_hw_if mavb_sa_hw_if = { 270 mavb_open, 271 mavb_close, 272 0, 273 mavb_query_encoding, 274 mavb_set_params, 275 mavb_round_blocksize, 276 0, 277 0, 278 0, 279 0, 280 0, 281 mavb_halt_output, 282 mavb_halt_input, 283 0, 284 mavb_getdev, 285 0, 286 mavb_set_port, 287 mavb_get_port, 288 mavb_query_devinfo, 289 0, 290 0, 291 mavb_round_buffersize, 292 0, 293 mavb_get_props, 294 mavb_trigger_output, 295 mavb_trigger_input, 296 NULL, 297 }; 298 299 struct audio_device mavb_device = { 300 "A3", 301 "", 302 "mavb" 303 }; 304 305 int 306 mavb_open(void *hdl, int flags) 307 { 308 309 return 0; 310 } 311 312 void 313 mavb_close(void *hdl) 314 { 315 } 316 317 int 318 mavb_query_encoding(void *hdl, struct audio_encoding *ae) 319 { 320 struct mavb_softc *sc = (struct mavb_softc *)hdl; 321 322 return auconv_query_encoding(sc->sc_encodings, ae); 323 } 324 325 static int 326 mavb_set_play_rate(struct mavb_softc *sc, u_long sample_rate) 327 { 328 329 if (sample_rate < 4000 || sample_rate > 48000) 330 return EINVAL; 331 332 if (sc->sc_play_rate != sample_rate) { 333 ad1843_reg_write(sc, AD1843_CLOCK2_SAMPLE_RATE, sample_rate); 334 sc->sc_play_rate = sample_rate; 335 } 336 return 0; 337 } 338 339 static int 340 mavb_set_play_format(struct mavb_softc *sc, u_int encoding) 341 { 342 uint16_t value; 343 u_int format; 344 345 switch(encoding) { 346 case AUDIO_ENCODING_ULINEAR_BE: 347 format = AD1843_PCM8; 348 break; 349 case AUDIO_ENCODING_SLINEAR_BE: 350 format = AD1843_PCM16; 351 break; 352 case AUDIO_ENCODING_ULAW: 353 format = AD1843_ULAW; 354 break; 355 case AUDIO_ENCODING_ALAW: 356 format = AD1843_ALAW; 357 break; 358 default: 359 return EINVAL; 360 } 361 362 if (sc->sc_play_format != format) { 363 value = ad1843_reg_read(sc, AD1843_SERIAL_INTERFACE); 364 value &= ~AD1843_DA1F_MASK; 365 value |= (format << AD1843_DA1F_SHIFT); 366 ad1843_reg_write(sc, AD1843_SERIAL_INTERFACE, value); 367 sc->sc_play_format = format; 368 } 369 return 0; 370 } 371 372 int 373 mavb_set_params(void *hdl, int setmode, int usemode, 374 struct audio_params *play, struct audio_params *rec, 375 stream_filter_list_t *pfil, stream_filter_list_t *rfil) 376 { 377 struct mavb_softc *sc = (struct mavb_softc *)hdl; 378 struct audio_params *p; 379 stream_filter_list_t *fil; 380 int error; 381 382 DPRINTF(1, ("%s: mavb_set_params: sample=%u precision=%d " 383 "channels=%d\n", sc->sc_dev.dv_xname, play->sample_rate, 384 play->precision, play->channels)); 385 386 if (setmode & AUMODE_PLAY) { 387 if (play->sample_rate < 4000 || play->sample_rate > 48000) 388 return EINVAL; 389 390 p = play; 391 fil = pfil; 392 if (auconv_set_converter(sc->sc_formats, MAVB_NFORMATS, 393 AUMODE_PLAY, p, TRUE, fil) < 0) 394 return EINVAL; 395 396 fil->append(fil, mavb_16to24, p); 397 if (p->channels == 1) 398 fil->append(fil, mavb_mts, p); 399 if (fil->req_size > 0) 400 p = &fil->filters[0].param; 401 402 error = mavb_set_play_rate(sc, p->sample_rate); 403 if (error) 404 return error; 405 406 error = mavb_set_play_format(sc, p->encoding); 407 if (error) 408 return error; 409 } 410 411 #if 0 412 if (setmode & AUMODE_RECORD) { 413 if (rec->sample_rate < 4000 || rec->sample_rate > 48000) 414 return EINVAL; 415 } 416 #endif 417 418 return 0; 419 } 420 421 int 422 mavb_round_blocksize(void *hdl, int bs, int mode, const audio_params_t *p) 423 { 424 425 /* Block size should be a multiple of 32. */ 426 return (bs + 0x1f) & ~0x1f; 427 } 428 429 int 430 mavb_halt_output(void *hdl) 431 { 432 struct mavb_softc *sc = (struct mavb_softc *)hdl; 433 434 DPRINTF(1, ("%s: mavb_halt_output called\n", sc->sc_dev.dv_xname)); 435 436 bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0); 437 return 0; 438 } 439 440 int 441 mavb_halt_input(void *hdl) 442 { 443 444 return 0; 445 } 446 447 int 448 mavb_getdev(void *hdl, struct audio_device *ret) 449 { 450 451 *ret = mavb_device; 452 return 0; 453 } 454 455 int 456 mavb_set_port(void *hdl, struct mixer_ctrl *mc) 457 { 458 struct mavb_softc *sc = (struct mavb_softc *)hdl; 459 u_char left, right; 460 ad1843_addr_t reg; 461 uint16_t value; 462 463 DPRINTF(1, ("%s: mavb_set_port: dev=%d\n", sc->sc_dev.dv_xname, 464 mc->dev)); 465 466 switch (mc->dev) { 467 case AD1843_ADC_SOURCE: 468 value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN); 469 value &= ~(AD1843_LSS_MASK | AD1843_RSS_MASK); 470 value |= ((mc->un.ord << AD1843_LSS_SHIFT) & AD1843_LSS_MASK); 471 value |= ((mc->un.ord << AD1843_RSS_SHIFT) & AD1843_RSS_MASK); 472 ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value); 473 break; 474 case AD1843_ADC_GAIN: 475 left = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 476 right = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 477 value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN); 478 value &= ~(AD1843_LIG_MASK | AD1843_RIG_MASK); 479 value |= ((left >> 4) << AD1843_LIG_SHIFT); 480 value |= ((right >> 4) << AD1843_RIG_SHIFT); 481 ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value); 482 break; 483 484 case AD1843_DAC1_GAIN: 485 left = AUDIO_MAX_GAIN - 486 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 487 right = AUDIO_MAX_GAIN - 488 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 489 value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); 490 value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK); 491 value |= ((left >> 2) << AD1843_LDA1G_SHIFT); 492 value |= ((right >> 2) << AD1843_RDA1G_SHIFT); 493 ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value); 494 break; 495 case AD1843_DAC1_MUTE: 496 value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); 497 if (mc->un.ord == 0) 498 value &= ~(AD1843_LDA1GM | AD1843_RDA1GM); 499 else 500 value |= (AD1843_LDA1GM | AD1843_RDA1GM); 501 ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value); 502 break; 503 504 case AD1843_DAC2_GAIN: 505 case AD1843_AUX1_GAIN: 506 case AD1843_AUX2_GAIN: 507 case AD1843_AUX3_GAIN: 508 case AD1843_MIC_GAIN: 509 left = AUDIO_MAX_GAIN - 510 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 511 right = AUDIO_MAX_GAIN - 512 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 513 reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN; 514 value = ad1843_reg_read(sc, reg); 515 value &= ~(AD1843_LD2M_MASK | AD1843_RD2M_MASK); 516 value |= ((left >> 3) << AD1843_LD2M_SHIFT); 517 value |= ((right >> 3) << AD1843_RD2M_SHIFT); 518 ad1843_reg_write(sc, reg, value); 519 break; 520 case AD1843_MONO_GAIN: 521 left = AUDIO_MAX_GAIN - 522 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 523 value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); 524 value &= ~AD1843_MNM_MASK; 525 value |= ((left >> 3) << AD1843_MNM_SHIFT); 526 ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value); 527 break; 528 case AD1843_DAC2_MUTE: 529 case AD1843_AUX1_MUTE: 530 case AD1843_AUX2_MUTE: 531 case AD1843_AUX3_MUTE: 532 case AD1843_MIC_MUTE: 533 case AD1843_MONO_MUTE: /* matches left channel */ 534 reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE; 535 value = ad1843_reg_read(sc, reg); 536 if (mc->un.ord == 0) 537 value &= ~(AD1843_LD2MM | AD1843_RD2MM); 538 else 539 value |= (AD1843_LD2MM | AD1843_RD2MM); 540 ad1843_reg_write(sc, reg, value); 541 break; 542 543 case AD1843_SUM_MUTE: 544 value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); 545 if (mc->un.ord == 0) 546 value &= ~AD1843_SUMM; 547 else 548 value |= AD1843_SUMM; 549 ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value); 550 break; 551 552 case AD1843_MNO_MUTE: 553 value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); 554 if (mc->un.ord == 0) 555 value &= ~AD1843_MNOM; 556 else 557 value |= AD1843_MNOM; 558 ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value); 559 break; 560 561 case AD1843_HPO_MUTE: 562 value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); 563 if (mc->un.ord == 0) 564 value &= ~AD1843_HPOM; 565 else 566 value |= AD1843_HPOM; 567 ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value); 568 value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); 569 break; 570 571 default: 572 return EINVAL; 573 } 574 575 return 0; 576 } 577 578 int 579 mavb_get_port(void *hdl, struct mixer_ctrl *mc) 580 { 581 struct mavb_softc *sc = (struct mavb_softc *)hdl; 582 u_char left, right; 583 ad1843_addr_t reg; 584 uint16_t value; 585 586 DPRINTF(1, ("%s: mavb_get_port: dev=%d\n", sc->sc_dev.dv_xname, 587 mc->dev)); 588 589 switch (mc->dev) { 590 case AD1843_ADC_SOURCE: 591 value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN); 592 mc->un.ord = (value & AD1843_LSS_MASK) >> AD1843_LSS_SHIFT; 593 break; 594 case AD1843_ADC_GAIN: 595 value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN); 596 left = (value & AD1843_LIG_MASK) >> AD1843_LIG_SHIFT; 597 right = (value & AD1843_RIG_MASK) >> AD1843_RIG_SHIFT; 598 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 599 (left << 4) | left; 600 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 601 (right << 2) | right; 602 break; 603 604 case AD1843_DAC1_GAIN: 605 value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); 606 left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT; 607 right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT; 608 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 609 AUDIO_MAX_GAIN - (left << 2); 610 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 611 AUDIO_MAX_GAIN - (right << 2); 612 break; 613 case AD1843_DAC1_MUTE: 614 value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); 615 mc->un.ord = (value & AD1843_LDA1GM) ? 1 : 0; 616 break; 617 618 case AD1843_DAC2_GAIN: 619 case AD1843_AUX1_GAIN: 620 case AD1843_AUX2_GAIN: 621 case AD1843_AUX3_GAIN: 622 case AD1843_MIC_GAIN: 623 reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN; 624 value = ad1843_reg_read(sc, reg); 625 left = (value & AD1843_LD2M_MASK) >> AD1843_LD2M_SHIFT; 626 right = (value & AD1843_RD2M_MASK) >> AD1843_RD2M_SHIFT; 627 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 628 AUDIO_MAX_GAIN - (left << 3); 629 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 630 AUDIO_MAX_GAIN - (right << 3); 631 break; 632 case AD1843_MONO_GAIN: 633 if (mc->un.value.num_channels != 1) 634 return EINVAL; 635 636 value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); 637 left = (value & AD1843_MNM_MASK) >> AD1843_MNM_SHIFT; 638 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 639 AUDIO_MAX_GAIN - (left << 3); 640 break; 641 case AD1843_DAC2_MUTE: 642 case AD1843_AUX1_MUTE: 643 case AD1843_AUX2_MUTE: 644 case AD1843_AUX3_MUTE: 645 case AD1843_MIC_MUTE: 646 case AD1843_MONO_MUTE: /* matches left channel */ 647 reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE; 648 value = ad1843_reg_read(sc, reg); 649 mc->un.ord = (value & AD1843_LD2MM) ? 1 : 0; 650 break; 651 652 case AD1843_SUM_MUTE: 653 value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); 654 mc->un.ord = (value & AD1843_SUMM) ? 1 : 0; 655 break; 656 657 case AD1843_MNO_MUTE: 658 value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); 659 mc->un.ord = (value & AD1843_MNOM) ? 1 : 0; 660 break; 661 662 case AD1843_HPO_MUTE: 663 value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); 664 mc->un.ord = (value & AD1843_HPOM) ? 1 : 0; 665 break; 666 667 default: 668 return EINVAL; 669 } 670 671 return 0; 672 } 673 674 int 675 mavb_query_devinfo(void *hdl, struct mixer_devinfo *di) 676 { 677 int i; 678 679 di->prev = di->next = AUDIO_MIXER_LAST; 680 681 switch (di->index) { 682 case AD1843_RECORD_CLASS: 683 di->type = AUDIO_MIXER_CLASS; 684 di->mixer_class = AD1843_RECORD_CLASS; 685 strlcpy(di->label.name, AudioCrecord, sizeof di->label.name); 686 break; 687 688 case AD1843_ADC_SOURCE: 689 di->type = AUDIO_MIXER_ENUM; 690 di->mixer_class = AD1843_RECORD_CLASS; 691 di->next = AD1843_ADC_GAIN; 692 strlcpy(di->label.name, AudioNsource, sizeof di->label.name); 693 di->un.e.num_mem = 694 sizeof ad1843_source / sizeof ad1843_source[1]; 695 for (i = 0; i < di->un.e.num_mem; i++) { 696 strlcpy(di->un.e.member[i].label.name, 697 ad1843_source[i], 698 sizeof di->un.e.member[0].label.name); 699 di->un.e.member[i].ord = i; 700 } 701 break; 702 case AD1843_ADC_GAIN: 703 di->type = AUDIO_MIXER_VALUE; 704 di->mixer_class = AD1843_RECORD_CLASS; 705 di->prev = AD1843_ADC_SOURCE; 706 strlcpy(di->label.name, AudioNvolume, sizeof di->label.name); 707 di->un.v.num_channels = 2; 708 strlcpy(di->un.v.units.name, AudioNvolume, 709 sizeof di->un.v.units.name); 710 break; 711 712 case AD1843_INPUT_CLASS: 713 di->type = AUDIO_MIXER_CLASS; 714 di->mixer_class = AD1843_INPUT_CLASS; 715 strlcpy(di->label.name, AudioCinputs, sizeof di->label.name); 716 break; 717 718 case AD1843_DAC1_GAIN: 719 di->type = AUDIO_MIXER_VALUE; 720 di->mixer_class = AD1843_INPUT_CLASS; 721 di->next = AD1843_DAC1_MUTE; 722 strlcpy(di->label.name, AudioNdac "1", sizeof di->label.name); 723 di->un.v.num_channels = 2; 724 strlcpy(di->un.v.units.name, AudioNvolume, 725 sizeof di->un.v.units.name); 726 break; 727 case AD1843_DAC1_MUTE: 728 di->type = AUDIO_MIXER_ENUM; 729 di->mixer_class = AD1843_INPUT_CLASS; 730 di->prev = AD1843_DAC1_GAIN; 731 strlcpy(di->label.name, AudioNmute, sizeof di->label.name); 732 di->un.e.num_mem = 2; 733 strlcpy(di->un.e.member[0].label.name, AudioNoff, 734 sizeof di->un.e.member[0].label.name); 735 di->un.e.member[0].ord = 0; 736 strlcpy(di->un.e.member[1].label.name, AudioNon, 737 sizeof di->un.e.member[1].label.name); 738 di->un.e.member[1].ord = 1; 739 break; 740 741 case AD1843_DAC2_GAIN: 742 case AD1843_AUX1_GAIN: 743 case AD1843_AUX2_GAIN: 744 case AD1843_AUX3_GAIN: 745 case AD1843_MIC_GAIN: 746 case AD1843_MONO_GAIN: 747 di->type = AUDIO_MIXER_VALUE; 748 di->mixer_class = AD1843_INPUT_CLASS; 749 di->next = di->index + AD1843_DAC2_MUTE - AD1843_DAC2_GAIN; 750 strlcpy(di->label.name, 751 ad1843_input[di->index - AD1843_DAC2_GAIN], 752 sizeof di->label.name); 753 if (di->index == AD1843_MONO_GAIN) 754 di->un.v.num_channels = 1; 755 else 756 di->un.v.num_channels = 2; 757 strlcpy(di->un.v.units.name, AudioNvolume, 758 sizeof di->un.v.units.name); 759 break; 760 case AD1843_DAC2_MUTE: 761 case AD1843_AUX1_MUTE: 762 case AD1843_AUX2_MUTE: 763 case AD1843_AUX3_MUTE: 764 case AD1843_MIC_MUTE: 765 case AD1843_MONO_MUTE: 766 di->type = AUDIO_MIXER_ENUM; 767 di->mixer_class = AD1843_INPUT_CLASS; 768 di->prev = di->index + AD1843_DAC2_GAIN - AD1843_DAC2_MUTE; 769 strlcpy(di->label.name, AudioNmute, sizeof di->label.name); 770 di->un.e.num_mem = 2; 771 strlcpy(di->un.e.member[0].label.name, AudioNoff, 772 sizeof di->un.e.member[0].label.name); 773 di->un.e.member[0].ord = 0; 774 strlcpy(di->un.e.member[1].label.name, AudioNon, 775 sizeof di->un.e.member[1].label.name); 776 di->un.e.member[1].ord = 1; 777 break; 778 779 case AD1843_SUM_MUTE: 780 di->type = AUDIO_MIXER_ENUM; 781 di->mixer_class = AD1843_INPUT_CLASS; 782 strlcpy(di->label.name, "sum." AudioNmute, 783 sizeof di->label.name); 784 di->un.e.num_mem = 2; 785 strlcpy(di->un.e.member[0].label.name, AudioNoff, 786 sizeof di->un.e.member[0].label.name); 787 di->un.e.member[0].ord = 0; 788 strlcpy(di->un.e.member[1].label.name, AudioNon, 789 sizeof di->un.e.member[1].label.name); 790 di->un.e.member[1].ord = 1; 791 break; 792 793 case AD1843_OUTPUT_CLASS: 794 di->type = AUDIO_MIXER_CLASS; 795 di->mixer_class = AD1843_OUTPUT_CLASS; 796 strlcpy(di->label.name, AudioCoutputs, sizeof di->label.name); 797 break; 798 799 case AD1843_MNO_MUTE: 800 di->type = AUDIO_MIXER_ENUM; 801 di->mixer_class = AD1843_OUTPUT_CLASS; 802 strlcpy(di->label.name, AudioNmono "." AudioNmute, 803 sizeof di->label.name); 804 di->un.e.num_mem = 2; 805 strlcpy(di->un.e.member[0].label.name, AudioNoff, 806 sizeof di->un.e.member[0].label.name); 807 di->un.e.member[0].ord = 0; 808 strlcpy(di->un.e.member[1].label.name, AudioNon, 809 sizeof di->un.e.member[1].label.name); 810 di->un.e.member[1].ord = 1; 811 break; 812 813 case AD1843_HPO_MUTE: 814 di->type = AUDIO_MIXER_ENUM; 815 di->mixer_class = AD1843_OUTPUT_CLASS; 816 strlcpy(di->label.name, AudioNheadphone "." AudioNmute, 817 sizeof di->label.name); 818 di->un.e.num_mem = 2; 819 strlcpy(di->un.e.member[0].label.name, AudioNoff, 820 sizeof di->un.e.member[0].label.name); 821 di->un.e.member[0].ord = 0; 822 strlcpy(di->un.e.member[1].label.name, AudioNon, 823 sizeof di->un.e.member[1].label.name); 824 di->un.e.member[1].ord = 1; 825 break; 826 827 default: 828 return EINVAL; 829 } 830 831 return 0; 832 } 833 834 size_t 835 mavb_round_buffersize(void *hdl, int dir, size_t bufsize) 836 { 837 838 return bufsize; 839 } 840 841 int 842 mavb_get_props(void *hdl) 843 { 844 845 return AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT; 846 } 847 848 static void 849 mavb_dma_output(struct mavb_softc *sc) 850 { 851 bus_space_tag_t st = sc->sc_st; 852 bus_space_handle_t sh = sc->sc_sh; 853 uint64_t write_ptr; 854 uint64_t depth; 855 uint8_t *src, *dst; 856 int count; 857 858 write_ptr = bus_space_read_8(st, sh, MAVB_CHANNEL2_WRITE_PTR); 859 depth = bus_space_read_8(st, sh, MAVB_CHANNEL2_DEPTH); 860 861 dst = sc->sc_ring + write_ptr; 862 src = sc->sc_get; 863 864 count = (MAVB_ISA_RING_SIZE - depth - 32); 865 while (--count >= 0) { 866 *dst++ = *src++; 867 if (dst >= sc->sc_ring + MAVB_ISA_RING_SIZE) 868 dst = sc->sc_ring; 869 if (src >= sc->sc_end) 870 src = sc->sc_start; 871 if (++sc->sc_count >= sc->sc_blksize) { 872 if (sc->sc_intr) 873 sc->sc_intr(sc->sc_intrarg); 874 sc->sc_count = 0; 875 } 876 } 877 878 write_ptr = dst - sc->sc_ring; 879 bus_space_write_8(st, sh, MAVB_CHANNEL2_WRITE_PTR, write_ptr); 880 sc->sc_get = src; 881 } 882 883 int 884 mavb_trigger_output(void *hdl, void *start, void *end, int blksize, 885 void (*intr)(void *), void *intrarg, 886 const audio_params_t *param) 887 { 888 struct mavb_softc *sc = (struct mavb_softc *)hdl; 889 890 DPRINTF(1, ("%s: mavb_trigger_output: start=%p end=%p " 891 "blksize=%d intr=%p(%p)\n", sc->sc_dev.dv_xname, 892 start, end, blksize, intr, intrarg)); 893 894 sc->sc_blksize = blksize; 895 sc->sc_intr = intr; 896 sc->sc_intrarg = intrarg; 897 898 sc->sc_start = sc->sc_get = start; 899 sc->sc_end = end; 900 901 sc->sc_count = 0; 902 903 bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 904 MAVB_CHANNEL_RESET); 905 delay(1000); 906 bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0); 907 908 mavb_dma_output(sc); 909 910 bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 911 MAVB_CHANNEL_DMA_ENABLE | MAVB_CHANNEL_INT_50); 912 return 0; 913 } 914 915 int 916 mavb_trigger_input(void *hdl, void *start, void *end, int blksize, 917 void (*intr)(void *), void *intrarg, 918 const audio_params_t *param) 919 { 920 921 return 0; 922 } 923 924 static void 925 mavb_button_repeat(void *hdl) 926 { 927 struct mavb_softc *sc = (struct mavb_softc *)hdl; 928 uint64_t intmask, control; 929 uint16_t value, left, right; 930 931 DPRINTF(1, ("%s: mavb_repeat called\n", sc->sc_dev.dv_xname)); 932 933 #define MAVB_CONTROL_VOLUME_BUTTONS \ 934 (MAVB_CONTROL_VOLUME_BUTTON_UP | MAVB_CONTROL_VOLUME_BUTTON_DOWN) 935 936 control = bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL); 937 if (control & MAVB_CONTROL_VOLUME_BUTTONS) { 938 value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); 939 left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT; 940 right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT; 941 if (control & MAVB_CONTROL_VOLUME_BUTTON_UP) { 942 control &= ~MAVB_CONTROL_VOLUME_BUTTON_UP; 943 if (left > 0) 944 left--; /* attenuation! */ 945 if (right > 0) 946 right--; 947 } 948 if (control & MAVB_CONTROL_VOLUME_BUTTON_DOWN) { 949 control &= ~MAVB_CONTROL_VOLUME_BUTTON_DOWN; 950 if (left < 63) 951 left++; 952 if (right < 63) 953 right++; 954 } 955 bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, control); 956 957 value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK); 958 value |= (left << AD1843_LDA1G_SHIFT); 959 value |= (right << AD1843_RDA1G_SHIFT); 960 ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value); 961 962 callout_reset(&sc->sc_volume_button_ch, 963 (hz * MAVB_VOLUME_BUTTON_REPEAT_DELN) / 1000, 964 mavb_button_repeat, sc); 965 } else { 966 /* Enable volume button interrupts again. */ 967 intmask = bus_space_read_8(sc->sc_st, sc->sc_isash, 968 MACE_ISA_INT_MASK); 969 bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK, 970 intmask | MACE_ISA_INT_AUDIO_SC); 971 } 972 } 973 974 static int 975 mavb_intr(void *arg) 976 { 977 struct mavb_softc *sc = arg; 978 uint64_t stat, intmask; 979 980 stat = bus_space_read_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_STATUS); 981 DPRINTF(MAVB_DEBUG_INTR, ("%s: mavb_intr: stat = 0x%llx\n", 982 sc->sc_dev.dv_xname, stat)); 983 984 if (stat & MACE_ISA_INT_AUDIO_SC) { 985 /* Disable volume button interrupts. */ 986 intmask = bus_space_read_8(sc->sc_st, sc->sc_isash, 987 MACE_ISA_INT_MASK); 988 bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK, 989 intmask & ~MACE_ISA_INT_AUDIO_SC); 990 991 callout_reset(&sc->sc_volume_button_ch, 992 (hz * MAVB_VOLUME_BUTTON_REPEAT_DEL1) / 1000, 993 mavb_button_repeat, sc); 994 } 995 996 if (stat & MACE_ISA_INT_AUDIO_DMA2) 997 mavb_dma_output(sc); 998 999 return 1; 1000 } 1001 1002 int 1003 mavb_match(struct device *parent, struct cfdata *match, void *aux) 1004 { 1005 1006 return 1; 1007 } 1008 1009 void 1010 mavb_attach(struct device *parent, struct device *self, void *aux) 1011 { 1012 struct mavb_softc *sc = (void *)self; 1013 struct mace_attach_args *maa = aux; 1014 bus_dma_segment_t seg; 1015 uint64_t control; 1016 uint16_t value; 1017 int rseg, err; 1018 1019 sc->sc_st = maa->maa_st; 1020 if (bus_space_subregion(sc->sc_st, maa->maa_sh, maa->maa_offset, 1021 0, &sc->sc_sh) != 0) { 1022 printf(": can't map i/o space\n"); 1023 return; 1024 } 1025 1026 /* XXX We need access to some of the MACE ISA registers. */ 1027 if (bus_space_subregion(sc->sc_st, maa->maa_sh, 0, 0, 1028 &sc->sc_isash) != 0) { 1029 printf(": can't map isa i/o space\n"); 1030 return; 1031 } 1032 1033 /* Set up DMA structures. */ 1034 sc->sc_dmat = maa->maa_dmat; 1035 if (bus_dmamap_create(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE, 1, 1036 4 * MAVB_ISA_RING_SIZE, 0, 0, &sc->sc_dmamap)) { 1037 printf(": can't create MACE ISA DMA map\n"); 1038 return; 1039 } 1040 1041 if (bus_dmamem_alloc(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE, 1042 MACE_ISA_RING_ALIGN, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { 1043 printf(": can't allocate ring buffer\n"); 1044 return; 1045 } 1046 1047 if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, 4 * MAVB_ISA_RING_SIZE, 1048 (void *)&sc->sc_ring, BUS_DMA_COHERENT)) { 1049 printf(": can't map ring buffer\n"); 1050 return; 1051 } 1052 1053 if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_ring, 1054 4 * MAVB_ISA_RING_SIZE, NULL, BUS_DMA_NOWAIT)) { 1055 printf(": can't load MACE ISA DMA map\n"); 1056 return; 1057 } 1058 1059 sc->sc_ring += MAVB_ISA_RING_SIZE; /* XXX */ 1060 1061 bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_RINGBASE, 1062 sc->sc_dmamap->dm_segs[0].ds_addr); 1063 1064 /* Establish interrupt. */ 1065 cpu_intr_establish(maa->maa_intr, maa->maa_intrmask, 1066 mavb_intr, sc); 1067 1068 control = bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL); 1069 if (!(control & MAVB_CONTROL_CODEC_PRESENT)) { 1070 printf(": no codec present\n"); 1071 return; 1072 } 1073 1074 /* 2. Assert the RESET signal. */ 1075 bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, 1076 MAVB_CONTROL_RESET); 1077 delay(1); /* at least 100 ns */ 1078 1079 /* 3. Deassert the RESET signal and enter a wait period to 1080 allow the AD1843 internal clocks and the external 1081 crystal oscillator to stabilize. */ 1082 bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, 0); 1083 delay(800); /* typically 400 us to 800 us */ 1084 if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_INIT) { 1085 printf(": codec not ready\n"); 1086 return; 1087 } 1088 1089 /* 4. Put the conversion sources into standby. */ 1090 value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS); 1091 ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS, 1092 value & ~AD1843_PDNI); 1093 delay (500000); /* approximately 474 ms */ 1094 if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_PDNO) { 1095 printf(": can't power up conversion resources\n"); 1096 return; 1097 } 1098 1099 /* 5. Power up the clock generators and enable clock output pins. */ 1100 value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS); 1101 ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS, value | AD1843_C2EN); 1102 1103 /* 6. Configure conversion resources while they are in standby. */ 1104 value = ad1843_reg_read(sc, AD1843_CHANNEL_SAMPLE_RATE); 1105 ad1843_reg_write(sc, AD1843_CHANNEL_SAMPLE_RATE, 1106 value | (2 << AD1843_DA1C_SHIFT)); 1107 1108 /* 7. Enable conversion resources. */ 1109 value = ad1843_reg_read(sc, AD1843_CHANNEL_POWER_DOWN); 1110 ad1843_reg_write(sc, AD1843_CHANNEL_POWER_DOWN, 1111 value | (AD1843_DA1EN | AD1843_AAMEN)); 1112 1113 /* 8. Configure conversion resources while they are enabled. */ 1114 value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); 1115 ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, 1116 value & ~(AD1843_LDA1GM | AD1843_RDA1GM)); 1117 value = ad1843_reg_read(sc, AD1843_DAC1_DIGITAL_GAIN); 1118 ad1843_reg_write(sc, AD1843_DAC1_DIGITAL_GAIN, 1119 value & ~(AD1843_LDA1AM | AD1843_RDA1AM)); 1120 value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); 1121 ad1843_reg_write(sc, AD1843_MISC_SETTINGS, 1122 value & ~(AD1843_HPOM | AD1843_MNOM)); 1123 1124 value = ad1843_reg_read(sc, AD1843_CODEC_STATUS); 1125 printf(": AD1843 rev %d\n", (u_int)value & AD1843_REVISION_MASK); 1126 1127 sc->sc_play_rate = 48000; 1128 sc->sc_play_format = AD1843_PCM8; 1129 1130 memcpy(sc->sc_formats, mavb_formats, sizeof(mavb_formats)); 1131 err = auconv_create_encodings(sc->sc_formats, MAVB_NFORMATS, 1132 &sc->sc_encodings); 1133 if (err) { 1134 printf("%s: couldn't create encodings: %d\n", 1135 device_xname(self), err); 1136 return; 1137 } 1138 1139 callout_init(&sc->sc_volume_button_ch, 0); 1140 1141 audio_attach_mi(&mavb_sa_hw_if, sc, &sc->sc_dev); 1142 1143 return; 1144 } 1145 1146 uint16_t 1147 ad1843_reg_read(struct mavb_softc *sc, ad1843_addr_t addr) 1148 { 1149 bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL, 1150 (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT | 1151 MAVB_CODEC_READ); 1152 delay(200); 1153 return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS); 1154 } 1155 1156 uint16_t 1157 ad1843_reg_write(struct mavb_softc *sc, ad1843_addr_t addr, uint16_t value) 1158 { 1159 bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL, 1160 (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT | 1161 (value & MAVB_CODEC_WORD_MASK) << MAVB_CODEC_WORD_SHIFT); 1162 delay(200); 1163 return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS); 1164 } 1165 1166 void 1167 ad1843_dump_regs(struct mavb_softc *sc) 1168 { 1169 uint16_t addr; 1170 1171 for (addr = 0; addr < AD1843_NREGS; addr++) 1172 printf("%d: 0x%04x\n", addr, ad1843_reg_read(sc, addr)); 1173 } 1174