Commit 215b6771 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA update

  - ALS4000 - improved mixer support
  - ICE1712 - added ICE1724 (Envy24HT code)
            - fixed Delta410 support
  - usbaudio - added quirks for more Yamaha devices
parent a58bec86
......@@ -225,7 +225,6 @@ typedef struct _snd_sb sb_t;
#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
......@@ -235,6 +234,14 @@ typedef struct _snd_sb sb_t;
#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
#define SB_IRQSETUP_IRQ5 0x02
......
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc5"
#define CONFIG_SND_DATE " (Sat Nov 23 10:12:47 2002 UTC)"
#define CONFIG_SND_VERSION "0.9.0rc6"
#define CONFIG_SND_DATE " (Thu Dec 05 10:04:08 2002 UTC)"
......@@ -106,7 +106,7 @@ int snd_pcm_update_hw_ptr_interrupt(snd_pcm_substream_t *substream)
if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP)
snd_timestamp_now((snd_timestamp_t*)&runtime->status->tstamp);
#ifdef CONFIG_SND_DEBUG
if (pos > runtime->buffer_size) {
if (pos >= runtime->buffer_size) {
snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
} else
#endif
......@@ -172,7 +172,7 @@ int snd_pcm_update_hw_ptr(snd_pcm_substream_t *substream)
if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP)
snd_timestamp_now((snd_timestamp_t*)&runtime->status->tstamp);
#ifdef CONFIG_SND_DEBUG
if (pos > runtime->buffer_size) {
if (pos >= runtime->buffer_size) {
snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
} else
#endif
......
......@@ -428,13 +428,22 @@ static int snd_sb16mixer_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
return change;
}
#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)
#define SB20_CONTROLS (sizeof(snd_sb20_controls)/sizeof(snd_kcontrol_new_t *))
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 @@ static unsigned char snd_sb20_init_values[][2] = {
{ SB_DSP20_FM_DEV, 0 },
};
#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)
#define SBPRO_CONTROLS (sizeof(snd_sbpro_controls)/sizeof(snd_kcontrol_new_t *))
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 @@ static unsigned char snd_sbpro_init_values[][2] = {
{ SB_DSP_FM_DEV, 0 },
};
#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)
#define SB16_CONTROLS (sizeof(snd_sb16_controls)/sizeof(snd_kcontrol_new_t *))
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 @@ static unsigned char snd_sb16_init_values[][2] = {
{ SB_DSP4_SPEAKER_DEV, 0 },
};
#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,
},
#define DT019X_CONTROLS (sizeof(snd_dt019x_controls)/sizeof(snd_kcontrol_new_t *))
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 @@ static unsigned char snd_dt019x_init_values[][2] = {
{ 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 @@ static int snd_sbmixer_init(sb_t *chip,
}
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,13 +784,19 @@ int snd_sbmixer_new(sb_t *chip)
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:
if ((err = snd_sbmixer_init(chip,
snd_dt019x_controls, DT019X_CONTROLS,
......
......@@ -2,6 +2,7 @@
* card-als4000.c - driver for Avance Logic ALS4000 based soundcards.
* Copyright (C) 2000 by Bart Hartgers <bart@etpmod.phys.tue.nl>,
* Jaroslav Kysela <perex@suse.cz>
* Copyright (C) 2002 by Andreas Mohr <hw7oshyuv3001@sneakemail.com>
*
* 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 @@ static int snd_als4000_playback_prepare(snd_pcm_substream_t *substream)
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 @@ static void snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
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 @@ static void __devinit snd_als4000_configure(sb_t *chip)
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 @@ static int __devinit snd_card_als4k_probe(struct pci_dev *pci,
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 @@ static int __devinit snd_card_als4k_probe(struct pci_dev *pci,
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 void __devexit snd_card_als4k_remove(struct pci_dev *pci)
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 @@ static int __init alsa_card_als4k_init(void)
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
......
......@@ -985,7 +985,7 @@ static void snd_es1938_free_pcm(snd_pcm_t *pcm)
snd_pcm_lib_preallocate_free_for_all(pcm);
}
static int __init snd_es1938_new_pcm(es1938_t *chip, int device, snd_pcm_t ** rpcm)
static int __devinit snd_es1938_new_pcm(es1938_t *chip, int device, snd_pcm_t ** rpcm)
{
snd_pcm_t *pcm;
int err;
......@@ -1364,7 +1364,7 @@ static int snd_es1938_dev_free(snd_device_t *device)
return snd_es1938_free(chip);
}
static int __init snd_es1938_create(snd_card_t * card,
static int __devinit snd_es1938_create(snd_card_t * card,
struct pci_dev * pci,
unsigned long dma1size,
unsigned long dma2size,
......@@ -1541,7 +1541,7 @@ static void snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#define ES1938_DMA_SIZE 64
static int __init snd_es1938_mixer(snd_pcm_t *pcm)
static int __devinit snd_es1938_mixer(snd_pcm_t *pcm)
{
snd_card_t *card;
es1938_t *chip;
......
......@@ -5,7 +5,7 @@
export-objs := ice1712.o
snd-ice1712-objs := ice1712.o ak4524.o delta.o hoontech.o ews.o
snd-ice1712-objs := ice1712.o ak4524.o delta.o hoontech.o ews.o amp.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o
......
......@@ -65,10 +65,8 @@ void snd_ice1712_ak4524_write(ice1712_t *ice, int chip,
tmp |= ak->cs_addr;
}
addr &= 0x07;
/* build I2C address + data byte */
/* assume C1=1, C0=0 */
addrdata = 0xa000 | (addr << 8) | data;
addrdata = (ak->caddr << 14) | 0x2000 | ((addr & 0x0f) << 8) | data;
for (idx = 15; idx >= 0; idx--) {
tmp &= ~(ak->data_mask | ak->clk_mask);
if (addrdata & (1 << idx))
......@@ -86,6 +84,9 @@ void snd_ice1712_ak4524_write(ice1712_t *ice, int chip,
ak->images[chip][addr] = data;
else
ak->ipga_gain[chip][addr-4] = data;
} else {
/* AK4529 */
ak->images[chip][addr] = data;
}
if (ak->cs_mask == ak->cs_addr) {
......@@ -170,7 +171,7 @@ void __devinit snd_ice1712_ak4524_init(ice1712_t *ice)
static unsigned char inits_ak4529[] = {
0x09, 0x01, /* 9: ATS=0, RSTN=1 */
0x0a, 0x3f, /* A: all power up, no zero/overflow detection */
0x00, 0x08, /* 0: TDM=0, 24bit I2S, SMUTE=0 */
0x00, 0x0c, /* 0: TDM=0, 24bit I2S, SMUTE=0 */
0x01, 0x00, /* 1: ACKS=0, ADC, loop off */
0x02, 0xff, /* 2: LOUT1 muted */
0x03, 0xff, /* 3: ROUT1 muted */
......@@ -217,14 +218,17 @@ void __devinit snd_ice1712_ak4524_init(ice1712_t *ice)
#define AK_GET_CHIP(val) (((val) >> 8) & 0xff)
#define AK_GET_ADDR(val) ((val) & 0xff)
#define AK_GET_SHIFT(val) (((val) >> 16) & 0xff)
#define AK_COMPOSE(chip,addr,shift) (((chip) << 8) | (addr) | ((shift) << 16))
#define AK_GET_MASK(val) (((val) >> 24) & 0xff)
#define AK_COMPOSE(chip,addr,shift,mask) (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24))
static int snd_ice1712_ak4524_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
unsigned int mask = AK_GET_MASK(kcontrol->private_value);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 127;
uinfo->value.integer.max = mask;
return 0;
}
......@@ -233,7 +237,8 @@ static int snd_ice1712_ak4524_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
ucontrol->value.integer.value[0] = ice->ak4524.images[chip][addr];
unsigned int mask = AK_GET_MASK(kcontrol->private_value);
ucontrol->value.integer.value[0] = mask - ice->ak4524.images[chip][addr];
return 0;
}
......@@ -242,7 +247,8 @@ static int snd_ice1712_ak4524_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
unsigned char nval = ucontrol->value.integer.value[0];
unsigned int mask = AK_GET_MASK(kcontrol->private_value);
unsigned char nval = mask - (ucontrol->value.integer.value[0] % (mask+1));
int change = ice->ak4524.images[chip][addr] != nval;
if (change)
snd_ice1712_ak4524_write(ice, chip, addr, nval);
......@@ -340,14 +346,14 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
ctl.put = snd_ice1712_ak4524_volume_put;
switch (ak->type) {
case SND_AK4524:
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0); /* register 6 & 7 */
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */
break;
case SND_AK4528:
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0); /* register 4 & 5 */
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */
break;
case SND_AK4529: {
int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; /* registers 2-7 and b,c */
ctl.private_value = AK_COMPOSE(0, val, 0);
ctl.private_value = AK_COMPOSE(0, val, 0, 255);
break;
}
}
......@@ -365,7 +371,7 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
ctl.access = SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE;
ctl.get = snd_ice1712_ak4524_volume_get;
ctl.put = snd_ice1712_ak4524_volume_put;
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0); /* register 4 & 5 */
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */
ctl.private_data = ice;
if ((err = snd_ctl_add(ice->card, snd_ctl_new(&ctl))) < 0)
return err;
......@@ -377,7 +383,7 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
ctl.access = SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE;
ctl.get = snd_ice1712_ak4524_ipga_gain_get;
ctl.put = snd_ice1712_ak4524_ipga_gain_put;
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0); /* register 4 & 5 */
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); /* register 4 & 5 */
ctl.private_data = ice;
if ((err = snd_ctl_add(ice->card, snd_ctl_new(&ctl))) < 0)
return err;
......@@ -395,11 +401,11 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
switch (ak->type) {
case SND_AK4524:
case SND_AK4528:
ctl.private_value = AK_COMPOSE(idx, 3, 0); /* register 3 */
ctl.private_value = AK_COMPOSE(idx, 3, 0, 0); /* register 3 */
break;
case SND_AK4529: {
int shift = idx == 3 ? 6 : (2 - idx) * 2;
ctl.private_value = AK_COMPOSE(0, 8, shift); /* register 8 with shift */
ctl.private_value = AK_COMPOSE(0, 8, shift, 0); /* register 8 with shift */
break;
}
}
......
/*
* ALSA driver for ICEnsemble VT1724 (Envy24HT)
*
* Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000
*
* Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <sound/driver.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <sound/core.h>
#include "ice1712.h"
#include "amp.h"
static int __devinit snd_vt1724_amp_init(ice1712_t *ice)
{
/* only use basic functionality for now */
ice->num_total_dacs = 2; /* only PSDOUT0 is connected */
return 0;
}
/* entry point */
struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
{
VT1724_SUBDEVICE_AUDIO2000,
"AMP Ltd AUDIO2000",
snd_vt1724_amp_init,
},
{ } /* terminator */
};
#ifndef __SOUND_AMP_H
#define __SOUND_AMP_H
/*
* ALSA driver for VIA VT1724 (Envy24HT)
*
* Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000
*
* Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#define AMP_AUDIO2000_DEVICE_DESC "{AMP Ltd AUDIO2000},"
#define VT1724_SUBDEVICE_AUDIO2000 0x12142417 /* Advanced Micro Peripherals Ltd AUDIO2000 */
extern struct snd_ice1712_card_info snd_vt1724_amp_cards[];
#endif /* __SOUND_AMP_H */
......@@ -383,9 +383,11 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
case ICE1712_SUBDEVICE_DELTA410:
ak->num_adcs = ak->num_dacs = 2;
ak->type = SND_AK4528;
ak->caddr = 2;
if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA410) {
ak->num_dacs = 8;
ak->type = SND_AK4529;
ak->caddr = 0;
}
ak->cif = 0; /* the default level of the CIF pin from AK4528/4529 */
ak->data_mask = ICE1712_DELTA_AP_DOUT;
......@@ -400,6 +402,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
case ICE1712_SUBDEVICE_DELTA1010LT:
ak->num_adcs = ak->num_dacs = 8;
ak->type = SND_AK4524;
ak->caddr = 2;
ak->cif = 0; /* the default level of the CIF pin from AK4524 */
ak->data_mask = ICE1712_DELTA_1010LT_DOUT;
ak->clk_mask = ICE1712_DELTA_1010LT_CCLK;
......@@ -415,6 +418,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
case ICE1712_SUBDEVICE_DELTA44:
ak->num_adcs = ak->num_dacs = 4;
ak->type = SND_AK4524;
ak->caddr = 2;
ak->cif = 0; /* the default level of the CIF pin from AK4524 */
ak->data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA;
ak->clk_mask = ICE1712_DELTA_CODEC_SERIAL_CLOCK;
......
#ifndef __SOUND_VT1724_H
#define __SOUND_VT1724_H
/*
* ALSA driver for ICEnsemble VT1724 (Envy24)
*
* Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <sound/control.h>
#include <sound/ac97_codec.h>
#include <sound/rawmidi.h>
#include <sound/i2c.h>
#include <sound/pcm.h>
#include "ice1712.h"
/*
* Direct registers
*/
#define ICEREG1724(ice, x) ((ice)->port + VT1724_REG_##x)
#define VT1724_REG_CONTROL 0x00 /* byte */
#define VT1724_RESET 0x80 /* reset whole chip */
#define VT1724_REG_IRQMASK 0x01 /* byte */
#define VT1724_IRQ_MPU_RX 0x80
#define VT1724_IRQ_MPU_TX 0x20
#define VT1724_IRQ_MTPCM 0x10
#define VT1724_REG_IRQSTAT 0x02 /* byte */
/* look to VT1724_IRQ_* */
#define VT1724_REG_SYS_CFG 0x04 /* byte - system configuration PCI60 on Envy24*/
#define VT1724_CFG_CLOCK 0xc0
#define VT1724_CFG_CLOCK512 0x00 /* 22.5692Mhz, 44.1kHz*512 */
#define VT1724_CFG_CLOCK384 0x40 /* 16.9344Mhz, 44.1kHz*384 */
#define VT1724_CFG_MPU401 0x20 /* MPU401 UARTs */
#define VT1724_CFG_ADC_MASK 0x0c /* one, two or one and S/PDIF, stereo ADCs */
#define VT1724_CFG_DAC_MASK 0x03 /* one, two, three, four stereo DACs */
#define VT1724_REG_AC97_CFG 0x05 /* byte */
#define VT1724_CFG_PRO_I2S 0x80 /* multitrack converter: I2S or AC'97 */
#define VT1724_CFG_AC97_PACKED 0x01 /* split or packed mode - AC'97 */
#define VT1724_REG_I2S_FEATURES 0x06 /* byte */
#define VT1724_CFG_I2S_VOLUME 0x80 /* volume/mute capability */
#define VT1724_CFG_I2S_96KHZ 0x40 /* supports 96kHz sampling */
#define VT1724_CFG_I2S_RESMASK 0x30 /* resolution mask, 16,18,20,24-bit */
#define VT1724_CFG_I2S_192KHZ 0x08 /* supports 192kHz sampling */
#define VT1724_CFG_I2S_OTHER 0x07 /* other I2S IDs */
#define VT1724_REG_SPDIF_CFG 0x07 /* byte */
#define VT1724_CFG_SPDIF_OUT_EN 0x80 /*Internal S/PDIF output is enabled*/
#define VT1724_CFG_SPDIF_OUT_INT 0x40 /*Internal S/PDIF output is implemented*/
#define VT1724_CFG_I2S_CHIPID 0x3c /* I2S chip ID */
#define VT1724_CFG_SPDIF_IN 0x02 /* S/PDIF input is present */
#define VT1724_CFG_SPDIF_OUT 0x01 /* External S/PDIF output is present */
/*there is no consumer AC97 codec with the VT1724*/
//#define VT1724_REG_AC97_INDEX 0x08 /* byte */
//#define VT1724_REG_AC97_CMD 0x09 /* byte */
#define VT1724_AC97_COLD 0x80 /* cold reset */
#define VT1724_AC97_WARM 0x40 /* warm reset */
#define VT1724_AC97_WRITE 0x20 /* W: write, R: write in progress */
#define VT1724_AC97_READ 0x10 /* W: read, R: read in progress */
#define VT1724_AC97_READY 0x08 /* codec ready status bit */
#define VT1724_AC97_PBK_VSR 0x02 /* playback VSR */
#define VT1724_AC97_CAP_VSR 0x01 /* capture VSR */
#define VT1724_REG_MPU_TXFIFO 0x0a /*byte ro. number of bytes in TX fifo*/
#define VT1724_REG_MPU_RXFIFO 0x0b /*byte ro. number of bytes in RX fifo*/
//are these 2 the wrong way around? they don't seem to be used yet anyway
#define VT1724_REG_MPU_CTRL 0x0c /* byte */
#define VT1724_REG_MPU_DATA 0x0d /* byte */
#define VT1724_REG_MPU_FIFO_WM 0x0e /*byte set the high/low watermarks for RX/TX fifos*/
#define VT1724_MPU_RX_FIFO 0x20 //1=rx fifo watermark 0=tx fifo watermark
#define VT1724_MPU_FIFO_MASK 0x1f
#define VT1724_REG_I2C_DEV_ADDR 0x10 /* byte */
#define VT1724_I2C_WRITE 0x01 /* write direction */
#define VT1724_REG_I2C_BYTE_ADDR 0x11 /* byte */
#define VT1724_REG_I2C_DATA 0x12 /* byte */
#define VT1724_REG_I2C_CTRL 0x13 /* byte */
#define VT1724_I2C_EEPROM 0x80 /* EEPROM exists */
#define VT1724_I2C_BUSY 0x01 /* busy bit */
#define VT1724_REG_GPIO_DATA 0x14 /* word */
#define VT1724_REG_GPIO_WRITE_MASK 0x15 /* word */
#define VT1724_REG_GPIO_DIRECTION 0x16 /* dword? (3 bytes) 0=input 1=output.
bit3 - during reset used for Eeprom power-on strapping
if TESTEN# pin active, bit 2 always input*/
#define VT1724_REG_POWERDOWN 0x1c
#define VT1724_REG_GPIO_DIRECTION_22 0x1e /* byte direction for GPIO 16:22 */
#define VT1724_REG_GPIO_WRITE_MASK_22 0x1f /* byte write mask for GPIO 16:22 */
/*
* Professional multi-track direct control registers
*/
#define ICEMT1724(ice, x) ((ice)->profi_port + VT1724_MT_##x)
#define VT1724_MT_IRQ 0x00 /* byte - interrupt mask */
#define VT1724_MULTI_PDMA4 0x80 /* SPDIF Out / PDMA4 */
#define VT1724_MULTI_PDMA3 0x40 /* PDMA3 */
#define VT1724_MULTI_PDMA2 0x20 /* PDMA2 */
#define VT1724_MULTI_PDMA1 0x10 /* PDMA1 */
#define VT1724_MULTI_FIFO_ERR 0x08 /* DMA FIFO underrun/overrun. */
#define VT1724_MULTI_RDMA1 0x04 /* RDMA1 (S/PDIF input) */
#define VT1724_MULTI_RDMA0 0x02 /* RMDA0 */
#define VT1724_MULTI_PDMA0 0x01 /* MC Interleave/PDMA0 */
#define VT1724_MT_RATE 0x01 /* byte - sampling rate select */
#define VT1724_SPDIF_MASTER 0x10 /* S/PDIF input is master clock */
#define VT1724_MT_I2S_FORMAT 0x02 /* byte - I2S data format */
#define VT1724_MT_DMA_INT_MASK 0x03 /* byte -DMA Interrupt Mask */
/* lool to VT1724_MULTI_* */
#define VT1724_MT_AC97_INDEX 0x04 /* byte - AC'97 index */
#define VT1724_MT_AC97_CMD 0x05 /* byte - AC'97 command & status */
/* look to VT1724_AC97_* */
#define VT1724_MT_AC97_DATA 0x06 /* word - AC'97 data */
#define VT1724_MT_PLAYBACK_ADDR 0x10 /* dword - playback address */
#define VT1724_MT_PLAYBACK_SIZE 0x14 /* dword - playback size */
#define VT1724_MT_PLAYBACK_CONTROL 0x18 /* byte - control */
#define VT1724_PDMA4_START 0x80 /* SPDIF out / PDMA4 start */
#define VT1724_PDMA3_START 0x40 /* PDMA3 start */
#define VT1724_PDMA2_START 0x20 /* PDMA2 start */
#define VT1724_PDMA1_START 0x10 /* PDMA1 start */
#define VT1724_RDMA1_START 0x04 /* RDMA1 start */
#define VT1724_RDMA0_START 0x02 /* RMDA0 start */
#define VT1724_PDMA0_START 0x01 /* MC Interleave / PDMA0 start */
#define VT1724_MT_BURST 0x19 /* Interleaved playback DMA Active streams / PCI burst size */
#define VT1724_MT_DMA_FIFO_ERR 0x1a /*Global playback and record DMA FIFO Underrun/Overrun */
#define VT1724_PDMA4_UNDERRUN 0x80
#define VT1724_PDMA2_UNDERRUN 0x40
#define VT1724_PDMA3_UNDERRUN 0x20
#define VT1724_PDMA1_UNDERRUN 0x10
#define VT1724_RDMA1_UNDERRUN 0x04
#define VT1724_RDMA0_UNDERRUN 0x02
#define VT1724_PDMA0_UNDERRUN 0x01
#define VT1724_MT_DMA_PAUSE 0x1b /*Global playback and record DMA FIFO pause/resume */
#define VT1724_PDMA4_PAUSE 0x80
#define VT1724_PDMA3_PAUSE 0x40
#define VT1724_PDMA2_PAUSE 0x20
#define VT1724_PDMA1_PAUSE 0x10
#define VT1724_RDMA1_PAUSE 0x04
#define VT1724_RDMA0_PAUSE 0x02
#define VT1724_PDMA0_PAUSE 0x01
#define VT1724_MT_PLAYBACK_COUNT 0x1c /* word - playback count */
#define VT1724_MT_CAPTURE_ADDR 0x20 /* dword - capture address */
#define VT1724_MT_CAPTURE_SIZE 0x24 /* word - capture size */
#define VT1724_MT_CAPTURE_COUNT 0x26 /* word - capture count */
#define VT1724_MT_RDMA1_ADDR 0x30 /* dword - RDMA1 capture address */
#define VT1724_MT_RDMA1_SIZE 0x34 /* word - RDMA1 capture size */
#define VT1724_MT_RDMA1_COUNT 0x36 /* word - RDMA1 capture count */
#define VT1724_MT_ROUTE_PLAYBACK 0x2c /* word */
//#define VT1724_MT_MONITOR_VOLUME 0x3f /* word */
//#define VT1724_MT_MONITOR_INDEX 0x3e /* byte */
#define VT1724_MT_PDMA4_ADDR 0x40 /* dword */
#define VT7124_MT_PDMA4_SIZE 0x44 /* word */
#define VT1724_MT_PDMA4_COUNT 0x46 /* word */
#define VT1724_MT_PDMA3_ADDR 0x50 /* dword */
#define VT7124_MT_PDMA3_SIZE 0x54 /* word */
#define VT1724_MT_PDMA3_COUNT 0x56 /* word */
#define VT1724_MT_PDMA2_ADDR 0x60 /* dword */
#define VT7124_MT_PDMA2_SIZE 0x64 /* word */
#define VT1724_MT_PDMA2_COUNT 0x66 /* word */
#define VT1724_MT_PDMA1_ADDR 0x70 /* dword */
#define VT7124_MT_PDMA1_SIZE 0x74 /* word */
#define VT1724_MT_PDMA1_COUNT 0x76 /* word */
//does VT1724 have these? don't think so
//#define VT1724_MT_MONITOR_RATE 0x3b /* byte */
//#define VT1724_MT_MONITOR_ROUTECTRL 0x3c /* byte */
//#define VT1724_ROUTE_AC97 0x01 /* route digital mixer output to AC'97 */
#define VT1724_MT_MONITOR_PEAKINDEX 0x3e /* byte */
#define VT1724_MT_MONITOR_PEAKDATA 0x3f /* byte */
#endif /* __SOUND_VT1724_H */
......@@ -405,6 +405,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
case ICE1712_SUBDEVICE_EWS88MT:
ak->num_adcs = ak->num_dacs = 8;
ak->type = SND_AK4524;
ak->caddr = 2;
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_EWS88_SERIAL_DATA;
ak->clk_mask = ICE1712_EWS88_SERIAL_CLOCK;
......@@ -418,6 +419,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
case ICE1712_SUBDEVICE_EWX2496:
ak->num_adcs = ak->num_dacs = 2;
ak->type = SND_AK4524;
ak->caddr = 2;
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_EWS88_SERIAL_DATA;
ak->clk_mask = ICE1712_EWS88_SERIAL_CLOCK;
......@@ -431,6 +433,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
case ICE1712_SUBDEVICE_DMX6FIRE:
ak->num_adcs = ak->num_dacs = 6;
ak->type = SND_AK4524;
ak->caddr = 2;
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_6FIRE_SERIAL_DATA;
ak->clk_mask = ICE1712_6FIRE_SERIAL_CLOCK;
......
......@@ -32,6 +32,11 @@
* split the code to several files. each low-level routine
* is stored in the local file and called from registration
* function from card_info struct.
*
* 2002.11.26 James Stafford <jstafford@ampltd.com>
* Added support for VT1724 (Envy24HT)
* I have left out support for 176.4 and 192 KHz for the moment.
* I also haven't done anything with the internal S/PDIF transmitter or the MPU-401
*/
......@@ -52,11 +57,13 @@
#include <sound/asoundef.h>
#include "ice1712.h"
#include "envy24ht.h"
/* lowlevel routines */
#include "delta.h"
#include "ews.h"
#include "hoontech.h"
#include "amp.h"
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("ICEnsemble ICE1712 (Envy24)");
......@@ -66,8 +73,11 @@ MODULE_DEVICES("{"
HOONTECH_DEVICE_DESC
DELTA_DEVICE_DESC
EWS_DEVICE_DESC
AMP_AUDIO2000_DEVICE_DESC
"{ICEnsemble,Generic ICE1712},"
"{ICEnsemble,Generic Envy24}}");
"{ICEnsemble,Generic Envy24},"
"{ICEnsemble,Generic ICE1724},"
"{ICEnsemble,Generic Envy24HT}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
......@@ -93,9 +103,13 @@ MODULE_PARM_SYNTAX(omni, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
#ifndef PCI_DEVICE_ID_ICE_1712
#define PCI_DEVICE_ID_ICE_1712 0x1712
#endif
#ifndef PCI_DEVICE_ID_VT1724
#define PCI_DEVICE_ID_VT1724 0x1724
#endif
static struct pci_device_id snd_ice1712_ids[] __devinitdata = {
{ PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ICE1712 */
{ PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_VT1724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* VT1724 */
{ 0, }
};
......@@ -286,26 +300,67 @@ static snd_kcontrol_new_t snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
void snd_ice1712_gpio_write_bits(ice1712_t *ice, int mask, int bits)
{
ice->gpio_direction |= mask;
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, ice->gpio_direction);
snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~mask);
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, mask & bits);
if (ice->vt1724) {
outw(ice->gpio_direction, ICEREG1724(ice, GPIO_DIRECTION));
outb((ice->gpio_direction&0xff0000)>>16, ICEREG1724(ice, GPIO_DIRECTION_22));
outw(~mask, ICEREG1724(ice, GPIO_WRITE_MASK));
outb((~mask & 0xff0000)>>16, ICEREG1724(ice, GPIO_WRITE_MASK_22));
outl(mask & bits, ICEREG1724(ice, GPIO_DATA));
}
else {
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, ice->gpio_direction);
snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~mask);
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, mask & bits);
}
}
/*
*/
/*
the VT1724 has 23 GPIO pins, so need 3 bytes for direction and 3 bytes for write mask
*/
void snd_ice1712_save_gpio_status(ice1712_t *ice, unsigned char *tmp)
{
down(&ice->gpio_mutex);
tmp[0] = ice->gpio_direction;
tmp[1] = ice->gpio_write_mask;
if (ice->vt1724) {
tmp[0] = ice->gpio_direction & 0xff;
tmp[1] = (ice->gpio_direction &0xff00)>>8;
tmp[2] = (ice->gpio_direction &0xff0000)>>16;
tmp[3] = ice->gpio_write_mask & 0xff;
tmp[4] = (ice->gpio_write_mask &0xff00)>>8;
tmp[5] = (ice->gpio_write_mask &0xff0000)>>16;
}
else {
tmp[0] = ice->gpio_direction;
tmp[1] = ice->gpio_write_mask;
}
}
void snd_ice1712_restore_gpio_status(ice1712_t *ice, unsigned char *tmp)
{
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, tmp[0]);
snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, tmp[1]);
ice->gpio_direction = tmp[0];
ice->gpio_write_mask = tmp[1];
if (ice->vt1724) {
outw(tmp[0] | ((tmp[1]&0xff00)<<8), ICEREG1724(ice, GPIO_DIRECTION));
outb(tmp[2], ICEREG1724(ice, GPIO_DIRECTION_22));
outw(tmp[3] | ((tmp[4]&0xff00)<<8), ICEREG1724(ice, GPIO_WRITE_MASK));
outb(tmp[5], ICEREG1724(ice, GPIO_WRITE_MASK_22));
ice->gpio_direction=tmp[0] | ((tmp[1]<<8)&0xff00) |((tmp[2]<<16)&0xff0000);
ice->gpio_write_mask=tmp[3] | ((tmp[4]<<8)&0xff00) |((tmp[5]<<16)&0xff0000);
}
else {
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, tmp[0]);
snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, tmp[1]);
ice->gpio_direction = tmp[0];
ice->gpio_write_mask = tmp[1];
}
up(&ice->gpio_mutex);
}
......@@ -459,6 +514,48 @@ static void snd_ice1712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
static void snd_vt1724_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
ice1712_t *ice = snd_magic_cast(ice1712_t, dev_id, return);
unsigned char status;
while (1) {
status = inb(ICEREG(ice, IRQSTAT));
if (status == 0)
break;
/* these should probably be separated at some point,
but as we don't currently have MPU support on the board I will leave it */
if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) {
if (ice->rmidi[0])
snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data, regs);
outb(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX, ICEREG(ice, IRQSTAT));
status &= ~(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX);
}
if (status & VT1724_IRQ_MTPCM) {
unsigned char mtstat = inb(ICEMT(ice, IRQ));
if (mtstat & VT1724_MULTI_PDMA0) {
if (ice->playback_pro_substream)
snd_pcm_period_elapsed(ice->playback_pro_substream);
outb(VT1724_MULTI_PDMA0, ICEMT(ice, IRQ));
}
if (mtstat & VT1724_MULTI_RDMA0) {
if (ice->capture_pro_substream)
snd_pcm_period_elapsed(ice->capture_pro_substream);
outb(VT1724_MULTI_RDMA0, ICEMT(ice, IRQ));
}
/* ought to really handle this properly */
if (mtstat & VT1724_MULTI_FIFO_ERR) {
unsigned char fstat = inb(ICEMT1724(ice, DMA_FIFO_ERR));
outb(fstat, ICEMT1724(ice, DMA_FIFO_ERR));
outb(VT1724_MULTI_FIFO_ERR | inb(ICEMT1724(ice, DMA_INT_MASK)), ICEMT1724(ice, DMA_INT_MASK));
/* If I don't do this, I get machine lockup due to continual interrupts */
}
}
}
}
/*
* PCM part - misc
*/
......@@ -939,16 +1036,30 @@ static int snd_ice1712_pro_trigger(snd_pcm_substream_t *substream,
unsigned int old;
if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
return -EINVAL;
what = ICE1712_PLAYBACK_PAUSE;
snd_pcm_trigger_done(substream, substream);
spin_lock(&ice->reg_lock);
old = inl(ICEMT(ice, PLAYBACK_CONTROL));
if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)
old |= what;
else
old &= ~what;
outl(old, ICEMT(ice, PLAYBACK_CONTROL));
spin_unlock(&ice->reg_lock);
if (ice->vt1724) {
what = VT1724_PDMA0_PAUSE;
snd_pcm_trigger_done(substream, substream);
spin_lock(&ice->reg_lock);
old = inl(ICEMT1724(ice, DMA_PAUSE));
if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)
old |= what;
else
old &= ~what;
outl(old, ICEMT1724(ice, DMA_PAUSE));
spin_unlock(&ice->reg_lock);
}
else {
what = ICE1712_PLAYBACK_PAUSE;
snd_pcm_trigger_done(substream, substream);
spin_lock(&ice->reg_lock);
old = inl(ICEMT(ice, PLAYBACK_CONTROL));
if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)
old |= what;
else
old &= ~what;
outl(old, ICEMT(ice, PLAYBACK_CONTROL));
spin_unlock(&ice->reg_lock);
}
break;
}
case SNDRV_PCM_TRIGGER_START:
......@@ -957,12 +1068,16 @@ static int snd_ice1712_pro_trigger(snd_pcm_substream_t *substream,
unsigned int what = 0;
unsigned int old;
snd_pcm_substream_t *s = substream;
do {
if (s == ice->playback_pro_substream) {
what |= ICE1712_PLAYBACK_START;
snd_pcm_trigger_done(s, substream);
} else if (s == ice->capture_pro_substream) {
what |= ICE1712_CAPTURE_START_SHADOW;
if (ice->vt1724)
what |= VT1724_RDMA0_START;
else
what |= ICE1712_CAPTURE_START_SHADOW;
snd_pcm_trigger_done(s, substream);
}
s = s->link_next;
......@@ -991,9 +1106,15 @@ static void snd_ice1712_set_pro_rate(ice1712_t *ice, unsigned int rate, int forc
unsigned char val;
spin_lock_irqsave(&ice->reg_lock, flags);
if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW|
if (ice->vt1724 &&
((inb(ICEMT(ice, PLAYBACK_CONTROL)) & (VT1724_RDMA0_START|ICE1712_PLAYBACK_START)) ||
(inb(ICEMT1724(ice, DMA_PAUSE) & VT1724_PDMA0_PAUSE)))) {
spin_unlock_irqrestore(&ice->reg_lock, flags);
return;
}
else if (!ice->vt1724 && (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW|
ICE1712_PLAYBACK_PAUSE|
ICE1712_PLAYBACK_START)) {
ICE1712_PLAYBACK_START))) {
spin_unlock_irqrestore(&ice->reg_lock, flags);
return;
}
......@@ -1037,8 +1158,30 @@ static int snd_ice1712_playback_pro_prepare(snd_pcm_substream_t * substream)
snd_ice1712_set_pro_rate(ice, substream->runtime->rate, 0);
spin_lock(&ice->reg_lock);
outl(substream->runtime->dma_addr, ICEMT(ice, PLAYBACK_ADDR));
outw((ice->playback_pro_size >> 2) - 1, ICEMT(ice, PLAYBACK_SIZE));
outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ICEMT(ice, PLAYBACK_COUNT));
if (ice->vt1724) {
outl((ice->playback_pro_size >> 2) - 1, ICEMT(ice, PLAYBACK_SIZE));
outl((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ICEMT1724(ice, PLAYBACK_COUNT));
switch(substream->runtime->channels)
{
case 8:
outb(0, ICEMT1724(ice, BURST));
break;
case 6:
outb(1, ICEMT1724(ice, BURST));
break;
case 4:
outb(2, ICEMT1724(ice, BURST));
break;
case 2:
outb(3, ICEMT1724(ice, BURST));
break;
}
}
else {
outw((ice->playback_pro_size >> 2) - 1, ICEMT(ice, PLAYBACK_SIZE));
outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ICEMT(ice, PLAYBACK_COUNT));
}
spin_unlock(&ice->reg_lock);
if (ice->spdif.ops.setup)
......@@ -1068,7 +1211,10 @@ static snd_pcm_uframes_t snd_ice1712_playback_pro_pointer(snd_pcm_substream_t *
if (!(inl(ICEMT(ice, PLAYBACK_CONTROL)) & ICE1712_PLAYBACK_START))
return 0;
ptr = ice->playback_pro_size - (inw(ICEMT(ice, PLAYBACK_SIZE)) << 2);
if (ice->vt1724)
ptr = ice->playback_pro_size - ((inl(ICEMT(ice, PLAYBACK_SIZE))&0x7ffff) << 2);
else
ptr = ice->playback_pro_size - (inw(ICEMT(ice, PLAYBACK_SIZE)) << 2);
return bytes_to_frames(substream->runtime, ptr);
}
......@@ -1103,6 +1249,27 @@ static snd_pcm_hardware_t snd_ice1712_playback_pro =
.fifo_size = 0,
};
static snd_pcm_hardware_t snd_vt1724_playback_pro =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START),
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_96000,
.rate_min = 4000,
.rate_max = 96000,
.channels_min = 2,
.channels_max = 8,
.buffer_bytes_max = 0x7ffff0, /* we have 18bits for the buffer size, in dwords */
.period_bytes_min = 8 * 4 * 2,
.period_bytes_max = 131040, /* do we have 18bits for terminal count?
Datasheets says bits 18:0 but only has 2 byte registers (1C-1Dh ) */
.periods_min = 1,
.periods_max = 1024,
.fifo_size = 0,
};
static snd_pcm_hardware_t snd_ice1712_capture_pro =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
......@@ -1123,13 +1290,36 @@ static snd_pcm_hardware_t snd_ice1712_capture_pro =
.fifo_size = 0,
};
static snd_pcm_hardware_t snd_ice1724_capture_pro =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START),
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_96000,
.rate_min = 4000,
.rate_max = 96000,
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = (256*1024),
.period_bytes_min = 2 * 4 * 2,
.period_bytes_max = 131040,
.periods_min = 1,
.periods_max = 1024,
.fifo_size = 0,
};
static int snd_ice1712_playback_pro_open(snd_pcm_substream_t * substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
ice1712_t *ice = snd_pcm_substream_chip(substream);
ice->playback_pro_substream = substream;
runtime->hw = snd_ice1712_playback_pro;
if (ice->vt1724)
runtime->hw = snd_vt1724_playback_pro;
else
runtime->hw = snd_ice1712_playback_pro;
snd_pcm_set_sync(substream);
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
......@@ -1146,7 +1336,10 @@ static int snd_ice1712_capture_pro_open(snd_pcm_substream_t * substream)
snd_pcm_runtime_t *runtime = substream->runtime;
ice->capture_pro_substream = substream;
runtime->hw = snd_ice1712_capture_pro;
if (ice->vt1724)
runtime->hw = snd_ice1724_capture_pro;
else
runtime->hw = snd_ice1712_capture_pro;
snd_pcm_set_sync(substream);
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
......@@ -1336,7 +1529,7 @@ static int snd_ice1712_pro_mixer_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_e
}
static int __init snd_ice1712_build_pro_mixer(ice1712_t *ice)
static int __devinit snd_ice1712_build_pro_mixer(ice1712_t *ice)
{
snd_card_t * card = ice->card;
snd_kcontrol_t ctl;
......@@ -1482,9 +1675,19 @@ static void snd_ice1712_proc_read(snd_info_entry_t *entry,
for (idx = 0x1c; idx < ice->eeprom.size && idx < 0x1c + sizeof(ice->eeprom.extra); idx++)
snd_iprintf(buffer, " Extra #%02i : 0x%x\n", idx, ice->eeprom.extra[idx - 0x1c]);
snd_iprintf(buffer, "\nRegisters:\n");
snd_iprintf(buffer, " PSDOUT03 : 0x%04x\n", (unsigned)inw(ICEMT(ice, ROUTE_PSDOUT03)));
snd_iprintf(buffer, " CAPTURE : 0x%08x\n", inl(ICEMT(ice, ROUTE_CAPTURE)));
snd_iprintf(buffer, " SPDOUT : 0x%04x\n", (unsigned)inw(ICEMT(ice, ROUTE_SPDOUT)));
if (ice->vt1724) {
snd_iprintf(buffer, " PSDOUT03 : 0x%08x\n", (unsigned)inl(ICEMT1724(ice, ROUTE_PLAYBACK)));
for (idx = 0x0; idx < 0x20 ; idx++)
snd_iprintf(buffer, " CCS%02x : 0x%02x\n", idx, inb(ice->port+idx));
for (idx = 0x0; idx < 0x30 ; idx++)
snd_iprintf(buffer, " MT%02x : 0x%02x\n", idx, inb(ice->profi_port+idx));
}
else {
snd_iprintf(buffer, " PSDOUT03 : 0x%04x\n", (unsigned)inw(ICEMT(ice, ROUTE_PSDOUT03)));
snd_iprintf(buffer, " CAPTURE : 0x%08x\n", inl(ICEMT(ice, ROUTE_CAPTURE)));
snd_iprintf(buffer, " SPDOUT : 0x%04x\n", (unsigned)inw(ICEMT(ice, ROUTE_SPDOUT)));
}
}
static void __devinit snd_ice1712_proc_init(ice1712_t * ice)
......@@ -1678,10 +1881,13 @@ int snd_ice1712_gpio_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucont
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
unsigned char mask = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value & (1<<24)) ? 1 : 0;
unsigned char saved[2];
unsigned char saved[6];
snd_ice1712_save_gpio_status(ice, saved);
ucontrol->value.integer.value[0] = (snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & mask ? 1 : 0) ^ invert;
if (ice->vt1724)
ucontrol->value.integer.value[0] = (inb(ICEREG1724(ice, GPIO_DATA)) & mask ? 1 : 0) ^ invert;
else
ucontrol->value.integer.value[0] = (snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & mask ? 1 : 0) ^ invert;
snd_ice1712_restore_gpio_status(ice, saved);
return 0;
}
......@@ -1691,16 +1897,23 @@ int snd_ice1712_gpio_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucont
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
unsigned char mask = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value & (1<<24)) ? mask : 0;
unsigned char saved[2];
unsigned char saved[6];
int val, nval;
if (kcontrol->private_value & (1 << 31))
return -EPERM;
nval = (ucontrol->value.integer.value[0] ? mask : 0) ^ invert;
snd_ice1712_save_gpio_status(ice, saved);
val = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);
nval |= val & ~mask;
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, nval);
if (ice->vt1724) {
val = inb(ICEREG1724(ice, GPIO_DATA));
nval |= val & ~mask;
outb(nval, ICEREG1724(ice, GPIO_DATA));
}
else {
val = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);
nval |= val & ~mask;
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, nval);
}
snd_ice1712_restore_gpio_status(ice, saved);
return val != nval;
}
......@@ -2036,6 +2249,141 @@ static snd_kcontrol_new_t snd_ice1712_mixer_pro_spdif_route __devinitdata = {
};
static int snd_vt1724_pro_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
static char *texts[] = {
"PCM Out", /* 0 */
"H/W In 0", "H/W In 1", /* 1-2 */
"IEC958 In L", "IEC958 In R", /* 3-4 */
};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = 5;//kcontrol->id.index < 2 ? 12 : 11;
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
return 0;
}
static int snd_vt1724_pro_route_analog_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int idx = kcontrol->id.index;
unsigned long val;
unsigned char eitem;
static unsigned char xlate[8] = {
0, 255, 1, 2, 255, 255, 3, 4,
};
val = inl(ICEMT1724(ice, ROUTE_PLAYBACK));
val >>= ((idx % 2) * 12) + ((idx / 2) * 3)+8;
val &= 7; //we now have 3 bits per output
eitem=xlate[val];
if (eitem == 255) {
snd_BUG();
eitem = 0;
}
ucontrol->value.enumerated.item[0] = eitem;
return 0;
}
static int snd_vt1724_pro_route_analog_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int change, shift;
int idx = kcontrol->id.index;
unsigned int val, old_val, nval;
static unsigned char xroute[8] = {
0, /* PCM */
2, /* PSDIN0 Left */
3, /* PSDIN0 Right */
6, /* SPDIN Left */
7, /* SPDIN Right */
};
/* update PSDOUT */
nval=xroute[ucontrol->value.enumerated.item[0]&7];
shift = ((idx % 2) * 12) + ((idx / 2) * 3) +8;
val = old_val = inw(ICEMT1724(ice, ROUTE_PLAYBACK));
val &= ~(0x07 << shift);
val |= nval << shift;
change = val != old_val;
if (change)
outw(val, ICEMT1724(ice, ROUTE_PLAYBACK));
return change;
}
static int snd_vt1724_pro_route_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int idx = kcontrol->id.index;
unsigned long val;
unsigned char eitem;
static unsigned char xlate[8] = {
0, 255, 1, 2, 255, 255, 3, 4,
};
val = inl(ICEMT1724(ice, ROUTE_PLAYBACK));
val >>= idx*3; //I hope this is right
val &= 7;
eitem=xlate[val];
if (eitem == 255) {
snd_BUG();
eitem = 0;
}
ucontrol->value.enumerated.item[0] = eitem;
return 0;
}
static int snd_vt1724_pro_route_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int change, shift;
int idx = kcontrol->id.index;
unsigned long val, old_val, nval;
static unsigned char xroute[8] = {
0, /* PCM */
2, /* PSDIN0 Left */
3, /* PSDIN0 Right */
6, /* SPDIN Left */
7, /* SPDIN Right */
};
/* update SPDOUT */
val = old_val = inl(ICEMT1724(ice, ROUTE_PLAYBACK));
nval = xroute[ucontrol->value.enumerated.item[0]&7];
shift = idx * 2;
val &= ~(0x07 << shift);
val |= nval << shift;
shift = idx * 4 + 8;
change = val != old_val;
if (change)
outl(val, ICEMT1724(ice, ROUTE_PLAYBACK));
return change;
}
static snd_kcontrol_new_t snd_vt1724_mixer_pro_analog_route __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "H/W Playback Route",
.info = snd_vt1724_pro_route_info,
.get = snd_vt1724_pro_route_analog_get,
.put = snd_vt1724_pro_route_analog_put,
};
static snd_kcontrol_new_t snd_vt1724_mixer_pro_spdif_route __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "IEC958 Playback Route",
.info = snd_vt1724_pro_route_info,
.get = snd_vt1724_pro_route_spdif_get,
.put = snd_vt1724_pro_route_spdif_put,
};
static int snd_ice1712_pro_volume_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
......@@ -2144,9 +2492,13 @@ static int __devinit snd_ice1712_read_eeprom(ice1712_t *ice)
return -EIO;
}
ice->eeprom.codec = snd_ice1712_read_i2c(ice, dev, 0x06);
if (ice->vt1724)
ice->eeprom.codec |= ICE1712_CFG_NO_CON_AC97; /* little hack here */
ice->eeprom.aclink = snd_ice1712_read_i2c(ice, dev, 0x07);
ice->eeprom.i2sID = snd_ice1712_read_i2c(ice, dev, 0x08);
ice->eeprom.spdif = snd_ice1712_read_i2c(ice, dev, 0x09);
if (ice->vt1724)
ice->eeprom.spdif &= ~VT1724_CFG_SPDIF_OUT_EN; /* little hack here */
ice->eeprom.gpiomask = snd_ice1712_read_i2c(ice, dev, 0x0a);
ice->eeprom.gpiostate = snd_ice1712_read_i2c(ice, dev, 0x0b);
ice->eeprom.gpiodir = snd_ice1712_read_i2c(ice, dev, 0x0c);
......@@ -2203,6 +2555,27 @@ static int __devinit snd_ice1712_chip_init(ice1712_t *ice)
return 0;
}
static int __devinit snd_vt1724_chip_init(ice1712_t *ice)
{
outb(VT1724_RESET , ICEREG(ice, CONTROL));
udelay(200);
outb(0, ICEREG(ice, CONTROL));
udelay(200);
outb(ice->eeprom.codec, ICEREG1724(ice, SYS_CFG));
outb(ice->eeprom.aclink&0x7f, ICEREG1724(ice, AC97_CFG));
outb(ice->eeprom.i2sID, ICEREG1724(ice, I2S_FEATURES));
outb(ice->eeprom.spdif, ICEREG1724(ice, SPDIF_CFG));
ice->gpio_write_mask = ice->eeprom.gpiomask;
ice->gpio_direction = ice->eeprom.gpiodir;
outb(ice->eeprom.gpiomask, ICEREG1724(ice, GPIO_WRITE_MASK));
outb(ice->eeprom.gpiodir, ICEREG1724(ice, GPIO_DIRECTION));
outb(ice->eeprom.gpiostate, ICEREG1724(ice, GPIO_DATA));
outb(0, ICEREG1724(ice, POWERDOWN));
return 0;
}
int __devinit snd_ice1712_spdif_build_controls(ice1712_t *ice)
{
......@@ -2243,36 +2616,64 @@ static int __devinit snd_ice1712_build_controls(ice1712_t *ice)
err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_pro_internal_clock, ice));
if (err < 0)
return err;
err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_pro_rate_locking, ice));
if (err < 0)
return err;
err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_pro_rate_reset, ice));
if (err < 0)
return err;
for (idx = 0; idx < ice->num_total_dacs; idx++) {
kctl = snd_ctl_new1(&snd_ice1712_mixer_pro_analog_route, ice);
if (kctl == NULL)
return -ENOMEM;
kctl->id.index = idx;
err = snd_ctl_add(ice->card, kctl);
if (ice->vt1724) {
for (idx = 0; idx < ice->num_total_dacs; idx++) {
kctl = snd_ctl_new1(&snd_vt1724_mixer_pro_analog_route, ice);
if (kctl == NULL)
return -ENOMEM;
kctl->id.index = idx;
err = snd_ctl_add(ice->card, kctl);
if (err < 0)
return err;
}
for (idx = 0; idx < 2; idx++) {
kctl = snd_ctl_new1(&snd_vt1724_mixer_pro_spdif_route, ice);
if (kctl == NULL)
return -ENOMEM;
kctl->id.index = idx;
err = snd_ctl_add(ice->card, kctl);
if (err < 0)
return err;
}
err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_pro_peak, ice));
if (err < 0)
return err;
}
for (idx = 0; idx < 2; idx++) {
kctl = snd_ctl_new1(&snd_ice1712_mixer_pro_spdif_route, ice);
if (kctl == NULL)
return -ENOMEM;
kctl->id.index = idx;
err = snd_ctl_add(ice->card, kctl);
else {
err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_pro_rate_locking, ice));
if (err < 0)
return err;
err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_pro_rate_reset, ice));
if (err < 0)
return err;
for (idx = 0; idx < ice->num_total_dacs; idx++) {
kctl = snd_ctl_new1(&snd_ice1712_mixer_pro_analog_route, ice);
if (kctl == NULL)
return -ENOMEM;
kctl->id.index = idx;
err = snd_ctl_add(ice->card, kctl);
if (err < 0)
return err;
}
for (idx = 0; idx < 2; idx++) {
kctl = snd_ctl_new1(&snd_ice1712_mixer_pro_spdif_route, ice);
if (kctl == NULL)
return -ENOMEM;
kctl->id.index = idx;
err = snd_ctl_add(ice->card, kctl);
if (err < 0)
return err;
}
err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_pro_volume_rate, ice));
if (err < 0)
return err;
err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_pro_peak, ice));
if (err < 0)
return err;
}
err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_pro_volume_rate, ice));
if (err < 0)
return err;
err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_pro_peak, ice));
if (err < 0)
return err;
return 0;
}
......@@ -2281,7 +2682,10 @@ static int snd_ice1712_free(ice1712_t *ice)
if (ice->res_port == NULL)
goto __hw_end;
/* mask all interrupts */
outb(0xc0, ICEMT(ice, IRQ));
if (ice->vt1724)
outb(0xff, ICEMT1724(ice, DMA_INT_MASK));
else
outb(0xc0, ICEMT(ice, IRQ));
outb(0xff, ICEREG(ice, IRQMASK));
/* --- */
__hw_end:
......@@ -2332,16 +2736,22 @@ static int __devinit snd_ice1712_create(snd_card_t * card,
/* enable PCI device */
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 28 bits */
if (!pci_dma_supported(pci, 0x0fffffff)) {
snd_printk("architecture does not support 28bit PCI busmaster DMA\n");
return -ENXIO;
/* VT1724 does not have 28bit DMA transfer limit */
if (pci->device==PCI_DEVICE_ID_ICE_1712) {
/* check, if we can restrict PCI DMA transfers to 28 bits */
if (!pci_dma_supported(pci, 0x0fffffff)) {
snd_printk("architecture does not support 28bit PCI busmaster DMA\n");
return -ENXIO;
}
pci_set_dma_mask(pci, 0x0fffffff);
}
pci_set_dma_mask(pci, 0x0fffffff);
else pci_set_dma_mask(pci, 0xffffffff);
ice = snd_magic_kcalloc(ice1712_t, 0, GFP_KERNEL);
if (ice == NULL)
return -ENOMEM;
if (pci->device==PCI_DEVICE_ID_VT1724)
ice->vt1724=1;
ice->omni = omni ? 1 : 0;
spin_lock_init(&ice->reg_lock);
init_MUTEX(&ice->gpio_mutex);
......@@ -2353,60 +2763,105 @@ static int __devinit snd_ice1712_create(snd_card_t * card,
ice->pci = pci;
ice->irq = -1;
ice->port = pci_resource_start(pci, 0);
ice->ddma_port = pci_resource_start(pci, 1);
ice->dmapath_port = pci_resource_start(pci, 2);
ice->profi_port = pci_resource_start(pci, 3);
pci_set_master(pci);
pci_write_config_word(ice->pci, 0x40, 0x807f);
pci_write_config_word(ice->pci, 0x42, 0x0006);
snd_ice1712_proc_init(ice);
synchronize_irq(pci->irq);
if ((ice->res_port = request_region(ice->port, 32, "ICE1712 - Controller")) == NULL) {
snd_ice1712_free(ice);
snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->port, ice->port + 32 - 1);
return -EIO;
}
if ((ice->res_ddma_port = request_region(ice->ddma_port, 16, "ICE1712 - DDMA")) == NULL) {
snd_ice1712_free(ice);
snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->ddma_port, ice->ddma_port + 16 - 1);
return -EIO;
}
if ((ice->res_dmapath_port = request_region(ice->dmapath_port, 16, "ICE1712 - DMA path")) == NULL) {
snd_ice1712_free(ice);
snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->dmapath_port, ice->dmapath_port + 16 - 1);
return -EIO;
}
if ((ice->res_profi_port = request_region(ice->profi_port, 64, "ICE1712 - Professional")) == NULL) {
snd_ice1712_free(ice);
snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->profi_port, ice->profi_port + 16 - 1);
return -EIO;
}
if (request_irq(pci->irq, snd_ice1712_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1712", (void *) ice)) {
snd_ice1712_free(ice);
snd_printk("unable to grab IRQ %d\n", pci->irq);
return -EIO;
}
ice->irq = pci->irq;
if (ice->vt1724) {
ice->profi_port = pci_resource_start(pci, 1);
pci_set_master(pci);
snd_ice1712_proc_init(ice);
synchronize_irq(pci->irq);
if ((ice->res_port = request_region(ice->port, 32, "ICE1724 - Controller")) == NULL) {
snd_ice1712_free(ice);
snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->port, ice->port + 32 - 1);
return -EIO;
}
if (snd_ice1712_read_eeprom(ice) < 0) {
snd_ice1712_free(ice);
return -EIO;
}
if (snd_ice1712_chip_init(ice) < 0) {
snd_ice1712_free(ice);
return -EIO;
}
if ((ice->res_profi_port = request_region(ice->profi_port, 128, "ICE1724 - Professional")) == NULL) {
snd_ice1712_free(ice);
snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->profi_port, ice->profi_port + 16 - 1);
return -EIO;
}
if (request_irq(pci->irq, snd_vt1724_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1724", (void *) ice)) {
snd_ice1712_free(ice);
snd_printk("unable to grab IRQ %d\n", pci->irq);
return -EIO;
}
ice->irq = pci->irq;
/* unmask used interrupts */
outb((ice->eeprom.codec & ICE1712_CFG_2xMPU401) == 0 ? ICE1712_IRQ_MPU2 : 0 |
(ice->eeprom.codec & ICE1712_CFG_NO_CON_AC97) ? ICE1712_IRQ_PBKDS | ICE1712_IRQ_CONCAP | ICE1712_IRQ_CONPBK : 0,
ICEREG(ice, IRQMASK));
outb(0x00, ICEMT(ice, IRQ));
if (snd_ice1712_read_eeprom(ice) < 0) {
snd_ice1712_free(ice);
return -EIO;
}
if (snd_vt1724_chip_init(ice) < 0) {
snd_ice1712_free(ice);
return -EIO;
}
/* unmask used interrupts */
outb((ice->eeprom.codec & ICE1712_CFG_2xMPU401) == 0 ? (VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX) : 0 ,
ICEREG(ice, IRQMASK));
/* don't handle FIFO overrun/underruns (just yet), since they cause machine lockups */
outb(VT1724_MULTI_FIFO_ERR, ICEMT1724(ice, DMA_INT_MASK));
}
else {
ice->ddma_port = pci_resource_start(pci, 1);
ice->dmapath_port = pci_resource_start(pci, 2);
ice->profi_port = pci_resource_start(pci, 3);
pci_set_master(pci);
pci_write_config_word(ice->pci, 0x40, 0x807f);
pci_write_config_word(ice->pci, 0x42, 0x0006);
snd_ice1712_proc_init(ice);
synchronize_irq(pci->irq);
if ((ice->res_port = request_region(ice->port, 32, "ICE1712 - Controller")) == NULL) {
snd_ice1712_free(ice);
snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->port, ice->port + 32 - 1);
return -EIO;
}
if ((ice->res_ddma_port = request_region(ice->ddma_port, 16, "ICE1712 - DDMA")) == NULL) {
snd_ice1712_free(ice);
snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->ddma_port, ice->ddma_port + 16 - 1);
return -EIO;
}
if ((ice->res_dmapath_port = request_region(ice->dmapath_port, 16, "ICE1712 - DMA path")) == NULL) {
snd_ice1712_free(ice);
snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->dmapath_port, ice->dmapath_port + 16 - 1);
return -EIO;
}
if ((ice->res_profi_port = request_region(ice->profi_port, 64, "ICE1712 - Professional")) == NULL) {
snd_ice1712_free(ice);
snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->profi_port, ice->profi_port + 16 - 1);
return -EIO;
}
if (request_irq(pci->irq, snd_ice1712_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1712", (void *) ice)) {
snd_ice1712_free(ice);
snd_printk("unable to grab IRQ %d\n", pci->irq);
return -EIO;
}
ice->irq = pci->irq;
if (snd_ice1712_read_eeprom(ice) < 0) {
snd_ice1712_free(ice);
return -EIO;
}
if (snd_ice1712_chip_init(ice) < 0) {
snd_ice1712_free(ice);
return -EIO;
}
/* unmask used interrupts */
outb((ice->eeprom.codec & ICE1712_CFG_2xMPU401) == 0 ? ICE1712_IRQ_MPU2 : 0 |
(ice->eeprom.codec & ICE1712_CFG_NO_CON_AC97) ? ICE1712_IRQ_PBKDS | ICE1712_IRQ_CONCAP | ICE1712_IRQ_CONPBK : 0,
ICEREG(ice, IRQMASK));
outb(0x00, ICEMT(ice, IRQ));
}
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops)) < 0) {
snd_ice1712_free(ice);
return err;
return err;
}
*r_ice1712 = ice;
......@@ -2426,6 +2881,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
snd_ice1712_hoontech_cards,
snd_ice1712_delta_cards,
snd_ice1712_ews_cards,
snd_vt1724_amp_cards,
0,
};
......@@ -2450,8 +2906,13 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
if (card == NULL)
return -ENOMEM;
strcpy(card->driver, "ICE1712");
strcpy(card->shortname, "ICEnsemble ICE1712");
if (pci->device==PCI_DEVICE_ID_ICE_1712) {
strcpy(card->driver, "ICE1712");
strcpy(card->shortname, "ICEnsemble ICE1712");
} else {
strcpy(card->driver, "ICE1724");
strcpy(card->shortname, "ICEnsemble ICE1724");
}
if ((err = snd_ice1712_create(card, pci, omni[dev], &ice)) < 0) {
snd_card_free(card);
......
......@@ -248,6 +248,7 @@ struct snd_ak4524 {
unsigned int cif: 1;
unsigned char data_mask;
unsigned char clk_mask;
unsigned char caddr; /* C0 and C1 bits */
unsigned char cs_mask;
unsigned char cs_addr;
unsigned char cs_none;
......@@ -335,7 +336,8 @@ struct _snd_ice1712 {
snd_i2c_device_t *cs8427; /* CS8427 I2C device */
snd_i2c_device_t *i2cdevs[2]; /* additional i2c devices */
unsigned char gpio_direction, gpio_write_mask;
unsigned int gpio_direction, gpio_write_mask;
int vt1724;
};
#define chip_t ice1712_t
......
......@@ -291,21 +291,21 @@ static snd_pcm_hardware_t snd_rme32_playback_spdif_info = {
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE),
formats: (SNDRV_PCM_FMTBIT_S16_LE |
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE),
rates: (SNDRV_PCM_RATE_32000 |
.rates = (SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
rate_min: 32000,
rate_max: 48000,
channels_min: 2,
channels_max: 2,
buffer_bytes_max: RME32_BUFFER_SIZE,
period_bytes_min: RME32_BLOCK_SIZE,
period_bytes_max: RME32_BLOCK_SIZE,
periods_min: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
periods_max: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
fifo_size: 0,
.rate_min = 32000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = RME32_BUFFER_SIZE,
.period_bytes_min = RME32_BLOCK_SIZE,
.period_bytes_max = RME32_BLOCK_SIZE,
.periods_min = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
.periods_max = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
.fifo_size = 0,
};
/*
......@@ -315,19 +315,19 @@ static snd_pcm_hardware_t snd_rme32_capture_spdif_info = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE),
formats: (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE),
rates: (SNDRV_PCM_RATE_32000 |
.formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE),
.rates = (SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000),
rate_min: 32000,
rate_max: 48000,
channels_min: 2,
channels_max: 2,
buffer_bytes_max: RME32_BUFFER_SIZE,
period_bytes_min: RME32_BLOCK_SIZE,
period_bytes_max: RME32_BLOCK_SIZE,
periods_min: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
periods_max: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
fifo_size: 0,
.rate_min = 32000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = RME32_BUFFER_SIZE,
.period_bytes_min = RME32_BLOCK_SIZE,
.period_bytes_max = RME32_BLOCK_SIZE,
.periods_min = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
.periods_max = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
.fifo_size = 0,
};
/*
......@@ -339,19 +339,19 @@ static snd_pcm_hardware_t snd_rme32_playback_adat_info =
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE),
formats: SNDRV_PCM_FMTBIT_S16_LE,
rates: (SNDRV_PCM_RATE_44100 |
.formats= SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
rate_min: 44100,
rate_max: 48000,
channels_min: 8,
channels_max: 8,
buffer_bytes_max: RME32_BUFFER_SIZE,
period_bytes_min: RME32_BLOCK_SIZE,
period_bytes_max: RME32_BLOCK_SIZE,
periods_min: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
periods_max: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
fifo_size: 0,
.rate_min = 44100,
.rate_max = 48000,
.channels_min = 8,
.channels_max = 8,
.buffer_bytes_max = RME32_BUFFER_SIZE,
.period_bytes_min = RME32_BLOCK_SIZE,
.period_bytes_max = RME32_BLOCK_SIZE,
.periods_min = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
.periods_max = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
.fifo_size = 0,
};
/*
......@@ -363,19 +363,19 @@ static snd_pcm_hardware_t snd_rme32_capture_adat_info =
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE),
formats: SNDRV_PCM_FMTBIT_S16_LE,
rates: (SNDRV_PCM_RATE_44100 |
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
rate_min: 44100,
rate_max: 48000,
channels_min: 8,
channels_max: 8,
buffer_bytes_max: RME32_BUFFER_SIZE,
period_bytes_min: RME32_BLOCK_SIZE,
period_bytes_max: RME32_BLOCK_SIZE,
periods_min: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
periods_max: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
fifo_size: 0,
.rate_min = 44100,
.rate_max = 48000,
.channels_min = 8,
.channels_max = 8,
.buffer_bytes_max = RME32_BUFFER_SIZE,
.period_bytes_min = RME32_BLOCK_SIZE,
.period_bytes_max = RME32_BLOCK_SIZE,
.periods_min = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
.periods_max = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
.fifo_size = 0,
};
static void snd_rme32_reset_dac(rme32_t *rme32)
......
......@@ -161,6 +161,60 @@
.type = QUIRK_MIDI_YAMAHA
}
},
{
USB_DEVICE(0x0499, 0x1012),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "TYROS",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_YAMAHA
}
},
{
USB_DEVICE(0x0499, 0x1013),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "PF-500",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_YAMAHA
}
},
{
USB_DEVICE(0x0499, 0x1014),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "S90",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_YAMAHA
}
},
{
USB_DEVICE(0x0499, 0x5002),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "DME32",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_YAMAHA
}
},
{
USB_DEVICE(0x0499, 0x5003),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "DM2000",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_YAMAHA
}
},
{
USB_DEVICE(0x0499, 0x5004),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "02R96",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_YAMAHA
}
},
/*
* Once upon a time people thought, "Wouldn't it be nice if there was a
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment