Path: blob/master/sound/pci/echoaudio/gina20_dsp.c
10817 views
/****************************************************************************12Copyright Echo Digital Audio Corporation (c) 1998 - 20043All rights reserved4www.echoaudio.com56This file is part of Echo Digital Audio's generic driver library.78Echo Digital Audio's generic driver library is free software;9you can redistribute it and/or modify it under the terms of10the GNU General Public License as published by the Free Software11Foundation.1213This program is distributed in the hope that it will be useful,14but WITHOUT ANY WARRANTY; without even the implied warranty of15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the16GNU General Public License for more details.1718You should have received a copy of the GNU General Public License19along with this program; if not, write to the Free Software20Foundation, Inc., 59 Temple Place - Suite 330, Boston,21MA 02111-1307, USA.2223*************************************************************************2425Translation from C++ and adaptation for use in ALSA-Driver26were made by Giuliano Pochini <[email protected]>2728****************************************************************************/293031static int set_professional_spdif(struct echoaudio *chip, char prof);32static int update_flags(struct echoaudio *chip);333435static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)36{37int err;3839DE_INIT(("init_hw() - Gina20\n"));40if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA20))41return -ENODEV;4243if ((err = init_dsp_comm_page(chip))) {44DE_INIT(("init_hw - could not initialize DSP comm page\n"));45return err;46}4748chip->device_id = device_id;49chip->subdevice_id = subdevice_id;50chip->bad_board = TRUE;51chip->dsp_code_to_load = FW_GINA20_DSP;52chip->spdif_status = GD_SPDIF_STATUS_UNDEF;53chip->clock_state = GD_CLOCK_UNDEF;54/* Since this card has no ASIC, mark it as loaded so everything55works OK */56chip->asic_loaded = TRUE;57chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |58ECHO_CLOCK_BIT_SPDIF;5960if ((err = load_firmware(chip)) < 0)61return err;62chip->bad_board = FALSE;6364DE_INIT(("init_hw done\n"));65return err;66}67686970static int set_mixer_defaults(struct echoaudio *chip)71{72chip->professional_spdif = FALSE;73return init_line_levels(chip);74}75767778static u32 detect_input_clocks(const struct echoaudio *chip)79{80u32 clocks_from_dsp, clock_bits;8182/* Map the DSP clock detect bits to the generic driver clock83detect bits */84clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);8586clock_bits = ECHO_CLOCK_BIT_INTERNAL;8788if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)89clock_bits |= ECHO_CLOCK_BIT_SPDIF;9091return clock_bits;92}93949596/* The Gina20 has no ASIC. Just do nothing */97static int load_asic(struct echoaudio *chip)98{99return 0;100}101102103104static int set_sample_rate(struct echoaudio *chip, u32 rate)105{106u8 clock_state, spdif_status;107108if (wait_handshake(chip))109return -EIO;110111switch (rate) {112case 44100:113clock_state = GD_CLOCK_44;114spdif_status = GD_SPDIF_STATUS_44;115break;116case 48000:117clock_state = GD_CLOCK_48;118spdif_status = GD_SPDIF_STATUS_48;119break;120default:121clock_state = GD_CLOCK_NOCHANGE;122spdif_status = GD_SPDIF_STATUS_NOCHANGE;123break;124}125126if (chip->clock_state == clock_state)127clock_state = GD_CLOCK_NOCHANGE;128if (spdif_status == chip->spdif_status)129spdif_status = GD_SPDIF_STATUS_NOCHANGE;130131chip->comm_page->sample_rate = cpu_to_le32(rate);132chip->comm_page->gd_clock_state = clock_state;133chip->comm_page->gd_spdif_status = spdif_status;134chip->comm_page->gd_resampler_state = 3; /* magic number - should always be 3 */135136/* Save the new audio state if it changed */137if (clock_state != GD_CLOCK_NOCHANGE)138chip->clock_state = clock_state;139if (spdif_status != GD_SPDIF_STATUS_NOCHANGE)140chip->spdif_status = spdif_status;141chip->sample_rate = rate;142143clear_handshake(chip);144return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);145}146147148149static int set_input_clock(struct echoaudio *chip, u16 clock)150{151DE_ACT(("set_input_clock:\n"));152153switch (clock) {154case ECHO_CLOCK_INTERNAL:155/* Reset the audio state to unknown (just in case) */156chip->clock_state = GD_CLOCK_UNDEF;157chip->spdif_status = GD_SPDIF_STATUS_UNDEF;158set_sample_rate(chip, chip->sample_rate);159chip->input_clock = clock;160DE_ACT(("Set Gina clock to INTERNAL\n"));161break;162case ECHO_CLOCK_SPDIF:163chip->comm_page->gd_clock_state = GD_CLOCK_SPDIFIN;164chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_NOCHANGE;165clear_handshake(chip);166send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);167chip->clock_state = GD_CLOCK_SPDIFIN;168DE_ACT(("Set Gina20 clock to SPDIF\n"));169chip->input_clock = clock;170break;171default:172return -EINVAL;173}174175return 0;176}177178179180/* Set input bus gain (one unit is 0.5dB !) */181static int set_input_gain(struct echoaudio *chip, u16 input, int gain)182{183if (snd_BUG_ON(input >= num_busses_in(chip)))184return -EINVAL;185186if (wait_handshake(chip))187return -EIO;188189chip->input_gain[input] = gain;190gain += GL20_INPUT_GAIN_MAGIC_NUMBER;191chip->comm_page->line_in_level[input] = gain;192return 0;193}194195196197/* Tell the DSP to reread the flags from the comm page */198static int update_flags(struct echoaudio *chip)199{200if (wait_handshake(chip))201return -EIO;202clear_handshake(chip);203return send_vector(chip, DSP_VC_UPDATE_FLAGS);204}205206207208static int set_professional_spdif(struct echoaudio *chip, char prof)209{210DE_ACT(("set_professional_spdif %d\n", prof));211if (prof)212chip->comm_page->flags |=213cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);214else215chip->comm_page->flags &=216~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);217chip->professional_spdif = prof;218return update_flags(chip);219}220221222