Path: blob/master/sound/pci/echoaudio/layla24_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 Software Foundation.1112This program is distributed in the hope that it will be useful,13but WITHOUT ANY WARRANTY; without even the implied warranty of14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the15GNU General Public License for more details.1617You should have received a copy of the GNU General Public License18along with this program; if not, write to the Free Software19Foundation, Inc., 59 Temple Place - Suite 330, Boston,20MA 02111-1307, USA.2122*************************************************************************2324Translation from C++ and adaptation for use in ALSA-Driver25were made by Giuliano Pochini <[email protected]>2627****************************************************************************/282930static int write_control_reg(struct echoaudio *chip, u32 value, char force);31static int set_input_clock(struct echoaudio *chip, u16 clock);32static int set_professional_spdif(struct echoaudio *chip, char prof);33static int set_digital_mode(struct echoaudio *chip, u8 mode);34static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic);35static int check_asic_status(struct echoaudio *chip);363738static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)39{40int err;4142DE_INIT(("init_hw() - Layla24\n"));43if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA24))44return -ENODEV;4546if ((err = init_dsp_comm_page(chip))) {47DE_INIT(("init_hw - could not initialize DSP comm page\n"));48return err;49}5051chip->device_id = device_id;52chip->subdevice_id = subdevice_id;53chip->bad_board = TRUE;54chip->has_midi = TRUE;55chip->dsp_code_to_load = FW_LAYLA24_DSP;56chip->input_clock_types =57ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |58ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT;59chip->digital_modes =60ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |61ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |62ECHOCAPS_HAS_DIGITAL_MODE_ADAT;6364if ((err = load_firmware(chip)) < 0)65return err;66chip->bad_board = FALSE;6768if ((err = init_line_levels(chip)) < 0)69return err;7071DE_INIT(("init_hw done\n"));72return err;73}74757677static int set_mixer_defaults(struct echoaudio *chip)78{79chip->digital_mode = DIGITAL_MODE_SPDIF_RCA;80chip->professional_spdif = FALSE;81chip->digital_in_automute = TRUE;82return init_line_levels(chip);83}84858687static u32 detect_input_clocks(const struct echoaudio *chip)88{89u32 clocks_from_dsp, clock_bits;9091/* Map the DSP clock detect bits to the generic driver clock detect bits */92clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);9394clock_bits = ECHO_CLOCK_BIT_INTERNAL;9596if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF)97clock_bits |= ECHO_CLOCK_BIT_SPDIF;9899if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT)100clock_bits |= ECHO_CLOCK_BIT_ADAT;101102if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD)103clock_bits |= ECHO_CLOCK_BIT_WORD;104105return clock_bits;106}107108109110/* Layla24 has an ASIC on the PCI card and another ASIC in the external box;111both need to be loaded. */112static int load_asic(struct echoaudio *chip)113{114int err;115116if (chip->asic_loaded)117return 1;118119DE_INIT(("load_asic\n"));120121/* Give the DSP a few milliseconds to settle down */122mdelay(10);123124/* Load the ASIC for the PCI card */125err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC,126FW_LAYLA24_1_ASIC);127if (err < 0)128return err;129130chip->asic_code = FW_LAYLA24_2S_ASIC;131132/* Now give the new ASIC a little time to set up */133mdelay(10);134135/* Do the external one */136err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC,137FW_LAYLA24_2S_ASIC);138if (err < 0)139return FALSE;140141/* Now give the external ASIC a little time to set up */142mdelay(10);143144/* See if it worked */145err = check_asic_status(chip);146147/* Set up the control register if the load succeeded -14848 kHz, internal clock, S/PDIF RCA mode */149if (!err)150err = write_control_reg(chip, GML_CONVERTER_ENABLE | GML_48KHZ,151TRUE);152153DE_INIT(("load_asic() done\n"));154return err;155}156157158159static int set_sample_rate(struct echoaudio *chip, u32 rate)160{161u32 control_reg, clock, base_rate;162163if (snd_BUG_ON(rate >= 50000 &&164chip->digital_mode == DIGITAL_MODE_ADAT))165return -EINVAL;166167/* Only set the clock for internal mode. */168if (chip->input_clock != ECHO_CLOCK_INTERNAL) {169DE_ACT(("set_sample_rate: Cannot set sample rate - "170"clock not set to CLK_CLOCKININTERNAL\n"));171/* Save the rate anyhow */172chip->comm_page->sample_rate = cpu_to_le32(rate);173chip->sample_rate = rate;174return 0;175}176177/* Get the control register & clear the appropriate bits */178control_reg = le32_to_cpu(chip->comm_page->control_register);179control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK;180181clock = 0;182183switch (rate) {184case 96000:185clock = GML_96KHZ;186break;187case 88200:188clock = GML_88KHZ;189break;190case 48000:191clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;192break;193case 44100:194clock = GML_44KHZ;195/* Professional mode */196if (control_reg & GML_SPDIF_PRO_MODE)197clock |= GML_SPDIF_SAMPLE_RATE0;198break;199case 32000:200clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 |201GML_SPDIF_SAMPLE_RATE1;202break;203case 22050:204clock = GML_22KHZ;205break;206case 16000:207clock = GML_16KHZ;208break;209case 11025:210clock = GML_11KHZ;211break;212case 8000:213clock = GML_8KHZ;214break;215default:216/* If this is a non-standard rate, then the driver needs to217use Layla24's special "continuous frequency" mode */218clock = LAYLA24_CONTINUOUS_CLOCK;219if (rate > 50000) {220base_rate = rate >> 1;221control_reg |= GML_DOUBLE_SPEED_MODE;222} else {223base_rate = rate;224}225226if (base_rate < 25000)227base_rate = 25000;228229if (wait_handshake(chip))230return -EIO;231232chip->comm_page->sample_rate =233cpu_to_le32(LAYLA24_MAGIC_NUMBER / base_rate - 2);234235clear_handshake(chip);236send_vector(chip, DSP_VC_SET_LAYLA24_FREQUENCY_REG);237}238239control_reg |= clock;240241chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP ? */242chip->sample_rate = rate;243DE_ACT(("set_sample_rate: %d clock %d\n", rate, control_reg));244245return write_control_reg(chip, control_reg, FALSE);246}247248249250static int set_input_clock(struct echoaudio *chip, u16 clock)251{252u32 control_reg, clocks_from_dsp;253254/* Mask off the clock select bits */255control_reg = le32_to_cpu(chip->comm_page->control_register) &256GML_CLOCK_CLEAR_MASK;257clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);258259/* Pick the new clock */260switch (clock) {261case ECHO_CLOCK_INTERNAL:262DE_ACT(("Set Layla24 clock to INTERNAL\n"));263chip->input_clock = ECHO_CLOCK_INTERNAL;264return set_sample_rate(chip, chip->sample_rate);265case ECHO_CLOCK_SPDIF:266if (chip->digital_mode == DIGITAL_MODE_ADAT)267return -EAGAIN;268control_reg |= GML_SPDIF_CLOCK;269/* Layla24 doesn't support 96KHz S/PDIF */270control_reg &= ~GML_DOUBLE_SPEED_MODE;271DE_ACT(("Set Layla24 clock to SPDIF\n"));272break;273case ECHO_CLOCK_WORD:274control_reg |= GML_WORD_CLOCK;275if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD96)276control_reg |= GML_DOUBLE_SPEED_MODE;277else278control_reg &= ~GML_DOUBLE_SPEED_MODE;279DE_ACT(("Set Layla24 clock to WORD\n"));280break;281case ECHO_CLOCK_ADAT:282if (chip->digital_mode != DIGITAL_MODE_ADAT)283return -EAGAIN;284control_reg |= GML_ADAT_CLOCK;285control_reg &= ~GML_DOUBLE_SPEED_MODE;286DE_ACT(("Set Layla24 clock to ADAT\n"));287break;288default:289DE_ACT(("Input clock 0x%x not supported for Layla24\n", clock));290return -EINVAL;291}292293chip->input_clock = clock;294return write_control_reg(chip, control_reg, TRUE);295}296297298299/* Depending on what digital mode you want, Layla24 needs different ASICs300loaded. This function checks the ASIC needed for the new mode and sees301if it matches the one already loaded. */302static int switch_asic(struct echoaudio *chip, short asic)303{304s8 *monitors;305306/* Check to see if this is already loaded */307if (asic != chip->asic_code) {308monitors = kmemdup(chip->comm_page->monitors,309MONITOR_ARRAY_SIZE, GFP_KERNEL);310if (! monitors)311return -ENOMEM;312313memset(chip->comm_page->monitors, ECHOGAIN_MUTED,314MONITOR_ARRAY_SIZE);315316/* Load the desired ASIC */317if (load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC,318asic) < 0) {319memcpy(chip->comm_page->monitors, monitors,320MONITOR_ARRAY_SIZE);321kfree(monitors);322return -EIO;323}324chip->asic_code = asic;325memcpy(chip->comm_page->monitors, monitors, MONITOR_ARRAY_SIZE);326kfree(monitors);327}328329return 0;330}331332333334static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)335{336u32 control_reg;337int err, incompatible_clock;338short asic;339340/* Set clock to "internal" if it's not compatible with the new mode */341incompatible_clock = FALSE;342switch (mode) {343case DIGITAL_MODE_SPDIF_OPTICAL:344case DIGITAL_MODE_SPDIF_RCA:345if (chip->input_clock == ECHO_CLOCK_ADAT)346incompatible_clock = TRUE;347asic = FW_LAYLA24_2S_ASIC;348break;349case DIGITAL_MODE_ADAT:350if (chip->input_clock == ECHO_CLOCK_SPDIF)351incompatible_clock = TRUE;352asic = FW_LAYLA24_2A_ASIC;353break;354default:355DE_ACT(("Digital mode not supported: %d\n", mode));356return -EINVAL;357}358359if (incompatible_clock) { /* Switch to 48KHz, internal */360chip->sample_rate = 48000;361spin_lock_irq(&chip->lock);362set_input_clock(chip, ECHO_CLOCK_INTERNAL);363spin_unlock_irq(&chip->lock);364}365366/* switch_asic() can sleep */367if (switch_asic(chip, asic) < 0)368return -EIO;369370spin_lock_irq(&chip->lock);371372/* Tweak the control register */373control_reg = le32_to_cpu(chip->comm_page->control_register);374control_reg &= GML_DIGITAL_MODE_CLEAR_MASK;375376switch (mode) {377case DIGITAL_MODE_SPDIF_OPTICAL:378control_reg |= GML_SPDIF_OPTICAL_MODE;379break;380case DIGITAL_MODE_SPDIF_RCA:381/* GML_SPDIF_OPTICAL_MODE bit cleared */382break;383case DIGITAL_MODE_ADAT:384control_reg |= GML_ADAT_MODE;385control_reg &= ~GML_DOUBLE_SPEED_MODE;386break;387}388389err = write_control_reg(chip, control_reg, TRUE);390spin_unlock_irq(&chip->lock);391if (err < 0)392return err;393chip->digital_mode = mode;394395DE_ACT(("set_digital_mode to %d\n", mode));396return incompatible_clock;397}398399400