Jacob Meuser writes: > that (AC97_HOST_SWAPPED_CHANNELS) just tells the ac97 layer to > swap the gains (change the left gain when the request was to > change the right gain), not the channels.
HD Audio can actually do it in the driver; I just don't think it's worth adding more mixer items. The most I've seen so far is 99, can anyone beat that? If anyone's feeling too lazy to move and has azalia... (from NetBSD) Index: azalia.h =================================================================== RCS file: /cvs/src/sys/dev/pci/azalia.h,v retrieving revision 1.14 diff -u -p -r1.14 azalia.h --- azalia.h 10 Oct 2007 03:39:21 -0000 1.14 +++ azalia.h 21 Jan 2008 01:49:29 -0000 @@ -554,6 +554,7 @@ typedef struct { #define MI_TARGET_ADC 0x105 #define MI_TARGET_VOLUME 0x106 #define MI_TARGET_EAPD 0x107 +#define MI_TARGET_LRSWAP 0x108 } mixer_item_t; #define VALID_WIDGET_NID(nid, codec) (nid == (codec)->audiofunc || \ Index: azalia_codec.c =================================================================== RCS file: /cvs/src/sys/dev/pci/azalia_codec.c,v retrieving revision 1.46 diff -u -p -r1.46 azalia_codec.c --- azalia_codec.c 16 Dec 2007 18:48:19 -0000 1.46 +++ azalia_codec.c 21 Jan 2008 02:09:23 -0000 @@ -679,6 +679,29 @@ azalia_generic_mixer_init(codec_t *this) this->nmixers++; } + if (w->widgetcap & COP_AWCAP_LRSWAP) { + MIXER_REG_PROLOG; + DPRINTF(("%s: lrswap %s\n", __func__, w->name)); + snprintf(d->label.name, sizeof(d->label.name), + "%s.lrswap", w->name); + d->type = AUDIO_MIXER_ENUM; + if (w->type == COP_AWTYPE_PIN_COMPLEX) + d->mixer_class = AZ_CLASS_OUTPUT; + else if (w->type == COP_AWTYPE_AUDIO_INPUT) + d->mixer_class = AZ_CLASS_RECORD; + else + d->mixer_class = AZ_CLASS_INPUT; + m->target = MI_TARGET_LRSWAP; + d->un.e.num_mem = 2; + d->un.e.member[0].ord = 0; + strlcpy(d->un.e.member[0].label.name, AudioNoff, + MAX_AUDIO_DEV_LEN); + d->un.e.member[1].ord = 1; + strlcpy(d->un.e.member[1].label.name, AudioNon, + MAX_AUDIO_DEV_LEN); + this->nmixers++; + } + /* volume knob */ if (w->type == COP_AWTYPE_VOLUME_KNOB && w->d.volume.cap & COP_VKCAP_DELTA) { @@ -1004,6 +1027,15 @@ azalia_generic_mixer_get(const codec_t * mc->un.ord = result & CORB_EAPD_EAPD ? 1 : 0; } + /* LR-Swap */ + else if (target == MI_TARGET_LRSWAP) { + err = this->comresp(this, nid, + CORB_GET_EAPD_BTL_ENABLE, 0, &result); + if (err) + return err; + mc->un.ord = result & CORB_EAPD_LRSWAP ? 1 : 0; + } + else { printf("%s: internal error in %s: target=%x\n", XNAME(this), __func__, target); @@ -1278,6 +1310,26 @@ azalia_generic_mixer_set(codec_t *this, if (err) return err; } + + /* LR-Swap */ + else if (target == MI_TARGET_LRSWAP) { + if (mc->un.ord >= 2) + return EINVAL; + err = this->comresp(this, nid, + CORB_GET_EAPD_BTL_ENABLE, 0, &result); + if (err) + return err; + result &= 0xff; + if (mc->un.ord == 0) { + result &= ~CORB_EAPD_LRSWAP; + } else { + result |= CORB_EAPD_LRSWAP; + } + err = this->comresp(this, nid, + CORB_SET_EAPD_BTL_ENABLE, result, &result); + if (err) + return err; + } else { printf("%s: internal error in %s: target=%x\n",