linux/sound/pci/echoaudio/mia_dsp.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
  32static int set_input_clock(struct echoaudio *chip, u16 clock);
  33static int set_professional_spdif(struct echoaudio *chip, char prof);
  34static int update_flags(struct echoaudio *chip);
  35static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
  36                           int gain);
  37static int update_vmixer_level(struct echoaudio *chip);
  38
  39
  40static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
  41{
  42        int err;
  43
  44        if (snd_BUG_ON((subdevice_id & 0xfff0) != MIA))
  45                return -ENODEV;
  46
  47        err = init_dsp_comm_page(chip);
  48        if (err) {
  49                dev_err(chip->card->dev,
  50                        "init_hw - could not initialize DSP comm page\n");
  51                return err;
  52        }
  53
  54        chip->device_id = device_id;
  55        chip->subdevice_id = subdevice_id;
  56        chip->bad_board = true;
  57        chip->dsp_code_to_load = FW_MIA_DSP;
  58        /* Since this card has no ASIC, mark it as loaded so everything
  59           works OK */
  60        chip->asic_loaded = true;
  61        if ((subdevice_id & 0x0000f) == MIA_MIDI_REV)
  62                chip->has_midi = true;
  63        chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
  64                ECHO_CLOCK_BIT_SPDIF;
  65
  66        err = load_firmware(chip);
  67        if (err < 0)
  68                return err;
  69        chip->bad_board = false;
  70
  71        return err;
  72}
  73
  74
  75
  76static int set_mixer_defaults(struct echoaudio *chip)
  77{
  78        return init_line_levels(chip);
  79}
  80
  81
  82
  83static u32 detect_input_clocks(const struct echoaudio *chip)
  84{
  85        u32 clocks_from_dsp, clock_bits;
  86
  87        /* Map the DSP clock detect bits to the generic driver clock
  88           detect bits */
  89        clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
  90
  91        clock_bits = ECHO_CLOCK_BIT_INTERNAL;
  92
  93        if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
  94                clock_bits |= ECHO_CLOCK_BIT_SPDIF;
  95
  96        return clock_bits;
  97}
  98
  99
 100
 101/* The Mia has no ASIC. Just do nothing */
 102static int load_asic(struct echoaudio *chip)
 103{
 104        return 0;
 105}
 106
 107
 108
 109static int set_sample_rate(struct echoaudio *chip, u32 rate)
 110{
 111        u32 control_reg;
 112
 113        switch (rate) {
 114        case 96000:
 115                control_reg = MIA_96000;
 116                break;
 117        case 88200:
 118                control_reg = MIA_88200;
 119                break;
 120        case 48000:
 121                control_reg = MIA_48000;
 122                break;
 123        case 44100:
 124                control_reg = MIA_44100;
 125                break;
 126        case 32000:
 127                control_reg = MIA_32000;
 128                break;
 129        default:
 130                dev_err(chip->card->dev,
 131                        "set_sample_rate: %d invalid!\n", rate);
 132                return -EINVAL;
 133        }
 134
 135        /* Override the clock setting if this Mia is set to S/PDIF clock */
 136        if (chip->input_clock == ECHO_CLOCK_SPDIF)
 137                control_reg |= MIA_SPDIF;
 138
 139        /* Set the control register if it has changed */
 140        if (control_reg != le32_to_cpu(chip->comm_page->control_register)) {
 141                if (wait_handshake(chip))
 142                        return -EIO;
 143
 144                chip->comm_page->sample_rate = cpu_to_le32(rate);       /* ignored by the DSP */
 145                chip->comm_page->control_register = cpu_to_le32(control_reg);
 146                chip->sample_rate = rate;
 147
 148                clear_handshake(chip);
 149                return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
 150        }
 151        return 0;
 152}
 153
 154
 155
 156static int set_input_clock(struct echoaudio *chip, u16 clock)
 157{
 158        dev_dbg(chip->card->dev, "set_input_clock(%d)\n", clock);
 159        if (snd_BUG_ON(clock != ECHO_CLOCK_INTERNAL &&
 160                       clock != ECHO_CLOCK_SPDIF))
 161                return -EINVAL;
 162
 163        chip->input_clock = clock;
 164        return set_sample_rate(chip, chip->sample_rate);
 165}
 166
 167
 168
 169/* This function routes the sound from a virtual channel to a real output */
 170static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
 171                           int gain)
 172{
 173        int index;
 174
 175        if (snd_BUG_ON(pipe >= num_pipes_out(chip) ||
 176                       output >= num_busses_out(chip)))
 177                return -EINVAL;
 178
 179        if (wait_handshake(chip))
 180                return -EIO;
 181
 182        chip->vmixer_gain[output][pipe] = gain;
 183        index = output * num_pipes_out(chip) + pipe;
 184        chip->comm_page->vmixer[index] = gain;
 185
 186        dev_dbg(chip->card->dev,
 187                "set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain);
 188        return 0;
 189}
 190
 191
 192
 193/* Tell the DSP to read and update virtual mixer levels in comm page. */
 194static int update_vmixer_level(struct echoaudio *chip)
 195{
 196        if (wait_handshake(chip))
 197                return -EIO;
 198        clear_handshake(chip);
 199        return send_vector(chip, DSP_VC_SET_VMIXER_GAIN);
 200}
 201
 202
 203
 204/* Tell the DSP to reread the flags from the comm page */
 205static int update_flags(struct echoaudio *chip)
 206{
 207        if (wait_handshake(chip))
 208                return -EIO;
 209        clear_handshake(chip);
 210        return send_vector(chip, DSP_VC_UPDATE_FLAGS);
 211}
 212
 213
 214
 215static int set_professional_spdif(struct echoaudio *chip, char prof)
 216{
 217        dev_dbg(chip->card->dev, "set_professional_spdif %d\n", prof);
 218        if (prof)
 219                chip->comm_page->flags |=
 220                        cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 221        else
 222                chip->comm_page->flags &=
 223                        ~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 224        chip->professional_spdif = prof;
 225        return update_flags(chip);
 226}
 227
 228