1 1.50 thorpej /* $NetBSD: ym.c,v 1.50 2021/08/07 16:19:12 thorpej Exp $ */ 2 1.1 augustss 3 1.10 itohy /*- 4 1.42 jmcneill * Copyright (c) 1999-2002, 2008 The NetBSD Foundation, Inc. 5 1.10 itohy * All rights reserved. 6 1.10 itohy * 7 1.10 itohy * This code is derived from software contributed to The NetBSD Foundation 8 1.10 itohy * by ITOH Yasufumi. 9 1.10 itohy * 10 1.10 itohy * Redistribution and use in source and binary forms, with or without 11 1.10 itohy * modification, are permitted provided that the following conditions 12 1.10 itohy * are met: 13 1.10 itohy * 1. Redistributions of source code must retain the above copyright 14 1.10 itohy * notice, this list of conditions and the following disclaimer. 15 1.10 itohy * 2. Redistributions in binary form must reproduce the above copyright 16 1.10 itohy * notice, this list of conditions and the following disclaimer in the 17 1.10 itohy * documentation and/or other materials provided with the distribution. 18 1.10 itohy * 19 1.10 itohy * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.10 itohy * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.10 itohy * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.10 itohy * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.10 itohy * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.10 itohy * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.10 itohy * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.10 itohy * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.10 itohy * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.10 itohy * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.10 itohy * POSSIBILITY OF SUCH DAMAGE. 30 1.10 itohy */ 31 1.1 augustss 32 1.1 augustss /* 33 1.1 augustss * Copyright (c) 1998 Constantine Sapuntzakis. All rights reserved. 34 1.10 itohy * 35 1.1 augustss * Redistribution and use in source and binary forms, with or without 36 1.1 augustss * modification, are permitted provided that the following conditions 37 1.1 augustss * are met: 38 1.1 augustss * 1. Redistributions of source code must retain the above copyright 39 1.1 augustss * notice, this list of conditions and the following disclaimer. 40 1.1 augustss * 2. Redistributions in binary form must reproduce the above copyright 41 1.1 augustss * notice, this list of conditions and the following disclaimer in the 42 1.1 augustss * documentation and/or other materials provided with the distribution. 43 1.1 augustss * 3. The name of the author may not be used to endorse or promote products 44 1.1 augustss * derived from this software without specific prior written permission. 45 1.1 augustss * 46 1.1 augustss * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 47 1.1 augustss * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 1.1 augustss * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 1.1 augustss * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 50 1.1 augustss * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 51 1.1 augustss * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 1.1 augustss * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 1.1 augustss * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 1.1 augustss * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 55 1.1 augustss * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 1.1 augustss */ 57 1.1 augustss 58 1.1 augustss /* 59 1.1 augustss * Original code from OpenBSD. 60 1.1 augustss */ 61 1.19 lukem 62 1.19 lukem #include <sys/cdefs.h> 63 1.50 thorpej __KERNEL_RCSID(0, "$NetBSD: ym.c,v 1.50 2021/08/07 16:19:12 thorpej Exp $"); 64 1.1 augustss 65 1.10 itohy #include "mpu_ym.h" 66 1.10 itohy #include "opt_ym.h" 67 1.1 augustss 68 1.1 augustss #include <sys/param.h> 69 1.1 augustss #include <sys/systm.h> 70 1.1 augustss #include <sys/errno.h> 71 1.1 augustss #include <sys/device.h> 72 1.10 itohy #include <sys/fcntl.h> 73 1.10 itohy #include <sys/kernel.h> 74 1.10 itohy #include <sys/proc.h> 75 1.1 augustss 76 1.32 ad #include <sys/cpu.h> 77 1.32 ad #include <sys/intr.h> 78 1.32 ad #include <sys/bus.h> 79 1.1 augustss 80 1.1 augustss #include <sys/audioio.h> 81 1.46 isaki #include <dev/audio/audio_if.h> 82 1.1 augustss 83 1.1 augustss #include <dev/isa/isavar.h> 84 1.1 augustss #include <dev/isa/isadmavar.h> 85 1.1 augustss 86 1.1 augustss #include <dev/ic/ad1848reg.h> 87 1.1 augustss #include <dev/isa/ad1848var.h> 88 1.10 itohy #include <dev/ic/opl3sa3reg.h> 89 1.10 itohy #include <dev/isa/wssreg.h> 90 1.10 itohy #if NMPU_YM > 0 91 1.10 itohy #include <dev/ic/mpuvar.h> 92 1.10 itohy #endif 93 1.1 augustss #include <dev/isa/ymvar.h> 94 1.10 itohy #include <dev/isa/sbreg.h> 95 1.1 augustss 96 1.10 itohy /* Power management mode. */ 97 1.10 itohy #ifndef YM_POWER_MODE 98 1.10 itohy #define YM_POWER_MODE YM_POWER_POWERSAVE 99 1.10 itohy #endif 100 1.10 itohy 101 1.10 itohy /* Time in second before power down the chip. */ 102 1.10 itohy #ifndef YM_POWER_OFF_SEC 103 1.10 itohy #define YM_POWER_OFF_SEC 5 104 1.10 itohy #endif 105 1.10 itohy 106 1.12 itohy /* Default mixer settings. */ 107 1.11 itohy #ifndef YM_VOL_MASTER 108 1.20 itohy #define YM_VOL_MASTER 208 109 1.11 itohy #endif 110 1.11 itohy 111 1.11 itohy #ifndef YM_VOL_DAC 112 1.11 itohy #define YM_VOL_DAC 224 113 1.11 itohy #endif 114 1.11 itohy 115 1.11 itohy #ifndef YM_VOL_OPL3 116 1.11 itohy #define YM_VOL_OPL3 184 117 1.11 itohy #endif 118 1.11 itohy 119 1.16 itohy /* 120 1.20 itohy * Default position of the equalizer. 121 1.16 itohy */ 122 1.20 itohy #ifndef YM_DEFAULT_TREBLE 123 1.20 itohy #define YM_DEFAULT_TREBLE YM_EQ_FLAT_OFFSET 124 1.16 itohy #endif 125 1.20 itohy #ifndef YM_DEFAULT_BASS 126 1.20 itohy #define YM_DEFAULT_BASS YM_EQ_FLAT_OFFSET 127 1.15 augustss #endif 128 1.15 augustss 129 1.10 itohy #ifdef __i386__ /* XXX */ 130 1.10 itohy # include "joy.h" 131 1.10 itohy #else 132 1.10 itohy # define NJOY 0 133 1.10 itohy #endif 134 1.10 itohy 135 1.10 itohy #ifdef AUDIO_DEBUG 136 1.10 itohy #define DPRINTF(x) if (ymdebug) printf x 137 1.10 itohy int ymdebug = 0; 138 1.10 itohy #else 139 1.10 itohy #define DPRINTF(x) 140 1.10 itohy #endif 141 1.41 tsutsui #define DVNAME(softc) (device_xname((softc)->sc_ad1848.sc_ad1848.sc_dev)) 142 1.1 augustss 143 1.24 kent int ym_getdev(void *, struct audio_device *); 144 1.24 kent int ym_mixer_set_port(void *, mixer_ctrl_t *); 145 1.24 kent int ym_mixer_get_port(void *, mixer_ctrl_t *); 146 1.24 kent int ym_query_devinfo(void *, mixer_devinfo_t *); 147 1.24 kent int ym_intr(void *); 148 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 149 1.24 kent static void ym_save_codec_regs(struct ym_softc *); 150 1.24 kent static void ym_restore_codec_regs(struct ym_softc *); 151 1.24 kent int ym_codec_power_ctl(void *, int); 152 1.24 kent static void ym_chip_powerdown(struct ym_softc *); 153 1.24 kent static void ym_chip_powerup(struct ym_softc *, int); 154 1.42 jmcneill static void ym_powerdown_blocks(struct ym_softc *); 155 1.42 jmcneill static void ym_powerdown_callout(void *); 156 1.24 kent void ym_power_ctl(struct ym_softc *, int, int); 157 1.24 kent #endif 158 1.24 kent 159 1.24 kent static void ym_init(struct ym_softc *); 160 1.24 kent static void ym_mute(struct ym_softc *, int, int); 161 1.24 kent static void ym_set_master_gain(struct ym_softc *, struct ad1848_volume*); 162 1.24 kent static void ym_hvol_to_master_gain(struct ym_softc *); 163 1.24 kent static void ym_set_mic_gain(struct ym_softc *, int); 164 1.24 kent static void ym_set_3d(struct ym_softc *, mixer_ctrl_t *, 165 1.24 kent struct ad1848_volume *, int); 166 1.39 dyoung static bool ym_suspend(device_t, const pmf_qual_t *); 167 1.39 dyoung static bool ym_resume(device_t, const pmf_qual_t *); 168 1.1 augustss 169 1.1 augustss 170 1.23 yamt const struct audio_hw_if ym_hw_if = { 171 1.45 isaki .open = ad1848_isa_open, 172 1.45 isaki .close = ad1848_isa_close, 173 1.46 isaki .query_format = ad1848_query_format, 174 1.46 isaki .set_format = ad1848_set_format, 175 1.45 isaki .commit_settings = ad1848_commit_settings, 176 1.45 isaki .halt_output = ad1848_isa_halt_output, 177 1.45 isaki .halt_input = ad1848_isa_halt_input, 178 1.45 isaki .getdev = ym_getdev, 179 1.45 isaki .set_port = ym_mixer_set_port, 180 1.45 isaki .get_port = ym_mixer_get_port, 181 1.45 isaki .query_devinfo = ym_query_devinfo, 182 1.45 isaki .allocm = ad1848_isa_malloc, 183 1.45 isaki .freem = ad1848_isa_free, 184 1.45 isaki .round_buffersize = ad1848_isa_round_buffersize, 185 1.45 isaki .get_props = ad1848_isa_get_props, 186 1.45 isaki .trigger_output = ad1848_isa_trigger_output, 187 1.45 isaki .trigger_input = ad1848_isa_trigger_input, 188 1.45 isaki .get_locks = ad1848_get_locks, 189 1.1 augustss }; 190 1.1 augustss 191 1.27 perry static inline int ym_read(struct ym_softc *, int); 192 1.27 perry static inline void ym_write(struct ym_softc *, int, int); 193 1.1 augustss 194 1.1 augustss void 195 1.24 kent ym_attach(struct ym_softc *sc) 196 1.1 augustss { 197 1.11 itohy static struct ad1848_volume vol_master = {YM_VOL_MASTER, YM_VOL_MASTER}; 198 1.11 itohy static struct ad1848_volume vol_dac = {YM_VOL_DAC, YM_VOL_DAC}; 199 1.11 itohy static struct ad1848_volume vol_opl3 = {YM_VOL_OPL3, YM_VOL_OPL3}; 200 1.24 kent struct ad1848_softc *ac; 201 1.15 augustss mixer_ctrl_t mctl; 202 1.10 itohy struct audio_attach_args arg; 203 1.10 itohy 204 1.24 kent ac = &sc->sc_ad1848.sc_ad1848; 205 1.42 jmcneill callout_init(&sc->sc_powerdown_ch, CALLOUT_MPSAFE); 206 1.42 jmcneill cv_init(&sc->sc_cv, "ym"); 207 1.43 mrg ad1848_init_locks(ac, IPL_AUDIO); 208 1.14 thorpej 209 1.11 itohy /* Mute the output to reduce noise during initialization. */ 210 1.11 itohy ym_mute(sc, SA3_VOL_L, 1); 211 1.11 itohy ym_mute(sc, SA3_VOL_R, 1); 212 1.11 itohy 213 1.21 itohy sc->sc_version = ym_read(sc, SA3_MISC) & SA3_MISC_VER; 214 1.21 itohy ac->chip_name = YM_IS_SA3(sc) ? "OPL3-SA3" : "OPL3-SA2"; 215 1.21 itohy 216 1.5 pk sc->sc_ad1848.sc_ih = isa_intr_establish(sc->sc_ic, sc->ym_irq, 217 1.43 mrg IST_EDGE, IPL_AUDIO, ym_intr, sc); 218 1.1 augustss 219 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 220 1.10 itohy sc->sc_ad1848.powerctl = ym_codec_power_ctl; 221 1.10 itohy sc->sc_ad1848.powerarg = sc; 222 1.10 itohy #endif 223 1.6 augustss ad1848_isa_attach(&sc->sc_ad1848); 224 1.2 augustss printf("\n"); 225 1.5 pk ac->parent = sc; 226 1.2 augustss 227 1.2 augustss /* Establish chip in well known mode */ 228 1.11 itohy ym_set_master_gain(sc, &vol_master); 229 1.10 itohy ym_set_mic_gain(sc, 0); 230 1.2 augustss sc->master_mute = 0; 231 1.10 itohy 232 1.11 itohy /* Override ad1848 settings. */ 233 1.11 itohy ad1848_set_channel_gain(ac, AD1848_DAC_CHANNEL, &vol_dac); 234 1.11 itohy ad1848_set_channel_gain(ac, AD1848_AUX2_CHANNEL, &vol_opl3); 235 1.15 augustss 236 1.13 itohy /* 237 1.13 itohy * Mute all external sources. If you change this, you must 238 1.13 itohy * also change the initial value of sc->sc_external_sources 239 1.13 itohy * (currently 0 --- no external source is active). 240 1.13 itohy */ 241 1.20 itohy sc->mic_mute = 1; 242 1.20 itohy ym_mute(sc, SA3_MIC_VOL, sc->mic_mute); 243 1.13 itohy ad1848_mute_channel(ac, AD1848_AUX1_CHANNEL, MUTE_ALL); /* CD */ 244 1.13 itohy ad1848_mute_channel(ac, AD1848_LINE_CHANNEL, MUTE_ALL); /* line */ 245 1.13 itohy ac->mute[AD1848_AUX1_CHANNEL] = MUTE_ALL; 246 1.13 itohy ac->mute[AD1848_LINE_CHANNEL] = MUTE_ALL; 247 1.13 itohy /* speaker is muted by default */ 248 1.13 itohy 249 1.10 itohy /* We use only one IRQ (IRQ-A). */ 250 1.10 itohy ym_write(sc, SA3_IRQ_CONF, SA3_IRQ_CONF_MPU_A | SA3_IRQ_CONF_WSS_A); 251 1.10 itohy ym_write(sc, SA3_HVOL_INTR_CNF, SA3_HVOL_INTR_CNF_A); 252 1.10 itohy 253 1.10 itohy /* audio at ym attachment */ 254 1.40 nonaka sc->sc_audiodev = audio_attach_mi(&ym_hw_if, ac, ac->sc_dev); 255 1.10 itohy 256 1.10 itohy /* opl at ym attachment */ 257 1.10 itohy if (sc->sc_opl_ioh) { 258 1.10 itohy arg.type = AUDIODEV_TYPE_OPL; 259 1.10 itohy arg.hwif = 0; 260 1.10 itohy arg.hdl = 0; 261 1.49 thorpej (void)config_found(ac->sc_dev, &arg, audioprint, 262 1.50 thorpej CFARGS(.iattr = "ym")); 263 1.10 itohy } 264 1.10 itohy 265 1.10 itohy #if NMPU_YM > 0 266 1.10 itohy /* mpu at ym attachment */ 267 1.10 itohy if (sc->sc_mpu_ioh) { 268 1.10 itohy arg.type = AUDIODEV_TYPE_MPU; 269 1.10 itohy arg.hwif = 0; 270 1.10 itohy arg.hdl = 0; 271 1.48 thorpej sc->sc_mpudev = config_found(ac->sc_dev, &arg, audioprint, 272 1.50 thorpej CFARGS(.iattr = "ym")); 273 1.10 itohy } 274 1.10 itohy #endif 275 1.10 itohy 276 1.10 itohy /* This must be AFTER the attachment of sub-devices. */ 277 1.42 jmcneill mutex_spin_enter(&sc->sc_ad1848.sc_ad1848.sc_intr_lock); 278 1.10 itohy ym_init(sc); 279 1.10 itohy 280 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 281 1.10 itohy /* 282 1.10 itohy * Initialize power control. 283 1.10 itohy */ 284 1.10 itohy sc->sc_pow_mode = YM_POWER_MODE; 285 1.10 itohy sc->sc_pow_timeout = YM_POWER_OFF_SEC; 286 1.10 itohy 287 1.10 itohy sc->sc_on_blocks = sc->sc_turning_off = 288 1.24 kent YM_POWER_CODEC_P | YM_POWER_CODEC_R | 289 1.24 kent YM_POWER_OPL3 | YM_POWER_MPU401 | YM_POWER_3D | 290 1.24 kent YM_POWER_CODEC_DA | YM_POWER_CODEC_AD | YM_POWER_OPL3_DA; 291 1.10 itohy #if NJOY > 0 292 1.11 itohy sc->sc_on_blocks |= YM_POWER_JOYSTICK; /* prevents chip powerdown */ 293 1.10 itohy #endif 294 1.10 itohy ym_powerdown_blocks(sc); 295 1.42 jmcneill mutex_spin_exit(&sc->sc_ad1848.sc_ad1848.sc_intr_lock); 296 1.1 augustss 297 1.40 nonaka if (!pmf_device_register(ac->sc_dev, ym_suspend, ym_resume)) { 298 1.40 nonaka aprint_error_dev(ac->sc_dev, 299 1.36 christos "cannot set power mgmt handler\n"); 300 1.36 christos } 301 1.10 itohy #endif 302 1.16 itohy 303 1.16 itohy /* Set tone control to the default position. */ 304 1.16 itohy mctl.un.value.num_channels = 1; 305 1.20 itohy mctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = YM_DEFAULT_TREBLE; 306 1.16 itohy mctl.dev = YM_MASTER_TREBLE; 307 1.16 itohy ym_mixer_set_port(sc, &mctl); 308 1.20 itohy mctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = YM_DEFAULT_BASS; 309 1.16 itohy mctl.dev = YM_MASTER_BASS; 310 1.16 itohy ym_mixer_set_port(sc, &mctl); 311 1.20 itohy 312 1.20 itohy /* Unmute the output now if the chip is on. */ 313 1.20 itohy #ifndef AUDIO_NO_POWER_CTL 314 1.20 itohy if (sc->sc_on_blocks & YM_POWER_ACTIVE) 315 1.16 itohy #endif 316 1.20 itohy { 317 1.20 itohy ym_mute(sc, SA3_VOL_L, sc->master_mute); 318 1.20 itohy ym_mute(sc, SA3_VOL_R, sc->master_mute); 319 1.20 itohy } 320 1.1 augustss } 321 1.1 augustss 322 1.27 perry static inline int 323 1.24 kent ym_read(struct ym_softc *sc, int reg) 324 1.1 augustss { 325 1.24 kent 326 1.10 itohy bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 327 1.24 kent SA3_CTL_INDEX, (reg & 0xff)); 328 1.24 kent return bus_space_read_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_DATA); 329 1.1 augustss } 330 1.1 augustss 331 1.27 perry static inline void 332 1.24 kent ym_write(struct ym_softc *sc, int reg, int data) 333 1.1 augustss { 334 1.24 kent 335 1.10 itohy bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 336 1.24 kent SA3_CTL_INDEX, (reg & 0xff)); 337 1.10 itohy bus_space_write_1(sc->sc_iot, sc->sc_controlioh, 338 1.24 kent SA3_CTL_DATA, (data & 0xff)); 339 1.1 augustss } 340 1.1 augustss 341 1.10 itohy static void 342 1.24 kent ym_init(struct ym_softc *sc) 343 1.10 itohy { 344 1.24 kent uint8_t dpd, apd; 345 1.10 itohy 346 1.42 jmcneill KASSERT(mutex_owned(&sc->sc_ad1848.sc_ad1848.sc_intr_lock)); 347 1.42 jmcneill 348 1.10 itohy /* Mute SoundBlaster output if possible. */ 349 1.10 itohy if (sc->sc_sb_ioh) { 350 1.10 itohy bus_space_write_1(sc->sc_iot, sc->sc_sb_ioh, SBP_MIXER_ADDR, 351 1.24 kent SBP_MASTER_VOL); 352 1.10 itohy bus_space_write_1(sc->sc_iot, sc->sc_sb_ioh, SBP_MIXER_DATA, 353 1.24 kent 0x00); 354 1.10 itohy } 355 1.10 itohy 356 1.21 itohy if (!YM_IS_SA3(sc)) { 357 1.21 itohy /* OPL3-SA2 */ 358 1.21 itohy ym_write(sc, SA3_PWR_MNG, SA2_PWR_MNG_CLKO | 359 1.21 itohy (sc->sc_opl_ioh == 0 ? SA2_PWR_MNG_FMPS : 0)); 360 1.21 itohy return; 361 1.21 itohy } 362 1.21 itohy 363 1.21 itohy /* OPL3-SA3 */ 364 1.10 itohy /* Figure out which part can be power down. */ 365 1.10 itohy dpd = SA3_DPWRDWN_SB /* we never use SB */ 366 1.10 itohy #if NMPU_YM > 0 367 1.24 kent | (sc->sc_mpu_ioh ? 0 : SA3_DPWRDWN_MPU) 368 1.10 itohy #else 369 1.24 kent | SA3_DPWRDWN_MPU 370 1.10 itohy #endif 371 1.10 itohy #if NJOY == 0 372 1.24 kent | SA3_DPWRDWN_JOY 373 1.10 itohy #endif 374 1.24 kent | SA3_DPWRDWN_PNP /* ISA Plug and Play is done */ 375 1.24 kent /* 376 1.24 kent * The master clock is for external wavetable synthesizer 377 1.24 kent * OPL4-ML (YMF704) or OPL4-ML2 (YMF721), 378 1.24 kent * and is currently unused. 379 1.24 kent */ 380 1.24 kent | SA3_DPWRDWN_MCLKO; 381 1.10 itohy 382 1.10 itohy apd = SA3_APWRDWN_SBDAC; /* we never use SB */ 383 1.10 itohy 384 1.10 itohy /* Power down OPL3 if not attached. */ 385 1.10 itohy if (sc->sc_opl_ioh == 0) { 386 1.10 itohy dpd |= SA3_DPWRDWN_FM; 387 1.10 itohy apd |= SA3_APWRDWN_FMDAC; 388 1.10 itohy } 389 1.10 itohy /* CODEC is always attached. */ 390 1.10 itohy 391 1.10 itohy /* Power down unused digital parts. */ 392 1.10 itohy ym_write(sc, SA3_DPWRDWN, dpd); 393 1.10 itohy 394 1.10 itohy /* Power down unused analog parts. */ 395 1.10 itohy ym_write(sc, SA3_APWRDWN, apd); 396 1.10 itohy } 397 1.1 augustss 398 1.1 augustss 399 1.1 augustss int 400 1.24 kent ym_getdev(void *addr, struct audio_device *retp) 401 1.1 augustss { 402 1.24 kent struct ym_softc *sc; 403 1.24 kent struct ad1848_softc *ac; 404 1.10 itohy 405 1.24 kent sc = addr; 406 1.24 kent ac = &sc->sc_ad1848.sc_ad1848; 407 1.22 itojun strlcpy(retp->name, ac->chip_name, sizeof(retp->name)); 408 1.22 itojun snprintf(retp->version, sizeof(retp->version), "%d", sc->sc_version); 409 1.22 itojun strlcpy(retp->config, "ym", sizeof(retp->config)); 410 1.10 itohy 411 1.2 augustss return 0; 412 1.1 augustss } 413 1.1 augustss 414 1.1 augustss 415 1.1 augustss static ad1848_devmap_t mappings[] = { 416 1.10 itohy { YM_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL }, 417 1.2 augustss { YM_MIDI_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL }, 418 1.2 augustss { YM_CD_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL }, 419 1.2 augustss { YM_LINE_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL }, 420 1.2 augustss { YM_SPEAKER_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL }, 421 1.2 augustss { YM_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL }, 422 1.10 itohy { YM_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL }, 423 1.2 augustss { YM_MIDI_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL }, 424 1.2 augustss { YM_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL }, 425 1.2 augustss { YM_LINE_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL }, 426 1.2 augustss { YM_SPEAKER_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL }, 427 1.2 augustss { YM_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL }, 428 1.2 augustss { YM_REC_LVL, AD1848_KIND_RECORDGAIN, -1 }, 429 1.2 augustss { YM_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1} 430 1.1 augustss }; 431 1.1 augustss 432 1.10 itohy #define NUMMAP (sizeof(mappings) / sizeof(mappings[0])) 433 1.1 augustss 434 1.1 augustss 435 1.1 augustss static void 436 1.24 kent ym_mute(struct ym_softc *sc, int left_reg, int mute) 437 1.1 augustss { 438 1.24 kent uint8_t reg; 439 1.1 augustss 440 1.10 itohy reg = ym_read(sc, left_reg); 441 1.10 itohy if (mute) 442 1.10 itohy ym_write(sc, left_reg, reg | 0x80); 443 1.10 itohy else 444 1.10 itohy ym_write(sc, left_reg, reg & ~0x80); 445 1.1 augustss } 446 1.1 augustss 447 1.1 augustss 448 1.1 augustss static void 449 1.24 kent ym_set_master_gain(struct ym_softc *sc, struct ad1848_volume *vol) 450 1.1 augustss { 451 1.21 itohy u_int atten; 452 1.10 itohy 453 1.2 augustss sc->master_gain = *vol; 454 1.10 itohy 455 1.10 itohy atten = ((AUDIO_MAX_GAIN - vol->left) * (SA3_VOL_MV + 1)) / 456 1.10 itohy (AUDIO_MAX_GAIN + 1); 457 1.10 itohy 458 1.10 itohy ym_write(sc, SA3_VOL_L, (ym_read(sc, SA3_VOL_L) & ~SA3_VOL_MV) | atten); 459 1.10 itohy 460 1.10 itohy atten = ((AUDIO_MAX_GAIN - vol->right) * (SA3_VOL_MV + 1)) / 461 1.10 itohy (AUDIO_MAX_GAIN + 1); 462 1.10 itohy 463 1.10 itohy ym_write(sc, SA3_VOL_R, (ym_read(sc, SA3_VOL_R) & ~SA3_VOL_MV) | atten); 464 1.1 augustss } 465 1.1 augustss 466 1.21 itohy /* 467 1.21 itohy * Read current setting of master volume from hardware 468 1.21 itohy * and update the software value if changed. 469 1.21 itohy * [SA3] This function clears hardware volume interrupt. 470 1.21 itohy */ 471 1.21 itohy static void 472 1.24 kent ym_hvol_to_master_gain(struct ym_softc *sc) 473 1.21 itohy { 474 1.21 itohy u_int prevval, val; 475 1.24 kent int changed; 476 1.21 itohy 477 1.24 kent changed = 0; 478 1.21 itohy val = SA3_VOL_MV & ~ym_read(sc, SA3_VOL_L); 479 1.21 itohy prevval = (sc->master_gain.left * (SA3_VOL_MV + 1)) / 480 1.21 itohy (AUDIO_MAX_GAIN + 1); 481 1.21 itohy if (val != prevval) { 482 1.21 itohy sc->master_gain.left = 483 1.21 itohy val * ((AUDIO_MAX_GAIN + 1) / (SA3_VOL_MV + 1)); 484 1.21 itohy changed = 1; 485 1.21 itohy } 486 1.21 itohy 487 1.21 itohy val = SA3_VOL_MV & ~ym_read(sc, SA3_VOL_R); 488 1.21 itohy prevval = (sc->master_gain.right * (SA3_VOL_MV + 1)) / 489 1.21 itohy (AUDIO_MAX_GAIN + 1); 490 1.21 itohy if (val != prevval) { 491 1.21 itohy sc->master_gain.right = 492 1.21 itohy val * ((AUDIO_MAX_GAIN + 1) / (SA3_VOL_MV + 1)); 493 1.21 itohy changed = 1; 494 1.21 itohy } 495 1.21 itohy 496 1.21 itohy #if 0 /* XXX NOT YET */ 497 1.21 itohy /* Notify the change to async processes. */ 498 1.21 itohy if (changed && sc->sc_audiodev) 499 1.21 itohy mixer_signal(sc->sc_audiodev); 500 1.44 christos #else 501 1.44 christos __USE(changed); 502 1.21 itohy #endif 503 1.21 itohy } 504 1.21 itohy 505 1.1 augustss static void 506 1.24 kent ym_set_mic_gain(struct ym_softc *sc, int vol) 507 1.1 augustss { 508 1.10 itohy u_int atten; 509 1.10 itohy 510 1.10 itohy sc->mic_gain = vol; 511 1.10 itohy 512 1.10 itohy atten = ((AUDIO_MAX_GAIN - vol) * (SA3_MIC_MCV + 1)) / 513 1.10 itohy (AUDIO_MAX_GAIN + 1); 514 1.10 itohy 515 1.10 itohy ym_write(sc, SA3_MIC_VOL, 516 1.10 itohy (ym_read(sc, SA3_MIC_VOL) & ~SA3_MIC_MCV) | atten); 517 1.10 itohy } 518 1.1 augustss 519 1.10 itohy static void 520 1.24 kent ym_set_3d(struct ym_softc *sc, mixer_ctrl_t *cp, 521 1.24 kent struct ad1848_volume *val, int reg) 522 1.10 itohy { 523 1.24 kent uint8_t l, r, e; 524 1.1 augustss 525 1.42 jmcneill KASSERT(mutex_owned(&sc->sc_ad1848.sc_ad1848.sc_intr_lock)); 526 1.42 jmcneill 527 1.10 itohy ad1848_to_vol(cp, val); 528 1.1 augustss 529 1.20 itohy l = val->left; 530 1.20 itohy r = val->right; 531 1.20 itohy if (reg != SA3_3D_WIDE) { 532 1.20 itohy /* flat on center */ 533 1.20 itohy l = YM_EQ_EXPAND_VALUE(l); 534 1.20 itohy r = YM_EQ_EXPAND_VALUE(r); 535 1.20 itohy } 536 1.20 itohy 537 1.20 itohy e = (l * (SA3_3D_BITS + 1) + (SA3_3D_BITS + 1) / 2) / 538 1.24 kent (AUDIO_MAX_GAIN + 1) << SA3_3D_LSHIFT | 539 1.20 itohy (r * (SA3_3D_BITS + 1) + (SA3_3D_BITS + 1) / 2) / 540 1.24 kent (AUDIO_MAX_GAIN + 1) << SA3_3D_RSHIFT; 541 1.10 itohy 542 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 543 1.10 itohy /* turn wide stereo on if necessary */ 544 1.10 itohy if (e) 545 1.10 itohy ym_power_ctl(sc, YM_POWER_3D, 1); 546 1.10 itohy #endif 547 1.10 itohy 548 1.10 itohy ym_write(sc, reg, e); 549 1.10 itohy 550 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 551 1.10 itohy /* turn wide stereo off if necessary */ 552 1.10 itohy if (YM_EQ_OFF(&sc->sc_treble) && YM_EQ_OFF(&sc->sc_bass) && 553 1.20 itohy YM_WIDE_OFF(&sc->sc_wide)) 554 1.10 itohy ym_power_ctl(sc, YM_POWER_3D, 0); 555 1.10 itohy #endif 556 1.1 augustss } 557 1.1 augustss 558 1.1 augustss int 559 1.24 kent ym_mixer_set_port(void *addr, mixer_ctrl_t *cp) 560 1.1 augustss { 561 1.24 kent struct ad1848_softc *ac; 562 1.24 kent struct ym_softc *sc; 563 1.2 augustss struct ad1848_volume vol; 564 1.24 kent int error; 565 1.24 kent uint8_t extsources; 566 1.1 augustss 567 1.24 kent ac = addr; 568 1.24 kent sc = ac->parent; 569 1.24 kent error = 0; 570 1.10 itohy DPRINTF(("%s: ym_mixer_set_port: dev 0x%x, type 0x%x, 0x%x (%d; %d, %d)\n", 571 1.10 itohy DVNAME(sc), cp->dev, cp->type, cp->un.ord, 572 1.10 itohy cp->un.value.num_channels, cp->un.value.level[0], 573 1.10 itohy cp->un.value.level[1])); 574 1.10 itohy 575 1.21 itohy /* SA2 doesn't have equalizer */ 576 1.21 itohy if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(cp->dev)) 577 1.21 itohy return ENXIO; 578 1.21 itohy 579 1.42 jmcneill mutex_spin_enter(&ac->sc_intr_lock); 580 1.42 jmcneill 581 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 582 1.10 itohy /* Power-up chip */ 583 1.10 itohy ym_power_ctl(sc, YM_POWER_CODEC_CTL, 1); 584 1.10 itohy #endif 585 1.1 augustss 586 1.2 augustss switch (cp->dev) { 587 1.2 augustss case YM_OUTPUT_LVL: 588 1.2 augustss ad1848_to_vol(cp, &vol); 589 1.2 augustss ym_set_master_gain(sc, &vol); 590 1.10 itohy goto out; 591 1.2 augustss 592 1.2 augustss case YM_OUTPUT_MUTE: 593 1.2 augustss sc->master_mute = (cp->un.ord != 0); 594 1.10 itohy ym_mute(sc, SA3_VOL_L, sc->master_mute); 595 1.10 itohy ym_mute(sc, SA3_VOL_R, sc->master_mute); 596 1.10 itohy goto out; 597 1.2 augustss 598 1.2 augustss case YM_MIC_LVL: 599 1.2 augustss if (cp->un.value.num_channels != 1) 600 1.2 augustss error = EINVAL; 601 1.10 itohy else 602 1.10 itohy ym_set_mic_gain(sc, 603 1.24 kent cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]); 604 1.10 itohy goto out; 605 1.10 itohy 606 1.10 itohy case YM_MASTER_EQMODE: 607 1.10 itohy sc->sc_eqmode = cp->un.ord & SA3_SYS_CTL_YMODE; 608 1.10 itohy ym_write(sc, SA3_SYS_CTL, (ym_read(sc, SA3_SYS_CTL) & 609 1.24 kent ~SA3_SYS_CTL_YMODE) | sc->sc_eqmode); 610 1.10 itohy goto out; 611 1.10 itohy 612 1.10 itohy case YM_MASTER_TREBLE: 613 1.10 itohy ym_set_3d(sc, cp, &sc->sc_treble, SA3_3D_TREBLE); 614 1.10 itohy goto out; 615 1.10 itohy 616 1.10 itohy case YM_MASTER_BASS: 617 1.10 itohy ym_set_3d(sc, cp, &sc->sc_bass, SA3_3D_BASS); 618 1.10 itohy goto out; 619 1.10 itohy 620 1.10 itohy case YM_MASTER_WIDE: 621 1.10 itohy ym_set_3d(sc, cp, &sc->sc_wide, SA3_3D_WIDE); 622 1.10 itohy goto out; 623 1.10 itohy 624 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 625 1.10 itohy case YM_PWR_MODE: 626 1.10 itohy if ((unsigned) cp->un.ord > YM_POWER_NOSAVE) 627 1.10 itohy error = EINVAL; 628 1.10 itohy else 629 1.10 itohy sc->sc_pow_mode = cp->un.ord; 630 1.10 itohy goto out; 631 1.10 itohy 632 1.10 itohy case YM_PWR_TIMEOUT: 633 1.10 itohy if (cp->un.value.num_channels != 1) 634 1.10 itohy error = EINVAL; 635 1.10 itohy else 636 1.10 itohy sc->sc_pow_timeout = 637 1.24 kent cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 638 1.10 itohy goto out; 639 1.10 itohy 640 1.10 itohy /* 641 1.13 itohy * Needs power-up to hear external sources. 642 1.13 itohy */ 643 1.13 itohy case YM_CD_MUTE: 644 1.13 itohy case YM_LINE_MUTE: 645 1.13 itohy case YM_SPEAKER_MUTE: 646 1.20 itohy case YM_MIC_MUTE: 647 1.13 itohy extsources = YM_MIXER_TO_XS(cp->dev); 648 1.13 itohy if (cp->un.ord) { 649 1.13 itohy if ((sc->sc_external_sources &= ~extsources) == 0) { 650 1.13 itohy /* 651 1.13 itohy * All the external sources are muted 652 1.13 itohy * --- no need to keep the chip on. 653 1.13 itohy */ 654 1.13 itohy ym_power_ctl(sc, YM_POWER_EXT_SRC, 0); 655 1.13 itohy DPRINTF(("%s: ym_mixer_set_port: off for ext\n", 656 1.13 itohy DVNAME(sc))); 657 1.13 itohy } 658 1.13 itohy } else { 659 1.13 itohy /* mute off - power-up the chip */ 660 1.13 itohy sc->sc_external_sources |= extsources; 661 1.13 itohy ym_power_ctl(sc, YM_POWER_EXT_SRC, 1); 662 1.13 itohy DPRINTF(("%s: ym_mixer_set_port: on for ext\n", 663 1.13 itohy DVNAME(sc))); 664 1.13 itohy } 665 1.13 itohy break; /* fall to ad1848_mixer_set_port() */ 666 1.13 itohy 667 1.13 itohy /* 668 1.10 itohy * Power on/off the playback part for monitoring. 669 1.10 itohy */ 670 1.10 itohy case YM_MONITOR_MUTE: 671 1.10 itohy if ((ac->open_mode & (FREAD | FWRITE)) == FREAD) 672 1.10 itohy ym_power_ctl(sc, YM_POWER_CODEC_P | YM_POWER_CODEC_DA, 673 1.24 kent cp->un.ord == 0); 674 1.10 itohy break; /* fall to ad1848_mixer_set_port() */ 675 1.10 itohy #endif 676 1.10 itohy } 677 1.10 itohy 678 1.10 itohy error = ad1848_mixer_set_port(ac, mappings, NUMMAP, cp); 679 1.10 itohy 680 1.10 itohy if (error != ENXIO) 681 1.10 itohy goto out; 682 1.10 itohy 683 1.10 itohy error = 0; 684 1.2 augustss 685 1.10 itohy switch (cp->dev) { 686 1.2 augustss case YM_MIC_MUTE: 687 1.2 augustss sc->mic_mute = (cp->un.ord != 0); 688 1.10 itohy ym_mute(sc, SA3_MIC_VOL, sc->mic_mute); 689 1.2 augustss break; 690 1.2 augustss 691 1.2 augustss default: 692 1.10 itohy error = ENXIO; 693 1.10 itohy break; 694 1.2 augustss } 695 1.10 itohy 696 1.10 itohy out: 697 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 698 1.10 itohy /* Power-down chip */ 699 1.10 itohy ym_power_ctl(sc, YM_POWER_CODEC_CTL, 0); 700 1.10 itohy #endif 701 1.42 jmcneill mutex_spin_exit(&ac->sc_intr_lock); 702 1.10 itohy 703 1.24 kent return error; 704 1.1 augustss } 705 1.1 augustss 706 1.1 augustss int 707 1.24 kent ym_mixer_get_port(void *addr, mixer_ctrl_t *cp) 708 1.1 augustss { 709 1.24 kent struct ad1848_softc *ac; 710 1.24 kent struct ym_softc *sc; 711 1.10 itohy int error; 712 1.1 augustss 713 1.24 kent ac = addr; 714 1.24 kent sc = ac->parent; 715 1.21 itohy /* SA2 doesn't have equalizer */ 716 1.21 itohy if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(cp->dev)) 717 1.21 itohy return ENXIO; 718 1.21 itohy 719 1.2 augustss switch (cp->dev) { 720 1.2 augustss case YM_OUTPUT_LVL: 721 1.21 itohy if (!YM_IS_SA3(sc)) { 722 1.21 itohy /* 723 1.21 itohy * SA2 doesn't have hardware volume interrupt. 724 1.21 itohy * Read current value and update every time. 725 1.21 itohy */ 726 1.42 jmcneill mutex_spin_enter(&ac->sc_intr_lock); 727 1.21 itohy #ifndef AUDIO_NO_POWER_CTL 728 1.21 itohy /* Power-up chip */ 729 1.21 itohy ym_power_ctl(sc, YM_POWER_CODEC_CTL, 1); 730 1.21 itohy #endif 731 1.21 itohy ym_hvol_to_master_gain(sc); 732 1.21 itohy #ifndef AUDIO_NO_POWER_CTL 733 1.21 itohy /* Power-down chip */ 734 1.21 itohy ym_power_ctl(sc, YM_POWER_CODEC_CTL, 0); 735 1.21 itohy #endif 736 1.42 jmcneill mutex_spin_exit(&ac->sc_intr_lock); 737 1.21 itohy } 738 1.2 augustss ad1848_from_vol(cp, &sc->master_gain); 739 1.10 itohy return 0; 740 1.10 itohy 741 1.2 augustss case YM_OUTPUT_MUTE: 742 1.2 augustss cp->un.ord = sc->master_mute; 743 1.10 itohy return 0; 744 1.10 itohy 745 1.2 augustss case YM_MIC_LVL: 746 1.2 augustss if (cp->un.value.num_channels != 1) 747 1.10 itohy return EINVAL; 748 1.10 itohy cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->mic_gain; 749 1.10 itohy return 0; 750 1.10 itohy 751 1.10 itohy case YM_MASTER_EQMODE: 752 1.10 itohy cp->un.ord = sc->sc_eqmode; 753 1.10 itohy return 0; 754 1.10 itohy 755 1.10 itohy case YM_MASTER_TREBLE: 756 1.10 itohy ad1848_from_vol(cp, &sc->sc_treble); 757 1.10 itohy return 0; 758 1.10 itohy 759 1.10 itohy case YM_MASTER_BASS: 760 1.10 itohy ad1848_from_vol(cp, &sc->sc_bass); 761 1.10 itohy return 0; 762 1.10 itohy 763 1.10 itohy case YM_MASTER_WIDE: 764 1.10 itohy ad1848_from_vol(cp, &sc->sc_wide); 765 1.10 itohy return 0; 766 1.10 itohy 767 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 768 1.10 itohy case YM_PWR_MODE: 769 1.10 itohy cp->un.ord = sc->sc_pow_mode; 770 1.10 itohy return 0; 771 1.10 itohy 772 1.10 itohy case YM_PWR_TIMEOUT: 773 1.10 itohy if (cp->un.value.num_channels != 1) 774 1.10 itohy return EINVAL; 775 1.10 itohy cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_pow_timeout; 776 1.10 itohy return 0; 777 1.10 itohy #endif 778 1.10 itohy } 779 1.10 itohy 780 1.10 itohy error = ad1848_mixer_get_port(ac, mappings, NUMMAP, cp); 781 1.10 itohy 782 1.10 itohy if (error != ENXIO) 783 1.24 kent return error; 784 1.10 itohy 785 1.10 itohy error = 0; 786 1.10 itohy 787 1.10 itohy switch (cp->dev) { 788 1.2 augustss case YM_MIC_MUTE: 789 1.2 augustss cp->un.ord = sc->mic_mute; 790 1.2 augustss break; 791 1.10 itohy 792 1.2 augustss default: 793 1.2 augustss error = ENXIO; 794 1.2 augustss break; 795 1.2 augustss } 796 1.10 itohy 797 1.24 kent return error; 798 1.1 augustss } 799 1.1 augustss 800 1.25 christos static const char *mixer_classes[] = { 801 1.10 itohy AudioCinputs, AudioCrecord, AudioCoutputs, AudioCmonitor, 802 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 803 1.21 itohy AudioCpower, 804 1.10 itohy #endif 805 1.21 itohy AudioCequalization 806 1.10 itohy }; 807 1.1 augustss 808 1.1 augustss int 809 1.24 kent ym_query_devinfo(void *addr, mixer_devinfo_t *dip) 810 1.1 augustss { 811 1.25 christos static const char *mixer_port_names[] = { 812 1.10 itohy AudioNdac, AudioNmidi, AudioNcd, AudioNline, AudioNspeaker, 813 1.10 itohy AudioNmicrophone, AudioNmonitor 814 1.10 itohy }; 815 1.24 kent struct ad1848_softc *ac; 816 1.24 kent struct ym_softc *sc; 817 1.21 itohy 818 1.24 kent ac = addr; 819 1.24 kent sc = ac->parent; 820 1.21 itohy /* SA2 doesn't have equalizer */ 821 1.21 itohy if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(dip->index)) 822 1.21 itohy return ENXIO; 823 1.1 augustss 824 1.2 augustss dip->next = dip->prev = AUDIO_MIXER_LAST; 825 1.10 itohy 826 1.2 augustss switch(dip->index) { 827 1.21 itohy case YM_INPUT_CLASS: 828 1.2 augustss case YM_OUTPUT_CLASS: 829 1.2 augustss case YM_MONITOR_CLASS: 830 1.2 augustss case YM_RECORD_CLASS: 831 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 832 1.10 itohy case YM_PWR_CLASS: 833 1.10 itohy #endif 834 1.21 itohy case YM_EQ_CLASS: 835 1.2 augustss dip->type = AUDIO_MIXER_CLASS; 836 1.2 augustss dip->mixer_class = dip->index; 837 1.10 itohy strcpy(dip->label.name, 838 1.2 augustss mixer_classes[dip->index - YM_INPUT_CLASS]); 839 1.2 augustss break; 840 1.10 itohy 841 1.10 itohy case YM_DAC_LVL: 842 1.2 augustss case YM_MIDI_LVL: 843 1.2 augustss case YM_CD_LVL: 844 1.10 itohy case YM_LINE_LVL: 845 1.2 augustss case YM_SPEAKER_LVL: 846 1.2 augustss case YM_MIC_LVL: 847 1.2 augustss case YM_MONITOR_LVL: 848 1.2 augustss dip->type = AUDIO_MIXER_VALUE; 849 1.2 augustss if (dip->index == YM_MONITOR_LVL) 850 1.2 augustss dip->mixer_class = YM_MONITOR_CLASS; 851 1.2 augustss else 852 1.2 augustss dip->mixer_class = YM_INPUT_CLASS; 853 1.10 itohy 854 1.2 augustss dip->next = dip->index + 7; 855 1.10 itohy 856 1.2 augustss strcpy(dip->label.name, 857 1.10 itohy mixer_port_names[dip->index - YM_DAC_LVL]); 858 1.10 itohy 859 1.2 augustss if (dip->index == YM_SPEAKER_LVL || 860 1.2 augustss dip->index == YM_MIC_LVL) 861 1.2 augustss dip->un.v.num_channels = 1; 862 1.2 augustss else 863 1.2 augustss dip->un.v.num_channels = 2; 864 1.10 itohy 865 1.20 itohy if (dip->index == YM_SPEAKER_LVL) 866 1.20 itohy dip->un.v.delta = 1 << (8 - 4 /* valid bits */); 867 1.20 itohy else if (dip->index == YM_DAC_LVL || 868 1.20 itohy dip->index == YM_MONITOR_LVL) 869 1.20 itohy dip->un.v.delta = 1 << (8 - 6 /* valid bits */); 870 1.20 itohy else 871 1.20 itohy dip->un.v.delta = 1 << (8 - 5 /* valid bits */); 872 1.20 itohy 873 1.2 augustss strcpy(dip->un.v.units.name, AudioNvolume); 874 1.2 augustss break; 875 1.10 itohy 876 1.10 itohy case YM_DAC_MUTE: 877 1.2 augustss case YM_MIDI_MUTE: 878 1.2 augustss case YM_CD_MUTE: 879 1.2 augustss case YM_LINE_MUTE: 880 1.2 augustss case YM_SPEAKER_MUTE: 881 1.2 augustss case YM_MIC_MUTE: 882 1.2 augustss case YM_MONITOR_MUTE: 883 1.2 augustss if (dip->index == YM_MONITOR_MUTE) 884 1.2 augustss dip->mixer_class = YM_MONITOR_CLASS; 885 1.2 augustss else 886 1.2 augustss dip->mixer_class = YM_INPUT_CLASS; 887 1.2 augustss dip->type = AUDIO_MIXER_ENUM; 888 1.2 augustss dip->prev = dip->index - 7; 889 1.2 augustss mute: 890 1.2 augustss strcpy(dip->label.name, AudioNmute); 891 1.2 augustss dip->un.e.num_mem = 2; 892 1.2 augustss strcpy(dip->un.e.member[0].label.name, AudioNoff); 893 1.2 augustss dip->un.e.member[0].ord = 0; 894 1.2 augustss strcpy(dip->un.e.member[1].label.name, AudioNon); 895 1.2 augustss dip->un.e.member[1].ord = 1; 896 1.2 augustss break; 897 1.10 itohy 898 1.10 itohy 899 1.2 augustss case YM_OUTPUT_LVL: 900 1.2 augustss dip->type = AUDIO_MIXER_VALUE; 901 1.2 augustss dip->mixer_class = YM_OUTPUT_CLASS; 902 1.2 augustss dip->next = YM_OUTPUT_MUTE; 903 1.2 augustss strcpy(dip->label.name, AudioNmaster); 904 1.2 augustss dip->un.v.num_channels = 2; 905 1.20 itohy dip->un.v.delta = (AUDIO_MAX_GAIN + 1) / (SA3_VOL_MV + 1); 906 1.2 augustss strcpy(dip->un.v.units.name, AudioNvolume); 907 1.2 augustss break; 908 1.10 itohy 909 1.2 augustss case YM_OUTPUT_MUTE: 910 1.2 augustss dip->mixer_class = YM_OUTPUT_CLASS; 911 1.2 augustss dip->type = AUDIO_MIXER_ENUM; 912 1.2 augustss dip->prev = YM_OUTPUT_LVL; 913 1.2 augustss goto mute; 914 1.10 itohy 915 1.10 itohy 916 1.2 augustss case YM_REC_LVL: /* record level */ 917 1.2 augustss dip->type = AUDIO_MIXER_VALUE; 918 1.2 augustss dip->mixer_class = YM_RECORD_CLASS; 919 1.2 augustss dip->next = YM_RECORD_SOURCE; 920 1.2 augustss strcpy(dip->label.name, AudioNrecord); 921 1.2 augustss dip->un.v.num_channels = 2; 922 1.20 itohy dip->un.v.delta = 1 << (8 - 4 /* valid bits */); 923 1.2 augustss strcpy(dip->un.v.units.name, AudioNvolume); 924 1.2 augustss break; 925 1.10 itohy 926 1.2 augustss case YM_RECORD_SOURCE: 927 1.2 augustss dip->mixer_class = YM_RECORD_CLASS; 928 1.2 augustss dip->type = AUDIO_MIXER_ENUM; 929 1.2 augustss dip->prev = YM_REC_LVL; 930 1.2 augustss strcpy(dip->label.name, AudioNsource); 931 1.2 augustss dip->un.e.num_mem = 4; 932 1.2 augustss strcpy(dip->un.e.member[0].label.name, AudioNmicrophone); 933 1.2 augustss dip->un.e.member[0].ord = MIC_IN_PORT; 934 1.2 augustss strcpy(dip->un.e.member[1].label.name, AudioNline); 935 1.2 augustss dip->un.e.member[1].ord = LINE_IN_PORT; 936 1.2 augustss strcpy(dip->un.e.member[2].label.name, AudioNdac); 937 1.2 augustss dip->un.e.member[2].ord = DAC_IN_PORT; 938 1.2 augustss strcpy(dip->un.e.member[3].label.name, AudioNcd); 939 1.2 augustss dip->un.e.member[3].ord = AUX1_IN_PORT; 940 1.2 augustss break; 941 1.10 itohy 942 1.10 itohy 943 1.10 itohy case YM_MASTER_EQMODE: 944 1.10 itohy dip->type = AUDIO_MIXER_ENUM; 945 1.10 itohy dip->mixer_class = YM_EQ_CLASS; 946 1.10 itohy strcpy(dip->label.name, AudioNmode); 947 1.10 itohy strcpy(dip->un.v.units.name, AudioNmode); 948 1.10 itohy dip->un.e.num_mem = 4; 949 1.10 itohy strcpy(dip->un.e.member[0].label.name, AudioNdesktop); 950 1.10 itohy dip->un.e.member[0].ord = SA3_SYS_CTL_YMODE0; 951 1.10 itohy strcpy(dip->un.e.member[1].label.name, AudioNlaptop); 952 1.10 itohy dip->un.e.member[1].ord = SA3_SYS_CTL_YMODE1; 953 1.10 itohy strcpy(dip->un.e.member[2].label.name, AudioNsubnote); 954 1.10 itohy dip->un.e.member[2].ord = SA3_SYS_CTL_YMODE2; 955 1.10 itohy strcpy(dip->un.e.member[3].label.name, AudioNhifi); 956 1.10 itohy dip->un.e.member[3].ord = SA3_SYS_CTL_YMODE3; 957 1.10 itohy break; 958 1.10 itohy 959 1.10 itohy case YM_MASTER_TREBLE: 960 1.10 itohy dip->type = AUDIO_MIXER_VALUE; 961 1.10 itohy dip->mixer_class = YM_EQ_CLASS; 962 1.10 itohy strcpy(dip->label.name, AudioNtreble); 963 1.10 itohy dip->un.v.num_channels = 2; 964 1.20 itohy dip->un.v.delta = (AUDIO_MAX_GAIN + 1) / (SA3_3D_BITS + 1) 965 1.20 itohy >> YM_EQ_REDUCE_BIT; 966 1.10 itohy strcpy(dip->un.v.units.name, AudioNtreble); 967 1.10 itohy break; 968 1.10 itohy 969 1.10 itohy case YM_MASTER_BASS: 970 1.10 itohy dip->type = AUDIO_MIXER_VALUE; 971 1.10 itohy dip->mixer_class = YM_EQ_CLASS; 972 1.10 itohy strcpy(dip->label.name, AudioNbass); 973 1.10 itohy dip->un.v.num_channels = 2; 974 1.20 itohy dip->un.v.delta = (AUDIO_MAX_GAIN + 1) / (SA3_3D_BITS + 1) 975 1.20 itohy >> YM_EQ_REDUCE_BIT; 976 1.10 itohy strcpy(dip->un.v.units.name, AudioNbass); 977 1.10 itohy break; 978 1.10 itohy 979 1.10 itohy case YM_MASTER_WIDE: 980 1.10 itohy dip->type = AUDIO_MIXER_VALUE; 981 1.10 itohy dip->mixer_class = YM_EQ_CLASS; 982 1.10 itohy strcpy(dip->label.name, AudioNsurround); 983 1.10 itohy dip->un.v.num_channels = 2; 984 1.20 itohy dip->un.v.delta = (AUDIO_MAX_GAIN + 1) / (SA3_3D_BITS + 1); 985 1.10 itohy strcpy(dip->un.v.units.name, AudioNsurround); 986 1.10 itohy break; 987 1.10 itohy 988 1.10 itohy 989 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 990 1.10 itohy case YM_PWR_MODE: 991 1.10 itohy dip->type = AUDIO_MIXER_ENUM; 992 1.10 itohy dip->mixer_class = YM_PWR_CLASS; 993 1.10 itohy dip->next = YM_PWR_TIMEOUT; 994 1.13 itohy strcpy(dip->label.name, AudioNsave); 995 1.10 itohy dip->un.e.num_mem = 3; 996 1.10 itohy strcpy(dip->un.e.member[0].label.name, AudioNpowerdown); 997 1.10 itohy dip->un.e.member[0].ord = YM_POWER_POWERDOWN; 998 1.10 itohy strcpy(dip->un.e.member[1].label.name, AudioNpowersave); 999 1.10 itohy dip->un.e.member[1].ord = YM_POWER_POWERSAVE; 1000 1.10 itohy strcpy(dip->un.e.member[2].label.name, AudioNnosave); 1001 1.10 itohy dip->un.e.member[2].ord = YM_POWER_NOSAVE; 1002 1.10 itohy break; 1003 1.10 itohy 1004 1.10 itohy case YM_PWR_TIMEOUT: 1005 1.10 itohy dip->type = AUDIO_MIXER_VALUE; 1006 1.10 itohy dip->mixer_class = YM_PWR_CLASS; 1007 1.10 itohy dip->prev = YM_PWR_MODE; 1008 1.10 itohy strcpy(dip->label.name, AudioNtimeout); 1009 1.10 itohy dip->un.v.num_channels = 1; 1010 1.10 itohy strcpy(dip->un.v.units.name, AudioNtimeout); 1011 1.10 itohy break; 1012 1.10 itohy #endif /* not AUDIO_NO_POWER_CTL */ 1013 1.10 itohy 1014 1.2 augustss default: 1015 1.2 augustss return ENXIO; 1016 1.2 augustss /*NOTREACHED*/ 1017 1.2 augustss } 1018 1.10 itohy 1019 1.10 itohy return 0; 1020 1.10 itohy } 1021 1.10 itohy 1022 1.10 itohy int 1023 1.24 kent ym_intr(void *arg) 1024 1.10 itohy { 1025 1.33 xtraeme struct ym_softc *sc = arg; 1026 1.33 xtraeme #if NMPU_YM > 0 1027 1.33 xtraeme struct mpu_softc *sc_mpu = device_private(sc->sc_mpudev); 1028 1.33 xtraeme #endif 1029 1.10 itohy u_int8_t ist; 1030 1.10 itohy int processed; 1031 1.10 itohy 1032 1.42 jmcneill mutex_spin_enter(&sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1033 1.42 jmcneill 1034 1.10 itohy /* OPL3 timer is currently unused. */ 1035 1.10 itohy if (((ist = ym_read(sc, SA3_IRQA_STAT)) & 1036 1.10 itohy ~(SA3_IRQ_STAT_SB|SA3_IRQ_STAT_OPL3)) == 0) { 1037 1.10 itohy DPRINTF(("%s: ym_intr: spurious interrupt\n", DVNAME(sc))); 1038 1.42 jmcneill mutex_spin_exit(&sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1039 1.10 itohy return 0; 1040 1.10 itohy } 1041 1.10 itohy 1042 1.10 itohy /* Process pending interrupts. */ 1043 1.10 itohy do { 1044 1.10 itohy processed = 0; 1045 1.10 itohy /* 1046 1.10 itohy * CODEC interrupts. 1047 1.10 itohy */ 1048 1.10 itohy if (ist & (SA3_IRQ_STAT_TI|SA3_IRQ_STAT_CI|SA3_IRQ_STAT_PI)) { 1049 1.10 itohy ad1848_isa_intr(&sc->sc_ad1848); 1050 1.10 itohy processed = 1; 1051 1.10 itohy } 1052 1.10 itohy #if NMPU_YM > 0 1053 1.10 itohy /* 1054 1.10 itohy * MPU401 interrupt. 1055 1.10 itohy */ 1056 1.10 itohy if (ist & SA3_IRQ_STAT_MPU) { 1057 1.33 xtraeme mpu_intr(sc_mpu); 1058 1.10 itohy processed = 1; 1059 1.10 itohy } 1060 1.10 itohy #endif 1061 1.10 itohy /* 1062 1.21 itohy * Hardware volume interrupt (SA3 only). 1063 1.10 itohy * Recalculate master volume from the hardware setting. 1064 1.10 itohy */ 1065 1.21 itohy if ((ist & SA3_IRQ_STAT_MV) && YM_IS_SA3(sc)) { 1066 1.21 itohy ym_hvol_to_master_gain(sc); 1067 1.10 itohy processed = 1; 1068 1.10 itohy } 1069 1.10 itohy } while (processed && (ist = ym_read(sc, SA3_IRQA_STAT))); 1070 1.10 itohy 1071 1.42 jmcneill mutex_spin_exit(&sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1072 1.10 itohy return 1; 1073 1.10 itohy } 1074 1.10 itohy 1075 1.10 itohy 1076 1.10 itohy #ifndef AUDIO_NO_POWER_CTL 1077 1.10 itohy static void 1078 1.24 kent ym_save_codec_regs(struct ym_softc *sc) 1079 1.10 itohy { 1080 1.24 kent struct ad1848_softc *ac; 1081 1.10 itohy int i; 1082 1.10 itohy 1083 1.10 itohy DPRINTF(("%s: ym_save_codec_regs\n", DVNAME(sc))); 1084 1.24 kent ac = &sc->sc_ad1848.sc_ad1848; 1085 1.10 itohy for (i = 0; i <= 0x1f; i++) 1086 1.10 itohy sc->sc_codec_scan[i] = ad_read(ac, i); 1087 1.10 itohy } 1088 1.10 itohy 1089 1.10 itohy static void 1090 1.24 kent ym_restore_codec_regs(struct ym_softc *sc) 1091 1.10 itohy { 1092 1.24 kent struct ad1848_softc *ac; 1093 1.10 itohy int i, t; 1094 1.10 itohy 1095 1.10 itohy DPRINTF(("%s: ym_restore_codec_regs\n", DVNAME(sc))); 1096 1.24 kent ac = &sc->sc_ad1848.sc_ad1848; 1097 1.10 itohy for (i = 0; i <= 0x1f; i++) { 1098 1.10 itohy /* 1099 1.10 itohy * Wait til the chip becomes ready. 1100 1.10 itohy * This is required after suspend/resume. 1101 1.10 itohy */ 1102 1.10 itohy for (t = 0; 1103 1.10 itohy t < 100000 && ADREAD(ac, AD1848_IADDR) & SP_IN_INIT; t++) 1104 1.10 itohy ; 1105 1.10 itohy #ifdef AUDIO_DEBUG 1106 1.10 itohy if (t) 1107 1.10 itohy DPRINTF(("%s: ym_restore_codec_regs: reg %d, t %d\n", 1108 1.10 itohy DVNAME(sc), i, t)); 1109 1.10 itohy #endif 1110 1.10 itohy ad_write(ac, i, sc->sc_codec_scan[i]); 1111 1.10 itohy } 1112 1.10 itohy } 1113 1.10 itohy 1114 1.10 itohy /* 1115 1.10 itohy * Save and restore the state on suspending / resumning. 1116 1.10 itohy * 1117 1.10 itohy * XXX This is not complete. 1118 1.10 itohy * Currently only the parameters, such as output gain, are restored. 1119 1.10 itohy * DMA state should also be restored. FIXME. 1120 1.10 itohy */ 1121 1.36 christos static bool 1122 1.39 dyoung ym_suspend(device_t self, const pmf_qual_t *qual) 1123 1.10 itohy { 1124 1.36 christos struct ym_softc *sc = device_private(self); 1125 1.10 itohy 1126 1.36 christos DPRINTF(("%s: ym_power_hook: suspend\n", DVNAME(sc))); 1127 1.10 itohy 1128 1.42 jmcneill mutex_spin_enter(&sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1129 1.10 itohy 1130 1.36 christos /* 1131 1.36 christos * suspending... 1132 1.36 christos */ 1133 1.42 jmcneill callout_halt(&sc->sc_powerdown_ch, 1134 1.42 jmcneill &sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1135 1.36 christos if (sc->sc_turning_off) 1136 1.36 christos ym_powerdown_blocks(sc); 1137 1.10 itohy 1138 1.36 christos /* 1139 1.36 christos * Save CODEC registers. 1140 1.36 christos * Note that the registers read incorrect 1141 1.36 christos * if the CODEC part is in power-down mode. 1142 1.36 christos */ 1143 1.36 christos if (sc->sc_on_blocks & YM_POWER_CODEC_DIGITAL) 1144 1.36 christos ym_save_codec_regs(sc); 1145 1.10 itohy 1146 1.36 christos /* 1147 1.36 christos * Save OPL3-SA3 control registers and power-down the chip. 1148 1.36 christos * Note that the registers read incorrect 1149 1.36 christos * if the chip is in global power-down mode. 1150 1.36 christos */ 1151 1.36 christos sc->sc_sa3_scan[SA3_PWR_MNG] = ym_read(sc, SA3_PWR_MNG); 1152 1.36 christos if (sc->sc_on_blocks) 1153 1.36 christos ym_chip_powerdown(sc); 1154 1.42 jmcneill mutex_spin_exit(&sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1155 1.36 christos return true; 1156 1.37 christos } 1157 1.17 takemura 1158 1.36 christos static bool 1159 1.39 dyoung ym_resume(device_t self, const pmf_qual_t *qual) 1160 1.36 christos { 1161 1.36 christos struct ym_softc *sc = device_private(self); 1162 1.36 christos int i, xmax; 1163 1.10 itohy 1164 1.36 christos DPRINTF(("%s: ym_power_hook: resume\n", DVNAME(sc))); 1165 1.10 itohy 1166 1.42 jmcneill mutex_spin_enter(&sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1167 1.36 christos /* 1168 1.36 christos * resuming... 1169 1.36 christos */ 1170 1.36 christos ym_chip_powerup(sc, 1); 1171 1.36 christos ym_init(sc); /* power-on CODEC */ 1172 1.10 itohy 1173 1.36 christos /* Restore control registers. */ 1174 1.36 christos xmax = YM_IS_SA3(sc)? YM_SAVE_REG_MAX_SA3 : YM_SAVE_REG_MAX_SA2; 1175 1.36 christos for (i = SA3_PWR_MNG + 1; i <= xmax; i++) { 1176 1.36 christos if (i == SA3_SB_SCAN || i == SA3_SB_SCAN_DATA || 1177 1.36 christos i == SA3_DPWRDWN) 1178 1.36 christos continue; 1179 1.36 christos ym_write(sc, i, sc->sc_sa3_scan[i]); 1180 1.10 itohy } 1181 1.36 christos 1182 1.36 christos /* Restore CODEC registers (including mixer). */ 1183 1.36 christos ym_restore_codec_regs(sc); 1184 1.36 christos 1185 1.36 christos /* Restore global/digital power-down state. */ 1186 1.36 christos ym_write(sc, SA3_PWR_MNG, sc->sc_sa3_scan[SA3_PWR_MNG]); 1187 1.36 christos if (YM_IS_SA3(sc)) 1188 1.36 christos ym_write(sc, SA3_DPWRDWN, sc->sc_sa3_scan[SA3_DPWRDWN]); 1189 1.42 jmcneill mutex_spin_exit(&sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1190 1.36 christos return true; 1191 1.10 itohy } 1192 1.10 itohy 1193 1.10 itohy int 1194 1.24 kent ym_codec_power_ctl(void *arg, int flags) 1195 1.10 itohy { 1196 1.24 kent struct ym_softc *sc; 1197 1.24 kent struct ad1848_softc *ac; 1198 1.10 itohy int parts; 1199 1.10 itohy 1200 1.24 kent sc = arg; 1201 1.24 kent ac = &sc->sc_ad1848.sc_ad1848; 1202 1.10 itohy DPRINTF(("%s: ym_codec_power_ctl: flags = 0x%x\n", DVNAME(sc), flags)); 1203 1.42 jmcneill KASSERT(mutex_owned(&ac->sc_intr_lock)); 1204 1.10 itohy 1205 1.10 itohy if (flags != 0) { 1206 1.10 itohy parts = 0; 1207 1.10 itohy if (flags & FREAD) { 1208 1.10 itohy parts |= YM_POWER_CODEC_R | YM_POWER_CODEC_AD; 1209 1.10 itohy if (ac->mute[AD1848_MONITOR_CHANNEL] == 0) 1210 1.10 itohy parts |= YM_POWER_CODEC_P | YM_POWER_CODEC_DA; 1211 1.10 itohy } 1212 1.10 itohy if (flags & FWRITE) 1213 1.10 itohy parts |= YM_POWER_CODEC_P | YM_POWER_CODEC_DA; 1214 1.10 itohy } else 1215 1.10 itohy parts = YM_POWER_CODEC_P | YM_POWER_CODEC_R | 1216 1.10 itohy YM_POWER_CODEC_DA | YM_POWER_CODEC_AD; 1217 1.10 itohy 1218 1.10 itohy ym_power_ctl(sc, parts, flags); 1219 1.10 itohy 1220 1.2 augustss return 0; 1221 1.1 augustss } 1222 1.10 itohy 1223 1.10 itohy /* 1224 1.10 itohy * Enter Power Save mode or Global Power Down mode. 1225 1.10 itohy * Total dissipation becomes 5mA and 10uA (typ.) respective. 1226 1.10 itohy */ 1227 1.10 itohy static void 1228 1.24 kent ym_chip_powerdown(struct ym_softc *sc) 1229 1.10 itohy { 1230 1.25 christos int i, xmax; 1231 1.10 itohy 1232 1.10 itohy DPRINTF(("%s: ym_chip_powerdown\n", DVNAME(sc))); 1233 1.42 jmcneill KASSERT(mutex_owned(&sc->sc_ad1848.sc_ad1848.sc_intr_lock)); 1234 1.10 itohy 1235 1.25 christos xmax = YM_IS_SA3(sc) ? YM_SAVE_REG_MAX_SA3 : YM_SAVE_REG_MAX_SA2; 1236 1.21 itohy 1237 1.10 itohy /* Save control registers. */ 1238 1.25 christos for (i = SA3_PWR_MNG + 1; i <= xmax; i++) { 1239 1.10 itohy if (i == SA3_SB_SCAN || i == SA3_SB_SCAN_DATA) 1240 1.10 itohy continue; 1241 1.10 itohy sc->sc_sa3_scan[i] = ym_read(sc, i); 1242 1.10 itohy } 1243 1.10 itohy ym_write(sc, SA3_PWR_MNG, 1244 1.10 itohy (sc->sc_pow_mode == YM_POWER_POWERDOWN ? 1245 1.10 itohy SA3_PWR_MNG_PDN : SA3_PWR_MNG_PSV) | SA3_PWR_MNG_PDX); 1246 1.10 itohy } 1247 1.10 itohy 1248 1.10 itohy /* 1249 1.10 itohy * Power up from Power Save / Global Power Down Mode. 1250 1.10 itohy */ 1251 1.10 itohy static void 1252 1.24 kent ym_chip_powerup(struct ym_softc *sc, int nosleep) 1253 1.10 itohy { 1254 1.24 kent uint8_t pw; 1255 1.10 itohy 1256 1.10 itohy DPRINTF(("%s: ym_chip_powerup\n", DVNAME(sc))); 1257 1.42 jmcneill KASSERT(mutex_owned(&sc->sc_ad1848.sc_ad1848.sc_intr_lock)); 1258 1.10 itohy 1259 1.10 itohy pw = ym_read(sc, SA3_PWR_MNG); 1260 1.10 itohy 1261 1.10 itohy if ((pw & (SA3_PWR_MNG_PSV | SA3_PWR_MNG_PDN | SA3_PWR_MNG_PDX)) == 0) 1262 1.10 itohy return; /* already on */ 1263 1.10 itohy 1264 1.10 itohy pw &= ~SA3_PWR_MNG_PDX; 1265 1.10 itohy ym_write(sc, SA3_PWR_MNG, pw); 1266 1.10 itohy 1267 1.10 itohy /* wait 100 ms */ 1268 1.10 itohy if (nosleep) 1269 1.10 itohy delay(100000); 1270 1.10 itohy else 1271 1.42 jmcneill kpause("ym_pu1", false, hz / 10, 1272 1.42 jmcneill &sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1273 1.10 itohy 1274 1.10 itohy pw &= ~(SA3_PWR_MNG_PSV | SA3_PWR_MNG_PDN); 1275 1.10 itohy ym_write(sc, SA3_PWR_MNG, pw); 1276 1.10 itohy 1277 1.10 itohy /* wait 70 ms */ 1278 1.10 itohy if (nosleep) 1279 1.10 itohy delay(70000); 1280 1.10 itohy else 1281 1.42 jmcneill kpause("ym_pu1", false, hz / 10, 1282 1.42 jmcneill &sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1283 1.10 itohy 1284 1.10 itohy /* The chip is muted automatically --- unmute it now. */ 1285 1.10 itohy ym_mute(sc, SA3_VOL_L, sc->master_mute); 1286 1.10 itohy ym_mute(sc, SA3_VOL_R, sc->master_mute); 1287 1.10 itohy } 1288 1.10 itohy 1289 1.14 thorpej /* callout handler for power-down */ 1290 1.42 jmcneill static void 1291 1.42 jmcneill ym_powerdown_callout(void *arg) 1292 1.10 itohy { 1293 1.24 kent struct ym_softc *sc; 1294 1.42 jmcneill 1295 1.42 jmcneill sc = arg; 1296 1.42 jmcneill 1297 1.42 jmcneill mutex_spin_enter(&sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1298 1.42 jmcneill if ((sc->sc_in_power_ctl & YM_POWER_CTL_INUSE) == 0) { 1299 1.42 jmcneill ym_powerdown_blocks(sc); 1300 1.42 jmcneill } 1301 1.42 jmcneill mutex_spin_exit(&sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1302 1.42 jmcneill } 1303 1.42 jmcneill 1304 1.42 jmcneill static void 1305 1.42 jmcneill ym_powerdown_blocks(struct ym_softc *sc) 1306 1.42 jmcneill { 1307 1.24 kent uint16_t parts; 1308 1.24 kent uint16_t on_blocks; 1309 1.24 kent uint8_t sv; 1310 1.10 itohy 1311 1.24 kent on_blocks = sc->sc_on_blocks; 1312 1.10 itohy DPRINTF(("%s: ym_powerdown_blocks: turning_off 0x%x\n", 1313 1.10 itohy DVNAME(sc), sc->sc_turning_off)); 1314 1.42 jmcneill KASSERT(mutex_owned(&sc->sc_ad1848.sc_ad1848.sc_intr_lock)); 1315 1.10 itohy 1316 1.10 itohy on_blocks = sc->sc_on_blocks; 1317 1.10 itohy 1318 1.10 itohy /* Be sure not to change the state of the chip. Save it first. */ 1319 1.10 itohy sv = bus_space_read_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_INDEX); 1320 1.10 itohy 1321 1.10 itohy parts = sc->sc_turning_off; 1322 1.10 itohy 1323 1.10 itohy if (on_blocks & ~parts & YM_POWER_CODEC_CTL) 1324 1.10 itohy parts &= ~(YM_POWER_CODEC_P | YM_POWER_CODEC_R); 1325 1.10 itohy if (parts & YM_POWER_CODEC_CTL) { 1326 1.10 itohy if ((on_blocks & YM_POWER_CODEC_P) == 0) 1327 1.10 itohy parts |= YM_POWER_CODEC_P; 1328 1.10 itohy if ((on_blocks & YM_POWER_CODEC_R) == 0) 1329 1.10 itohy parts |= YM_POWER_CODEC_R; 1330 1.10 itohy } 1331 1.13 itohy parts &= ~YM_POWER_CODEC_PSEUDO; 1332 1.10 itohy 1333 1.10 itohy /* If CODEC is being off, save the state. */ 1334 1.10 itohy if ((sc->sc_on_blocks & YM_POWER_CODEC_DIGITAL) && 1335 1.10 itohy (sc->sc_on_blocks & ~sc->sc_turning_off & 1336 1.10 itohy YM_POWER_CODEC_DIGITAL) == 0) 1337 1.10 itohy ym_save_codec_regs(sc); 1338 1.10 itohy 1339 1.21 itohy if (YM_IS_SA3(sc)) { 1340 1.21 itohy /* OPL3-SA3 */ 1341 1.21 itohy ym_write(sc, SA3_DPWRDWN, 1342 1.21 itohy ym_read(sc, SA3_DPWRDWN) | (u_int8_t) parts); 1343 1.21 itohy ym_write(sc, SA3_APWRDWN, 1344 1.21 itohy ym_read(sc, SA3_APWRDWN) | (parts >> 8)); 1345 1.21 itohy } else { 1346 1.21 itohy /* OPL3-SA2 (only OPL3 can be off partially) */ 1347 1.21 itohy if (parts & YM_POWER_OPL3) 1348 1.21 itohy ym_write(sc, SA3_PWR_MNG, 1349 1.21 itohy ym_read(sc, SA3_PWR_MNG) | SA2_PWR_MNG_FMPS); 1350 1.21 itohy } 1351 1.10 itohy 1352 1.10 itohy if (((sc->sc_on_blocks &= ~sc->sc_turning_off) & YM_POWER_ACTIVE) == 0) 1353 1.10 itohy ym_chip_powerdown(sc); 1354 1.10 itohy 1355 1.10 itohy sc->sc_turning_off = 0; 1356 1.10 itohy 1357 1.10 itohy /* Restore the state of the chip. */ 1358 1.10 itohy bus_space_write_1(sc->sc_iot, sc->sc_controlioh, SA3_CTL_INDEX, sv); 1359 1.10 itohy } 1360 1.10 itohy 1361 1.10 itohy /* 1362 1.10 itohy * Power control entry point. 1363 1.10 itohy */ 1364 1.10 itohy void 1365 1.24 kent ym_power_ctl(struct ym_softc *sc, int parts, int onoff) 1366 1.10 itohy { 1367 1.10 itohy int need_restore_codec; 1368 1.10 itohy 1369 1.42 jmcneill KASSERT(mutex_owned(&sc->sc_ad1848.sc_ad1848.sc_intr_lock)); 1370 1.42 jmcneill 1371 1.10 itohy DPRINTF(("%s: ym_power_ctl: parts = 0x%x, %s\n", 1372 1.10 itohy DVNAME(sc), parts, onoff ? "on" : "off")); 1373 1.10 itohy 1374 1.10 itohy /* This function may sleep --- needs locking. */ 1375 1.10 itohy while (sc->sc_in_power_ctl & YM_POWER_CTL_INUSE) { 1376 1.10 itohy sc->sc_in_power_ctl |= YM_POWER_CTL_WANTED; 1377 1.10 itohy DPRINTF(("%s: ym_power_ctl: sleeping\n", DVNAME(sc))); 1378 1.42 jmcneill cv_wait(&sc->sc_cv, &sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1379 1.10 itohy DPRINTF(("%s: ym_power_ctl: awaken\n", DVNAME(sc))); 1380 1.10 itohy } 1381 1.10 itohy sc->sc_in_power_ctl |= YM_POWER_CTL_INUSE; 1382 1.10 itohy 1383 1.10 itohy /* If ON requested to parts which are scheduled to OFF, cancel it. */ 1384 1.10 itohy if (onoff && sc->sc_turning_off && (sc->sc_turning_off &= ~parts) == 0) 1385 1.42 jmcneill callout_halt(&sc->sc_powerdown_ch, 1386 1.42 jmcneill &sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1387 1.10 itohy 1388 1.10 itohy if (!onoff && sc->sc_turning_off) 1389 1.10 itohy parts &= ~sc->sc_turning_off; 1390 1.10 itohy 1391 1.10 itohy /* Discard bits which are currently {on,off}. */ 1392 1.10 itohy parts &= onoff ? ~sc->sc_on_blocks : sc->sc_on_blocks; 1393 1.10 itohy 1394 1.10 itohy /* Cancel previous timeout if needed. */ 1395 1.10 itohy if (parts != 0 && sc->sc_turning_off) 1396 1.42 jmcneill callout_halt(&sc->sc_powerdown_ch, 1397 1.42 jmcneill &sc->sc_ad1848.sc_ad1848.sc_intr_lock); 1398 1.10 itohy 1399 1.10 itohy if (parts == 0) 1400 1.10 itohy goto unlock; /* no work to do */ 1401 1.10 itohy 1402 1.10 itohy if (onoff) { 1403 1.10 itohy /* Turning on is done immediately. */ 1404 1.10 itohy 1405 1.10 itohy /* If the chip is off, turn it on. */ 1406 1.10 itohy if ((sc->sc_on_blocks & YM_POWER_ACTIVE) == 0) 1407 1.10 itohy ym_chip_powerup(sc, 0); 1408 1.10 itohy 1409 1.10 itohy need_restore_codec = (parts & YM_POWER_CODEC_DIGITAL) && 1410 1.10 itohy (sc->sc_on_blocks & YM_POWER_CODEC_DIGITAL) == 0; 1411 1.10 itohy 1412 1.10 itohy sc->sc_on_blocks |= parts; 1413 1.10 itohy if (parts & YM_POWER_CODEC_CTL) 1414 1.10 itohy parts |= YM_POWER_CODEC_P | YM_POWER_CODEC_R; 1415 1.10 itohy 1416 1.21 itohy if (YM_IS_SA3(sc)) { 1417 1.21 itohy /* OPL3-SA3 */ 1418 1.21 itohy ym_write(sc, SA3_DPWRDWN, 1419 1.21 itohy ym_read(sc, SA3_DPWRDWN) & (u_int8_t)~parts); 1420 1.21 itohy ym_write(sc, SA3_APWRDWN, 1421 1.21 itohy ym_read(sc, SA3_APWRDWN) & ~(parts >> 8)); 1422 1.21 itohy } else { 1423 1.21 itohy /* OPL3-SA2 (only OPL3 can be off partially) */ 1424 1.21 itohy if (parts & YM_POWER_OPL3) 1425 1.21 itohy ym_write(sc, SA3_PWR_MNG, 1426 1.21 itohy ym_read(sc, SA3_PWR_MNG) 1427 1.21 itohy & ~SA2_PWR_MNG_FMPS); 1428 1.21 itohy } 1429 1.10 itohy if (need_restore_codec) 1430 1.10 itohy ym_restore_codec_regs(sc); 1431 1.10 itohy } else { 1432 1.10 itohy /* Turning off is delayed. */ 1433 1.10 itohy sc->sc_turning_off |= parts; 1434 1.10 itohy } 1435 1.10 itohy 1436 1.10 itohy /* Schedule turning off. */ 1437 1.10 itohy if (sc->sc_pow_mode != YM_POWER_NOSAVE && sc->sc_turning_off) 1438 1.14 thorpej callout_reset(&sc->sc_powerdown_ch, hz * sc->sc_pow_timeout, 1439 1.42 jmcneill ym_powerdown_callout, sc); 1440 1.10 itohy 1441 1.10 itohy unlock: 1442 1.10 itohy if (sc->sc_in_power_ctl & YM_POWER_CTL_WANTED) 1443 1.42 jmcneill cv_broadcast(&sc->sc_cv); 1444 1.10 itohy sc->sc_in_power_ctl = 0; 1445 1.10 itohy } 1446 1.10 itohy #endif /* not AUDIO_NO_POWER_CTL */ 1447