patch-2.2.0-pre5 linux/drivers/sound/sb_mixer.c
Next file: linux/drivers/sound/sb_mixer.h
Previous file: linux/drivers/sound/sb_common.c
Back to the patch index
Back to the overall index
- Lines: 505
- Date:
Mon Jan 4 11:37:30 1999
- Orig file:
v2.2.0-pre4/linux/drivers/sound/sb_mixer.c
- Orig date:
Mon Dec 28 15:00:52 1998
diff -u --recursive --new-file v2.2.0-pre4/linux/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c
@@ -12,8 +12,16 @@
* for more info.
*
*
- * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
- * Rolf Fokkens : ES188x recording level support
+ * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
+ * Rolf Fokkens (Dec 20 1998) : ES188x recording level support on a per
+ * input basis
+ * (Dec 24 1998) : Recognition of ES188x (?), ES1868, ES1869
+ * and ES1878. Could be used for specific
+ * handling in the future. All except ES188x
+ * and ES688 are handled like ES1688
+ * (Dec 27 1998) : RECLEV for all (?) ES1688+ chips, see
+ * ess_mixer_reload for more info. ES188x now
+ * has the "Dec 20" support + RECLEV
*/
/*
@@ -42,14 +50,360 @@
#include "sb.h"
#include "sb_mixer.h"
+static mixer_tab sbpro_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+static mixer_tab es688_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+/*
+ * The ES1688 specifics... hopefully correct...
+ * - 6 bit master volume
+ * - RECLEV control
+ * These may apply to ES688 too. I have no idea.
+ */
+static mixer_tab es1688_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+/*
+ * The ES188x specifics.
+ * Note that de master volume unlike ES688 is now controlled by two 6 bit
+ * registers. These seem to work OK on 1868 too, but I have no idea if it's
+ * compatible to 688 or 1688....
+ * Also Note that the recording levels (ES188X_MIXER_REC...) have own
+ * entries as if they were playback devices. They are used internally in the
+ * driver only!
+ */
+static mixer_tab es188x_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECSYNTH, 0x6b, 7, 4, 0x6b, 3, 4),
+MIX_ENT(ES188X_MIXER_RECPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECSPEAKER,0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECLINE, 0x6e, 7, 4, 0x6e, 3, 4),
+MIX_ENT(ES188X_MIXER_RECMIC, 0x68, 7, 4, 0x68, 3, 4),
+MIX_ENT(ES188X_MIXER_RECCD, 0x6a, 7, 4, 0x6a, 3, 4),
+MIX_ENT(ES188X_MIXER_RECIMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECRECLEV, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECIGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECOGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECLINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECLINE2, 0x6c, 7, 4, 0x6c, 3, 4),
+MIX_ENT(ES188X_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+#ifdef __SGNXPRO__
+#if 0
+static mixer_tab sgnxpro_mix = { /* not used anywhere */
+MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS, 0x46, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0)
+};
+#endif
+#endif
+
+static mixer_tab sb16_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x30, 7, 5, 0x31, 7, 5),
+MIX_ENT(SOUND_MIXER_BASS, 0x46, 7, 4, 0x47, 7, 4),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 7, 4, 0x45, 7, 4),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x34, 7, 5, 0x35, 7, 5),
+MIX_ENT(SOUND_MIXER_PCM, 0x32, 7, 5, 0x33, 7, 5),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3b, 7, 2, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x38, 7, 5, 0x39, 7, 5),
+MIX_ENT(SOUND_MIXER_MIC, 0x3a, 7, 5, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_CD, 0x36, 7, 5, 0x37, 7, 5),
+MIX_ENT(SOUND_MIXER_IMIX, 0x3c, 0, 1, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0x3f, 7, 2, 0x40, 7, 2), /* Obsolete. Use IGAIN */
+MIX_ENT(SOUND_MIXER_IGAIN, 0x3f, 7, 2, 0x40, 7, 2),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x41, 7, 2, 0x42, 7, 2)
+};
+
+static mixer_tab als007_mix =
+{
+MIX_ENT(SOUND_MIXER_VOLUME, 0x62, 7, 4, 0x62, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x66, 7, 4, 0x66, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x64, 7, 4, 0x64, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x6e, 7, 4, 0x6e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x6a, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_CD, 0x68, 7, 4, 0x68, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), /* Obsolete. Use IGAIN */
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+
+/* SM_GAMES Master volume is lower and PCM & FM volumes
+ higher than with SB Pro. This improves the
+ sound quality */
+
+static int smg_default_levels[32] =
+{
+ 0x2020, /* Master Volume */
+ 0x4b4b, /* Bass */
+ 0x4b4b, /* Treble */
+ 0x6464, /* FM */
+ 0x6464, /* PCM */
+ 0x4b4b, /* PC Speaker */
+ 0x4b4b, /* Ext Line */
+ 0x0000, /* Mic */
+ 0x4b4b, /* CD */
+ 0x4b4b, /* Recording monitor */
+ 0x4b4b, /* SB PCM */
+ 0x4b4b, /* Recording level */
+ 0x4b4b, /* Input gain */
+ 0x4b4b, /* Output gain */
+ 0x4040, /* Line1 */
+ 0x4040, /* Line2 */
+ 0x1515 /* Line3 */
+};
+
+static int sb_default_levels[32] =
+{
+ 0x5a5a, /* Master Volume */
+ 0x4b4b, /* Bass */
+ 0x4b4b, /* Treble */
+ 0x4b4b, /* FM */
+ 0x4b4b, /* PCM */
+ 0x4b4b, /* PC Speaker */
+ 0x4b4b, /* Ext Line */
+ 0x1010, /* Mic */
+ 0x4b4b, /* CD */
+ 0x0000, /* Recording monitor */
+ 0x4b4b, /* SB PCM */
+ 0x4b4b, /* Recording level */
+ 0x4b4b, /* Input gain */
+ 0x4b4b, /* Output gain */
+ 0x4040, /* Line1 */
+ 0x4040, /* Line2 */
+ 0x1515 /* Line3 */
+};
+
+static unsigned char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] =
+{
+ 0x00, /* SOUND_MIXER_VOLUME */
+ 0x00, /* SOUND_MIXER_BASS */
+ 0x00, /* SOUND_MIXER_TREBLE */
+ 0x40, /* SOUND_MIXER_SYNTH */
+ 0x00, /* SOUND_MIXER_PCM */
+ 0x00, /* SOUND_MIXER_SPEAKER */
+ 0x10, /* SOUND_MIXER_LINE */
+ 0x01, /* SOUND_MIXER_MIC */
+ 0x04, /* SOUND_MIXER_CD */
+ 0x00, /* SOUND_MIXER_IMIX */
+ 0x00, /* SOUND_MIXER_ALTPCM */
+ 0x00, /* SOUND_MIXER_RECLEV */
+ 0x00, /* SOUND_MIXER_IGAIN */
+ 0x00 /* SOUND_MIXER_OGAIN */
+};
+
+static unsigned char sb16_recmasks_R[SOUND_MIXER_NRDEVICES] =
+{
+ 0x00, /* SOUND_MIXER_VOLUME */
+ 0x00, /* SOUND_MIXER_BASS */
+ 0x00, /* SOUND_MIXER_TREBLE */
+ 0x20, /* SOUND_MIXER_SYNTH */
+ 0x00, /* SOUND_MIXER_PCM */
+ 0x00, /* SOUND_MIXER_SPEAKER */
+ 0x08, /* SOUND_MIXER_LINE */
+ 0x01, /* SOUND_MIXER_MIC */
+ 0x02, /* SOUND_MIXER_CD */
+ 0x00, /* SOUND_MIXER_IMIX */
+ 0x00, /* SOUND_MIXER_ALTPCM */
+ 0x00, /* SOUND_MIXER_RECLEV */
+ 0x00, /* SOUND_MIXER_IGAIN */
+ 0x00 /* SOUND_MIXER_OGAIN */
+};
+
+static char smw_mix_regs[] = /* Left mixer registers */
+{
+ 0x0b, /* SOUND_MIXER_VOLUME */
+ 0x0d, /* SOUND_MIXER_BASS */
+ 0x0d, /* SOUND_MIXER_TREBLE */
+ 0x05, /* SOUND_MIXER_SYNTH */
+ 0x09, /* SOUND_MIXER_PCM */
+ 0x00, /* SOUND_MIXER_SPEAKER */
+ 0x03, /* SOUND_MIXER_LINE */
+ 0x01, /* SOUND_MIXER_MIC */
+ 0x07, /* SOUND_MIXER_CD */
+ 0x00, /* SOUND_MIXER_IMIX */
+ 0x00, /* SOUND_MIXER_ALTPCM */
+ 0x00, /* SOUND_MIXER_RECLEV */
+ 0x00, /* SOUND_MIXER_IGAIN */
+ 0x00, /* SOUND_MIXER_OGAIN */
+ 0x00, /* SOUND_MIXER_LINE1 */
+ 0x00, /* SOUND_MIXER_LINE2 */
+ 0x00 /* SOUND_MIXER_LINE3 */
+};
+
+#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
+
+/* Same as SB Pro, unless I find otherwise */
+#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
+
+#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | SOUND_MASK_VOLUME)
+
+/* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
+ * channel is the COVOX/DisneySoundSource emulation volume control
+ * on the mixer. It does NOT control speaker volume. Should have own
+ * mask eventually?
+ */
+#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
+ SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
+
+#define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD)
+
+#define SB16_OUTFILTER_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD)
+
+#define ES688_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
+#define ES688_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER)
+
+#define ES1688_RECORDING_DEVICES ES688_RECORDING_DEVICES
+#define ES1688_MIXER_DEVICES (ES688_MIXER_DEVICES|SOUND_MASK_RECLEV)
+
+#define ES188X_RECORDING_DEVICES (ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 \
+ |SOUND_MASK_SYNTH)
+#define ES188X_MIXER_DEVICES (ES1688_MIXER_DEVICES)
+
+#define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | \
+ SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
+ SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
+ SOUND_MASK_IMIX)
+
+/* These are the only devices that are working at the moment. Others could
+ * be added once they are identified and a method is found to control them.
+ */
+#define ALS007_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
+ SOUND_MASK_PCM | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | \
+ SOUND_MASK_VOLUME)
+
+/*
+ * Mixer registers of ES188x
+ *
+ * These registers specifically take care of recording levels. To make the
+ * mapping from playback devices to recording devices every recording
+ * devices = playback device + ES188X_MIXER_RECDIFF
+ */
+#define ES188X_MIXER_RECBASE (SOUND_MIXER_LINE3 + 1)
+#define ES188X_MIXER_RECDIFF (ES188X_MIXER_RECBASE - SOUND_MIXER_SYNTH)
+
+#define ES188X_MIXER_RECSYNTH (SOUND_MIXER_SYNTH + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECPCM (SOUND_MIXER_PCM + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECSPEAKER (SOUND_MIXER_SPEAKER + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE (SOUND_MIXER_LINE + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECMIC (SOUND_MIXER_MIC + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECCD (SOUND_MIXER_CD + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECIMIX (SOUND_MIXER_IMIX + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECALTPCM (SOUND_MIXER_ALTPCM + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECRECLEV (SOUND_MIXER_RECLEV + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECIGAIN (SOUND_MIXER_IGAIN + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECOGAIN (SOUND_MIXER_OGAIN + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE1 (SOUND_MIXER_LINE1 + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE2 (SOUND_MIXER_LINE2 + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE3 (SOUND_MIXER_LINE3 + ES188X_MIXER_RECDIFF)
+
+
static int sbmixnum = 1;
static void sb_mixer_reset(sb_devc * devc);
+inline void sb_mixer_bits
+ (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val)
+{
+ int value;
+
+ value = sb_getmixer(devc, reg);
+ value = (value & ~mask) | (val & mask);
+ sb_setmixer(devc, reg, value);
+}
+
+
void sb_mixer_set_stereo(sb_devc * devc, int mode)
{
- sb_setmixer(devc, OUT_FILTER, ((sb_getmixer(devc, OUT_FILTER) & ~STEREO_DAC)
- | (mode ? STEREO_DAC : MONO_DAC)));
+ sb_mixer_bits(devc, OUT_FILTER, STEREO_DAC, (mode ? STEREO_DAC : MONO_DAC));
}
static int detect_mixer(sb_devc * devc)
@@ -109,8 +463,6 @@
val = sb_getmixer(devc, regoffs);
change_bits(devc, &val, dev, LEFT_CHN, left);
- devc->levels[dev] = left | (left << 8);
-
if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs) /*
* Change register
*/
@@ -133,11 +485,26 @@
sb_setmixer(devc, regoffs, val);
- devc->levels[dev] = left | (right << 8);
return left | (right << 8);
}
/*
+ * After a sb_dsp_reset extended register 0xb4 (RECLEV) is reset too. After
+ * sb_dsp_reset RECLEV has to be restored. This is where ess_mixer_reload
+ * helps.
+ */
+void ess_mixer_reload (sb_devc * devc, int dev)
+{
+ int left, right, value;
+
+ value = devc->levels[dev];
+ left = value & 0x000000ff;
+ right = (value & 0x0000ff00) >> 8;
+
+ common_mixer_set(devc, dev, left, right);
+}
+
+/*
* Changing playback levels at ES188x means having to take care of recording
* levels of recorded inputs (devc->recmask) too!
*/
@@ -191,6 +558,7 @@
{
int left = value & 0x000000ff;
int right = (value & 0x0000ff00) >> 8;
+ int retval;
if (left > 100)
left = 100;
@@ -205,19 +573,24 @@
*/
return -EINVAL;
- /* Differentiate dependong on the chipsets */
+ /* Differentiate depending on the chipsets */
switch (devc->model) {
case MDL_SMW:
- return smw_mixer_set(devc, dev, left, right);
+ retval = smw_mixer_set(devc, dev, left, right);
break;
case MDL_ESS:
if (devc->submodel == SUBMDL_ES188X) {
- return es188x_mixer_set(devc, dev, left, right);
+ retval = es188x_mixer_set(devc, dev, left, right);
+ } else {
+ retval = common_mixer_set(devc, dev, left, right);
}
break;
+ default:
+ retval = common_mixer_set(devc, dev, left, right);
}
+ if (retval >= 0) devc->levels[dev] = retval;
- return common_mixer_set(devc, dev, left, right);
+ return retval;
}
/*
@@ -496,7 +869,7 @@
static void sb_mixer_reset(sb_devc * devc)
{
char name[32];
- int i, regval;
+ int i;
extern int sm_games;
sprintf(name, "SB_%d", devc->sbmixnum);
@@ -516,12 +889,8 @@
* Then call set_recmask twice to do extra ES188x initializations
*/
if (devc->model == MDL_ESS && devc->submodel == SUBMDL_ES188X) {
- regval = sb_getmixer(devc, 0x7a);
- regval = (regval & 0xe7) | 0x08;
- sb_setmixer(devc, 0x7a, regval);
- regval = sb_getmixer(devc, 0x1c);
- regval = (regval & 0xf8) | 0x07;
- sb_setmixer(devc, 0x1c, regval);
+ sb_mixer_bits(devc, 0x7a, 0x18, 0x08);
+ sb_mixer_bits(devc, 0x1c, 0x07, 0x07);
set_recmask(devc, ES188X_RECORDING_DEVICES);
set_recmask(devc, 0);
@@ -568,11 +937,19 @@
devc->iomap = &es188x_mix;
break;
default:
- devc->supported_devices
- = ES688_MIXER_DEVICES;
- devc->supported_rec_devices
- = ES688_RECORDING_DEVICES;
- devc->iomap = &es688_mix;
+ if (devc->submodel < 8) {
+ devc->supported_devices
+ = ES688_MIXER_DEVICES;
+ devc->supported_rec_devices
+ = ES688_RECORDING_DEVICES;
+ devc->iomap = &es688_mix;
+ } else {
+ devc->supported_devices
+ = ES1688_MIXER_DEVICES;
+ devc->supported_rec_devices
+ = ES1688_RECORDING_DEVICES;
+ devc->iomap = &es1688_mix;
+ }
}
break;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov