Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-5]: src/sys/dev/isa Pull up revisions 1.19-1.21 (via patch, req...
details: https://anonhg.NetBSD.org/src/rev/d4cda8c13ba8
branches: netbsd-1-5
changeset: 493006:d4cda8c13ba8
user: he <he%NetBSD.org@localhost>
date: Wed Mar 27 10:18:04 2002 +0000
description:
Pull up revisions 1.19-1.21 (via patch, requested by itohy):
Several changes to wss-compatible audio devices:
o Fix ADPCM playback/recording
o Add explicit support for OPL3-SA2 (YMF711), fixes PR#14819
o Add AD1845 support
o other minor bugfixes and cleanups
diffstat:
sys/dev/isa/ym.c | 166 ++++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 129 insertions(+), 37 deletions(-)
diffs (truncated from 342 to 300 lines):
diff -r 1bb3bd468b9e -r d4cda8c13ba8 sys/dev/isa/ym.c
--- a/sys/dev/isa/ym.c Wed Mar 27 10:16:06 2002 +0000
+++ b/sys/dev/isa/ym.c Wed Mar 27 10:18:04 2002 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: ym.c,v 1.14.4.3 2001/05/06 15:05:59 he Exp $ */
+/* $NetBSD: ym.c,v 1.14.4.4 2002/03/27 10:18:04 he Exp $ */
/*-
- * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * Copyright (c) 1999-2002 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -66,6 +66,9 @@
* Original code from OpenBSD.
*/
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ym.c,v 1.14.4.4 2002/03/27 10:18:04 he Exp $");
+
#include "mpu_ym.h"
#include "opt_ym.h"
@@ -168,6 +171,7 @@
static void ym_init __P((struct ym_softc *));
static void ym_mute __P((struct ym_softc *, int, int));
static void ym_set_master_gain __P((struct ym_softc *, struct ad1848_volume*));
+static void ym_hvol_to_master_gain __P((struct ym_softc *));
static void ym_set_mic_gain __P((struct ym_softc *, int));
static void ym_set_3d __P((struct ym_softc *, mixer_ctrl_t *,
struct ad1848_volume *, int));
@@ -224,6 +228,9 @@
ym_mute(sc, SA3_VOL_L, 1);
ym_mute(sc, SA3_VOL_R, 1);
+ sc->sc_version = ym_read(sc, SA3_MISC) & SA3_MISC_VER;
+ ac->chip_name = YM_IS_SA3(sc) ? "OPL3-SA3" : "OPL3-SA2";
+
sc->sc_ad1848.sc_ih = isa_intr_establish(sc->sc_ic, sc->ym_irq,
IST_EDGE, IPL_AUDIO,
ym_intr, sc);
@@ -259,8 +266,6 @@
ac->mute[AD1848_LINE_CHANNEL] = MUTE_ALL;
/* speaker is muted by default */
- sc->sc_version = ym_read(sc, SA3_MISC) & SA3_MISC_VER;
-
/* We use only one IRQ (IRQ-A). */
ym_write(sc, SA3_IRQ_CONF, SA3_IRQ_CONF_MPU_A | SA3_IRQ_CONF_WSS_A);
ym_write(sc, SA3_HVOL_INTR_CNF, SA3_HVOL_INTR_CNF_A);
@@ -367,6 +372,14 @@
0x00);
}
+ if (!YM_IS_SA3(sc)) {
+ /* OPL3-SA2 */
+ ym_write(sc, SA3_PWR_MNG, SA2_PWR_MNG_CLKO |
+ (sc->sc_opl_ioh == 0 ? SA2_PWR_MNG_FMPS : 0));
+ return;
+ }
+
+ /* OPL3-SA3 */
/* Figure out which part can be power down. */
dpd = SA3_DPWRDWN_SB /* we never use SB */
#if NMPU_YM > 0
@@ -408,8 +421,9 @@
struct audio_device *retp;
{
struct ym_softc *sc = addr;
+ struct ad1848_softc *ac = &sc->sc_ad1848.sc_ad1848;
- strcpy(retp->name, "OPL3-SA3");
+ strcpy(retp->name, ac->chip_name);
sprintf(retp->version, "%d", sc->sc_version);
strcpy(retp->config, "ym");
@@ -442,7 +456,6 @@
struct ym_softc *sc;
int left_reg;
int mute;
-
{
u_int8_t reg;
@@ -459,7 +472,7 @@
struct ym_softc *sc;
struct ad1848_volume *vol;
{
- u_int atten;
+ u_int atten;
sc->master_gain = *vol;
@@ -474,6 +487,43 @@
ym_write(sc, SA3_VOL_R, (ym_read(sc, SA3_VOL_R) & ~SA3_VOL_MV) | atten);
}
+/*
+ * Read current setting of master volume from hardware
+ * and update the software value if changed.
+ * [SA3] This function clears hardware volume interrupt.
+ */
+static void
+ym_hvol_to_master_gain(sc)
+ struct ym_softc *sc;
+{
+ u_int prevval, val;
+ int changed = 0;
+
+ val = SA3_VOL_MV & ~ym_read(sc, SA3_VOL_L);
+ prevval = (sc->master_gain.left * (SA3_VOL_MV + 1)) /
+ (AUDIO_MAX_GAIN + 1);
+ if (val != prevval) {
+ sc->master_gain.left =
+ val * ((AUDIO_MAX_GAIN + 1) / (SA3_VOL_MV + 1));
+ changed = 1;
+ }
+
+ val = SA3_VOL_MV & ~ym_read(sc, SA3_VOL_R);
+ prevval = (sc->master_gain.right * (SA3_VOL_MV + 1)) /
+ (AUDIO_MAX_GAIN + 1);
+ if (val != prevval) {
+ sc->master_gain.right =
+ val * ((AUDIO_MAX_GAIN + 1) / (SA3_VOL_MV + 1));
+ changed = 1;
+ }
+
+#if 0 /* XXX NOT YET */
+ /* Notify the change to async processes. */
+ if (changed && sc->sc_audiodev)
+ mixer_signal(sc->sc_audiodev);
+#endif
+}
+
static void
ym_set_mic_gain(sc, vol)
struct ym_softc *sc;
@@ -538,6 +588,10 @@
cp->un.value.num_channels, cp->un.value.level[0],
cp->un.value.level[1]));
+ /* SA2 doesn't have equalizer */
+ if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(cp->dev))
+ return ENXIO;
+
#ifndef AUDIO_NO_POWER_CTL
/* Power-up chip */
ym_power_ctl(sc, YM_POWER_CODEC_CTL, 1);
@@ -603,6 +657,7 @@
case YM_CD_MUTE:
case YM_LINE_MUTE:
case YM_SPEAKER_MUTE:
+ case YM_MIC_MUTE:
extsources = YM_MIXER_TO_XS(cp->dev);
if (cp->un.ord) {
if ((sc->sc_external_sources &= ~extsources) == 0) {
@@ -670,8 +725,27 @@
struct ym_softc *sc = ac->parent;
int error;
+ /* SA2 doesn't have equalizer */
+ if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(cp->dev))
+ return ENXIO;
+
switch (cp->dev) {
case YM_OUTPUT_LVL:
+ if (!YM_IS_SA3(sc)) {
+ /*
+ * SA2 doesn't have hardware volume interrupt.
+ * Read current value and update every time.
+ */
+#ifndef AUDIO_NO_POWER_CTL
+ /* Power-up chip */
+ ym_power_ctl(sc, YM_POWER_CODEC_CTL, 1);
+#endif
+ ym_hvol_to_master_gain(sc);
+#ifndef AUDIO_NO_POWER_CTL
+ /* Power-down chip */
+ ym_power_ctl(sc, YM_POWER_CODEC_CTL, 0);
+#endif
+ }
ad1848_from_vol(cp, &sc->master_gain);
return 0;
@@ -736,10 +810,10 @@
static char *mixer_classes[] = {
AudioCinputs, AudioCrecord, AudioCoutputs, AudioCmonitor,
+#ifndef AUDIO_NO_POWER_CTL
+ AudioCpower,
+#endif
AudioCequalization
-#ifndef AUDIO_NO_POWER_CTL
- , AudioCpower
-#endif
};
int
@@ -751,18 +825,24 @@
AudioNdac, AudioNmidi, AudioNcd, AudioNline, AudioNspeaker,
AudioNmicrophone, AudioNmonitor
};
+ struct ad1848_softc *ac = addr;
+ struct ym_softc *sc = ac->parent;
+
+ /* SA2 doesn't have equalizer */
+ if (!YM_IS_SA3(sc) && YM_MIXER_SA3_ONLY(dip->index))
+ return ENXIO;
dip->next = dip->prev = AUDIO_MIXER_LAST;
switch(dip->index) {
- case YM_INPUT_CLASS: /* input class descriptor */
+ case YM_INPUT_CLASS:
case YM_OUTPUT_CLASS:
case YM_MONITOR_CLASS:
case YM_RECORD_CLASS:
- case YM_EQ_CLASS:
#ifndef AUDIO_NO_POWER_CTL
case YM_PWR_CLASS:
#endif
+ case YM_EQ_CLASS:
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = dip->index;
strcpy(dip->label.name,
@@ -970,22 +1050,11 @@
}
#endif
/*
- * Hardware volume interrupt.
+ * Hardware volume interrupt (SA3 only).
* Recalculate master volume from the hardware setting.
*/
- if (ist & SA3_IRQ_STAT_MV) {
- sc->master_gain.left =
- (SA3_VOL_MV & ~ym_read(sc, SA3_VOL_L)) *
- (SA3_VOL_MV + 1) + (SA3_VOL_MV + 1) / 2;
- sc->master_gain.right =
- (SA3_VOL_MV & ~ym_read(sc, SA3_VOL_R)) *
- (SA3_VOL_MV + 1) + (SA3_VOL_MV + 1) / 2;
-
-#if 0 /* XXX NOT YET */
- /* Notify the change to async processes. */
- if (sc->sc_audiodev)
- mixer_signal(sc->sc_audiodev);
-#endif
+ if ((ist & SA3_IRQ_STAT_MV) && YM_IS_SA3(sc)) {
+ ym_hvol_to_master_gain(sc);
processed = 1;
}
} while (processed && (ist = ym_read(sc, SA3_IRQA_STAT)));
@@ -1047,7 +1116,7 @@
void *v;
{
struct ym_softc *sc = v;
- int i;
+ int i, max;
int s;
DPRINTF(("%s: ym_power_hook: why = %d\n", DVNAME(sc), why));
@@ -1090,7 +1159,8 @@
ym_init(sc); /* power-on CODEC */
/* Restore control registers. */
- for (i = SA3_PWR_MNG + 1; i <= YM_SAVE_REG_MAX; i++) {
+ max = YM_IS_SA3(sc)? YM_SAVE_REG_MAX_SA3 : YM_SAVE_REG_MAX_SA2;
+ for (i = SA3_PWR_MNG + 1; i <= max; i++) {
if (i == SA3_SB_SCAN || i == SA3_SB_SCAN_DATA ||
i == SA3_DPWRDWN)
continue;
@@ -1102,7 +1172,8 @@
/* Restore global/digital power-down state. */
ym_write(sc, SA3_PWR_MNG, sc->sc_sa3_scan[SA3_PWR_MNG]);
- ym_write(sc, SA3_DPWRDWN, sc->sc_sa3_scan[SA3_DPWRDWN]);
+ if (YM_IS_SA3(sc))
+ ym_write(sc, SA3_DPWRDWN, sc->sc_sa3_scan[SA3_DPWRDWN]);
break;
case PWR_SOFTSUSPEND:
case PWR_SOFTSTANDBY:
@@ -1151,12 +1222,14 @@
ym_chip_powerdown(sc)
struct ym_softc *sc;
{
- int i;
+ int i, max;
DPRINTF(("%s: ym_chip_powerdown\n", DVNAME(sc)));
+ max = YM_IS_SA3(sc) ? YM_SAVE_REG_MAX_SA3 : YM_SAVE_REG_MAX_SA2;
+
/* Save control registers. */
- for (i = SA3_PWR_MNG + 1; i <= YM_SAVE_REG_MAX; i++) {
+ for (i = SA3_PWR_MNG + 1; i <= max; i++) {
if (i == SA3_SB_SCAN || i == SA3_SB_SCAN_DATA)
continue;
sc->sc_sa3_scan[i] = ym_read(sc, i);
@@ -1249,8 +1322,18 @@
YM_POWER_CODEC_DIGITAL) == 0)
ym_save_codec_regs(sc);
Home |
Main Index |
Thread Index |
Old Index