Path: blob/master/sound/pci/echoaudio/gina24_dsp.c
10818 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 write_control_reg(struct echoaudio *chip, u32 value, char force);32static int set_input_clock(struct echoaudio *chip, u16 clock);33static int set_professional_spdif(struct echoaudio *chip, char prof);34static int set_digital_mode(struct echoaudio *chip, u8 mode);35static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic);36static int check_asic_status(struct echoaudio *chip);373839static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)40{41int err;4243DE_INIT(("init_hw() - Gina24\n"));44if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA24))45return -ENODEV;4647if ((err = init_dsp_comm_page(chip))) {48DE_INIT(("init_hw - could not initialize DSP comm page\n"));49return err;50}5152chip->device_id = device_id;53chip->subdevice_id = subdevice_id;54chip->bad_board = TRUE;55chip->input_clock_types =56ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |57ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96 |58ECHO_CLOCK_BIT_ADAT;5960/* Gina24 comes in both '301 and '361 flavors */61if (chip->device_id == DEVICE_ID_56361) {62chip->dsp_code_to_load = FW_GINA24_361_DSP;63chip->digital_modes =64ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |65ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |66ECHOCAPS_HAS_DIGITAL_MODE_ADAT;67} else {68chip->dsp_code_to_load = FW_GINA24_301_DSP;69chip->digital_modes =70ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |71ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |72ECHOCAPS_HAS_DIGITAL_MODE_ADAT |73ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM;74}7576if ((err = load_firmware(chip)) < 0)77return err;78chip->bad_board = FALSE;7980DE_INIT(("init_hw done\n"));81return err;82}83848586static int set_mixer_defaults(struct echoaudio *chip)87{88chip->digital_mode = DIGITAL_MODE_SPDIF_RCA;89chip->professional_spdif = FALSE;90chip->digital_in_automute = TRUE;91return init_line_levels(chip);92}93949596static u32 detect_input_clocks(const struct echoaudio *chip)97{98u32 clocks_from_dsp, clock_bits;99100/* Map the DSP clock detect bits to the generic driver clock101detect bits */102clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);103104clock_bits = ECHO_CLOCK_BIT_INTERNAL;105106if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF)107clock_bits |= ECHO_CLOCK_BIT_SPDIF;108109if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT)110clock_bits |= ECHO_CLOCK_BIT_ADAT;111112if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ESYNC)113clock_bits |= ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96;114115return clock_bits;116}117118119120/* Gina24 has an ASIC on the PCI card which must be loaded for anything121interesting to happen. */122static int load_asic(struct echoaudio *chip)123{124u32 control_reg;125int err;126short asic;127128if (chip->asic_loaded)129return 1;130131/* Give the DSP a few milliseconds to settle down */132mdelay(10);133134/* Pick the correct ASIC for '301 or '361 Gina24 */135if (chip->device_id == DEVICE_ID_56361)136asic = FW_GINA24_361_ASIC;137else138asic = FW_GINA24_301_ASIC;139140err = load_asic_generic(chip, DSP_FNC_LOAD_GINA24_ASIC, asic);141if (err < 0)142return err;143144chip->asic_code = asic;145146/* Now give the new ASIC a little time to set up */147mdelay(10);148/* See if it worked */149err = check_asic_status(chip);150151/* Set up the control register if the load succeeded -15248 kHz, internal clock, S/PDIF RCA mode */153if (!err) {154control_reg = GML_CONVERTER_ENABLE | GML_48KHZ;155err = write_control_reg(chip, control_reg, TRUE);156}157DE_INIT(("load_asic() done\n"));158return err;159}160161162163static int set_sample_rate(struct echoaudio *chip, u32 rate)164{165u32 control_reg, clock;166167if (snd_BUG_ON(rate >= 50000 &&168chip->digital_mode == DIGITAL_MODE_ADAT))169return -EINVAL;170171/* Only set the clock for internal mode. */172if (chip->input_clock != ECHO_CLOCK_INTERNAL) {173DE_ACT(("set_sample_rate: Cannot set sample rate - "174"clock not set to CLK_CLOCKININTERNAL\n"));175/* Save the rate anyhow */176chip->comm_page->sample_rate = cpu_to_le32(rate);177chip->sample_rate = rate;178return 0;179}180181clock = 0;182183control_reg = le32_to_cpu(chip->comm_page->control_register);184control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK;185186switch (rate) {187case 96000:188clock = GML_96KHZ;189break;190case 88200:191clock = GML_88KHZ;192break;193case 48000:194clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;195break;196case 44100:197clock = GML_44KHZ;198/* Professional mode ? */199if (control_reg & GML_SPDIF_PRO_MODE)200clock |= GML_SPDIF_SAMPLE_RATE0;201break;202case 32000:203clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 |204GML_SPDIF_SAMPLE_RATE1;205break;206case 22050:207clock = GML_22KHZ;208break;209case 16000:210clock = GML_16KHZ;211break;212case 11025:213clock = GML_11KHZ;214break;215case 8000:216clock = GML_8KHZ;217break;218default:219DE_ACT(("set_sample_rate: %d invalid!\n", rate));220return -EINVAL;221}222223control_reg |= clock;224225chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */226chip->sample_rate = rate;227DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock));228229return write_control_reg(chip, control_reg, FALSE);230}231232233234static int set_input_clock(struct echoaudio *chip, u16 clock)235{236u32 control_reg, clocks_from_dsp;237238DE_ACT(("set_input_clock:\n"));239240/* Mask off the clock select bits */241control_reg = le32_to_cpu(chip->comm_page->control_register) &242GML_CLOCK_CLEAR_MASK;243clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);244245switch (clock) {246case ECHO_CLOCK_INTERNAL:247DE_ACT(("Set Gina24 clock to INTERNAL\n"));248chip->input_clock = ECHO_CLOCK_INTERNAL;249return set_sample_rate(chip, chip->sample_rate);250case ECHO_CLOCK_SPDIF:251if (chip->digital_mode == DIGITAL_MODE_ADAT)252return -EAGAIN;253DE_ACT(("Set Gina24 clock to SPDIF\n"));254control_reg |= GML_SPDIF_CLOCK;255if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96)256control_reg |= GML_DOUBLE_SPEED_MODE;257else258control_reg &= ~GML_DOUBLE_SPEED_MODE;259break;260case ECHO_CLOCK_ADAT:261if (chip->digital_mode != DIGITAL_MODE_ADAT)262return -EAGAIN;263DE_ACT(("Set Gina24 clock to ADAT\n"));264control_reg |= GML_ADAT_CLOCK;265control_reg &= ~GML_DOUBLE_SPEED_MODE;266break;267case ECHO_CLOCK_ESYNC:268DE_ACT(("Set Gina24 clock to ESYNC\n"));269control_reg |= GML_ESYNC_CLOCK;270control_reg &= ~GML_DOUBLE_SPEED_MODE;271break;272case ECHO_CLOCK_ESYNC96:273DE_ACT(("Set Gina24 clock to ESYNC96\n"));274control_reg |= GML_ESYNC_CLOCK | GML_DOUBLE_SPEED_MODE;275break;276default:277DE_ACT(("Input clock 0x%x not supported for Gina24\n", clock));278return -EINVAL;279}280281chip->input_clock = clock;282return write_control_reg(chip, control_reg, TRUE);283}284285286287static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)288{289u32 control_reg;290int err, incompatible_clock;291292/* Set clock to "internal" if it's not compatible with the new mode */293incompatible_clock = FALSE;294switch (mode) {295case DIGITAL_MODE_SPDIF_OPTICAL:296case DIGITAL_MODE_SPDIF_CDROM:297case DIGITAL_MODE_SPDIF_RCA:298if (chip->input_clock == ECHO_CLOCK_ADAT)299incompatible_clock = TRUE;300break;301case DIGITAL_MODE_ADAT:302if (chip->input_clock == ECHO_CLOCK_SPDIF)303incompatible_clock = TRUE;304break;305default:306DE_ACT(("Digital mode not supported: %d\n", mode));307return -EINVAL;308}309310spin_lock_irq(&chip->lock);311312if (incompatible_clock) { /* Switch to 48KHz, internal */313chip->sample_rate = 48000;314set_input_clock(chip, ECHO_CLOCK_INTERNAL);315}316317/* Clear the current digital mode */318control_reg = le32_to_cpu(chip->comm_page->control_register);319control_reg &= GML_DIGITAL_MODE_CLEAR_MASK;320321/* Tweak the control reg */322switch (mode) {323case DIGITAL_MODE_SPDIF_OPTICAL:324control_reg |= GML_SPDIF_OPTICAL_MODE;325break;326case DIGITAL_MODE_SPDIF_CDROM:327/* '361 Gina24 cards do not have the S/PDIF CD-ROM mode */328if (chip->device_id == DEVICE_ID_56301)329control_reg |= GML_SPDIF_CDROM_MODE;330break;331case DIGITAL_MODE_SPDIF_RCA:332/* GML_SPDIF_OPTICAL_MODE bit cleared */333break;334case DIGITAL_MODE_ADAT:335control_reg |= GML_ADAT_MODE;336control_reg &= ~GML_DOUBLE_SPEED_MODE;337break;338}339340err = write_control_reg(chip, control_reg, TRUE);341spin_unlock_irq(&chip->lock);342if (err < 0)343return err;344chip->digital_mode = mode;345346DE_ACT(("set_digital_mode to %d\n", chip->digital_mode));347return incompatible_clock;348}349350351