linux/sound/pci/echoaudio/gina20_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_professional_spdif(struct echoaudio *chip, char prof);
  33static int update_flags(struct echoaudio *chip);
  34
  35
  36static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
  37{
  38        int err;
  39
  40        DE_INIT(("init_hw() - Gina20\n"));
  41        if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA20))
  42                return -ENODEV;
  43
  44        if ((err = init_dsp_comm_page(chip))) {
  45                DE_INIT(("init_hw - could not initialize DSP comm page\n"));
  46                return err;
  47        }
  48
  49        chip->device_id = device_id;
  50        chip->subdevice_id = subdevice_id;
  51        chip->bad_board = TRUE;
  52        chip->dsp_code_to_load = &card_fw[FW_GINA20_DSP];
  53        chip->spdif_status = GD_SPDIF_STATUS_UNDEF;
  54        chip->clock_state = GD_CLOCK_UNDEF;
  55        /* Since this card has no ASIC, mark it as loaded so everything
  56           works OK */
  57        chip->asic_loaded = TRUE;
  58        chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
  59                ECHO_CLOCK_BIT_SPDIF;
  60
  61        if ((err = load_firmware(chip)) < 0)
  62                return err;
  63        chip->bad_board = FALSE;
  64
  65        if ((err = init_line_levels(chip)) < 0)
  66                return err;
  67
  68        err = set_professional_spdif(chip, TRUE);
  69
  70        DE_INIT(("init_hw done\n"));
  71        return err;
  72}
  73
  74
  75
  76static u32 detect_input_clocks(const struct echoaudio *chip)
  77{
  78        u32 clocks_from_dsp, clock_bits;
  79
  80        /* Map the DSP clock detect bits to the generic driver clock
  81           detect bits */
  82        clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
  83
  84        clock_bits = ECHO_CLOCK_BIT_INTERNAL;
  85
  86        if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
  87                clock_bits |= ECHO_CLOCK_BIT_SPDIF;
  88
  89        return clock_bits;
  90}
  91
  92
  93
  94/* The Gina20 has no ASIC. Just do nothing */
  95static int load_asic(struct echoaudio *chip)
  96{
  97        return 0;
  98}
  99
 100
 101
 102static int set_sample_rate(struct echoaudio *chip, u32 rate)
 103{
 104        u8 clock_state, spdif_status;
 105
 106        if (wait_handshake(chip))
 107                return -EIO;
 108
 109        switch (rate) {
 110        case 44100:
 111                clock_state = GD_CLOCK_44;
 112                spdif_status = GD_SPDIF_STATUS_44;
 113                break;
 114        case 48000:
 115                clock_state = GD_CLOCK_48;
 116                spdif_status = GD_SPDIF_STATUS_48;
 117                break;
 118        default:
 119                clock_state = GD_CLOCK_NOCHANGE;
 120                spdif_status = GD_SPDIF_STATUS_NOCHANGE;
 121                break;
 122        }
 123
 124        if (chip->clock_state == clock_state)
 125                clock_state = GD_CLOCK_NOCHANGE;
 126        if (spdif_status == chip->spdif_status)
 127                spdif_status = GD_SPDIF_STATUS_NOCHANGE;
 128
 129        chip->comm_page->sample_rate = cpu_to_le32(rate);
 130        chip->comm_page->gd_clock_state = clock_state;
 131        chip->comm_page->gd_spdif_status = spdif_status;
 132        chip->comm_page->gd_resampler_state = 3;        /* magic number - should always be 3 */
 133
 134        /* Save the new audio state if it changed */
 135        if (clock_state != GD_CLOCK_NOCHANGE)
 136                chip->clock_state = clock_state;
 137        if (spdif_status != GD_SPDIF_STATUS_NOCHANGE)
 138                chip->spdif_status = spdif_status;
 139        chip->sample_rate = rate;
 140
 141        clear_handshake(chip);
 142        return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
 143}
 144
 145
 146
 147static int set_input_clock(struct echoaudio *chip, u16 clock)
 148{
 149        DE_ACT(("set_input_clock:\n"));
 150
 151        switch (clock) {
 152        case ECHO_CLOCK_INTERNAL:
 153                /* Reset the audio state to unknown (just in case) */
 154                chip->clock_state = GD_CLOCK_UNDEF;
 155                chip->spdif_status = GD_SPDIF_STATUS_UNDEF;
 156                set_sample_rate(chip, chip->sample_rate);
 157                chip->input_clock = clock;
 158                DE_ACT(("Set Gina clock to INTERNAL\n"));
 159                break;
 160        case ECHO_CLOCK_SPDIF:
 161                chip->comm_page->gd_clock_state = GD_CLOCK_SPDIFIN;
 162                chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_NOCHANGE;
 163                clear_handshake(chip);
 164                send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
 165                chip->clock_state = GD_CLOCK_SPDIFIN;
 166                DE_ACT(("Set Gina20 clock to SPDIF\n"));
 167                chip->input_clock = clock;
 168                break;
 169        default:
 170                return -EINVAL;
 171        }
 172
 173        return 0;
 174}
 175
 176
 177
 178/* Set input bus gain (one unit is 0.5dB !) */
 179static int set_input_gain(struct echoaudio *chip, u16 input, int gain)
 180{
 181        if (snd_BUG_ON(input >= num_busses_in(chip)))
 182                return -EINVAL;
 183
 184        if (wait_handshake(chip))
 185                return -EIO;
 186
 187        chip->input_gain[input] = gain;
 188        gain += GL20_INPUT_GAIN_MAGIC_NUMBER;
 189        chip->comm_page->line_in_level[input] = gain;
 190        return 0;
 191}
 192
 193
 194
 195/* Tell the DSP to reread the flags from the comm page */
 196static int update_flags(struct echoaudio *chip)
 197{
 198        if (wait_handshake(chip))
 199                return -EIO;
 200        clear_handshake(chip);
 201        return send_vector(chip, DSP_VC_UPDATE_FLAGS);
 202}
 203
 204
 205
 206static int set_professional_spdif(struct echoaudio *chip, char prof)
 207{
 208        DE_ACT(("set_professional_spdif %d\n", prof));
 209        if (prof)
 210                chip->comm_page->flags |=
 211                        __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 212        else
 213                chip->comm_page->flags &=
 214                        ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 215        chip->professional_spdif = prof;
 216        return update_flags(chip);
 217}
 218
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.