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

gina24_dsp.c (9102B)


      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
     32static int write_control_reg(struct echoaudio *chip, u32 value, char force);
     33static int set_input_clock(struct echoaudio *chip, u16 clock);
     34static int set_professional_spdif(struct echoaudio *chip, char prof);
     35static int set_digital_mode(struct echoaudio *chip, u8 mode);
     36static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic);
     37static int check_asic_status(struct echoaudio *chip);
     38
     39
     40static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
     41{
     42	int err;
     43
     44	if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA24))
     45		return -ENODEV;
     46
     47	err = init_dsp_comm_page(chip);
     48	if (err) {
     49		dev_err(chip->card->dev,
     50			"init_hw - could not initialize DSP comm page\n");
     51		return err;
     52	}
     53
     54	chip->device_id = device_id;
     55	chip->subdevice_id = subdevice_id;
     56	chip->bad_board = true;
     57	chip->input_clock_types =
     58		ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |
     59		ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96 |
     60		ECHO_CLOCK_BIT_ADAT;
     61
     62	/* Gina24 comes in both '301 and '361 flavors */
     63	if (chip->device_id == DEVICE_ID_56361) {
     64		chip->dsp_code_to_load = FW_GINA24_361_DSP;
     65		chip->digital_modes =
     66			ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
     67			ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
     68			ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
     69	} else {
     70		chip->dsp_code_to_load = FW_GINA24_301_DSP;
     71		chip->digital_modes =
     72			ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
     73			ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
     74			ECHOCAPS_HAS_DIGITAL_MODE_ADAT |
     75			ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM;
     76	}
     77
     78	err = load_firmware(chip);
     79	if (err < 0)
     80		return err;
     81	chip->bad_board = false;
     82
     83	return err;
     84}
     85
     86
     87
     88static int set_mixer_defaults(struct echoaudio *chip)
     89{
     90	chip->digital_mode = DIGITAL_MODE_SPDIF_RCA;
     91	chip->professional_spdif = false;
     92	chip->digital_in_automute = true;
     93	return init_line_levels(chip);
     94}
     95
     96
     97
     98static u32 detect_input_clocks(const struct echoaudio *chip)
     99{
    100	u32 clocks_from_dsp, clock_bits;
    101
    102	/* Map the DSP clock detect bits to the generic driver clock
    103	   detect bits */
    104	clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
    105
    106	clock_bits = ECHO_CLOCK_BIT_INTERNAL;
    107
    108	if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF)
    109		clock_bits |= ECHO_CLOCK_BIT_SPDIF;
    110
    111	if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT)
    112		clock_bits |= ECHO_CLOCK_BIT_ADAT;
    113
    114	if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ESYNC)
    115		clock_bits |= ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96;
    116
    117	return clock_bits;
    118}
    119
    120
    121
    122/* Gina24 has an ASIC on the PCI card which must be loaded for anything
    123interesting to happen. */
    124static int load_asic(struct echoaudio *chip)
    125{
    126	u32 control_reg;
    127	int err;
    128	short asic;
    129
    130	if (chip->asic_loaded)
    131		return 1;
    132
    133	/* Give the DSP a few milliseconds to settle down */
    134	mdelay(10);
    135
    136	/* Pick the correct ASIC for '301 or '361 Gina24 */
    137	if (chip->device_id == DEVICE_ID_56361)
    138		asic = FW_GINA24_361_ASIC;
    139	else
    140		asic = FW_GINA24_301_ASIC;
    141
    142	err = load_asic_generic(chip, DSP_FNC_LOAD_GINA24_ASIC, asic);
    143	if (err < 0)
    144		return err;
    145
    146	chip->asic_code = asic;
    147
    148	/* Now give the new ASIC a little time to set up */
    149	mdelay(10);
    150	/* See if it worked */
    151	err = check_asic_status(chip);
    152
    153	/* Set up the control register if the load succeeded -
    154	   48 kHz, internal clock, S/PDIF RCA mode */
    155	if (!err) {
    156		control_reg = GML_CONVERTER_ENABLE | GML_48KHZ;
    157		err = write_control_reg(chip, control_reg, true);
    158	}
    159	return err;
    160}
    161
    162
    163
    164static int set_sample_rate(struct echoaudio *chip, u32 rate)
    165{
    166	u32 control_reg, clock;
    167
    168	if (snd_BUG_ON(rate >= 50000 &&
    169		       chip->digital_mode == DIGITAL_MODE_ADAT))
    170		return -EINVAL;
    171
    172	/* Only set the clock for internal mode. */
    173	if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
    174		dev_warn(chip->card->dev,
    175			 "Cannot set sample rate - clock not set to CLK_CLOCKININTERNAL\n");
    176		/* Save the rate anyhow */
    177		chip->comm_page->sample_rate = cpu_to_le32(rate);
    178		chip->sample_rate = rate;
    179		return 0;
    180	}
    181
    182	clock = 0;
    183
    184	control_reg = le32_to_cpu(chip->comm_page->control_register);
    185	control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK;
    186
    187	switch (rate) {
    188	case 96000:
    189		clock = GML_96KHZ;
    190		break;
    191	case 88200:
    192		clock = GML_88KHZ;
    193		break;
    194	case 48000:
    195		clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;
    196		break;
    197	case 44100:
    198		clock = GML_44KHZ;
    199		/* Professional mode ? */
    200		if (control_reg & GML_SPDIF_PRO_MODE)
    201			clock |= GML_SPDIF_SAMPLE_RATE0;
    202		break;
    203	case 32000:
    204		clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 |
    205			GML_SPDIF_SAMPLE_RATE1;
    206		break;
    207	case 22050:
    208		clock = GML_22KHZ;
    209		break;
    210	case 16000:
    211		clock = GML_16KHZ;
    212		break;
    213	case 11025:
    214		clock = GML_11KHZ;
    215		break;
    216	case 8000:
    217		clock = GML_8KHZ;
    218		break;
    219	default:
    220		dev_err(chip->card->dev,
    221			"set_sample_rate: %d invalid!\n", rate);
    222		return -EINVAL;
    223	}
    224
    225	control_reg |= clock;
    226
    227	chip->comm_page->sample_rate = cpu_to_le32(rate);	/* ignored by the DSP */
    228	chip->sample_rate = rate;
    229	dev_dbg(chip->card->dev, "set_sample_rate: %d clock %d\n", rate, clock);
    230
    231	return write_control_reg(chip, control_reg, false);
    232}
    233
    234
    235
    236static int set_input_clock(struct echoaudio *chip, u16 clock)
    237{
    238	u32 control_reg, clocks_from_dsp;
    239
    240
    241	/* Mask off the clock select bits */
    242	control_reg = le32_to_cpu(chip->comm_page->control_register) &
    243		GML_CLOCK_CLEAR_MASK;
    244	clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
    245
    246	switch (clock) {
    247	case ECHO_CLOCK_INTERNAL:
    248		chip->input_clock = ECHO_CLOCK_INTERNAL;
    249		return set_sample_rate(chip, chip->sample_rate);
    250	case ECHO_CLOCK_SPDIF:
    251		if (chip->digital_mode == DIGITAL_MODE_ADAT)
    252			return -EAGAIN;
    253		control_reg |= GML_SPDIF_CLOCK;
    254		if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96)
    255			control_reg |= GML_DOUBLE_SPEED_MODE;
    256		else
    257			control_reg &= ~GML_DOUBLE_SPEED_MODE;
    258		break;
    259	case ECHO_CLOCK_ADAT:
    260		if (chip->digital_mode != DIGITAL_MODE_ADAT)
    261			return -EAGAIN;
    262		control_reg |= GML_ADAT_CLOCK;
    263		control_reg &= ~GML_DOUBLE_SPEED_MODE;
    264		break;
    265	case ECHO_CLOCK_ESYNC:
    266		control_reg |= GML_ESYNC_CLOCK;
    267		control_reg &= ~GML_DOUBLE_SPEED_MODE;
    268		break;
    269	case ECHO_CLOCK_ESYNC96:
    270		control_reg |= GML_ESYNC_CLOCK | GML_DOUBLE_SPEED_MODE;
    271		break;
    272	default:
    273		dev_err(chip->card->dev,
    274			"Input clock 0x%x not supported for Gina24\n", clock);
    275		return -EINVAL;
    276	}
    277
    278	chip->input_clock = clock;
    279	return write_control_reg(chip, control_reg, true);
    280}
    281
    282
    283
    284static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)
    285{
    286	u32 control_reg;
    287	int err, incompatible_clock;
    288
    289	/* Set clock to "internal" if it's not compatible with the new mode */
    290	incompatible_clock = false;
    291	switch (mode) {
    292	case DIGITAL_MODE_SPDIF_OPTICAL:
    293	case DIGITAL_MODE_SPDIF_CDROM:
    294	case DIGITAL_MODE_SPDIF_RCA:
    295		if (chip->input_clock == ECHO_CLOCK_ADAT)
    296			incompatible_clock = true;
    297		break;
    298	case DIGITAL_MODE_ADAT:
    299		if (chip->input_clock == ECHO_CLOCK_SPDIF)
    300			incompatible_clock = true;
    301		break;
    302	default:
    303		dev_err(chip->card->dev,
    304			"Digital mode not supported: %d\n", mode);
    305		return -EINVAL;
    306	}
    307
    308	spin_lock_irq(&chip->lock);
    309
    310	if (incompatible_clock) {	/* Switch to 48KHz, internal */
    311		chip->sample_rate = 48000;
    312		set_input_clock(chip, ECHO_CLOCK_INTERNAL);
    313	}
    314
    315	/* Clear the current digital mode */
    316	control_reg = le32_to_cpu(chip->comm_page->control_register);
    317	control_reg &= GML_DIGITAL_MODE_CLEAR_MASK;
    318
    319	/* Tweak the control reg */
    320	switch (mode) {
    321	case DIGITAL_MODE_SPDIF_OPTICAL:
    322		control_reg |= GML_SPDIF_OPTICAL_MODE;
    323		break;
    324	case DIGITAL_MODE_SPDIF_CDROM:
    325		/* '361 Gina24 cards do not have the S/PDIF CD-ROM mode */
    326		if (chip->device_id == DEVICE_ID_56301)
    327			control_reg |= GML_SPDIF_CDROM_MODE;
    328		break;
    329	case DIGITAL_MODE_SPDIF_RCA:
    330		/* GML_SPDIF_OPTICAL_MODE bit cleared */
    331		break;
    332	case DIGITAL_MODE_ADAT:
    333		control_reg |= GML_ADAT_MODE;
    334		control_reg &= ~GML_DOUBLE_SPEED_MODE;
    335		break;
    336	}
    337
    338	err = write_control_reg(chip, control_reg, true);
    339	spin_unlock_irq(&chip->lock);
    340	if (err < 0)
    341		return err;
    342	chip->digital_mode = mode;
    343
    344	dev_dbg(chip->card->dev,
    345		"set_digital_mode to %d\n", chip->digital_mode);
    346	return incompatible_clock;
    347}