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