Hi all, - make snd_kcontrol_new_t arrays in sb_mixer.c arrays of *pointers* to snd_kcontrol_new_t in order to have way more flexibility in implementing "close but not quite" matches in SB-like mixer interfaces (assembling new clone card SB mixers from *preexisting* controls) - added 3D sound controls and many more controls to ALS4000, also some fixes to other cards (SB16 etc.) - tried to fix ALS4000 open/close clicking and popping but failed (documented failure) - added hint about official ALS4000 chip specs - some cleanup
Greetings, Andreas Mohr Index: alsa-kernel/include/sb.h =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/include/sb.h,v retrieving revision 1.7 diff -u -r1.7 sb.h --- alsa-kernel/include/sb.h 23 Oct 2002 19:07:44 -0000 1.7 +++ alsa-kernel/include/sb.h 10 Nov 2002 13:48:44 -0000 @@ -225,7 +225,6 @@ #define SB_DT019X_MIC_DEV 0x6a #define SB_DT019X_SPKR_DEV 0x6a #define SB_DT019X_LINE_DEV 0x6e -#define SB_DT019X_OUTPUT_SW1 0x3c #define SB_DT019X_OUTPUT_SW2 0x4c #define SB_DT019X_CAPTURE_SW 0x6c @@ -234,6 +233,14 @@ #define SB_DT019X_CAP_LINE 0x06 #define SB_DT019X_CAP_SYNTH 0x07 #define SB_DT019X_CAP_MAIN 0x07 + +#define SB_ALS4000_MONO_IO_CTRL 0x4b +#define SB_ALS4000_MIC_IN_GAIN 0x4d +#define SB_ALS4000_FMDAC 0x4f +#define SB_ALS4000_3D_SND_FX 0x50 +#define SB_ALS4000_3D_TIME_DELAY 0x51 +#define SB_ALS4000_3D_AUTO_MUTE 0x52 +#define SB_ALS4000_QSOUND 0xdb /* IRQ setting bitmap */ #define SB_IRQSETUP_IRQ9 0x01 Index: alsa-kernel/isa/sb/sb_mixer.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/isa/sb/sb_mixer.c,v retrieving revision 1.9 diff -u -r1.9 sb_mixer.c --- alsa-kernel/isa/sb/sb_mixer.c 15 Aug 2002 12:13:07 -0000 1.9 +++ alsa-kernel/isa/sb/sb_mixer.c 10 Nov 2002 13:48:45 -0000 @@ -428,13 +428,22 @@ return change; } -#define SB20_CONTROLS (sizeof(snd_sb20_controls)/sizeof(snd_kcontrol_new_t)) +#define SB20_CONTROLS (sizeof(snd_sb20_controls)/sizeof(snd_kcontrol_new_t *)) -static snd_kcontrol_new_t snd_sb20_controls[] = { -SB_SINGLE("Master Playback Volume", SB_DSP20_MASTER_DEV, 1, 7), -SB_SINGLE("PCM Playback Volume", SB_DSP20_PCM_DEV, 1, 3), -SB_SINGLE("Synth Playback Volume", SB_DSP20_FM_DEV, 1, 7), -SB_SINGLE("CD Playback Volume", SB_DSP20_CD_DEV, 1, 7) +static snd_kcontrol_new_t snd_sb20_ctl_master_play_vol = + SB_SINGLE("Master Playback Volume", SB_DSP20_MASTER_DEV, 1, 7); +static snd_kcontrol_new_t snd_sb20_ctl_pcm_play_vol = + SB_SINGLE("PCM Playback Volume", SB_DSP20_PCM_DEV, 1, 3); +static snd_kcontrol_new_t snd_sb20_ctl_synth_play_vol = + SB_SINGLE("Synth Playback Volume", SB_DSP20_FM_DEV, 1, 7); +static snd_kcontrol_new_t snd_sb20_ctl_cd_play_vol = + SB_SINGLE("CD Playback Volume", SB_DSP20_CD_DEV, 1, 7); + +static snd_kcontrol_new_t *snd_sb20_controls[] = { + &snd_sb20_ctl_master_play_vol, + &snd_sb20_ctl_pcm_play_vol, + &snd_sb20_ctl_synth_play_vol, + &snd_sb20_ctl_cd_play_vol }; #define SB20_INIT_VALUES (sizeof(snd_sb20_init_values)/sizeof(unsigned char)/2) @@ -444,25 +453,46 @@ { SB_DSP20_FM_DEV, 0 }, }; -#define SBPRO_CONTROLS (sizeof(snd_sbpro_controls)/sizeof(snd_kcontrol_new_t)) +#define SBPRO_CONTROLS (sizeof(snd_sbpro_controls)/sizeof(snd_kcontrol_new_t *)) -static snd_kcontrol_new_t snd_sbpro_controls[] = { -SB_DOUBLE("Master Playback Volume", SB_DSP_MASTER_DEV, SB_DSP_MASTER_DEV, 5, 1, 7), -SB_DOUBLE("PCM Playback Volume", SB_DSP_PCM_DEV, SB_DSP_PCM_DEV, 5, 1, 7), -SB_SINGLE("PCM Playback Filter", SB_DSP_PLAYBACK_FILT, 5, 1), -SB_DOUBLE("Synth Playback Volume", SB_DSP_FM_DEV, SB_DSP_FM_DEV, 5, 1, 7), -SB_DOUBLE("CD Playback Volume", SB_DSP_CD_DEV, SB_DSP_CD_DEV, 5, 1, 7), -SB_DOUBLE("Line Playback Volume", SB_DSP_LINE_DEV, SB_DSP_LINE_DEV, 5, 1, 7), -SB_SINGLE("Mic Playback Volume", SB_DSP_MIC_DEV, 1, 3), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_sb8mixer_info_mux, - .get = snd_sb8mixer_get_mux, - .put = snd_sb8mixer_put_mux, -}, -SB_SINGLE("Capture Filter", SB_DSP_CAPTURE_FILT, 5, 1), -SB_SINGLE("Capture Low-Pass Filter", SB_DSP_CAPTURE_FILT, 3, 1) +static snd_kcontrol_new_t snd_sbpro_ctl_master_play_vol = + SB_DOUBLE("Master Playback Volume", SB_DSP_MASTER_DEV, SB_DSP_MASTER_DEV, 5, +1, 7); +static snd_kcontrol_new_t snd_sbpro_ctl_pcm_play_vol = + SB_DOUBLE("PCM Playback Volume", SB_DSP_PCM_DEV, SB_DSP_PCM_DEV, 5, 1, 7); +static snd_kcontrol_new_t snd_sbpro_ctl_pcm_play_filter = + SB_SINGLE("PCM Playback Filter", SB_DSP_PLAYBACK_FILT, 5, 1); +static snd_kcontrol_new_t snd_sbpro_ctl_synth_play_vol = + SB_DOUBLE("Synth Playback Volume", SB_DSP_FM_DEV, SB_DSP_FM_DEV, 5, 1, 7); +static snd_kcontrol_new_t snd_sbpro_ctl_cd_play_vol = + SB_DOUBLE("CD Playback Volume", SB_DSP_CD_DEV, SB_DSP_CD_DEV, 5, 1, 7); +static snd_kcontrol_new_t snd_sbpro_ctl_line_play_vol = + SB_DOUBLE("Line Playback Volume", SB_DSP_LINE_DEV, SB_DSP_LINE_DEV, 5, 1, 7); +static snd_kcontrol_new_t snd_sbpro_ctl_mic_play_vol = + SB_SINGLE("Mic Playback Volume", SB_DSP_MIC_DEV, 1, 3); +static snd_kcontrol_new_t snd_sbpro_ctl_capture_source = + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = snd_sb8mixer_info_mux, + .get = snd_sb8mixer_get_mux, + .put = snd_sb8mixer_put_mux, + }; +static snd_kcontrol_new_t snd_sbpro_ctl_capture_filter = + SB_SINGLE("Capture Filter", SB_DSP_CAPTURE_FILT, 5, 1); +static snd_kcontrol_new_t snd_sbpro_ctl_capture_low_filter = + SB_SINGLE("Capture Low-Pass Filter", SB_DSP_CAPTURE_FILT, 3, 1); + +static snd_kcontrol_new_t *snd_sbpro_controls[] = { + &snd_sbpro_ctl_master_play_vol, + &snd_sbpro_ctl_pcm_play_vol, + &snd_sbpro_ctl_pcm_play_filter, + &snd_sbpro_ctl_synth_play_vol, + &snd_sbpro_ctl_cd_play_vol, + &snd_sbpro_ctl_line_play_vol, + &snd_sbpro_ctl_mic_play_vol, + &snd_sbpro_ctl_capture_source, + &snd_sbpro_ctl_capture_filter, + &snd_sbpro_ctl_capture_low_filter }; #define SBPRO_INIT_VALUES (sizeof(snd_sbpro_init_values)/sizeof(unsigned char)/2) @@ -473,29 +503,70 @@ { SB_DSP_FM_DEV, 0 }, }; -#define SB16_CONTROLS (sizeof(snd_sb16_controls)/sizeof(snd_kcontrol_new_t)) +#define SB16_CONTROLS (sizeof(snd_sb16_controls)/sizeof(snd_kcontrol_new_t *)) -static snd_kcontrol_new_t snd_sb16_controls[] = { -SB_DOUBLE("Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31), -SB_SINGLE("3D Enhancement Switch", SB_DSP4_3DSE, 0, 1), -SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15), -SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15), -SB_DOUBLE("PCM Playback Volume", SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31), -SB16_INPUT_SW("Synth Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 6, 5), -SB_DOUBLE("Synth Playback Volume", SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31), -SB16_INPUT_SW("CD Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 2, 1), -SB_DOUBLE("CD Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1), -SB_DOUBLE("CD Playback Volume", SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31), -SB16_INPUT_SW("Line Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 4, 3), -SB_DOUBLE("Line Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1), -SB_DOUBLE("Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31), -SB_DOUBLE("Mic Capture Switch", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0, 1), -SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1), -SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31), -SB_SINGLE("PC Speaker Volume", SB_DSP4_SPEAKER_DEV, 6, 3), -SB_DOUBLE("Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3), -SB_DOUBLE("Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3), -SB_SINGLE("Auto Mic Gain", SB_DSP4_MIC_AGC, 0, 1) +static snd_kcontrol_new_t snd_sb16_ctl_master_play_vol = + SB_DOUBLE("Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + +1), 3, 3, 31); +static snd_kcontrol_new_t snd_sb16_ctl_3d_enhance_switch = + SB_SINGLE("3D Enhancement Switch", SB_DSP4_3DSE, 0, 1); +static snd_kcontrol_new_t snd_sb16_ctl_tone_bass = + SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, +4, 15); +static snd_kcontrol_new_t snd_sb16_ctl_tone_treble = + SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + +1), 4, 4, 15); +static snd_kcontrol_new_t snd_sb16_ctl_pcm_play_vol = + SB_DOUBLE("PCM Playback Volume", SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, +31); +static snd_kcontrol_new_t snd_sb16_ctl_synth_capture_route = + SB16_INPUT_SW("Synth Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, +6, 5); +static snd_kcontrol_new_t snd_sb16_ctl_synth_play_vol = + SB_DOUBLE("Synth Playback Volume", SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), +3, 3, 31); +static snd_kcontrol_new_t snd_sb16_ctl_cd_capture_route = + SB16_INPUT_SW("CD Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 2, +1); +static snd_kcontrol_new_t snd_sb16_ctl_cd_play_switch = + SB_DOUBLE("CD Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1); +static snd_kcontrol_new_t snd_sb16_ctl_cd_play_vol = + SB_DOUBLE("CD Playback Volume", SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, +31); +static snd_kcontrol_new_t snd_sb16_ctl_line_capture_route = + SB16_INPUT_SW("Line Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, +4, 3); +static snd_kcontrol_new_t snd_sb16_ctl_line_play_switch = + SB_DOUBLE("Line Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, +1); +static snd_kcontrol_new_t snd_sb16_ctl_line_play_vol = + SB_DOUBLE("Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, +3, 31); +static snd_kcontrol_new_t snd_sb16_ctl_mic_capture_route = + SB16_INPUT_SW("Mic Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, +0); +static snd_kcontrol_new_t snd_sb16_ctl_mic_play_switch = + SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1); +static snd_kcontrol_new_t snd_sb16_ctl_mic_play_vol = + SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31); +static snd_kcontrol_new_t snd_sb16_ctl_pc_speaker_vol = + SB_SINGLE("PC Speaker Volume", SB_DSP4_SPEAKER_DEV, 6, 3); +static snd_kcontrol_new_t snd_sb16_ctl_capture_vol = + SB_DOUBLE("Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, +3); +static snd_kcontrol_new_t snd_sb16_ctl_play_vol = + SB_DOUBLE("Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, +3); +static snd_kcontrol_new_t snd_sb16_ctl_auto_mic_gain = + SB_SINGLE("Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1); + +static snd_kcontrol_new_t *snd_sb16_controls[] = { + &snd_sb16_ctl_master_play_vol, + &snd_sb16_ctl_3d_enhance_switch, + &snd_sb16_ctl_tone_bass, + &snd_sb16_ctl_tone_treble, + &snd_sb16_ctl_pcm_play_vol, + &snd_sb16_ctl_synth_capture_route, + &snd_sb16_ctl_synth_play_vol, + &snd_sb16_ctl_cd_capture_route, + &snd_sb16_ctl_cd_play_switch, + &snd_sb16_ctl_cd_play_vol, + &snd_sb16_ctl_line_capture_route, + &snd_sb16_ctl_line_play_switch, + &snd_sb16_ctl_line_play_vol, + &snd_sb16_ctl_mic_capture_route, + &snd_sb16_ctl_mic_play_switch, + &snd_sb16_ctl_mic_play_vol, + &snd_sb16_ctl_pc_speaker_vol, + &snd_sb16_ctl_capture_vol, + &snd_sb16_ctl_play_vol, + &snd_sb16_ctl_auto_mic_gain }; #define SB16_INIT_VALUES (sizeof(snd_sb16_init_values)/sizeof(unsigned char)/2) @@ -513,28 +584,50 @@ { SB_DSP4_SPEAKER_DEV, 0 }, }; -#define DT019X_CONTROLS (sizeof(snd_dt019x_controls)/sizeof(snd_kcontrol_new_t)) +#define DT019X_CONTROLS (sizeof(snd_dt019x_controls)/sizeof(snd_kcontrol_new_t *)) -static snd_kcontrol_new_t snd_dt019x_controls[] = { -SB_DOUBLE("Master Playback Volume", SB_DT019X_MASTER_DEV, SB_DT019X_MASTER_DEV, 4,0, 15), -SB_DOUBLE("PCM Playback Volume", SB_DT019X_PCM_DEV, SB_DT019X_PCM_DEV, 4,0, 15), -SB_DOUBLE("Synth Playback Volume", SB_DT019X_SYNTH_DEV, SB_DT019X_SYNTH_DEV, 4,0, 15), -SB_DOUBLE("CD Playback Volume", SB_DT019X_CD_DEV, SB_DT019X_CD_DEV, 4,0, 15), -SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7), -SB_SINGLE("PC Speaker Volume", SB_DT019X_SPKR_DEV, 0, 7), -SB_DOUBLE("Line Playback Volume", SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4,0, 15), -SB_SINGLE("Mic Playback Switch", SB_DT019X_OUTPUT_SW1, 0, 1), -SB_DOUBLE("CD Playback Switch", SB_DT019X_OUTPUT_SW1, SB_DT019X_OUTPUT_SW1, 2,1, 1), -SB_DOUBLE("Line Playback Switch", SB_DT019X_OUTPUT_SW1, SB_DT019X_OUTPUT_SW1, 4,3, 1), -SB_DOUBLE("PCM Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2,1, 1), -SB_DOUBLE("Synth Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4,3, 1), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_dt019x_input_sw_info, - .get = snd_dt019x_input_sw_get, - .put = snd_dt019x_input_sw_put, -}, + +static snd_kcontrol_new_t snd_dt019x_ctl_master_play_vol = + SB_DOUBLE("Master Playback Volume", SB_DT019X_MASTER_DEV, +SB_DT019X_MASTER_DEV, 4,0, 15); +static snd_kcontrol_new_t snd_dt019x_ctl_pcm_play_vol = + SB_DOUBLE("PCM Playback Volume", SB_DT019X_PCM_DEV, SB_DT019X_PCM_DEV, 4,0, +15); +static snd_kcontrol_new_t snd_dt019x_ctl_synth_play_vol = + SB_DOUBLE("Synth Playback Volume", SB_DT019X_SYNTH_DEV, SB_DT019X_SYNTH_DEV, +4,0, 15); +static snd_kcontrol_new_t snd_dt019x_ctl_cd_play_vol = + SB_DOUBLE("CD Playback Volume", SB_DT019X_CD_DEV, SB_DT019X_CD_DEV, 4,0, 15); +static snd_kcontrol_new_t snd_dt019x_ctl_mic_play_vol = + SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7); +static snd_kcontrol_new_t snd_dt019x_ctl_pc_speaker_vol = + SB_SINGLE("PC Speaker Volume", SB_DT019X_SPKR_DEV, 0, 7); +static snd_kcontrol_new_t snd_dt019x_ctl_line_play_vol = + SB_DOUBLE("Line Playback Volume", SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4,0, +15); +static snd_kcontrol_new_t snd_dt019x_ctl_pcm_play_switch = + SB_DOUBLE("PCM Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, +2,1, 1); +static snd_kcontrol_new_t snd_dt019x_ctl_synth_play_switch = + SB_DOUBLE("Synth Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, +4,3, 1); +static snd_kcontrol_new_t snd_dt019x_ctl_capture_source = + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = snd_dt019x_input_sw_info, + .get = snd_dt019x_input_sw_get, + .put = snd_dt019x_input_sw_put, + }; + +static snd_kcontrol_new_t *snd_dt019x_controls[] = { + &snd_dt019x_ctl_master_play_vol, + &snd_dt019x_ctl_pcm_play_vol, + &snd_dt019x_ctl_synth_play_vol, + &snd_dt019x_ctl_cd_play_vol, + &snd_dt019x_ctl_mic_play_vol, + &snd_dt019x_ctl_pc_speaker_vol, + &snd_dt019x_ctl_line_play_vol, + &snd_sb16_ctl_mic_play_switch, + &snd_sb16_ctl_cd_play_switch, + &snd_sb16_ctl_line_play_switch, + &snd_dt019x_ctl_pcm_play_switch, + &snd_dt019x_ctl_synth_play_switch, + &snd_dt019x_ctl_capture_source }; #define DT019X_INIT_VALUES (sizeof(snd_dt019x_init_values)/sizeof(unsigned char)/2) @@ -546,13 +639,92 @@ { SB_DT019X_CD_DEV, 0 }, { SB_DT019X_MIC_DEV, 0 }, /* Includes PC-speaker in high nibble */ { SB_DT019X_LINE_DEV, 0 }, - { SB_DT019X_OUTPUT_SW1, 0 }, + { SB_DSP4_OUTPUT_SW, 0 }, { SB_DT019X_OUTPUT_SW2, 0 }, { SB_DT019X_CAPTURE_SW, 0x06 }, }; +/* FIXME: SB_ALS4000_MONO_IO_CTRL needs output select ctrl ! */ +static snd_kcontrol_new_t snd_als4000_ctl_mono_output_switch = + SB_SINGLE("Mono Output Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1); +/* FIXME: mono input switch also available on DT019X ? */ +static snd_kcontrol_new_t snd_als4000_ctl_mono_input_switch = + SB_SINGLE("Mono Input Switch", SB_DT019X_OUTPUT_SW2, 0, 1); +static snd_kcontrol_new_t snd_als4000_ctl_mic_20db_boost = + SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03); +static snd_kcontrol_new_t snd_als4000_ctl_mixer_out_to_in = + SB_SINGLE("Mixer Out To In", SB_ALS4000_MIC_IN_GAIN, 7, 0x01); +/* FIXME: 3D needs much more sophisticated controls, many more features ! */ +static snd_kcontrol_new_t snd_als4000_ctl_3d_output_switch = + SB_SINGLE("3D Output Switch", SB_ALS4000_3D_SND_FX, 6, 0x01); +static snd_kcontrol_new_t snd_als4000_ctl_3d_output_ratio = + SB_SINGLE("3D Output Ratio", SB_ALS4000_3D_SND_FX, 0, 0x07); +static snd_kcontrol_new_t snd_als4000_ctl_3d_poweroff_switch = + SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01); +static snd_kcontrol_new_t snd_als4000_ctl_3d_delay = + SB_SINGLE("3D Delay", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f); +#if NOT_AVAILABLE +static snd_kcontrol_new_t snd_als4000_ctl_fmdac = + SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01); +static snd_kcontrol_new_t snd_als4000_ctl_qsound = + SB_SINGLE("QSound Mode", SB_ALS4000_QSOUND, 1, 0x1f); +#endif + +#define ALS4000_CONTROLS (sizeof(snd_als4000_controls)/sizeof(snd_kcontrol_new_t *)) + +static snd_kcontrol_new_t *snd_als4000_controls[] = { + &snd_sb16_ctl_master_play_vol, + &snd_dt019x_ctl_pcm_play_switch, + &snd_sb16_ctl_pcm_play_vol, + &snd_sb16_ctl_synth_capture_route, + &snd_dt019x_ctl_synth_play_switch, + &snd_sb16_ctl_synth_play_vol, + &snd_sb16_ctl_cd_capture_route, + &snd_sb16_ctl_cd_play_switch, + &snd_sb16_ctl_cd_play_vol, + &snd_sb16_ctl_line_capture_route, + &snd_sb16_ctl_line_play_switch, + &snd_sb16_ctl_line_play_vol, + &snd_sb16_ctl_mic_capture_route, + &snd_als4000_ctl_mic_20db_boost, + &snd_sb16_ctl_auto_mic_gain, + &snd_sb16_ctl_mic_play_switch, + &snd_sb16_ctl_mic_play_vol, + &snd_sb16_ctl_pc_speaker_vol, + &snd_sb16_ctl_capture_vol, + &snd_sb16_ctl_play_vol, + &snd_als4000_ctl_mono_output_switch, + &snd_als4000_ctl_mono_input_switch, + &snd_als4000_ctl_mixer_out_to_in, + &snd_als4000_ctl_3d_output_switch, + &snd_als4000_ctl_3d_output_ratio, + &snd_als4000_ctl_3d_delay, + &snd_als4000_ctl_3d_poweroff_switch, +#if NOT_AVAILABLE + &snd_als4000_ctl_fmdac, + &snd_als4000_ctl_qsound, +#endif +}; + +#define ALS4000_INIT_VALUES (sizeof(snd_als4000_init_values)/sizeof(unsigned char)/2) + +static unsigned char snd_als4000_init_values[][2] = { + { SB_DSP4_MASTER_DEV + 0, 0 }, + { SB_DSP4_MASTER_DEV + 1, 0 }, + { SB_DSP4_PCM_DEV + 0, 0 }, + { SB_DSP4_PCM_DEV + 1, 0 }, + { SB_DSP4_SYNTH_DEV + 0, 0 }, + { SB_DSP4_SYNTH_DEV + 1, 0 }, + { SB_DSP4_SPEAKER_DEV, 0 }, + { SB_DSP4_OUTPUT_SW, 0 }, + { SB_DSP4_INPUT_LEFT, 0 }, + { SB_DSP4_INPUT_RIGHT, 0 }, + { SB_DT019X_OUTPUT_SW2, 0 }, + { SB_ALS4000_MIC_IN_GAIN, 0 }, +}; + static int snd_sbmixer_init(sb_t *chip, - snd_kcontrol_new_t *controls, + snd_kcontrol_new_t **controls, int controls_count, unsigned char map[][2], int map_count, @@ -575,7 +747,7 @@ } for (idx = 0; idx < controls_count; idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&controls[idx], chip))) < 0) + if ((err = snd_ctl_add(card, snd_ctl_new1(controls[idx], chip))) < 0) return err; } snd_component_add(card, name); @@ -612,11 +784,17 @@ break; case SB_HW_16: case SB_HW_ALS100: - case SB_HW_ALS4000: if ((err = snd_sbmixer_init(chip, snd_sb16_controls, SB16_CONTROLS, snd_sb16_init_values, SB16_INIT_VALUES, "CTL1745")) < 0) + return err; + break; + case SB_HW_ALS4000: + if ((err = snd_sbmixer_init(chip, + snd_als4000_controls, ALS4000_CONTROLS, + snd_als4000_init_values, +ALS4000_INIT_VALUES, + "ALS4000")) < 0) return err; break; case SB_HW_DT019X: Index: alsa-kernel/pci/als4000.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/pci/als4000.c,v retrieving revision 1.17 diff -u -r1.17 als4000.c --- alsa-kernel/pci/als4000.c 21 Oct 2002 18:28:23 -0000 1.17 +++ alsa-kernel/pci/als4000.c 10 Nov 2002 13:48:46 -0000 @@ -2,6 +2,7 @@ * card-als4000.c - driver for Avance Logic ALS4000 based soundcards. * Copyright (C) 2000 by Bart Hartgers <[EMAIL PROTECTED]>, * Jaroslav Kysela <[EMAIL PROTECTED]> + * Copyright (C) 2002 by Andreas Mohr <[EMAIL PROTECTED]> * * Framework borrowed from Massimo Piccioni's card-als100.c. * @@ -11,6 +12,9 @@ * bought an ALS4000 based soundcard, I was forced to base this driver * on reverse engineering. * + * Note: this is no longer true. Pretty verbose chip docu (ALS4000a.PDF) + * can be found on the ALSA web site. + * * The ALS4000 seems to be the PCI-cousin of the ALS100. It contains an * ALS100-like SB DSP/mixer, an OPL3 synth, a MPU401 and a gameport * interface. These subsystems can be mapped into ISA io-port space, @@ -23,11 +27,21 @@ * * The ALS4000 can do real full duplex playback/capture. * - * BUGS - * The box suggests there is some support for 3D sound, but I did not - * investigate this yet. - * + * FMDAC: + * - 0x4f -> port 0x14 + * - port 0x15 |= 1 + * + * Enable/disable 3D sound: + * - 0x50 -> port 0x14 + * - change bit 6 (0x40) of port 0x15 + * + * Set QSound: + * - 0xdb -> port 0x14 + * - set port 0x15: + * 0x3e (mode 3), 0x3c (mode 2), 0x3a (mode 1), 0x38 (mode 0) * + * Set KSound: + * - value -> some port 0x0c0d * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -256,11 +270,18 @@ count >>=1; count--; + /* FIXME: from second playback on, there's a lot more clicks and pops + * involved here than on first playback. Fiddling with + * tons of different settings didn't help (DMA, speaker on/off, + * reordering, ...). Something seems to get enabled on playback + * that I haven't found out how to disable again, which then causes + * the switching pops to reach the speakers the next time here. */ spin_lock_irqsave(&chip->reg_lock, flags); snd_als4000_set_rate(chip, runtime->rate); snd_als4000_set_playback_dma(chip, runtime->dma_addr, size); - snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON); + /* SPEAKER_ON not needed, since dma_on seems to also enable speaker */ + /* snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON); */ snd_sbdsp_command(chip, playback_cmd(chip).dsp_cmd); snd_sbdsp_command(chip, playback_cmd(chip).format); snd_sbdsp_command(chip, count); @@ -359,9 +380,9 @@ spin_unlock_irqrestore(&chip->mixer_lock, flags); if (sb_status & SB_IRQTYPE_8BIT) - inb(SBP(chip, DATA_AVAIL)); + snd_sb_ack_8bit(chip); if (sb_status & SB_IRQTYPE_16BIT) - inb(SBP(chip, DATA_AVAIL_16)); + snd_sb_ack_16bit(chip); if (sb_status & SB_IRQTYPE_MPUIN) inb(chip->mpu_port); if (sb_status & 0x20) @@ -547,14 +568,14 @@ spin_unlock_irqrestore(&chip->reg_lock,flags); } -static void snd_card_als4k_free( snd_card_t *card ) +static void snd_card_als4000_free( snd_card_t *card ) { snd_card_als4000_t * acard = (snd_card_als4000_t *)card->private_data; /* make sure that interrupts are disabled */ snd_als4000_gcr_write_addr( acard->gcr, 0x8c, 0); } -static int __devinit snd_card_als4k_probe(struct pci_dev *pci, +static int __devinit snd_card_als4000_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; @@ -608,7 +629,7 @@ acard = (snd_card_als4000_t *)card->private_data; acard->gcr = gcr; - card->private_free = snd_card_als4k_free; + card->private_free = snd_card_als4000_free; if ((err = snd_sbdsp_create(card, gcr + 0x10, @@ -672,7 +693,7 @@ return 0; } -static void __devexit snd_card_als4k_remove(struct pci_dev *pci) +static void __devexit snd_card_als4000_remove(struct pci_dev *pci) { snd_card_free(pci_get_drvdata(pci)); pci_set_drvdata(pci, NULL); @@ -681,11 +702,11 @@ static struct pci_driver driver = { .name = "ALS4000", .id_table = snd_als4000_ids, - .probe = snd_card_als4k_probe, - .remove = __devexit_p(snd_card_als4k_remove), + .probe = snd_card_als4000_probe, + .remove = __devexit_p(snd_card_als4000_remove), }; -static int __init alsa_card_als4k_init(void) +static int __init alsa_card_als4000_init(void) { int err; @@ -698,13 +719,13 @@ return 0; } -static void __exit alsa_card_als4k_exit(void) +static void __exit alsa_card_als4000_exit(void) { pci_unregister_driver(&driver); } -module_init(alsa_card_als4k_init) -module_exit(alsa_card_als4k_exit) +module_init(alsa_card_als4000_init) +module_exit(alsa_card_als4000_exit) #ifndef MODULE ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ Alsa-devel mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/alsa-devel