linux/sound/pci/echoaudio/layla20_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 read_dsp(struct echoaudio *chip, u32 *data);
  33static int set_professional_spdif(struct echoaudio *chip, char prof);
  34static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic);
  35static int check_asic_status(struct echoaudio *chip);
  36static int update_flags(struct echoaudio *chip);
  37
  38
  39static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
  40{
  41        int err;
  42
  43        if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA20))
  44                return -ENODEV;
  45
  46        err = init_dsp_comm_page(chip);
  47        if (err) {
  48                dev_err(chip->card->dev,
  49                        "init_hw - could not initialize DSP comm page\n");
  50                return err;
  51        }
  52
  53        chip->device_id = device_id;
  54        chip->subdevice_id = subdevice_id;
  55        chip->bad_board = true;
  56        chip->has_midi = true;
  57        chip->dsp_code_to_load = FW_LAYLA20_DSP;
  58        chip->input_clock_types =
  59                ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |
  60                ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER;
  61        chip->output_clock_types =
  62                ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER;
  63
  64        err = load_firmware(chip);
  65        if (err < 0)
  66                return err;
  67        chip->bad_board = false;
  68
  69        return err;
  70}
  71
  72
  73
  74static int set_mixer_defaults(struct echoaudio *chip)
  75{
  76        chip->professional_spdif = false;
  77        return init_line_levels(chip);
  78}
  79
  80
  81
  82static u32 detect_input_clocks(const struct echoaudio *chip)
  83{
  84        u32 clocks_from_dsp, clock_bits;
  85
  86        /* Map the DSP clock detect bits to the generic driver clock detect bits */
  87        clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
  88
  89        clock_bits = ECHO_CLOCK_BIT_INTERNAL;
  90
  91        if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
  92                clock_bits |= ECHO_CLOCK_BIT_SPDIF;
  93
  94        if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_WORD) {
  95                if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SUPER)
  96                        clock_bits |= ECHO_CLOCK_BIT_SUPER;
  97                else
  98                        clock_bits |= ECHO_CLOCK_BIT_WORD;
  99        }
 100
 101        return clock_bits;
 102}
 103
 104
 105
 106/* ASIC status check - some cards have one or two ASICs that need to be
 107loaded.  Once that load is complete, this function is called to see if
 108the load was successful.
 109If this load fails, it does not necessarily mean that the hardware is
 110defective - the external box may be disconnected or turned off.
 111This routine sometimes fails for Layla20; for Layla20, the loop runs
 1125 times and succeeds if it wins on three of the loops. */
 113static int check_asic_status(struct echoaudio *chip)
 114{
 115        u32 asic_status;
 116        int goodcnt, i;
 117
 118        chip->asic_loaded = false;
 119        for (i = goodcnt = 0; i < 5; i++) {
 120                send_vector(chip, DSP_VC_TEST_ASIC);
 121
 122                /* The DSP will return a value to indicate whether or not
 123                   the ASIC is currently loaded */
 124                if (read_dsp(chip, &asic_status) < 0) {
 125                        dev_err(chip->card->dev,
 126                                "check_asic_status: failed on read_dsp\n");
 127                        return -EIO;
 128                }
 129
 130                if (asic_status == ASIC_ALREADY_LOADED) {
 131                        if (++goodcnt == 3) {
 132                                chip->asic_loaded = true;
 133                                return 0;
 134                        }
 135                }
 136        }
 137        return -EIO;
 138}
 139
 140
 141
 142/* Layla20 has an ASIC in the external box */
 143static int load_asic(struct echoaudio *chip)
 144{
 145        int err;
 146
 147        if (chip->asic_loaded)
 148                return 0;
 149
 150        err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA_ASIC,
 151                                FW_LAYLA20_ASIC);
 152        if (err < 0)
 153                return err;
 154
 155        /* Check if ASIC is alive and well. */
 156        return check_asic_status(chip);
 157}
 158
 159
 160
 161static int set_sample_rate(struct echoaudio *chip, u32 rate)
 162{
 163        if (snd_BUG_ON(rate < 8000 || rate > 50000))
 164                return -EINVAL;
 165
 166        /* Only set the clock for internal mode. Do not return failure,
 167           simply treat it as a non-event. */
 168        if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
 169                dev_warn(chip->card->dev,
 170                         "Cannot set sample rate - clock not set to CLK_CLOCKININTERNAL\n");
 171                chip->comm_page->sample_rate = cpu_to_le32(rate);
 172                chip->sample_rate = rate;
 173                return 0;
 174        }
 175
 176        if (wait_handshake(chip))
 177                return -EIO;
 178
 179        dev_dbg(chip->card->dev, "set_sample_rate(%d)\n", rate);
 180        chip->sample_rate = rate;
 181        chip->comm_page->sample_rate = cpu_to_le32(rate);
 182        clear_handshake(chip);
 183        return send_vector(chip, DSP_VC_SET_LAYLA_SAMPLE_RATE);
 184}
 185
 186
 187
 188static int set_input_clock(struct echoaudio *chip, u16 clock_source)
 189{
 190        u16 clock;
 191        u32 rate;
 192
 193        rate = 0;
 194        switch (clock_source) {
 195        case ECHO_CLOCK_INTERNAL:
 196                rate = chip->sample_rate;
 197                clock = LAYLA20_CLOCK_INTERNAL;
 198                break;
 199        case ECHO_CLOCK_SPDIF:
 200                clock = LAYLA20_CLOCK_SPDIF;
 201                break;
 202        case ECHO_CLOCK_WORD:
 203                clock = LAYLA20_CLOCK_WORD;
 204                break;
 205        case ECHO_CLOCK_SUPER:
 206                clock = LAYLA20_CLOCK_SUPER;
 207                break;
 208        default:
 209                dev_err(chip->card->dev,
 210                        "Input clock 0x%x not supported for Layla24\n",
 211                        clock_source);
 212                return -EINVAL;
 213        }
 214        chip->input_clock = clock_source;
 215
 216        chip->comm_page->input_clock = cpu_to_le16(clock);
 217        clear_handshake(chip);
 218        send_vector(chip, DSP_VC_UPDATE_CLOCKS);
 219
 220        if (rate)
 221                set_sample_rate(chip, rate);
 222
 223        return 0;
 224}
 225
 226
 227
 228static int set_output_clock(struct echoaudio *chip, u16 clock)
 229{
 230        switch (clock) {
 231        case ECHO_CLOCK_SUPER:
 232                clock = LAYLA20_OUTPUT_CLOCK_SUPER;
 233                break;
 234        case ECHO_CLOCK_WORD:
 235                clock = LAYLA20_OUTPUT_CLOCK_WORD;
 236                break;
 237        default:
 238                dev_err(chip->card->dev, "set_output_clock wrong clock\n");
 239                return -EINVAL;
 240        }
 241
 242        if (wait_handshake(chip))
 243                return -EIO;
 244
 245        chip->comm_page->output_clock = cpu_to_le16(clock);
 246        chip->output_clock = clock;
 247        clear_handshake(chip);
 248        return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
 249}
 250
 251
 252
 253/* Set input bus gain (one unit is 0.5dB !) */
 254static int set_input_gain(struct echoaudio *chip, u16 input, int gain)
 255{
 256        if (snd_BUG_ON(input >= num_busses_in(chip)))
 257                return -EINVAL;
 258
 259        if (wait_handshake(chip))
 260                return -EIO;
 261
 262        chip->input_gain[input] = gain;
 263        gain += GL20_INPUT_GAIN_MAGIC_NUMBER;
 264        chip->comm_page->line_in_level[input] = gain;
 265        return 0;
 266}
 267
 268
 269
 270/* Tell the DSP to reread the flags from the comm page */
 271static int update_flags(struct echoaudio *chip)
 272{
 273        if (wait_handshake(chip))
 274                return -EIO;
 275        clear_handshake(chip);
 276        return send_vector(chip, DSP_VC_UPDATE_FLAGS);
 277}
 278
 279
 280
 281static int set_professional_spdif(struct echoaudio *chip, char prof)
 282{
 283        if (prof)
 284                chip->comm_page->flags |=
 285                        cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 286        else
 287                chip->comm_page->flags &=
 288                        ~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 289        chip->professional_spdif = prof;
 290        return update_flags(chip);
 291}
 292