cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

echoaudio_gml.c (6052B)


      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
     32/* These functions are common for Gina24, Layla24 and Mona cards */
     33
     34
     35/* ASIC status check - some cards have one or two ASICs that need to be
     36loaded.  Once that load is complete, this function is called to see if
     37the load was successful.
     38If this load fails, it does not necessarily mean that the hardware is
     39defective - the external box may be disconnected or turned off. */
     40static int check_asic_status(struct echoaudio *chip)
     41{
     42	u32 asic_status;
     43
     44	send_vector(chip, DSP_VC_TEST_ASIC);
     45
     46	/* The DSP will return a value to indicate whether or not the
     47	   ASIC is currently loaded */
     48	if (read_dsp(chip, &asic_status) < 0) {
     49		dev_err(chip->card->dev,
     50			"check_asic_status: failed on read_dsp\n");
     51		chip->asic_loaded = false;
     52		return -EIO;
     53	}
     54
     55	chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED);
     56	return chip->asic_loaded ? 0 : -EIO;
     57}
     58
     59
     60
     61/* Most configuration of Gina24, Layla24, or Mona is accomplished by writing
     62the control register.  write_control_reg sends the new control register
     63value to the DSP. */
     64static int write_control_reg(struct echoaudio *chip, u32 value, char force)
     65{
     66	__le32 reg_value;
     67
     68	/* Handle the digital input auto-mute */
     69	if (chip->digital_in_automute)
     70		value |= GML_DIGITAL_IN_AUTO_MUTE;
     71	else
     72		value &= ~GML_DIGITAL_IN_AUTO_MUTE;
     73
     74	dev_dbg(chip->card->dev, "write_control_reg: 0x%x\n", value);
     75
     76	/* Write the control register */
     77	reg_value = cpu_to_le32(value);
     78	if (reg_value != chip->comm_page->control_register || force) {
     79		if (wait_handshake(chip))
     80			return -EIO;
     81		chip->comm_page->control_register = reg_value;
     82		clear_handshake(chip);
     83		return send_vector(chip, DSP_VC_WRITE_CONTROL_REG);
     84	}
     85	return 0;
     86}
     87
     88
     89
     90/* Gina24, Layla24, and Mona support digital input auto-mute.  If the digital
     91input auto-mute is enabled, the DSP will only enable the digital inputs if
     92the card is syncing to a valid clock on the ADAT or S/PDIF inputs.
     93If the auto-mute is disabled, the digital inputs are enabled regardless of
     94what the input clock is set or what is connected. */
     95static int set_input_auto_mute(struct echoaudio *chip, int automute)
     96{
     97	dev_dbg(chip->card->dev, "set_input_auto_mute %d\n", automute);
     98
     99	chip->digital_in_automute = automute;
    100
    101	/* Re-set the input clock to the current value - indirectly causes
    102	the auto-mute flag to be sent to the DSP */
    103	return set_input_clock(chip, chip->input_clock);
    104}
    105
    106
    107
    108/* S/PDIF coax / S/PDIF optical / ADAT - switch */
    109static int set_digital_mode(struct echoaudio *chip, u8 mode)
    110{
    111	u8 previous_mode;
    112	int err, i, o;
    113
    114	if (chip->bad_board)
    115		return -EIO;
    116
    117	/* All audio channels must be closed before changing the digital mode */
    118	if (snd_BUG_ON(chip->pipe_alloc_mask))
    119		return -EAGAIN;
    120
    121	if (snd_BUG_ON(!(chip->digital_modes & (1 << mode))))
    122		return -EINVAL;
    123
    124	previous_mode = chip->digital_mode;
    125	err = dsp_set_digital_mode(chip, mode);
    126
    127	/* If we successfully changed the digital mode from or to ADAT,
    128	   then make sure all output, input and monitor levels are
    129	   updated by the DSP comm object. */
    130	if (err >= 0 && previous_mode != mode &&
    131	    (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) {
    132		spin_lock_irq(&chip->lock);
    133		for (o = 0; o < num_busses_out(chip); o++)
    134			for (i = 0; i < num_busses_in(chip); i++)
    135				set_monitor_gain(chip, o, i,
    136						 chip->monitor_gain[o][i]);
    137
    138#ifdef ECHOCARD_HAS_INPUT_GAIN
    139		for (i = 0; i < num_busses_in(chip); i++)
    140			set_input_gain(chip, i, chip->input_gain[i]);
    141		update_input_line_level(chip);
    142#endif
    143
    144		for (o = 0; o < num_busses_out(chip); o++)
    145			set_output_gain(chip, o, chip->output_gain[o]);
    146		update_output_line_level(chip);
    147		spin_unlock_irq(&chip->lock);
    148	}
    149
    150	return err;
    151}
    152
    153
    154
    155/* Set the S/PDIF output format */
    156static int set_professional_spdif(struct echoaudio *chip, char prof)
    157{
    158	u32 control_reg;
    159	int err;
    160
    161	/* Clear the current S/PDIF flags */
    162	control_reg = le32_to_cpu(chip->comm_page->control_register);
    163	control_reg &= GML_SPDIF_FORMAT_CLEAR_MASK;
    164
    165	/* Set the new S/PDIF flags depending on the mode */
    166	control_reg |= GML_SPDIF_TWO_CHANNEL | GML_SPDIF_24_BIT |
    167		GML_SPDIF_COPY_PERMIT;
    168	if (prof) {
    169		/* Professional mode */
    170		control_reg |= GML_SPDIF_PRO_MODE;
    171
    172		switch (chip->sample_rate) {
    173		case 32000:
    174			control_reg |= GML_SPDIF_SAMPLE_RATE0 |
    175				GML_SPDIF_SAMPLE_RATE1;
    176			break;
    177		case 44100:
    178			control_reg |= GML_SPDIF_SAMPLE_RATE0;
    179			break;
    180		case 48000:
    181			control_reg |= GML_SPDIF_SAMPLE_RATE1;
    182			break;
    183		}
    184	} else {
    185		/* Consumer mode */
    186		switch (chip->sample_rate) {
    187		case 32000:
    188			control_reg |= GML_SPDIF_SAMPLE_RATE0 |
    189				GML_SPDIF_SAMPLE_RATE1;
    190			break;
    191		case 48000:
    192			control_reg |= GML_SPDIF_SAMPLE_RATE1;
    193			break;
    194		}
    195	}
    196
    197	err = write_control_reg(chip, control_reg, false);
    198	if (err)
    199		return err;
    200	chip->professional_spdif = prof;
    201	dev_dbg(chip->card->dev, "set_professional_spdif to %s\n",
    202		prof ? "Professional" : "Consumer");
    203	return 0;
    204}