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