1dd7b254dSGiuliano Pochini /**************************************************************************** 2dd7b254dSGiuliano Pochini 3dd7b254dSGiuliano Pochini Copyright Echo Digital Audio Corporation (c) 1998 - 2004 4dd7b254dSGiuliano Pochini All rights reserved 5dd7b254dSGiuliano Pochini www.echoaudio.com 6dd7b254dSGiuliano Pochini 7dd7b254dSGiuliano Pochini This file is part of Echo Digital Audio's generic driver library. 8dd7b254dSGiuliano Pochini 9dd7b254dSGiuliano Pochini Echo Digital Audio's generic driver library is free software; 10dd7b254dSGiuliano Pochini you can redistribute it and/or modify it under the terms of 11dd7b254dSGiuliano Pochini the GNU General Public License as published by the Free Software 12dd7b254dSGiuliano Pochini Foundation. 13dd7b254dSGiuliano Pochini 14dd7b254dSGiuliano Pochini This program is distributed in the hope that it will be useful, 15dd7b254dSGiuliano Pochini but WITHOUT ANY WARRANTY; without even the implied warranty of 16dd7b254dSGiuliano Pochini MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17dd7b254dSGiuliano Pochini GNU General Public License for more details. 18dd7b254dSGiuliano Pochini 19dd7b254dSGiuliano Pochini You should have received a copy of the GNU General Public License 20dd7b254dSGiuliano Pochini along with this program; if not, write to the Free Software 21dd7b254dSGiuliano Pochini Foundation, Inc., 59 Temple Place - Suite 330, Boston, 22dd7b254dSGiuliano Pochini MA 02111-1307, USA. 23dd7b254dSGiuliano Pochini 24dd7b254dSGiuliano Pochini ************************************************************************* 25dd7b254dSGiuliano Pochini 26dd7b254dSGiuliano Pochini Translation from C++ and adaptation for use in ALSA-Driver 27dd7b254dSGiuliano Pochini were made by Giuliano Pochini <pochini@shiny.it> 28dd7b254dSGiuliano Pochini 29dd7b254dSGiuliano Pochini ****************************************************************************/ 30dd7b254dSGiuliano Pochini 31dd7b254dSGiuliano Pochini 32dd7b254dSGiuliano Pochini /* These functions are common for Gina24, Layla24 and Mona cards */ 33dd7b254dSGiuliano Pochini 34dd7b254dSGiuliano Pochini 35dd7b254dSGiuliano Pochini /* ASIC status check - some cards have one or two ASICs that need to be 36dd7b254dSGiuliano Pochini loaded. Once that load is complete, this function is called to see if 37dd7b254dSGiuliano Pochini the load was successful. 38dd7b254dSGiuliano Pochini If this load fails, it does not necessarily mean that the hardware is 39dd7b254dSGiuliano Pochini defective - the external box may be disconnected or turned off. */ 40dd7b254dSGiuliano Pochini static int check_asic_status(struct echoaudio *chip) 41dd7b254dSGiuliano Pochini { 42dd7b254dSGiuliano Pochini u32 asic_status; 43dd7b254dSGiuliano Pochini 44dd7b254dSGiuliano Pochini send_vector(chip, DSP_VC_TEST_ASIC); 45dd7b254dSGiuliano Pochini 46dd7b254dSGiuliano Pochini /* The DSP will return a value to indicate whether or not the 47dd7b254dSGiuliano Pochini ASIC is currently loaded */ 48dd7b254dSGiuliano Pochini if (read_dsp(chip, &asic_status) < 0) { 49b5b4a41bSSudip Mukherjee dev_err(chip->card->dev, 50b5b4a41bSSudip Mukherjee "check_asic_status: failed on read_dsp\n"); 513f6175ecSMark Brown chip->asic_loaded = false; 52dd7b254dSGiuliano Pochini return -EIO; 53dd7b254dSGiuliano Pochini } 54dd7b254dSGiuliano Pochini 55dd7b254dSGiuliano Pochini chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED); 56dd7b254dSGiuliano Pochini return chip->asic_loaded ? 0 : -EIO; 57dd7b254dSGiuliano Pochini } 58dd7b254dSGiuliano Pochini 59dd7b254dSGiuliano Pochini 60dd7b254dSGiuliano Pochini 61dd7b254dSGiuliano Pochini /* Most configuration of Gina24, Layla24, or Mona is accomplished by writing 62dd7b254dSGiuliano Pochini the control register. write_control_reg sends the new control register 63dd7b254dSGiuliano Pochini value to the DSP. */ 64dd7b254dSGiuliano Pochini static int write_control_reg(struct echoaudio *chip, u32 value, char force) 65dd7b254dSGiuliano Pochini { 662a833a02STakashi Iwai __le32 reg_value; 672a833a02STakashi Iwai 68dd7b254dSGiuliano Pochini /* Handle the digital input auto-mute */ 69dd7b254dSGiuliano Pochini if (chip->digital_in_automute) 70dd7b254dSGiuliano Pochini value |= GML_DIGITAL_IN_AUTO_MUTE; 71dd7b254dSGiuliano Pochini else 72dd7b254dSGiuliano Pochini value &= ~GML_DIGITAL_IN_AUTO_MUTE; 73dd7b254dSGiuliano Pochini 74b5b4a41bSSudip Mukherjee dev_dbg(chip->card->dev, "write_control_reg: 0x%x\n", value); 75dd7b254dSGiuliano Pochini 76dd7b254dSGiuliano Pochini /* Write the control register */ 772a833a02STakashi Iwai reg_value = cpu_to_le32(value); 782a833a02STakashi Iwai if (reg_value != chip->comm_page->control_register || force) { 79dd7b254dSGiuliano Pochini if (wait_handshake(chip)) 80dd7b254dSGiuliano Pochini return -EIO; 812a833a02STakashi Iwai chip->comm_page->control_register = reg_value; 82dd7b254dSGiuliano Pochini clear_handshake(chip); 83dd7b254dSGiuliano Pochini return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); 84dd7b254dSGiuliano Pochini } 85dd7b254dSGiuliano Pochini return 0; 86dd7b254dSGiuliano Pochini } 87dd7b254dSGiuliano Pochini 88dd7b254dSGiuliano Pochini 89dd7b254dSGiuliano Pochini 90dd7b254dSGiuliano Pochini /* Gina24, Layla24, and Mona support digital input auto-mute. If the digital 91dd7b254dSGiuliano Pochini input auto-mute is enabled, the DSP will only enable the digital inputs if 92dd7b254dSGiuliano Pochini the card is syncing to a valid clock on the ADAT or S/PDIF inputs. 93dd7b254dSGiuliano Pochini If the auto-mute is disabled, the digital inputs are enabled regardless of 94dd7b254dSGiuliano Pochini what the input clock is set or what is connected. */ 95dd7b254dSGiuliano Pochini static int set_input_auto_mute(struct echoaudio *chip, int automute) 96dd7b254dSGiuliano Pochini { 97b5b4a41bSSudip Mukherjee dev_dbg(chip->card->dev, "set_input_auto_mute %d\n", automute); 98dd7b254dSGiuliano Pochini 99dd7b254dSGiuliano Pochini chip->digital_in_automute = automute; 100dd7b254dSGiuliano Pochini 101dd7b254dSGiuliano Pochini /* Re-set the input clock to the current value - indirectly causes 102dd7b254dSGiuliano Pochini the auto-mute flag to be sent to the DSP */ 103dd7b254dSGiuliano Pochini return set_input_clock(chip, chip->input_clock); 104dd7b254dSGiuliano Pochini } 105dd7b254dSGiuliano Pochini 106dd7b254dSGiuliano Pochini 107dd7b254dSGiuliano Pochini 108dd7b254dSGiuliano Pochini /* S/PDIF coax / S/PDIF optical / ADAT - switch */ 109dd7b254dSGiuliano Pochini static int set_digital_mode(struct echoaudio *chip, u8 mode) 110dd7b254dSGiuliano Pochini { 111dd7b254dSGiuliano Pochini u8 previous_mode; 112dd7b254dSGiuliano Pochini int err, i, o; 113dd7b254dSGiuliano Pochini 114dd7b254dSGiuliano Pochini if (chip->bad_board) 115dd7b254dSGiuliano Pochini return -EIO; 116dd7b254dSGiuliano Pochini 117dd7b254dSGiuliano Pochini /* All audio channels must be closed before changing the digital mode */ 118da3cec35STakashi Iwai if (snd_BUG_ON(chip->pipe_alloc_mask)) 119da3cec35STakashi Iwai return -EAGAIN; 120dd7b254dSGiuliano Pochini 121da3cec35STakashi Iwai if (snd_BUG_ON(!(chip->digital_modes & (1 << mode)))) 122da3cec35STakashi Iwai return -EINVAL; 123dd7b254dSGiuliano Pochini 124dd7b254dSGiuliano Pochini previous_mode = chip->digital_mode; 125dd7b254dSGiuliano Pochini err = dsp_set_digital_mode(chip, mode); 126dd7b254dSGiuliano Pochini 127dd7b254dSGiuliano Pochini /* If we successfully changed the digital mode from or to ADAT, 128dd7b254dSGiuliano Pochini then make sure all output, input and monitor levels are 129dd7b254dSGiuliano Pochini updated by the DSP comm object. */ 130dd7b254dSGiuliano Pochini if (err >= 0 && previous_mode != mode && 131dd7b254dSGiuliano Pochini (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { 132dd7b254dSGiuliano Pochini spin_lock_irq(&chip->lock); 133dd7b254dSGiuliano Pochini for (o = 0; o < num_busses_out(chip); o++) 134dd7b254dSGiuliano Pochini for (i = 0; i < num_busses_in(chip); i++) 135dd7b254dSGiuliano Pochini set_monitor_gain(chip, o, i, 136dd7b254dSGiuliano Pochini chip->monitor_gain[o][i]); 137dd7b254dSGiuliano Pochini 138dd7b254dSGiuliano Pochini #ifdef ECHOCARD_HAS_INPUT_GAIN 139dd7b254dSGiuliano Pochini for (i = 0; i < num_busses_in(chip); i++) 140dd7b254dSGiuliano Pochini set_input_gain(chip, i, chip->input_gain[i]); 141dd7b254dSGiuliano Pochini update_input_line_level(chip); 142dd7b254dSGiuliano Pochini #endif 143dd7b254dSGiuliano Pochini 144dd7b254dSGiuliano Pochini for (o = 0; o < num_busses_out(chip); o++) 145dd7b254dSGiuliano Pochini set_output_gain(chip, o, chip->output_gain[o]); 146dd7b254dSGiuliano Pochini update_output_line_level(chip); 147dd7b254dSGiuliano Pochini spin_unlock_irq(&chip->lock); 148dd7b254dSGiuliano Pochini } 149dd7b254dSGiuliano Pochini 150dd7b254dSGiuliano Pochini return err; 151dd7b254dSGiuliano Pochini } 152dd7b254dSGiuliano Pochini 153dd7b254dSGiuliano Pochini 154dd7b254dSGiuliano Pochini 155dd7b254dSGiuliano Pochini /* Set the S/PDIF output format */ 156dd7b254dSGiuliano Pochini static int set_professional_spdif(struct echoaudio *chip, char prof) 157dd7b254dSGiuliano Pochini { 158dd7b254dSGiuliano Pochini u32 control_reg; 159dd7b254dSGiuliano Pochini int err; 160dd7b254dSGiuliano Pochini 161dd7b254dSGiuliano Pochini /* Clear the current S/PDIF flags */ 162dd7b254dSGiuliano Pochini control_reg = le32_to_cpu(chip->comm_page->control_register); 163dd7b254dSGiuliano Pochini control_reg &= GML_SPDIF_FORMAT_CLEAR_MASK; 164dd7b254dSGiuliano Pochini 165dd7b254dSGiuliano Pochini /* Set the new S/PDIF flags depending on the mode */ 166dd7b254dSGiuliano Pochini control_reg |= GML_SPDIF_TWO_CHANNEL | GML_SPDIF_24_BIT | 167dd7b254dSGiuliano Pochini GML_SPDIF_COPY_PERMIT; 168dd7b254dSGiuliano Pochini if (prof) { 169dd7b254dSGiuliano Pochini /* Professional mode */ 170dd7b254dSGiuliano Pochini control_reg |= GML_SPDIF_PRO_MODE; 171dd7b254dSGiuliano Pochini 172dd7b254dSGiuliano Pochini switch (chip->sample_rate) { 173dd7b254dSGiuliano Pochini case 32000: 174dd7b254dSGiuliano Pochini control_reg |= GML_SPDIF_SAMPLE_RATE0 | 175dd7b254dSGiuliano Pochini GML_SPDIF_SAMPLE_RATE1; 176dd7b254dSGiuliano Pochini break; 177dd7b254dSGiuliano Pochini case 44100: 178dd7b254dSGiuliano Pochini control_reg |= GML_SPDIF_SAMPLE_RATE0; 179dd7b254dSGiuliano Pochini break; 180dd7b254dSGiuliano Pochini case 48000: 181dd7b254dSGiuliano Pochini control_reg |= GML_SPDIF_SAMPLE_RATE1; 182dd7b254dSGiuliano Pochini break; 183dd7b254dSGiuliano Pochini } 184dd7b254dSGiuliano Pochini } else { 185dd7b254dSGiuliano Pochini /* Consumer mode */ 186dd7b254dSGiuliano Pochini switch (chip->sample_rate) { 187dd7b254dSGiuliano Pochini case 32000: 188dd7b254dSGiuliano Pochini control_reg |= GML_SPDIF_SAMPLE_RATE0 | 189dd7b254dSGiuliano Pochini GML_SPDIF_SAMPLE_RATE1; 190dd7b254dSGiuliano Pochini break; 191dd7b254dSGiuliano Pochini case 48000: 192dd7b254dSGiuliano Pochini control_reg |= GML_SPDIF_SAMPLE_RATE1; 193dd7b254dSGiuliano Pochini break; 194dd7b254dSGiuliano Pochini } 195dd7b254dSGiuliano Pochini } 196dd7b254dSGiuliano Pochini 197*549717fcSTakashi Iwai err = write_control_reg(chip, control_reg, false); 198*549717fcSTakashi Iwai if (err) 199dd7b254dSGiuliano Pochini return err; 200dd7b254dSGiuliano Pochini chip->professional_spdif = prof; 201b5b4a41bSSudip Mukherjee dev_dbg(chip->card->dev, "set_professional_spdif to %s\n", 202b5b4a41bSSudip Mukherjee prof ? "Professional" : "Consumer"); 203dd7b254dSGiuliano Pochini return 0; 204dd7b254dSGiuliano Pochini } 205