162306a36Sopenharmony_ci/**************************************************************************** 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci Copyright Echo Digital Audio Corporation (c) 1998 - 2004 462306a36Sopenharmony_ci All rights reserved 562306a36Sopenharmony_ci www.echoaudio.com 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci This file is part of Echo Digital Audio's generic driver library. 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci Echo Digital Audio's generic driver library is free software; 1062306a36Sopenharmony_ci you can redistribute it and/or modify it under the terms of 1162306a36Sopenharmony_ci the GNU General Public License as published by the Free Software 1262306a36Sopenharmony_ci Foundation. 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci This program is distributed in the hope that it will be useful, 1562306a36Sopenharmony_ci but WITHOUT ANY WARRANTY; without even the implied warranty of 1662306a36Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1762306a36Sopenharmony_ci GNU General Public License for more details. 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci You should have received a copy of the GNU General Public License 2062306a36Sopenharmony_ci along with this program; if not, write to the Free Software 2162306a36Sopenharmony_ci Foundation, Inc., 59 Temple Place - Suite 330, Boston, 2262306a36Sopenharmony_ci MA 02111-1307, USA. 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci ************************************************************************* 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci Translation from C++ and adaptation for use in ALSA-Driver 2762306a36Sopenharmony_ci were made by Giuliano Pochini <pochini@shiny.it> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci****************************************************************************/ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* These functions are common for Gina24, Layla24 and Mona cards */ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* ASIC status check - some cards have one or two ASICs that need to be 3662306a36Sopenharmony_ciloaded. Once that load is complete, this function is called to see if 3762306a36Sopenharmony_cithe load was successful. 3862306a36Sopenharmony_ciIf this load fails, it does not necessarily mean that the hardware is 3962306a36Sopenharmony_cidefective - the external box may be disconnected or turned off. */ 4062306a36Sopenharmony_cistatic int check_asic_status(struct echoaudio *chip) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci u32 asic_status; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci send_vector(chip, DSP_VC_TEST_ASIC); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci /* The DSP will return a value to indicate whether or not the 4762306a36Sopenharmony_ci ASIC is currently loaded */ 4862306a36Sopenharmony_ci if (read_dsp(chip, &asic_status) < 0) { 4962306a36Sopenharmony_ci dev_err(chip->card->dev, 5062306a36Sopenharmony_ci "check_asic_status: failed on read_dsp\n"); 5162306a36Sopenharmony_ci chip->asic_loaded = false; 5262306a36Sopenharmony_ci return -EIO; 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED); 5662306a36Sopenharmony_ci return chip->asic_loaded ? 0 : -EIO; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* Most configuration of Gina24, Layla24, or Mona is accomplished by writing 6262306a36Sopenharmony_cithe control register. write_control_reg sends the new control register 6362306a36Sopenharmony_civalue to the DSP. */ 6462306a36Sopenharmony_cistatic int write_control_reg(struct echoaudio *chip, u32 value, char force) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci __le32 reg_value; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci /* Handle the digital input auto-mute */ 6962306a36Sopenharmony_ci if (chip->digital_in_automute) 7062306a36Sopenharmony_ci value |= GML_DIGITAL_IN_AUTO_MUTE; 7162306a36Sopenharmony_ci else 7262306a36Sopenharmony_ci value &= ~GML_DIGITAL_IN_AUTO_MUTE; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci dev_dbg(chip->card->dev, "write_control_reg: 0x%x\n", value); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci /* Write the control register */ 7762306a36Sopenharmony_ci reg_value = cpu_to_le32(value); 7862306a36Sopenharmony_ci if (reg_value != chip->comm_page->control_register || force) { 7962306a36Sopenharmony_ci if (wait_handshake(chip)) 8062306a36Sopenharmony_ci return -EIO; 8162306a36Sopenharmony_ci chip->comm_page->control_register = reg_value; 8262306a36Sopenharmony_ci clear_handshake(chip); 8362306a36Sopenharmony_ci return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci return 0; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci/* Gina24, Layla24, and Mona support digital input auto-mute. If the digital 9162306a36Sopenharmony_ciinput auto-mute is enabled, the DSP will only enable the digital inputs if 9262306a36Sopenharmony_cithe card is syncing to a valid clock on the ADAT or S/PDIF inputs. 9362306a36Sopenharmony_ciIf the auto-mute is disabled, the digital inputs are enabled regardless of 9462306a36Sopenharmony_ciwhat the input clock is set or what is connected. */ 9562306a36Sopenharmony_cistatic int set_input_auto_mute(struct echoaudio *chip, int automute) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci dev_dbg(chip->card->dev, "set_input_auto_mute %d\n", automute); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci chip->digital_in_automute = automute; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* Re-set the input clock to the current value - indirectly causes 10262306a36Sopenharmony_ci the auto-mute flag to be sent to the DSP */ 10362306a36Sopenharmony_ci return set_input_clock(chip, chip->input_clock); 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/* S/PDIF coax / S/PDIF optical / ADAT - switch */ 10962306a36Sopenharmony_cistatic int set_digital_mode(struct echoaudio *chip, u8 mode) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci u8 previous_mode; 11262306a36Sopenharmony_ci int err, i, o; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci if (chip->bad_board) 11562306a36Sopenharmony_ci return -EIO; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* All audio channels must be closed before changing the digital mode */ 11862306a36Sopenharmony_ci if (snd_BUG_ON(chip->pipe_alloc_mask)) 11962306a36Sopenharmony_ci return -EAGAIN; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if (snd_BUG_ON(!(chip->digital_modes & (1 << mode)))) 12262306a36Sopenharmony_ci return -EINVAL; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci previous_mode = chip->digital_mode; 12562306a36Sopenharmony_ci err = dsp_set_digital_mode(chip, mode); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci /* If we successfully changed the digital mode from or to ADAT, 12862306a36Sopenharmony_ci then make sure all output, input and monitor levels are 12962306a36Sopenharmony_ci updated by the DSP comm object. */ 13062306a36Sopenharmony_ci if (err >= 0 && previous_mode != mode && 13162306a36Sopenharmony_ci (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { 13262306a36Sopenharmony_ci spin_lock_irq(&chip->lock); 13362306a36Sopenharmony_ci for (o = 0; o < num_busses_out(chip); o++) 13462306a36Sopenharmony_ci for (i = 0; i < num_busses_in(chip); i++) 13562306a36Sopenharmony_ci set_monitor_gain(chip, o, i, 13662306a36Sopenharmony_ci chip->monitor_gain[o][i]); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci#ifdef ECHOCARD_HAS_INPUT_GAIN 13962306a36Sopenharmony_ci for (i = 0; i < num_busses_in(chip); i++) 14062306a36Sopenharmony_ci set_input_gain(chip, i, chip->input_gain[i]); 14162306a36Sopenharmony_ci update_input_line_level(chip); 14262306a36Sopenharmony_ci#endif 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci for (o = 0; o < num_busses_out(chip); o++) 14562306a36Sopenharmony_ci set_output_gain(chip, o, chip->output_gain[o]); 14662306a36Sopenharmony_ci update_output_line_level(chip); 14762306a36Sopenharmony_ci spin_unlock_irq(&chip->lock); 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return err; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci/* Set the S/PDIF output format */ 15662306a36Sopenharmony_cistatic int set_professional_spdif(struct echoaudio *chip, char prof) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci u32 control_reg; 15962306a36Sopenharmony_ci int err; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* Clear the current S/PDIF flags */ 16262306a36Sopenharmony_ci control_reg = le32_to_cpu(chip->comm_page->control_register); 16362306a36Sopenharmony_ci control_reg &= GML_SPDIF_FORMAT_CLEAR_MASK; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci /* Set the new S/PDIF flags depending on the mode */ 16662306a36Sopenharmony_ci control_reg |= GML_SPDIF_TWO_CHANNEL | GML_SPDIF_24_BIT | 16762306a36Sopenharmony_ci GML_SPDIF_COPY_PERMIT; 16862306a36Sopenharmony_ci if (prof) { 16962306a36Sopenharmony_ci /* Professional mode */ 17062306a36Sopenharmony_ci control_reg |= GML_SPDIF_PRO_MODE; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci switch (chip->sample_rate) { 17362306a36Sopenharmony_ci case 32000: 17462306a36Sopenharmony_ci control_reg |= GML_SPDIF_SAMPLE_RATE0 | 17562306a36Sopenharmony_ci GML_SPDIF_SAMPLE_RATE1; 17662306a36Sopenharmony_ci break; 17762306a36Sopenharmony_ci case 44100: 17862306a36Sopenharmony_ci control_reg |= GML_SPDIF_SAMPLE_RATE0; 17962306a36Sopenharmony_ci break; 18062306a36Sopenharmony_ci case 48000: 18162306a36Sopenharmony_ci control_reg |= GML_SPDIF_SAMPLE_RATE1; 18262306a36Sopenharmony_ci break; 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci } else { 18562306a36Sopenharmony_ci /* Consumer mode */ 18662306a36Sopenharmony_ci switch (chip->sample_rate) { 18762306a36Sopenharmony_ci case 32000: 18862306a36Sopenharmony_ci control_reg |= GML_SPDIF_SAMPLE_RATE0 | 18962306a36Sopenharmony_ci GML_SPDIF_SAMPLE_RATE1; 19062306a36Sopenharmony_ci break; 19162306a36Sopenharmony_ci case 48000: 19262306a36Sopenharmony_ci control_reg |= GML_SPDIF_SAMPLE_RATE1; 19362306a36Sopenharmony_ci break; 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci err = write_control_reg(chip, control_reg, false); 19862306a36Sopenharmony_ci if (err) 19962306a36Sopenharmony_ci return err; 20062306a36Sopenharmony_ci chip->professional_spdif = prof; 20162306a36Sopenharmony_ci dev_dbg(chip->card->dev, "set_professional_spdif to %s\n", 20262306a36Sopenharmony_ci prof ? "Professional" : "Consumer"); 20362306a36Sopenharmony_ci return 0; 20462306a36Sopenharmony_ci} 205