18c2ecf20Sopenharmony_ci/**************************************************************************** 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci Copyright Echo Digital Audio Corporation (c) 1998 - 2004 48c2ecf20Sopenharmony_ci All rights reserved 58c2ecf20Sopenharmony_ci www.echoaudio.com 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci This file is part of Echo Digital Audio's generic driver library. 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci Echo Digital Audio's generic driver library is free software; 108c2ecf20Sopenharmony_ci you can redistribute it and/or modify it under the terms of 118c2ecf20Sopenharmony_ci the GNU General Public License as published by the Free Software 128c2ecf20Sopenharmony_ci Foundation. 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci This program is distributed in the hope that it will be useful, 158c2ecf20Sopenharmony_ci but WITHOUT ANY WARRANTY; without even the implied warranty of 168c2ecf20Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 178c2ecf20Sopenharmony_ci GNU General Public License for more details. 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci You should have received a copy of the GNU General Public License 208c2ecf20Sopenharmony_ci along with this program; if not, write to the Free Software 218c2ecf20Sopenharmony_ci Foundation, Inc., 59 Temple Place - Suite 330, Boston, 228c2ecf20Sopenharmony_ci MA 02111-1307, USA. 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci ************************************************************************* 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci Translation from C++ and adaptation for use in ALSA-Driver 278c2ecf20Sopenharmony_ci were made by Giuliano Pochini <pochini@shiny.it> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci****************************************************************************/ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* These functions are common for Gina24, Layla24 and Mona cards */ 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* ASIC status check - some cards have one or two ASICs that need to be 368c2ecf20Sopenharmony_ciloaded. Once that load is complete, this function is called to see if 378c2ecf20Sopenharmony_cithe load was successful. 388c2ecf20Sopenharmony_ciIf this load fails, it does not necessarily mean that the hardware is 398c2ecf20Sopenharmony_cidefective - the external box may be disconnected or turned off. */ 408c2ecf20Sopenharmony_cistatic int check_asic_status(struct echoaudio *chip) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci u32 asic_status; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci send_vector(chip, DSP_VC_TEST_ASIC); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci /* The DSP will return a value to indicate whether or not the 478c2ecf20Sopenharmony_ci ASIC is currently loaded */ 488c2ecf20Sopenharmony_ci if (read_dsp(chip, &asic_status) < 0) { 498c2ecf20Sopenharmony_ci dev_err(chip->card->dev, 508c2ecf20Sopenharmony_ci "check_asic_status: failed on read_dsp\n"); 518c2ecf20Sopenharmony_ci chip->asic_loaded = false; 528c2ecf20Sopenharmony_ci return -EIO; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED); 568c2ecf20Sopenharmony_ci return chip->asic_loaded ? 0 : -EIO; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* Most configuration of Gina24, Layla24, or Mona is accomplished by writing 628c2ecf20Sopenharmony_cithe control register. write_control_reg sends the new control register 638c2ecf20Sopenharmony_civalue to the DSP. */ 648c2ecf20Sopenharmony_cistatic int write_control_reg(struct echoaudio *chip, u32 value, char force) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci __le32 reg_value; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci /* Handle the digital input auto-mute */ 698c2ecf20Sopenharmony_ci if (chip->digital_in_automute) 708c2ecf20Sopenharmony_ci value |= GML_DIGITAL_IN_AUTO_MUTE; 718c2ecf20Sopenharmony_ci else 728c2ecf20Sopenharmony_ci value &= ~GML_DIGITAL_IN_AUTO_MUTE; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci dev_dbg(chip->card->dev, "write_control_reg: 0x%x\n", value); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* Write the control register */ 778c2ecf20Sopenharmony_ci reg_value = cpu_to_le32(value); 788c2ecf20Sopenharmony_ci if (reg_value != chip->comm_page->control_register || force) { 798c2ecf20Sopenharmony_ci if (wait_handshake(chip)) 808c2ecf20Sopenharmony_ci return -EIO; 818c2ecf20Sopenharmony_ci chip->comm_page->control_register = reg_value; 828c2ecf20Sopenharmony_ci clear_handshake(chip); 838c2ecf20Sopenharmony_ci return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci return 0; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/* Gina24, Layla24, and Mona support digital input auto-mute. If the digital 918c2ecf20Sopenharmony_ciinput auto-mute is enabled, the DSP will only enable the digital inputs if 928c2ecf20Sopenharmony_cithe card is syncing to a valid clock on the ADAT or S/PDIF inputs. 938c2ecf20Sopenharmony_ciIf the auto-mute is disabled, the digital inputs are enabled regardless of 948c2ecf20Sopenharmony_ciwhat the input clock is set or what is connected. */ 958c2ecf20Sopenharmony_cistatic int set_input_auto_mute(struct echoaudio *chip, int automute) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci dev_dbg(chip->card->dev, "set_input_auto_mute %d\n", automute); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci chip->digital_in_automute = automute; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci /* Re-set the input clock to the current value - indirectly causes 1028c2ecf20Sopenharmony_ci the auto-mute flag to be sent to the DSP */ 1038c2ecf20Sopenharmony_ci return set_input_clock(chip, chip->input_clock); 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* S/PDIF coax / S/PDIF optical / ADAT - switch */ 1098c2ecf20Sopenharmony_cistatic int set_digital_mode(struct echoaudio *chip, u8 mode) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci u8 previous_mode; 1128c2ecf20Sopenharmony_ci int err, i, o; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (chip->bad_board) 1158c2ecf20Sopenharmony_ci return -EIO; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* All audio channels must be closed before changing the digital mode */ 1188c2ecf20Sopenharmony_ci if (snd_BUG_ON(chip->pipe_alloc_mask)) 1198c2ecf20Sopenharmony_ci return -EAGAIN; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (snd_BUG_ON(!(chip->digital_modes & (1 << mode)))) 1228c2ecf20Sopenharmony_ci return -EINVAL; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci previous_mode = chip->digital_mode; 1258c2ecf20Sopenharmony_ci err = dsp_set_digital_mode(chip, mode); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* If we successfully changed the digital mode from or to ADAT, 1288c2ecf20Sopenharmony_ci then make sure all output, input and monitor levels are 1298c2ecf20Sopenharmony_ci updated by the DSP comm object. */ 1308c2ecf20Sopenharmony_ci if (err >= 0 && previous_mode != mode && 1318c2ecf20Sopenharmony_ci (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { 1328c2ecf20Sopenharmony_ci spin_lock_irq(&chip->lock); 1338c2ecf20Sopenharmony_ci for (o = 0; o < num_busses_out(chip); o++) 1348c2ecf20Sopenharmony_ci for (i = 0; i < num_busses_in(chip); i++) 1358c2ecf20Sopenharmony_ci set_monitor_gain(chip, o, i, 1368c2ecf20Sopenharmony_ci chip->monitor_gain[o][i]); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci#ifdef ECHOCARD_HAS_INPUT_GAIN 1398c2ecf20Sopenharmony_ci for (i = 0; i < num_busses_in(chip); i++) 1408c2ecf20Sopenharmony_ci set_input_gain(chip, i, chip->input_gain[i]); 1418c2ecf20Sopenharmony_ci update_input_line_level(chip); 1428c2ecf20Sopenharmony_ci#endif 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci for (o = 0; o < num_busses_out(chip); o++) 1458c2ecf20Sopenharmony_ci set_output_gain(chip, o, chip->output_gain[o]); 1468c2ecf20Sopenharmony_ci update_output_line_level(chip); 1478c2ecf20Sopenharmony_ci spin_unlock_irq(&chip->lock); 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci return err; 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci/* Set the S/PDIF output format */ 1568c2ecf20Sopenharmony_cistatic int set_professional_spdif(struct echoaudio *chip, char prof) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci u32 control_reg; 1598c2ecf20Sopenharmony_ci int err; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci /* Clear the current S/PDIF flags */ 1628c2ecf20Sopenharmony_ci control_reg = le32_to_cpu(chip->comm_page->control_register); 1638c2ecf20Sopenharmony_ci control_reg &= GML_SPDIF_FORMAT_CLEAR_MASK; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* Set the new S/PDIF flags depending on the mode */ 1668c2ecf20Sopenharmony_ci control_reg |= GML_SPDIF_TWO_CHANNEL | GML_SPDIF_24_BIT | 1678c2ecf20Sopenharmony_ci GML_SPDIF_COPY_PERMIT; 1688c2ecf20Sopenharmony_ci if (prof) { 1698c2ecf20Sopenharmony_ci /* Professional mode */ 1708c2ecf20Sopenharmony_ci control_reg |= GML_SPDIF_PRO_MODE; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci switch (chip->sample_rate) { 1738c2ecf20Sopenharmony_ci case 32000: 1748c2ecf20Sopenharmony_ci control_reg |= GML_SPDIF_SAMPLE_RATE0 | 1758c2ecf20Sopenharmony_ci GML_SPDIF_SAMPLE_RATE1; 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci case 44100: 1788c2ecf20Sopenharmony_ci control_reg |= GML_SPDIF_SAMPLE_RATE0; 1798c2ecf20Sopenharmony_ci break; 1808c2ecf20Sopenharmony_ci case 48000: 1818c2ecf20Sopenharmony_ci control_reg |= GML_SPDIF_SAMPLE_RATE1; 1828c2ecf20Sopenharmony_ci break; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci } else { 1858c2ecf20Sopenharmony_ci /* Consumer mode */ 1868c2ecf20Sopenharmony_ci switch (chip->sample_rate) { 1878c2ecf20Sopenharmony_ci case 32000: 1888c2ecf20Sopenharmony_ci control_reg |= GML_SPDIF_SAMPLE_RATE0 | 1898c2ecf20Sopenharmony_ci GML_SPDIF_SAMPLE_RATE1; 1908c2ecf20Sopenharmony_ci break; 1918c2ecf20Sopenharmony_ci case 48000: 1928c2ecf20Sopenharmony_ci control_reg |= GML_SPDIF_SAMPLE_RATE1; 1938c2ecf20Sopenharmony_ci break; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if ((err = write_control_reg(chip, control_reg, false))) 1988c2ecf20Sopenharmony_ci return err; 1998c2ecf20Sopenharmony_ci chip->professional_spdif = prof; 2008c2ecf20Sopenharmony_ci dev_dbg(chip->card->dev, "set_professional_spdif to %s\n", 2018c2ecf20Sopenharmony_ci prof ? "Professional" : "Consumer"); 2028c2ecf20Sopenharmony_ci return 0; 2038c2ecf20Sopenharmony_ci} 204