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 3362306a36Sopenharmony_ci/* These functions are common for all "3G" cards */ 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic int check_asic_status(struct echoaudio *chip) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci u32 box_status; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci if (wait_handshake(chip)) 4162306a36Sopenharmony_ci return -EIO; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci chip->comm_page->ext_box_status = cpu_to_le32(E3G_ASIC_NOT_LOADED); 4462306a36Sopenharmony_ci chip->asic_loaded = false; 4562306a36Sopenharmony_ci clear_handshake(chip); 4662306a36Sopenharmony_ci send_vector(chip, DSP_VC_TEST_ASIC); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci if (wait_handshake(chip)) { 4962306a36Sopenharmony_ci chip->dsp_code = NULL; 5062306a36Sopenharmony_ci return -EIO; 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci box_status = le32_to_cpu(chip->comm_page->ext_box_status); 5462306a36Sopenharmony_ci dev_dbg(chip->card->dev, "box_status=%x\n", box_status); 5562306a36Sopenharmony_ci if (box_status == E3G_ASIC_NOT_LOADED) 5662306a36Sopenharmony_ci return -ENODEV; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci chip->asic_loaded = true; 5962306a36Sopenharmony_ci return box_status & E3G_BOX_TYPE_MASK; 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic inline u32 get_frq_reg(struct echoaudio *chip) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci return le32_to_cpu(chip->comm_page->e3g_frq_register); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* Most configuration of 3G cards is accomplished by writing the control 7262306a36Sopenharmony_ciregister. write_control_reg sends the new control register value to the DSP. */ 7362306a36Sopenharmony_cistatic int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq, 7462306a36Sopenharmony_ci char force) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci __le32 ctl_reg, frq_reg; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (wait_handshake(chip)) 7962306a36Sopenharmony_ci return -EIO; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci dev_dbg(chip->card->dev, 8262306a36Sopenharmony_ci "WriteControlReg: Setting 0x%x, 0x%x\n", ctl, frq); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci ctl_reg = cpu_to_le32(ctl); 8562306a36Sopenharmony_ci frq_reg = cpu_to_le32(frq); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (ctl_reg != chip->comm_page->control_register || 8862306a36Sopenharmony_ci frq_reg != chip->comm_page->e3g_frq_register || force) { 8962306a36Sopenharmony_ci chip->comm_page->e3g_frq_register = frq_reg; 9062306a36Sopenharmony_ci chip->comm_page->control_register = ctl_reg; 9162306a36Sopenharmony_ci clear_handshake(chip); 9262306a36Sopenharmony_ci return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci dev_dbg(chip->card->dev, "WriteControlReg: not written, no change\n"); 9662306a36Sopenharmony_ci return 0; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/* Set the digital mode - currently for Gina24, Layla24, Mona, 3G */ 10262306a36Sopenharmony_cistatic int set_digital_mode(struct echoaudio *chip, u8 mode) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci u8 previous_mode; 10562306a36Sopenharmony_ci int err, i, o; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /* All audio channels must be closed before changing the digital mode */ 10862306a36Sopenharmony_ci if (snd_BUG_ON(chip->pipe_alloc_mask)) 10962306a36Sopenharmony_ci return -EAGAIN; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci if (snd_BUG_ON(!(chip->digital_modes & (1 << mode)))) 11262306a36Sopenharmony_ci return -EINVAL; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci previous_mode = chip->digital_mode; 11562306a36Sopenharmony_ci err = dsp_set_digital_mode(chip, mode); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* If we successfully changed the digital mode from or to ADAT, 11862306a36Sopenharmony_ci * then make sure all output, input and monitor levels are 11962306a36Sopenharmony_ci * updated by the DSP comm object. */ 12062306a36Sopenharmony_ci if (err >= 0 && previous_mode != mode && 12162306a36Sopenharmony_ci (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { 12262306a36Sopenharmony_ci spin_lock_irq(&chip->lock); 12362306a36Sopenharmony_ci for (o = 0; o < num_busses_out(chip); o++) 12462306a36Sopenharmony_ci for (i = 0; i < num_busses_in(chip); i++) 12562306a36Sopenharmony_ci set_monitor_gain(chip, o, i, 12662306a36Sopenharmony_ci chip->monitor_gain[o][i]); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#ifdef ECHOCARD_HAS_INPUT_GAIN 12962306a36Sopenharmony_ci for (i = 0; i < num_busses_in(chip); i++) 13062306a36Sopenharmony_ci set_input_gain(chip, i, chip->input_gain[i]); 13162306a36Sopenharmony_ci update_input_line_level(chip); 13262306a36Sopenharmony_ci#endif 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci for (o = 0; o < num_busses_out(chip); o++) 13562306a36Sopenharmony_ci set_output_gain(chip, o, chip->output_gain[o]); 13662306a36Sopenharmony_ci update_output_line_level(chip); 13762306a36Sopenharmony_ci spin_unlock_irq(&chip->lock); 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci return err; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic u32 set_spdif_bits(struct echoaudio *chip, u32 control_reg, u32 rate) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci control_reg &= E3G_SPDIF_FORMAT_CLEAR_MASK; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci switch (rate) { 15062306a36Sopenharmony_ci case 32000 : 15162306a36Sopenharmony_ci control_reg |= E3G_SPDIF_SAMPLE_RATE0 | E3G_SPDIF_SAMPLE_RATE1; 15262306a36Sopenharmony_ci break; 15362306a36Sopenharmony_ci case 44100 : 15462306a36Sopenharmony_ci if (chip->professional_spdif) 15562306a36Sopenharmony_ci control_reg |= E3G_SPDIF_SAMPLE_RATE0; 15662306a36Sopenharmony_ci break; 15762306a36Sopenharmony_ci case 48000 : 15862306a36Sopenharmony_ci control_reg |= E3G_SPDIF_SAMPLE_RATE1; 15962306a36Sopenharmony_ci break; 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci if (chip->professional_spdif) 16362306a36Sopenharmony_ci control_reg |= E3G_SPDIF_PRO_MODE; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci if (chip->non_audio_spdif) 16662306a36Sopenharmony_ci control_reg |= E3G_SPDIF_NOT_AUDIO; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci control_reg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL | 16962306a36Sopenharmony_ci E3G_SPDIF_COPY_PERMIT; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return control_reg; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci/* Set the S/PDIF output format */ 17762306a36Sopenharmony_cistatic int set_professional_spdif(struct echoaudio *chip, char prof) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci u32 control_reg; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci control_reg = le32_to_cpu(chip->comm_page->control_register); 18262306a36Sopenharmony_ci chip->professional_spdif = prof; 18362306a36Sopenharmony_ci control_reg = set_spdif_bits(chip, control_reg, chip->sample_rate); 18462306a36Sopenharmony_ci return write_control_reg(chip, control_reg, get_frq_reg(chip), 0); 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci/* detect_input_clocks() returns a bitmask consisting of all the input clocks 19062306a36Sopenharmony_cicurrently connected to the hardware; this changes as the user connects and 19162306a36Sopenharmony_cidisconnects clock inputs. You should use this information to determine which 19262306a36Sopenharmony_ciclocks the user is allowed to select. */ 19362306a36Sopenharmony_cistatic u32 detect_input_clocks(const struct echoaudio *chip) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci u32 clocks_from_dsp, clock_bits; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* Map the DSP clock detect bits to the generic driver clock 19862306a36Sopenharmony_ci * detect bits */ 19962306a36Sopenharmony_ci clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci clock_bits = ECHO_CLOCK_BIT_INTERNAL; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD) 20462306a36Sopenharmony_ci clock_bits |= ECHO_CLOCK_BIT_WORD; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci switch(chip->digital_mode) { 20762306a36Sopenharmony_ci case DIGITAL_MODE_SPDIF_RCA: 20862306a36Sopenharmony_ci case DIGITAL_MODE_SPDIF_OPTICAL: 20962306a36Sopenharmony_ci if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF) 21062306a36Sopenharmony_ci clock_bits |= ECHO_CLOCK_BIT_SPDIF; 21162306a36Sopenharmony_ci break; 21262306a36Sopenharmony_ci case DIGITAL_MODE_ADAT: 21362306a36Sopenharmony_ci if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_ADAT) 21462306a36Sopenharmony_ci clock_bits |= ECHO_CLOCK_BIT_ADAT; 21562306a36Sopenharmony_ci break; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci return clock_bits; 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_cistatic int load_asic(struct echoaudio *chip) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci int box_type, err; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (chip->asic_loaded) 22862306a36Sopenharmony_ci return 0; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci /* Give the DSP a few milliseconds to settle down */ 23162306a36Sopenharmony_ci mdelay(2); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci err = load_asic_generic(chip, DSP_FNC_LOAD_3G_ASIC, FW_3G_ASIC); 23462306a36Sopenharmony_ci if (err < 0) 23562306a36Sopenharmony_ci return err; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci chip->asic_code = FW_3G_ASIC; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* Now give the new ASIC some time to set up */ 24062306a36Sopenharmony_ci msleep(1000); 24162306a36Sopenharmony_ci /* See if it worked */ 24262306a36Sopenharmony_ci box_type = check_asic_status(chip); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* Set up the control register if the load succeeded - 24562306a36Sopenharmony_ci * 48 kHz, internal clock, S/PDIF RCA mode */ 24662306a36Sopenharmony_ci if (box_type >= 0) { 24762306a36Sopenharmony_ci err = write_control_reg(chip, E3G_48KHZ, 24862306a36Sopenharmony_ci E3G_FREQ_REG_DEFAULT, true); 24962306a36Sopenharmony_ci if (err < 0) 25062306a36Sopenharmony_ci return err; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return box_type; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic int set_sample_rate(struct echoaudio *chip, u32 rate) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci u32 control_reg, clock, base_rate, frq_reg; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* Only set the clock for internal mode. */ 26362306a36Sopenharmony_ci if (chip->input_clock != ECHO_CLOCK_INTERNAL) { 26462306a36Sopenharmony_ci dev_warn(chip->card->dev, 26562306a36Sopenharmony_ci "Cannot set sample rate - clock not set to CLK_CLOCKININTERNAL\n"); 26662306a36Sopenharmony_ci /* Save the rate anyhow */ 26762306a36Sopenharmony_ci chip->comm_page->sample_rate = cpu_to_le32(rate); 26862306a36Sopenharmony_ci chip->sample_rate = rate; 26962306a36Sopenharmony_ci set_input_clock(chip, chip->input_clock); 27062306a36Sopenharmony_ci return 0; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci if (snd_BUG_ON(rate >= 50000 && 27462306a36Sopenharmony_ci chip->digital_mode == DIGITAL_MODE_ADAT)) 27562306a36Sopenharmony_ci return -EINVAL; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci clock = 0; 27862306a36Sopenharmony_ci control_reg = le32_to_cpu(chip->comm_page->control_register); 27962306a36Sopenharmony_ci control_reg &= E3G_CLOCK_CLEAR_MASK; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci switch (rate) { 28262306a36Sopenharmony_ci case 96000: 28362306a36Sopenharmony_ci clock = E3G_96KHZ; 28462306a36Sopenharmony_ci break; 28562306a36Sopenharmony_ci case 88200: 28662306a36Sopenharmony_ci clock = E3G_88KHZ; 28762306a36Sopenharmony_ci break; 28862306a36Sopenharmony_ci case 48000: 28962306a36Sopenharmony_ci clock = E3G_48KHZ; 29062306a36Sopenharmony_ci break; 29162306a36Sopenharmony_ci case 44100: 29262306a36Sopenharmony_ci clock = E3G_44KHZ; 29362306a36Sopenharmony_ci break; 29462306a36Sopenharmony_ci case 32000: 29562306a36Sopenharmony_ci clock = E3G_32KHZ; 29662306a36Sopenharmony_ci break; 29762306a36Sopenharmony_ci default: 29862306a36Sopenharmony_ci clock = E3G_CONTINUOUS_CLOCK; 29962306a36Sopenharmony_ci if (rate > 50000) 30062306a36Sopenharmony_ci clock |= E3G_DOUBLE_SPEED_MODE; 30162306a36Sopenharmony_ci break; 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci control_reg |= clock; 30562306a36Sopenharmony_ci control_reg = set_spdif_bits(chip, control_reg, rate); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci base_rate = rate; 30862306a36Sopenharmony_ci if (base_rate > 50000) 30962306a36Sopenharmony_ci base_rate /= 2; 31062306a36Sopenharmony_ci if (base_rate < 32000) 31162306a36Sopenharmony_ci base_rate = 32000; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci frq_reg = E3G_MAGIC_NUMBER / base_rate - 2; 31462306a36Sopenharmony_ci if (frq_reg > E3G_FREQ_REG_MAX) 31562306a36Sopenharmony_ci frq_reg = E3G_FREQ_REG_MAX; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ 31862306a36Sopenharmony_ci chip->sample_rate = rate; 31962306a36Sopenharmony_ci dev_dbg(chip->card->dev, 32062306a36Sopenharmony_ci "SetSampleRate: %d clock %x\n", rate, control_reg); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci /* Tell the DSP about it - DSP reads both control reg & freq reg */ 32362306a36Sopenharmony_ci return write_control_reg(chip, control_reg, frq_reg, 0); 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci/* Set the sample clock source to internal, S/PDIF, ADAT */ 32962306a36Sopenharmony_cistatic int set_input_clock(struct echoaudio *chip, u16 clock) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci u32 control_reg, clocks_from_dsp; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci /* Mask off the clock select bits */ 33562306a36Sopenharmony_ci control_reg = le32_to_cpu(chip->comm_page->control_register) & 33662306a36Sopenharmony_ci E3G_CLOCK_CLEAR_MASK; 33762306a36Sopenharmony_ci clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci switch (clock) { 34062306a36Sopenharmony_ci case ECHO_CLOCK_INTERNAL: 34162306a36Sopenharmony_ci chip->input_clock = ECHO_CLOCK_INTERNAL; 34262306a36Sopenharmony_ci return set_sample_rate(chip, chip->sample_rate); 34362306a36Sopenharmony_ci case ECHO_CLOCK_SPDIF: 34462306a36Sopenharmony_ci if (chip->digital_mode == DIGITAL_MODE_ADAT) 34562306a36Sopenharmony_ci return -EAGAIN; 34662306a36Sopenharmony_ci control_reg |= E3G_SPDIF_CLOCK; 34762306a36Sopenharmony_ci if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF96) 34862306a36Sopenharmony_ci control_reg |= E3G_DOUBLE_SPEED_MODE; 34962306a36Sopenharmony_ci else 35062306a36Sopenharmony_ci control_reg &= ~E3G_DOUBLE_SPEED_MODE; 35162306a36Sopenharmony_ci break; 35262306a36Sopenharmony_ci case ECHO_CLOCK_ADAT: 35362306a36Sopenharmony_ci if (chip->digital_mode != DIGITAL_MODE_ADAT) 35462306a36Sopenharmony_ci return -EAGAIN; 35562306a36Sopenharmony_ci control_reg |= E3G_ADAT_CLOCK; 35662306a36Sopenharmony_ci control_reg &= ~E3G_DOUBLE_SPEED_MODE; 35762306a36Sopenharmony_ci break; 35862306a36Sopenharmony_ci case ECHO_CLOCK_WORD: 35962306a36Sopenharmony_ci control_reg |= E3G_WORD_CLOCK; 36062306a36Sopenharmony_ci if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD96) 36162306a36Sopenharmony_ci control_reg |= E3G_DOUBLE_SPEED_MODE; 36262306a36Sopenharmony_ci else 36362306a36Sopenharmony_ci control_reg &= ~E3G_DOUBLE_SPEED_MODE; 36462306a36Sopenharmony_ci break; 36562306a36Sopenharmony_ci default: 36662306a36Sopenharmony_ci dev_err(chip->card->dev, 36762306a36Sopenharmony_ci "Input clock 0x%x not supported for Echo3G\n", clock); 36862306a36Sopenharmony_ci return -EINVAL; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci chip->input_clock = clock; 37262306a36Sopenharmony_ci return write_control_reg(chip, control_reg, get_frq_reg(chip), 1); 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci u32 control_reg; 38062306a36Sopenharmony_ci int err, incompatible_clock; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* Set clock to "internal" if it's not compatible with the new mode */ 38362306a36Sopenharmony_ci incompatible_clock = false; 38462306a36Sopenharmony_ci switch (mode) { 38562306a36Sopenharmony_ci case DIGITAL_MODE_SPDIF_OPTICAL: 38662306a36Sopenharmony_ci case DIGITAL_MODE_SPDIF_RCA: 38762306a36Sopenharmony_ci if (chip->input_clock == ECHO_CLOCK_ADAT) 38862306a36Sopenharmony_ci incompatible_clock = true; 38962306a36Sopenharmony_ci break; 39062306a36Sopenharmony_ci case DIGITAL_MODE_ADAT: 39162306a36Sopenharmony_ci if (chip->input_clock == ECHO_CLOCK_SPDIF) 39262306a36Sopenharmony_ci incompatible_clock = true; 39362306a36Sopenharmony_ci break; 39462306a36Sopenharmony_ci default: 39562306a36Sopenharmony_ci dev_err(chip->card->dev, 39662306a36Sopenharmony_ci "Digital mode not supported: %d\n", mode); 39762306a36Sopenharmony_ci return -EINVAL; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci spin_lock_irq(&chip->lock); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci if (incompatible_clock) { 40362306a36Sopenharmony_ci chip->sample_rate = 48000; 40462306a36Sopenharmony_ci set_input_clock(chip, ECHO_CLOCK_INTERNAL); 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci /* Clear the current digital mode */ 40862306a36Sopenharmony_ci control_reg = le32_to_cpu(chip->comm_page->control_register); 40962306a36Sopenharmony_ci control_reg &= E3G_DIGITAL_MODE_CLEAR_MASK; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci /* Tweak the control reg */ 41262306a36Sopenharmony_ci switch (mode) { 41362306a36Sopenharmony_ci case DIGITAL_MODE_SPDIF_OPTICAL: 41462306a36Sopenharmony_ci control_reg |= E3G_SPDIF_OPTICAL_MODE; 41562306a36Sopenharmony_ci break; 41662306a36Sopenharmony_ci case DIGITAL_MODE_SPDIF_RCA: 41762306a36Sopenharmony_ci /* E3G_SPDIF_OPTICAL_MODE bit cleared */ 41862306a36Sopenharmony_ci break; 41962306a36Sopenharmony_ci case DIGITAL_MODE_ADAT: 42062306a36Sopenharmony_ci control_reg |= E3G_ADAT_MODE; 42162306a36Sopenharmony_ci control_reg &= ~E3G_DOUBLE_SPEED_MODE; /* @@ useless */ 42262306a36Sopenharmony_ci break; 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci err = write_control_reg(chip, control_reg, get_frq_reg(chip), 1); 42662306a36Sopenharmony_ci spin_unlock_irq(&chip->lock); 42762306a36Sopenharmony_ci if (err < 0) 42862306a36Sopenharmony_ci return err; 42962306a36Sopenharmony_ci chip->digital_mode = mode; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci dev_dbg(chip->card->dev, "set_digital_mode(%d)\n", chip->digital_mode); 43262306a36Sopenharmony_ci return incompatible_clock; 43362306a36Sopenharmony_ci} 434