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

layla24_dsp.c (10240B)


      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 Foundation.
     12
     13   This program is distributed in the hope that it will be useful,
     14   but WITHOUT ANY WARRANTY; without even the implied warranty of
     15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16   GNU General Public License for more details.
     17
     18   You should have received a copy of the GNU General Public License
     19   along with this program; if not, write to the Free Software
     20   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
     21   MA  02111-1307, USA.
     22
     23   *************************************************************************
     24
     25 Translation from C++ and adaptation for use in ALSA-Driver
     26 were made by Giuliano Pochini <pochini@shiny.it>
     27
     28****************************************************************************/
     29
     30
     31static 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);
     37
     38
     39static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
     40{
     41	int err;
     42
     43	if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA24))
     44		return -ENODEV;
     45
     46	err = init_dsp_comm_page(chip);
     47	if (err) {
     48		dev_err(chip->card->dev,
     49			"init_hw - could not initialize DSP comm page\n");
     50		return err;
     51	}
     52
     53	chip->device_id = device_id;
     54	chip->subdevice_id = subdevice_id;
     55	chip->bad_board = true;
     56	chip->has_midi = true;
     57	chip->dsp_code_to_load = FW_LAYLA24_DSP;
     58	chip->input_clock_types =
     59		ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |
     60		ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT;
     61	chip->digital_modes =
     62		ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
     63		ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
     64		ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
     65
     66	err = load_firmware(chip);
     67	if (err < 0)
     68		return err;
     69	chip->bad_board = false;
     70
     71	err = init_line_levels(chip);
     72	if (err < 0)
     73		return err;
     74
     75	return err;
     76}
     77
     78
     79
     80static int set_mixer_defaults(struct echoaudio *chip)
     81{
     82	chip->digital_mode = DIGITAL_MODE_SPDIF_RCA;
     83	chip->professional_spdif = false;
     84	chip->digital_in_automute = true;
     85	return init_line_levels(chip);
     86}
     87
     88
     89
     90static u32 detect_input_clocks(const struct echoaudio *chip)
     91{
     92	u32 clocks_from_dsp, clock_bits;
     93
     94	/* Map the DSP clock detect bits to the generic driver clock detect bits */
     95	clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
     96
     97	clock_bits = ECHO_CLOCK_BIT_INTERNAL;
     98
     99	if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF)
    100		clock_bits |= ECHO_CLOCK_BIT_SPDIF;
    101
    102	if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT)
    103		clock_bits |= ECHO_CLOCK_BIT_ADAT;
    104
    105	if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD)
    106		clock_bits |= ECHO_CLOCK_BIT_WORD;
    107
    108	return clock_bits;
    109}
    110
    111
    112
    113/* Layla24 has an ASIC on the PCI card and another ASIC in the external box;
    114both need to be loaded. */
    115static int load_asic(struct echoaudio *chip)
    116{
    117	int err;
    118
    119	if (chip->asic_loaded)
    120		return 1;
    121
    122
    123	/* Give the DSP a few milliseconds to settle down */
    124	mdelay(10);
    125
    126	/* Load the ASIC for the PCI card */
    127	err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC,
    128				FW_LAYLA24_1_ASIC);
    129	if (err < 0)
    130		return err;
    131
    132	chip->asic_code = FW_LAYLA24_2S_ASIC;
    133
    134	/* Now give the new ASIC a little time to set up */
    135	mdelay(10);
    136
    137	/* Do the external one */
    138	err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC,
    139				FW_LAYLA24_2S_ASIC);
    140	if (err < 0)
    141		return err;
    142
    143	/* Now give the external ASIC a little time to set up */
    144	mdelay(10);
    145
    146	/* See if it worked */
    147	err = check_asic_status(chip);
    148
    149	/* Set up the control register if the load succeeded -
    150	   48 kHz, internal clock, S/PDIF RCA mode */
    151	if (!err)
    152		err = write_control_reg(chip, GML_CONVERTER_ENABLE | GML_48KHZ,
    153					true);
    154	
    155	return err;
    156}
    157
    158
    159
    160static int set_sample_rate(struct echoaudio *chip, u32 rate)
    161{
    162	u32 control_reg, clock, base_rate;
    163
    164	if (snd_BUG_ON(rate >= 50000 &&
    165		       chip->digital_mode == DIGITAL_MODE_ADAT))
    166		return -EINVAL;
    167
    168	/* Only set the clock for internal mode. */
    169	if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
    170		dev_warn(chip->card->dev,
    171			 "Cannot set sample rate - clock not set to CLK_CLOCKININTERNAL\n");
    172		/* Save the rate anyhow */
    173		chip->comm_page->sample_rate = cpu_to_le32(rate);
    174		chip->sample_rate = rate;
    175		return 0;
    176	}
    177
    178	/* Get the control register & clear the appropriate bits */
    179	control_reg = le32_to_cpu(chip->comm_page->control_register);
    180	control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK;
    181
    182	clock = 0;
    183
    184	switch (rate) {
    185	case 96000:
    186		clock = GML_96KHZ;
    187		break;
    188	case 88200:
    189		clock = GML_88KHZ;
    190		break;
    191	case 48000:
    192		clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;
    193		break;
    194	case 44100:
    195		clock = GML_44KHZ;
    196		/* Professional mode */
    197		if (control_reg & GML_SPDIF_PRO_MODE)
    198			clock |= GML_SPDIF_SAMPLE_RATE0;
    199		break;
    200	case 32000:
    201		clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 |
    202			GML_SPDIF_SAMPLE_RATE1;
    203		break;
    204	case 22050:
    205		clock = GML_22KHZ;
    206		break;
    207	case 16000:
    208		clock = GML_16KHZ;
    209		break;
    210	case 11025:
    211		clock = GML_11KHZ;
    212		break;
    213	case 8000:
    214		clock = GML_8KHZ;
    215		break;
    216	default:
    217		/* If this is a non-standard rate, then the driver needs to
    218		use Layla24's special "continuous frequency" mode */
    219		clock = LAYLA24_CONTINUOUS_CLOCK;
    220		if (rate > 50000) {
    221			base_rate = rate >> 1;
    222			control_reg |= GML_DOUBLE_SPEED_MODE;
    223		} else {
    224			base_rate = rate;
    225		}
    226
    227		if (base_rate < 25000)
    228			base_rate = 25000;
    229
    230		if (wait_handshake(chip))
    231			return -EIO;
    232
    233		chip->comm_page->sample_rate =
    234			cpu_to_le32(LAYLA24_MAGIC_NUMBER / base_rate - 2);
    235
    236		clear_handshake(chip);
    237		send_vector(chip, DSP_VC_SET_LAYLA24_FREQUENCY_REG);
    238	}
    239
    240	control_reg |= clock;
    241
    242	chip->comm_page->sample_rate = cpu_to_le32(rate);	/* ignored by the DSP ? */
    243	chip->sample_rate = rate;
    244	dev_dbg(chip->card->dev,
    245		"set_sample_rate: %d clock %d\n", rate, control_reg);
    246
    247	return write_control_reg(chip, control_reg, false);
    248}
    249
    250
    251
    252static int set_input_clock(struct echoaudio *chip, u16 clock)
    253{
    254	u32 control_reg, clocks_from_dsp;
    255
    256	/* Mask off the clock select bits */
    257	control_reg = le32_to_cpu(chip->comm_page->control_register) &
    258		GML_CLOCK_CLEAR_MASK;
    259	clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
    260
    261	/* Pick the new clock */
    262	switch (clock) {
    263	case ECHO_CLOCK_INTERNAL:
    264		chip->input_clock = ECHO_CLOCK_INTERNAL;
    265		return set_sample_rate(chip, chip->sample_rate);
    266	case ECHO_CLOCK_SPDIF:
    267		if (chip->digital_mode == DIGITAL_MODE_ADAT)
    268			return -EAGAIN;
    269		control_reg |= GML_SPDIF_CLOCK;
    270		/* Layla24 doesn't support 96KHz S/PDIF */
    271		control_reg &= ~GML_DOUBLE_SPEED_MODE;
    272		break;
    273	case ECHO_CLOCK_WORD:
    274		control_reg |= GML_WORD_CLOCK;
    275		if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD96)
    276			control_reg |= GML_DOUBLE_SPEED_MODE;
    277		else
    278			control_reg &= ~GML_DOUBLE_SPEED_MODE;
    279		break;
    280	case ECHO_CLOCK_ADAT:
    281		if (chip->digital_mode != DIGITAL_MODE_ADAT)
    282			return -EAGAIN;
    283		control_reg |= GML_ADAT_CLOCK;
    284		control_reg &= ~GML_DOUBLE_SPEED_MODE;
    285		break;
    286	default:
    287		dev_err(chip->card->dev,
    288			"Input clock 0x%x not supported for Layla24\n", clock);
    289		return -EINVAL;
    290	}
    291
    292	chip->input_clock = clock;
    293	return write_control_reg(chip, control_reg, true);
    294}
    295
    296
    297
    298/* Depending on what digital mode you want, Layla24 needs different ASICs
    299loaded.  This function checks the ASIC needed for the new mode and sees
    300if it matches the one already loaded. */
    301static int switch_asic(struct echoaudio *chip, short asic)
    302{
    303	s8 *monitors;
    304
    305	/*  Check to see if this is already loaded */
    306	if (asic != chip->asic_code) {
    307		monitors = kmemdup(chip->comm_page->monitors,
    308					MONITOR_ARRAY_SIZE, GFP_KERNEL);
    309		if (! monitors)
    310			return -ENOMEM;
    311
    312		memset(chip->comm_page->monitors, ECHOGAIN_MUTED,
    313		       MONITOR_ARRAY_SIZE);
    314
    315		/* Load the desired ASIC */
    316		if (load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC,
    317				      asic) < 0) {
    318			memcpy(chip->comm_page->monitors, monitors,
    319			       MONITOR_ARRAY_SIZE);
    320			kfree(monitors);
    321			return -EIO;
    322		}
    323		chip->asic_code = asic;
    324		memcpy(chip->comm_page->monitors, monitors, MONITOR_ARRAY_SIZE);
    325		kfree(monitors);
    326	}
    327
    328	return 0;
    329}
    330
    331
    332
    333static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)
    334{
    335	u32 control_reg;
    336	int err, incompatible_clock;
    337	short asic;
    338
    339	/* Set clock to "internal" if it's not compatible with the new mode */
    340	incompatible_clock = false;
    341	switch (mode) {
    342	case DIGITAL_MODE_SPDIF_OPTICAL:
    343	case DIGITAL_MODE_SPDIF_RCA:
    344		if (chip->input_clock == ECHO_CLOCK_ADAT)
    345			incompatible_clock = true;
    346		asic = FW_LAYLA24_2S_ASIC;
    347		break;
    348	case DIGITAL_MODE_ADAT:
    349		if (chip->input_clock == ECHO_CLOCK_SPDIF)
    350			incompatible_clock = true;
    351		asic = FW_LAYLA24_2A_ASIC;
    352		break;
    353	default:
    354		dev_err(chip->card->dev,
    355			"Digital mode not supported: %d\n", mode);
    356		return -EINVAL;
    357	}
    358
    359	if (incompatible_clock) {	/* Switch to 48KHz, internal */
    360		chip->sample_rate = 48000;
    361		spin_lock_irq(&chip->lock);
    362		set_input_clock(chip, ECHO_CLOCK_INTERNAL);
    363		spin_unlock_irq(&chip->lock);
    364	}
    365
    366	/* switch_asic() can sleep */
    367	if (switch_asic(chip, asic) < 0)
    368		return -EIO;
    369
    370	spin_lock_irq(&chip->lock);
    371
    372	/* Tweak the control register */
    373	control_reg = le32_to_cpu(chip->comm_page->control_register);
    374	control_reg &= GML_DIGITAL_MODE_CLEAR_MASK;
    375
    376	switch (mode) {
    377	case DIGITAL_MODE_SPDIF_OPTICAL:
    378		control_reg |= GML_SPDIF_OPTICAL_MODE;
    379		break;
    380	case DIGITAL_MODE_SPDIF_RCA:
    381		/* GML_SPDIF_OPTICAL_MODE bit cleared */
    382		break;
    383	case DIGITAL_MODE_ADAT:
    384		control_reg |= GML_ADAT_MODE;
    385		control_reg &= ~GML_DOUBLE_SPEED_MODE;
    386		break;
    387	}
    388
    389	err = write_control_reg(chip, control_reg, true);
    390	spin_unlock_irq(&chip->lock);
    391	if (err < 0)
    392		return err;
    393	chip->digital_mode = mode;
    394
    395	dev_dbg(chip->card->dev, "set_digital_mode to %d\n", mode);
    396	return incompatible_clock;
    397}