162306a36Sopenharmony_ci/****************************************************************************
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
462306a36Sopenharmony_ci   All rights reserved
562306a36Sopenharmony_ci   www.echoaudio.com
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci   This file is part of Echo Digital Audio's generic driver library.
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci   Echo Digital Audio's generic driver library is free software;
1062306a36Sopenharmony_ci   you can redistribute it and/or modify it under the terms of
1162306a36Sopenharmony_ci   the GNU General Public License as published by the Free Software
1262306a36Sopenharmony_ci   Foundation.
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci   This program is distributed in the hope that it will be useful,
1562306a36Sopenharmony_ci   but WITHOUT ANY WARRANTY; without even the implied warranty of
1662306a36Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1762306a36Sopenharmony_ci   GNU General Public License for more details.
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci   You should have received a copy of the GNU General Public License
2062306a36Sopenharmony_ci   along with this program; if not, write to the Free Software
2162306a36Sopenharmony_ci   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
2262306a36Sopenharmony_ci   MA  02111-1307, USA.
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci   *************************************************************************
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci Translation from C++ and adaptation for use in ALSA-Driver
2762306a36Sopenharmony_ci were made by Giuliano Pochini <pochini@shiny.it>
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci****************************************************************************/
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/* These functions are common for all "3G" cards */
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic int check_asic_status(struct echoaudio *chip)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	u32 box_status;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	if (wait_handshake(chip))
4162306a36Sopenharmony_ci		return -EIO;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	chip->comm_page->ext_box_status = cpu_to_le32(E3G_ASIC_NOT_LOADED);
4462306a36Sopenharmony_ci	chip->asic_loaded = false;
4562306a36Sopenharmony_ci	clear_handshake(chip);
4662306a36Sopenharmony_ci	send_vector(chip, DSP_VC_TEST_ASIC);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	if (wait_handshake(chip)) {
4962306a36Sopenharmony_ci		chip->dsp_code = NULL;
5062306a36Sopenharmony_ci		return -EIO;
5162306a36Sopenharmony_ci	}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	box_status = le32_to_cpu(chip->comm_page->ext_box_status);
5462306a36Sopenharmony_ci	dev_dbg(chip->card->dev, "box_status=%x\n", box_status);
5562306a36Sopenharmony_ci	if (box_status == E3G_ASIC_NOT_LOADED)
5662306a36Sopenharmony_ci		return -ENODEV;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	chip->asic_loaded = true;
5962306a36Sopenharmony_ci	return box_status & E3G_BOX_TYPE_MASK;
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic inline u32 get_frq_reg(struct echoaudio *chip)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	return le32_to_cpu(chip->comm_page->e3g_frq_register);
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/* Most configuration of 3G cards is accomplished by writing the control
7262306a36Sopenharmony_ciregister. write_control_reg sends the new control register value to the DSP. */
7362306a36Sopenharmony_cistatic int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq,
7462306a36Sopenharmony_ci			     char force)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	__le32 ctl_reg, frq_reg;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	if (wait_handshake(chip))
7962306a36Sopenharmony_ci		return -EIO;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	dev_dbg(chip->card->dev,
8262306a36Sopenharmony_ci		"WriteControlReg: Setting 0x%x, 0x%x\n", ctl, frq);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	ctl_reg = cpu_to_le32(ctl);
8562306a36Sopenharmony_ci	frq_reg = cpu_to_le32(frq);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	if (ctl_reg != chip->comm_page->control_register ||
8862306a36Sopenharmony_ci	    frq_reg != chip->comm_page->e3g_frq_register || force) {
8962306a36Sopenharmony_ci		chip->comm_page->e3g_frq_register = frq_reg;
9062306a36Sopenharmony_ci		chip->comm_page->control_register = ctl_reg;
9162306a36Sopenharmony_ci		clear_handshake(chip);
9262306a36Sopenharmony_ci		return send_vector(chip, DSP_VC_WRITE_CONTROL_REG);
9362306a36Sopenharmony_ci	}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	dev_dbg(chip->card->dev, "WriteControlReg: not written, no change\n");
9662306a36Sopenharmony_ci	return 0;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/* Set the digital mode - currently for Gina24, Layla24, Mona, 3G */
10262306a36Sopenharmony_cistatic int set_digital_mode(struct echoaudio *chip, u8 mode)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	u8 previous_mode;
10562306a36Sopenharmony_ci	int err, i, o;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	/* All audio channels must be closed before changing the digital mode */
10862306a36Sopenharmony_ci	if (snd_BUG_ON(chip->pipe_alloc_mask))
10962306a36Sopenharmony_ci		return -EAGAIN;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	if (snd_BUG_ON(!(chip->digital_modes & (1 << mode))))
11262306a36Sopenharmony_ci		return -EINVAL;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	previous_mode = chip->digital_mode;
11562306a36Sopenharmony_ci	err = dsp_set_digital_mode(chip, mode);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	/* If we successfully changed the digital mode from or to ADAT,
11862306a36Sopenharmony_ci	 * then make sure all output, input and monitor levels are
11962306a36Sopenharmony_ci	 * updated by the DSP comm object. */
12062306a36Sopenharmony_ci	if (err >= 0 && previous_mode != mode &&
12162306a36Sopenharmony_ci	    (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) {
12262306a36Sopenharmony_ci		spin_lock_irq(&chip->lock);
12362306a36Sopenharmony_ci		for (o = 0; o < num_busses_out(chip); o++)
12462306a36Sopenharmony_ci			for (i = 0; i < num_busses_in(chip); i++)
12562306a36Sopenharmony_ci				set_monitor_gain(chip, o, i,
12662306a36Sopenharmony_ci						 chip->monitor_gain[o][i]);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci#ifdef ECHOCARD_HAS_INPUT_GAIN
12962306a36Sopenharmony_ci		for (i = 0; i < num_busses_in(chip); i++)
13062306a36Sopenharmony_ci			set_input_gain(chip, i, chip->input_gain[i]);
13162306a36Sopenharmony_ci		update_input_line_level(chip);
13262306a36Sopenharmony_ci#endif
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci		for (o = 0; o < num_busses_out(chip); o++)
13562306a36Sopenharmony_ci			set_output_gain(chip, o, chip->output_gain[o]);
13662306a36Sopenharmony_ci		update_output_line_level(chip);
13762306a36Sopenharmony_ci		spin_unlock_irq(&chip->lock);
13862306a36Sopenharmony_ci	}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	return err;
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cistatic u32 set_spdif_bits(struct echoaudio *chip, u32 control_reg, u32 rate)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	control_reg &= E3G_SPDIF_FORMAT_CLEAR_MASK;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	switch (rate) {
15062306a36Sopenharmony_ci	case 32000 :
15162306a36Sopenharmony_ci		control_reg |= E3G_SPDIF_SAMPLE_RATE0 | E3G_SPDIF_SAMPLE_RATE1;
15262306a36Sopenharmony_ci		break;
15362306a36Sopenharmony_ci	case 44100 :
15462306a36Sopenharmony_ci		if (chip->professional_spdif)
15562306a36Sopenharmony_ci			control_reg |= E3G_SPDIF_SAMPLE_RATE0;
15662306a36Sopenharmony_ci		break;
15762306a36Sopenharmony_ci	case 48000 :
15862306a36Sopenharmony_ci		control_reg |= E3G_SPDIF_SAMPLE_RATE1;
15962306a36Sopenharmony_ci		break;
16062306a36Sopenharmony_ci	}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	if (chip->professional_spdif)
16362306a36Sopenharmony_ci		control_reg |= E3G_SPDIF_PRO_MODE;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	if (chip->non_audio_spdif)
16662306a36Sopenharmony_ci		control_reg |= E3G_SPDIF_NOT_AUDIO;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	control_reg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL |
16962306a36Sopenharmony_ci		E3G_SPDIF_COPY_PERMIT;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	return control_reg;
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci/* Set the S/PDIF output format */
17762306a36Sopenharmony_cistatic int set_professional_spdif(struct echoaudio *chip, char prof)
17862306a36Sopenharmony_ci{
17962306a36Sopenharmony_ci	u32 control_reg;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	control_reg = le32_to_cpu(chip->comm_page->control_register);
18262306a36Sopenharmony_ci	chip->professional_spdif = prof;
18362306a36Sopenharmony_ci	control_reg = set_spdif_bits(chip, control_reg, chip->sample_rate);
18462306a36Sopenharmony_ci	return write_control_reg(chip, control_reg, get_frq_reg(chip), 0);
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci/* detect_input_clocks() returns a bitmask consisting of all the input clocks
19062306a36Sopenharmony_cicurrently connected to the hardware; this changes as the user connects and
19162306a36Sopenharmony_cidisconnects clock inputs. You should use this information to determine which
19262306a36Sopenharmony_ciclocks the user is allowed to select. */
19362306a36Sopenharmony_cistatic u32 detect_input_clocks(const struct echoaudio *chip)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	u32 clocks_from_dsp, clock_bits;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	/* Map the DSP clock detect bits to the generic driver clock
19862306a36Sopenharmony_ci	 * detect bits */
19962306a36Sopenharmony_ci	clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	clock_bits = ECHO_CLOCK_BIT_INTERNAL;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD)
20462306a36Sopenharmony_ci		clock_bits |= ECHO_CLOCK_BIT_WORD;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	switch(chip->digital_mode) {
20762306a36Sopenharmony_ci	case DIGITAL_MODE_SPDIF_RCA:
20862306a36Sopenharmony_ci	case DIGITAL_MODE_SPDIF_OPTICAL:
20962306a36Sopenharmony_ci		if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF)
21062306a36Sopenharmony_ci			clock_bits |= ECHO_CLOCK_BIT_SPDIF;
21162306a36Sopenharmony_ci		break;
21262306a36Sopenharmony_ci	case DIGITAL_MODE_ADAT:
21362306a36Sopenharmony_ci		if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_ADAT)
21462306a36Sopenharmony_ci			clock_bits |= ECHO_CLOCK_BIT_ADAT;
21562306a36Sopenharmony_ci		break;
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	return clock_bits;
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_cistatic int load_asic(struct echoaudio *chip)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	int box_type, err;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	if (chip->asic_loaded)
22862306a36Sopenharmony_ci		return 0;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	/* Give the DSP a few milliseconds to settle down */
23162306a36Sopenharmony_ci	mdelay(2);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	err = load_asic_generic(chip, DSP_FNC_LOAD_3G_ASIC, FW_3G_ASIC);
23462306a36Sopenharmony_ci	if (err < 0)
23562306a36Sopenharmony_ci		return err;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	chip->asic_code = FW_3G_ASIC;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	/* Now give the new ASIC some time to set up */
24062306a36Sopenharmony_ci	msleep(1000);
24162306a36Sopenharmony_ci	/* See if it worked */
24262306a36Sopenharmony_ci	box_type = check_asic_status(chip);
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	/* Set up the control register if the load succeeded -
24562306a36Sopenharmony_ci	 * 48 kHz, internal clock, S/PDIF RCA mode */
24662306a36Sopenharmony_ci	if (box_type >= 0) {
24762306a36Sopenharmony_ci		err = write_control_reg(chip, E3G_48KHZ,
24862306a36Sopenharmony_ci					E3G_FREQ_REG_DEFAULT, true);
24962306a36Sopenharmony_ci		if (err < 0)
25062306a36Sopenharmony_ci			return err;
25162306a36Sopenharmony_ci	}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	return box_type;
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic int set_sample_rate(struct echoaudio *chip, u32 rate)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	u32 control_reg, clock, base_rate, frq_reg;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	/* Only set the clock for internal mode. */
26362306a36Sopenharmony_ci	if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
26462306a36Sopenharmony_ci		dev_warn(chip->card->dev,
26562306a36Sopenharmony_ci			 "Cannot set sample rate - clock not set to CLK_CLOCKININTERNAL\n");
26662306a36Sopenharmony_ci		/* Save the rate anyhow */
26762306a36Sopenharmony_ci		chip->comm_page->sample_rate = cpu_to_le32(rate);
26862306a36Sopenharmony_ci		chip->sample_rate = rate;
26962306a36Sopenharmony_ci		set_input_clock(chip, chip->input_clock);
27062306a36Sopenharmony_ci		return 0;
27162306a36Sopenharmony_ci	}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	if (snd_BUG_ON(rate >= 50000 &&
27462306a36Sopenharmony_ci		       chip->digital_mode == DIGITAL_MODE_ADAT))
27562306a36Sopenharmony_ci		return -EINVAL;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	clock = 0;
27862306a36Sopenharmony_ci	control_reg = le32_to_cpu(chip->comm_page->control_register);
27962306a36Sopenharmony_ci	control_reg &= E3G_CLOCK_CLEAR_MASK;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	switch (rate) {
28262306a36Sopenharmony_ci	case 96000:
28362306a36Sopenharmony_ci		clock = E3G_96KHZ;
28462306a36Sopenharmony_ci		break;
28562306a36Sopenharmony_ci	case 88200:
28662306a36Sopenharmony_ci		clock = E3G_88KHZ;
28762306a36Sopenharmony_ci		break;
28862306a36Sopenharmony_ci	case 48000:
28962306a36Sopenharmony_ci		clock = E3G_48KHZ;
29062306a36Sopenharmony_ci		break;
29162306a36Sopenharmony_ci	case 44100:
29262306a36Sopenharmony_ci		clock = E3G_44KHZ;
29362306a36Sopenharmony_ci		break;
29462306a36Sopenharmony_ci	case 32000:
29562306a36Sopenharmony_ci		clock = E3G_32KHZ;
29662306a36Sopenharmony_ci		break;
29762306a36Sopenharmony_ci	default:
29862306a36Sopenharmony_ci		clock = E3G_CONTINUOUS_CLOCK;
29962306a36Sopenharmony_ci		if (rate > 50000)
30062306a36Sopenharmony_ci			clock |= E3G_DOUBLE_SPEED_MODE;
30162306a36Sopenharmony_ci		break;
30262306a36Sopenharmony_ci	}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	control_reg |= clock;
30562306a36Sopenharmony_ci	control_reg = set_spdif_bits(chip, control_reg, rate);
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	base_rate = rate;
30862306a36Sopenharmony_ci	if (base_rate > 50000)
30962306a36Sopenharmony_ci		base_rate /= 2;
31062306a36Sopenharmony_ci	if (base_rate < 32000)
31162306a36Sopenharmony_ci		base_rate = 32000;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	frq_reg = E3G_MAGIC_NUMBER / base_rate - 2;
31462306a36Sopenharmony_ci	if (frq_reg > E3G_FREQ_REG_MAX)
31562306a36Sopenharmony_ci		frq_reg = E3G_FREQ_REG_MAX;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	chip->comm_page->sample_rate = cpu_to_le32(rate);	/* ignored by the DSP */
31862306a36Sopenharmony_ci	chip->sample_rate = rate;
31962306a36Sopenharmony_ci	dev_dbg(chip->card->dev,
32062306a36Sopenharmony_ci		"SetSampleRate: %d clock %x\n", rate, control_reg);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	/* Tell the DSP about it - DSP reads both control reg & freq reg */
32362306a36Sopenharmony_ci	return write_control_reg(chip, control_reg, frq_reg, 0);
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci/* Set the sample clock source to internal, S/PDIF, ADAT */
32962306a36Sopenharmony_cistatic int set_input_clock(struct echoaudio *chip, u16 clock)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	u32 control_reg, clocks_from_dsp;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	/* Mask off the clock select bits */
33562306a36Sopenharmony_ci	control_reg = le32_to_cpu(chip->comm_page->control_register) &
33662306a36Sopenharmony_ci		E3G_CLOCK_CLEAR_MASK;
33762306a36Sopenharmony_ci	clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	switch (clock) {
34062306a36Sopenharmony_ci	case ECHO_CLOCK_INTERNAL:
34162306a36Sopenharmony_ci		chip->input_clock = ECHO_CLOCK_INTERNAL;
34262306a36Sopenharmony_ci		return set_sample_rate(chip, chip->sample_rate);
34362306a36Sopenharmony_ci	case ECHO_CLOCK_SPDIF:
34462306a36Sopenharmony_ci		if (chip->digital_mode == DIGITAL_MODE_ADAT)
34562306a36Sopenharmony_ci			return -EAGAIN;
34662306a36Sopenharmony_ci		control_reg |= E3G_SPDIF_CLOCK;
34762306a36Sopenharmony_ci		if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF96)
34862306a36Sopenharmony_ci			control_reg |= E3G_DOUBLE_SPEED_MODE;
34962306a36Sopenharmony_ci		else
35062306a36Sopenharmony_ci			control_reg &= ~E3G_DOUBLE_SPEED_MODE;
35162306a36Sopenharmony_ci		break;
35262306a36Sopenharmony_ci	case ECHO_CLOCK_ADAT:
35362306a36Sopenharmony_ci		if (chip->digital_mode != DIGITAL_MODE_ADAT)
35462306a36Sopenharmony_ci			return -EAGAIN;
35562306a36Sopenharmony_ci		control_reg |= E3G_ADAT_CLOCK;
35662306a36Sopenharmony_ci		control_reg &= ~E3G_DOUBLE_SPEED_MODE;
35762306a36Sopenharmony_ci		break;
35862306a36Sopenharmony_ci	case ECHO_CLOCK_WORD:
35962306a36Sopenharmony_ci		control_reg |= E3G_WORD_CLOCK;
36062306a36Sopenharmony_ci		if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD96)
36162306a36Sopenharmony_ci			control_reg |= E3G_DOUBLE_SPEED_MODE;
36262306a36Sopenharmony_ci		else
36362306a36Sopenharmony_ci			control_reg &= ~E3G_DOUBLE_SPEED_MODE;
36462306a36Sopenharmony_ci		break;
36562306a36Sopenharmony_ci	default:
36662306a36Sopenharmony_ci		dev_err(chip->card->dev,
36762306a36Sopenharmony_ci			"Input clock 0x%x not supported for Echo3G\n", clock);
36862306a36Sopenharmony_ci		return -EINVAL;
36962306a36Sopenharmony_ci	}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	chip->input_clock = clock;
37262306a36Sopenharmony_ci	return write_control_reg(chip, control_reg, get_frq_reg(chip), 1);
37362306a36Sopenharmony_ci}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_cistatic int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)
37862306a36Sopenharmony_ci{
37962306a36Sopenharmony_ci	u32 control_reg;
38062306a36Sopenharmony_ci	int err, incompatible_clock;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	/* Set clock to "internal" if it's not compatible with the new mode */
38362306a36Sopenharmony_ci	incompatible_clock = false;
38462306a36Sopenharmony_ci	switch (mode) {
38562306a36Sopenharmony_ci	case DIGITAL_MODE_SPDIF_OPTICAL:
38662306a36Sopenharmony_ci	case DIGITAL_MODE_SPDIF_RCA:
38762306a36Sopenharmony_ci		if (chip->input_clock == ECHO_CLOCK_ADAT)
38862306a36Sopenharmony_ci			incompatible_clock = true;
38962306a36Sopenharmony_ci		break;
39062306a36Sopenharmony_ci	case DIGITAL_MODE_ADAT:
39162306a36Sopenharmony_ci		if (chip->input_clock == ECHO_CLOCK_SPDIF)
39262306a36Sopenharmony_ci			incompatible_clock = true;
39362306a36Sopenharmony_ci		break;
39462306a36Sopenharmony_ci	default:
39562306a36Sopenharmony_ci		dev_err(chip->card->dev,
39662306a36Sopenharmony_ci			"Digital mode not supported: %d\n", mode);
39762306a36Sopenharmony_ci		return -EINVAL;
39862306a36Sopenharmony_ci	}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	spin_lock_irq(&chip->lock);
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	if (incompatible_clock) {
40362306a36Sopenharmony_ci		chip->sample_rate = 48000;
40462306a36Sopenharmony_ci		set_input_clock(chip, ECHO_CLOCK_INTERNAL);
40562306a36Sopenharmony_ci	}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	/* Clear the current digital mode */
40862306a36Sopenharmony_ci	control_reg = le32_to_cpu(chip->comm_page->control_register);
40962306a36Sopenharmony_ci	control_reg &= E3G_DIGITAL_MODE_CLEAR_MASK;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	/* Tweak the control reg */
41262306a36Sopenharmony_ci	switch (mode) {
41362306a36Sopenharmony_ci	case DIGITAL_MODE_SPDIF_OPTICAL:
41462306a36Sopenharmony_ci		control_reg |= E3G_SPDIF_OPTICAL_MODE;
41562306a36Sopenharmony_ci		break;
41662306a36Sopenharmony_ci	case DIGITAL_MODE_SPDIF_RCA:
41762306a36Sopenharmony_ci		/* E3G_SPDIF_OPTICAL_MODE bit cleared */
41862306a36Sopenharmony_ci		break;
41962306a36Sopenharmony_ci	case DIGITAL_MODE_ADAT:
42062306a36Sopenharmony_ci		control_reg |= E3G_ADAT_MODE;
42162306a36Sopenharmony_ci		control_reg &= ~E3G_DOUBLE_SPEED_MODE;	/* @@ useless */
42262306a36Sopenharmony_ci		break;
42362306a36Sopenharmony_ci	}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	err = write_control_reg(chip, control_reg, get_frq_reg(chip), 1);
42662306a36Sopenharmony_ci	spin_unlock_irq(&chip->lock);
42762306a36Sopenharmony_ci	if (err < 0)
42862306a36Sopenharmony_ci		return err;
42962306a36Sopenharmony_ci	chip->digital_mode = mode;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	dev_dbg(chip->card->dev, "set_digital_mode(%d)\n", chip->digital_mode);
43262306a36Sopenharmony_ci	return incompatible_clock;
43362306a36Sopenharmony_ci}
434