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        if ((err = init_dsp_comm_page(chip))) {
  47                dev_err(chip->card->dev,
  48                        "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        return err;
  68}
  69
  70
  71
  72static int set_mixer_defaults(struct echoaudio *chip)
  73{
  74        chip->professional_spdif = false;
  75        return init_line_levels(chip);
  76}
  77
  78
  79
  80static u32 detect_input_clocks(const struct echoaudio *chip)
  81{
  82        u32 clocks_from_dsp, clock_bits;
  83
  84        /* Map the DSP clock detect bits to the generic driver clock detect bits */
  85        clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
  86
  87        clock_bits = ECHO_CLOCK_BIT_INTERNAL;
  88
  89        if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
  90                clock_bits |= ECHO_CLOCK_BIT_SPDIF;
  91
  92        if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_WORD) {
  93                if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SUPER)
  94                        clock_bits |= ECHO_CLOCK_BIT_SUPER;
  95                else
  96                        clock_bits |= ECHO_CLOCK_BIT_WORD;
  97        }
  98
  99        return clock_bits;
 100}
 101
 102
 103
 104/* ASIC status check - some cards have one or two ASICs that need to be
 105loaded.  Once that load is complete, this function is called to see if
 106the load was successful.
 107If this load fails, it does not necessarily mean that the hardware is
 108defective - the external box may be disconnected or turned off.
 109This routine sometimes fails for Layla20; for Layla20, the loop runs
 1105 times and succeeds if it wins on three of the loops. */
 111static int check_asic_status(struct echoaudio *chip)
 112{
 113        u32 asic_status;
 114        int goodcnt, i;
 115
 116        chip->asic_loaded = false;
 117        for (i = goodcnt = 0; i < 5; i++) {
 118                send_vector(chip, DSP_VC_TEST_ASIC);
 119
 120                /* The DSP will return a value to indicate whether or not
 121                   the ASIC is currently loaded */
 122                if (read_dsp(chip, &asic_status) < 0) {
 123                        dev_err(chip->card->dev,
 124                                "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                dev_warn(chip->card->dev,
 168                         "Cannot set sample rate - 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        dev_dbg(chip->card->dev, "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        rate = 0;
 192        switch (clock_source) {
 193        case ECHO_CLOCK_INTERNAL:
 194                rate = chip->sample_rate;
 195                clock = LAYLA20_CLOCK_INTERNAL;
 196                break;
 197        case ECHO_CLOCK_SPDIF:
 198                clock = LAYLA20_CLOCK_SPDIF;
 199                break;
 200        case ECHO_CLOCK_WORD:
 201                clock = LAYLA20_CLOCK_WORD;
 202                break;
 203        case ECHO_CLOCK_SUPER:
 204                clock = LAYLA20_CLOCK_SUPER;
 205                break;
 206        default:
 207                dev_err(chip->card->dev,
 208                        "Input clock 0x%x not supported for Layla24\n",
 209                        clock_source);
 210                return -EINVAL;
 211        }
 212        chip->input_clock = clock_source;
 213
 214        chip->comm_page->input_clock = cpu_to_le16(clock);
 215        clear_handshake(chip);
 216        send_vector(chip, DSP_VC_UPDATE_CLOCKS);
 217
 218        if (rate)
 219                set_sample_rate(chip, rate);
 220
 221        return 0;
 222}
 223
 224
 225
 226static int set_output_clock(struct echoaudio *chip, u16 clock)
 227{
 228        switch (clock) {
 229        case ECHO_CLOCK_SUPER:
 230                clock = LAYLA20_OUTPUT_CLOCK_SUPER;
 231                break;
 232        case ECHO_CLOCK_WORD:
 233                clock = LAYLA20_OUTPUT_CLOCK_WORD;
 234                break;
 235        default:
 236                dev_err(chip->card->dev, "set_output_clock wrong clock\n");
 237                return -EINVAL;
 238        }
 239
 240        if (wait_handshake(chip))
 241                return -EIO;
 242
 243        chip->comm_page->output_clock = cpu_to_le16(clock);
 244        chip->output_clock = clock;
 245        clear_handshake(chip);
 246        return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
 247}
 248
 249
 250
 251/* Set input bus gain (one unit is 0.5dB !) */
 252static int set_input_gain(struct echoaudio *chip, u16 input, int gain)
 253{
 254        if (snd_BUG_ON(input >= num_busses_in(chip)))
 255                return -EINVAL;
 256
 257        if (wait_handshake(chip))
 258                return -EIO;
 259
 260        chip->input_gain[input] = gain;
 261        gain += GL20_INPUT_GAIN_MAGIC_NUMBER;
 262        chip->comm_page->line_in_level[input] = gain;
 263        return 0;
 264}
 265
 266
 267
 268/* Tell the DSP to reread the flags from the comm page */
 269static int update_flags(struct echoaudio *chip)
 270{
 271        if (wait_handshake(chip))
 272                return -EIO;
 273        clear_handshake(chip);
 274        return send_vector(chip, DSP_VC_UPDATE_FLAGS);
 275}
 276
 277
 278
 279static int set_professional_spdif(struct echoaudio *chip, char prof)
 280{
 281        if (prof)
 282                chip->comm_page->flags |=
 283                        cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 284        else
 285                chip->comm_page->flags &=
 286                        ~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 287        chip->professional_spdif = prof;
 288        return update_flags(chip);
 289}
 290