static void get_audio_meters(struct echoaudio *chip, long *meters) { int i, m, n; m = 0; n = 0; for (i = 0; i < num_busses_out(chip); i++, m++) { meters[n++] = chip->comm_page->vu_meter[m]; meters[n++] = chip->comm_page->peak_meter[m]; } for (; n < 32; n++) meters[n] = 0; #ifdef ECHOCARD_ECHO3G m = E3G_MAX_OUTPUTS; /* */ #endif for (i = 0; i < num_busses_in(chip); i++, m++) { meters[n++] = chip->comm_page->vu_meter[m]; meters[n++] = chip->comm_page->peak_meter[m]; } for (; n < 64; n++) meters[n] = 0; #ifdef ECHOCARD_HAS_VMIXER for (i = 0; i < num_pipes_out(chip); i++, m++) { meters[n++] = chip->comm_page->vu_meter[m]; meters[n++] = chip->comm_page->peak_meter[m]; } #endif for (; n < 96; n++) meters[n] = 0; }
/* S/PDIF coax / S/PDIF optical / ADAT - switch */ static int set_digital_mode(struct echoaudio *chip, u8 mode) { u8 previous_mode; int err, i, o; if (chip->bad_board) return -EIO; /* All audio channels must be closed before changing the digital mode */ if (snd_BUG_ON(chip->pipe_alloc_mask)) return -EAGAIN; if (snd_BUG_ON(!(chip->digital_modes & (1 << mode)))) return -EINVAL; previous_mode = chip->digital_mode; err = dsp_set_digital_mode(chip, mode); /* If we successfully changed the digital mode from or to ADAT, then make sure all output, input and monitor levels are updated by the DSP comm object. */ if (err >= 0 && previous_mode != mode && (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { spin_lock_irq(&chip->lock); for (o = 0; o < num_busses_out(chip); o++) for (i = 0; i < num_busses_in(chip); i++) set_monitor_gain(chip, o, i, chip->monitor_gain[o][i]); #ifdef ECHOCARD_HAS_INPUT_GAIN for (i = 0; i < num_busses_in(chip); i++) set_input_gain(chip, i, chip->input_gain[i]); update_input_line_level(chip); #endif for (o = 0; o < num_busses_out(chip); o++) set_output_gain(chip, o, chip->output_gain[o]); update_output_line_level(chip); spin_unlock_irq(&chip->lock); } return err; }
/* This function initializes the several volume controls for busses and pipes. This MUST be called after the DSP is up and running ! */ static int init_line_levels(struct echoaudio *chip) { int st, i, o; DE_INIT(("init_line_levels\n")); /* Mute output busses */ for (i = 0; i < num_busses_out(chip); i++) if ((st = set_output_gain(chip, i, ECHOGAIN_MUTED))) return st; if ((st = update_output_line_level(chip))) return st; #ifdef ECHOCARD_HAS_VMIXER /* Mute the Vmixer */ for (i = 0; i < num_pipes_out(chip); i++) for (o = 0; o < num_busses_out(chip); o++) if ((st = set_vmixer_gain(chip, o, i, ECHOGAIN_MUTED))) return st; if ((st = update_vmixer_level(chip))) return st; #endif /* ECHOCARD_HAS_VMIXER */ #ifdef ECHOCARD_HAS_MONITOR /* Mute the monitor mixer */ for (o = 0; o < num_busses_out(chip); o++) for (i = 0; i < num_busses_in(chip); i++) if ((st = set_monitor_gain(chip, o, i, ECHOGAIN_MUTED))) return st; if ((st = update_output_line_level(chip))) return st; #endif /* ECHOCARD_HAS_MONITOR */ #ifdef ECHOCARD_HAS_INPUT_GAIN for (i = 0; i < num_busses_in(chip); i++) if ((st = set_input_gain(chip, i, ECHOGAIN_MUTED))) return st; if ((st = update_input_line_level(chip))) return st; #endif /* ECHOCARD_HAS_INPUT_GAIN */ return 0; }
static int set_digital_mode(struct echoaudio *chip, u8 mode) { u8 previous_mode; int err, i, o; if (chip->bad_board) return -EIO; if (snd_BUG_ON(chip->pipe_alloc_mask)) return -EAGAIN; if (snd_BUG_ON(!(chip->digital_modes & (1 << mode)))) return -EINVAL; previous_mode = chip->digital_mode; err = dsp_set_digital_mode(chip, mode); if (err >= 0 && previous_mode != mode && (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { spin_lock_irq(&chip->lock); for (o = 0; o < num_busses_out(chip); o++) for (i = 0; i < num_busses_in(chip); i++) set_monitor_gain(chip, o, i, chip->monitor_gain[o][i]); #ifdef ECHOCARD_HAS_INPUT_GAIN for (i = 0; i < num_busses_in(chip); i++) set_input_gain(chip, i, chip->input_gain[i]); update_input_line_level(chip); #endif for (o = 0; o < num_busses_out(chip); o++) set_output_gain(chip, o, chip->output_gain[o]); update_output_line_level(chip); spin_unlock_irq(&chip->lock); } return err; }
static int set_output_gain(struct echoaudio *chip, u16 channel, s8 gain) { if (snd_BUG_ON(channel >= num_busses_out(chip))) return -EINVAL; if (wait_handshake(chip)) return -EIO; /* */ chip->output_gain[channel] = gain; chip->comm_page->line_out_level[channel] = gain; return 0; }
static int set_monitor_gain(struct echoaudio *chip, u16 output, u16 input, s8 gain) { if (snd_BUG_ON(output >= num_busses_out(chip) || input >= num_busses_in(chip))) return -EINVAL; if (wait_handshake(chip)) return -EIO; chip->monitor_gain[output][input] = gain; chip->comm_page->monitors[monitor_index(chip, output, input)] = gain; return 0; }
static int set_nominal_level(struct echoaudio *chip, u16 index, char consumer) { if (snd_BUG_ON(index >= num_busses_out(chip) + num_busses_in(chip))) return -EINVAL; /* */ if (wait_handshake(chip)) return -EIO; chip->nominal_level[index] = consumer; if (consumer) chip->comm_page->nominal_level_mask |= cpu_to_le32(1 << index); else chip->comm_page->nominal_level_mask &= ~cpu_to_le32(1 << index); return 0; }
/* This function routes the sound from a virtual channel to a real output */ static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, int gain) { int index; if (snd_BUG_ON(pipe >= num_pipes_out(chip) || output >= num_busses_out(chip))) return -EINVAL; if (wait_handshake(chip)) return -EIO; chip->vmixer_gain[output][pipe] = gain; index = output * num_pipes_out(chip) + pipe; chip->comm_page->vmixer[index] = gain; DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); return 0; }
static int restore_dsp_rettings(struct echoaudio *chip) { int i, o, err; DE_INIT(("restore_dsp_settings\n")); if ((err = check_asic_status(chip)) < 0) return err; /* */ chip->comm_page->gd_clock_state = GD_CLOCK_UNDEF; chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_UNDEF; chip->comm_page->handshake = 0xffffffff; /* */ for (i = 0; i < num_busses_out(chip); i++) { err = set_output_gain(chip, i, chip->output_gain[i]); if (err < 0) return err; } #ifdef ECHOCARD_HAS_VMIXER for (i = 0; i < num_pipes_out(chip); i++) for (o = 0; o < num_busses_out(chip); o++) { err = set_vmixer_gain(chip, o, i, chip->vmixer_gain[o][i]); if (err < 0) return err; } if (update_vmixer_level(chip) < 0) return -EIO; #endif /* */ #ifdef ECHOCARD_HAS_MONITOR for (o = 0; o < num_busses_out(chip); o++) for (i = 0; i < num_busses_in(chip); i++) { err = set_monitor_gain(chip, o, i, chip->monitor_gain[o][i]); if (err < 0) return err; } #endif /* */ #ifdef ECHOCARD_HAS_INPUT_GAIN for (i = 0; i < num_busses_in(chip); i++) { err = set_input_gain(chip, i, chip->input_gain[i]); if (err < 0) return err; } #endif /* */ err = update_output_line_level(chip); if (err < 0) return err; err = update_input_line_level(chip); if (err < 0) return err; err = set_sample_rate(chip, chip->sample_rate); if (err < 0) return err; if (chip->meters_enabled) { err = send_vector(chip, DSP_VC_METERS_ON); if (err < 0) return err; } #ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH if (set_digital_mode(chip, chip->digital_mode) < 0) return -EIO; #endif #ifdef ECHOCARD_HAS_DIGITAL_IO if (set_professional_spdif(chip, chip->professional_spdif) < 0) return -EIO; #endif #ifdef ECHOCARD_HAS_PHANTOM_POWER if (set_phantom_power(chip, chip->phantom_power) < 0) return -EIO; #endif #ifdef ECHOCARD_HAS_EXTERNAL_CLOCK /* */ if (set_input_clock(chip, chip->input_clock) < 0) return -EIO; #endif #ifdef ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH if (set_output_clock(chip, chip->output_clock) < 0) return -EIO; #endif if (wait_handshake(chip) < 0) return -EIO; clear_handshake(chip); if (send_vector(chip, DSP_VC_UPDATE_FLAGS) < 0) return -EIO; DE_INIT(("restore_dsp_rettings done\n")); return 0; }