xref: /linux/sound/pci/echoaudio/echoaudio_gml.c (revision 353b7a55dcaf5fb8758e09ebe2ddf5f3adbac7c5)
1dd7b254dSGiuliano Pochini /****************************************************************************
2dd7b254dSGiuliano Pochini 
3dd7b254dSGiuliano Pochini    Copyright Echo Digital Audio Corporation (c) 1998 - 2004
4dd7b254dSGiuliano Pochini    All rights reserved
5dd7b254dSGiuliano Pochini    www.echoaudio.com
6dd7b254dSGiuliano Pochini 
7dd7b254dSGiuliano Pochini    This file is part of Echo Digital Audio's generic driver library.
8dd7b254dSGiuliano Pochini 
9dd7b254dSGiuliano Pochini    Echo Digital Audio's generic driver library is free software;
10dd7b254dSGiuliano Pochini    you can redistribute it and/or modify it under the terms of
11dd7b254dSGiuliano Pochini    the GNU General Public License as published by the Free Software
12dd7b254dSGiuliano Pochini    Foundation.
13dd7b254dSGiuliano Pochini 
14dd7b254dSGiuliano Pochini    This program is distributed in the hope that it will be useful,
15dd7b254dSGiuliano Pochini    but WITHOUT ANY WARRANTY; without even the implied warranty of
16dd7b254dSGiuliano Pochini    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17dd7b254dSGiuliano Pochini    GNU General Public License for more details.
18dd7b254dSGiuliano Pochini 
19dd7b254dSGiuliano Pochini    You should have received a copy of the GNU General Public License
20dd7b254dSGiuliano Pochini    along with this program; if not, write to the Free Software
21dd7b254dSGiuliano Pochini    Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22dd7b254dSGiuliano Pochini    MA  02111-1307, USA.
23dd7b254dSGiuliano Pochini 
24dd7b254dSGiuliano Pochini    *************************************************************************
25dd7b254dSGiuliano Pochini 
26dd7b254dSGiuliano Pochini  Translation from C++ and adaptation for use in ALSA-Driver
27dd7b254dSGiuliano Pochini  were made by Giuliano Pochini <pochini@shiny.it>
28dd7b254dSGiuliano Pochini 
29dd7b254dSGiuliano Pochini ****************************************************************************/
30dd7b254dSGiuliano Pochini 
31dd7b254dSGiuliano Pochini 
32dd7b254dSGiuliano Pochini /* These functions are common for Gina24, Layla24 and Mona cards */
33dd7b254dSGiuliano Pochini 
34dd7b254dSGiuliano Pochini 
35dd7b254dSGiuliano Pochini /* ASIC status check - some cards have one or two ASICs that need to be
36dd7b254dSGiuliano Pochini loaded.  Once that load is complete, this function is called to see if
37dd7b254dSGiuliano Pochini the load was successful.
38dd7b254dSGiuliano Pochini If this load fails, it does not necessarily mean that the hardware is
39dd7b254dSGiuliano Pochini defective - the external box may be disconnected or turned off. */
40dd7b254dSGiuliano Pochini static int check_asic_status(struct echoaudio *chip)
41dd7b254dSGiuliano Pochini {
42dd7b254dSGiuliano Pochini 	u32 asic_status;
43dd7b254dSGiuliano Pochini 
44dd7b254dSGiuliano Pochini 	send_vector(chip, DSP_VC_TEST_ASIC);
45dd7b254dSGiuliano Pochini 
46dd7b254dSGiuliano Pochini 	/* The DSP will return a value to indicate whether or not the
47dd7b254dSGiuliano Pochini 	   ASIC is currently loaded */
48dd7b254dSGiuliano Pochini 	if (read_dsp(chip, &asic_status) < 0) {
49b5b4a41bSSudip Mukherjee 		dev_err(chip->card->dev,
50b5b4a41bSSudip Mukherjee 			"check_asic_status: failed on read_dsp\n");
513f6175ecSMark Brown 		chip->asic_loaded = false;
52dd7b254dSGiuliano Pochini 		return -EIO;
53dd7b254dSGiuliano Pochini 	}
54dd7b254dSGiuliano Pochini 
55dd7b254dSGiuliano Pochini 	chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED);
56dd7b254dSGiuliano Pochini 	return chip->asic_loaded ? 0 : -EIO;
57dd7b254dSGiuliano Pochini }
58dd7b254dSGiuliano Pochini 
59dd7b254dSGiuliano Pochini 
60dd7b254dSGiuliano Pochini 
61dd7b254dSGiuliano Pochini /* Most configuration of Gina24, Layla24, or Mona is accomplished by writing
62dd7b254dSGiuliano Pochini the control register.  write_control_reg sends the new control register
63dd7b254dSGiuliano Pochini value to the DSP. */
64dd7b254dSGiuliano Pochini static int write_control_reg(struct echoaudio *chip, u32 value, char force)
65dd7b254dSGiuliano Pochini {
662a833a02STakashi Iwai 	__le32 reg_value;
672a833a02STakashi Iwai 
68dd7b254dSGiuliano Pochini 	/* Handle the digital input auto-mute */
69dd7b254dSGiuliano Pochini 	if (chip->digital_in_automute)
70dd7b254dSGiuliano Pochini 		value |= GML_DIGITAL_IN_AUTO_MUTE;
71dd7b254dSGiuliano Pochini 	else
72dd7b254dSGiuliano Pochini 		value &= ~GML_DIGITAL_IN_AUTO_MUTE;
73dd7b254dSGiuliano Pochini 
74b5b4a41bSSudip Mukherjee 	dev_dbg(chip->card->dev, "write_control_reg: 0x%x\n", value);
75dd7b254dSGiuliano Pochini 
76dd7b254dSGiuliano Pochini 	/* Write the control register */
772a833a02STakashi Iwai 	reg_value = cpu_to_le32(value);
782a833a02STakashi Iwai 	if (reg_value != chip->comm_page->control_register || force) {
79dd7b254dSGiuliano Pochini 		if (wait_handshake(chip))
80dd7b254dSGiuliano Pochini 			return -EIO;
812a833a02STakashi Iwai 		chip->comm_page->control_register = reg_value;
82dd7b254dSGiuliano Pochini 		clear_handshake(chip);
83dd7b254dSGiuliano Pochini 		return send_vector(chip, DSP_VC_WRITE_CONTROL_REG);
84dd7b254dSGiuliano Pochini 	}
85dd7b254dSGiuliano Pochini 	return 0;
86dd7b254dSGiuliano Pochini }
87dd7b254dSGiuliano Pochini 
88dd7b254dSGiuliano Pochini 
89dd7b254dSGiuliano Pochini 
90dd7b254dSGiuliano Pochini /* Gina24, Layla24, and Mona support digital input auto-mute.  If the digital
91dd7b254dSGiuliano Pochini input auto-mute is enabled, the DSP will only enable the digital inputs if
92dd7b254dSGiuliano Pochini the card is syncing to a valid clock on the ADAT or S/PDIF inputs.
93dd7b254dSGiuliano Pochini If the auto-mute is disabled, the digital inputs are enabled regardless of
94dd7b254dSGiuliano Pochini what the input clock is set or what is connected. */
95dd7b254dSGiuliano Pochini static int set_input_auto_mute(struct echoaudio *chip, int automute)
96dd7b254dSGiuliano Pochini {
97b5b4a41bSSudip Mukherjee 	dev_dbg(chip->card->dev, "set_input_auto_mute %d\n", automute);
98dd7b254dSGiuliano Pochini 
99dd7b254dSGiuliano Pochini 	chip->digital_in_automute = automute;
100dd7b254dSGiuliano Pochini 
101dd7b254dSGiuliano Pochini 	/* Re-set the input clock to the current value - indirectly causes
102dd7b254dSGiuliano Pochini 	the auto-mute flag to be sent to the DSP */
103dd7b254dSGiuliano Pochini 	return set_input_clock(chip, chip->input_clock);
104dd7b254dSGiuliano Pochini }
105dd7b254dSGiuliano Pochini 
106dd7b254dSGiuliano Pochini 
107dd7b254dSGiuliano Pochini 
108dd7b254dSGiuliano Pochini /* S/PDIF coax / S/PDIF optical / ADAT - switch */
109dd7b254dSGiuliano Pochini static int set_digital_mode(struct echoaudio *chip, u8 mode)
110dd7b254dSGiuliano Pochini {
111dd7b254dSGiuliano Pochini 	u8 previous_mode;
112dd7b254dSGiuliano Pochini 	int err, i, o;
113dd7b254dSGiuliano Pochini 
114dd7b254dSGiuliano Pochini 	if (chip->bad_board)
115dd7b254dSGiuliano Pochini 		return -EIO;
116dd7b254dSGiuliano Pochini 
117dd7b254dSGiuliano Pochini 	/* All audio channels must be closed before changing the digital mode */
118da3cec35STakashi Iwai 	if (snd_BUG_ON(chip->pipe_alloc_mask))
119da3cec35STakashi Iwai 		return -EAGAIN;
120dd7b254dSGiuliano Pochini 
121da3cec35STakashi Iwai 	if (snd_BUG_ON(!(chip->digital_modes & (1 << mode))))
122da3cec35STakashi Iwai 		return -EINVAL;
123dd7b254dSGiuliano Pochini 
124dd7b254dSGiuliano Pochini 	previous_mode = chip->digital_mode;
125dd7b254dSGiuliano Pochini 	err = dsp_set_digital_mode(chip, mode);
126dd7b254dSGiuliano Pochini 
127dd7b254dSGiuliano Pochini 	/* If we successfully changed the digital mode from or to ADAT,
128dd7b254dSGiuliano Pochini 	   then make sure all output, input and monitor levels are
129dd7b254dSGiuliano Pochini 	   updated by the DSP comm object. */
130dd7b254dSGiuliano Pochini 	if (err >= 0 && previous_mode != mode &&
131dd7b254dSGiuliano Pochini 	    (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) {
132dd7b254dSGiuliano Pochini 		spin_lock_irq(&chip->lock);
133dd7b254dSGiuliano Pochini 		for (o = 0; o < num_busses_out(chip); o++)
134dd7b254dSGiuliano Pochini 			for (i = 0; i < num_busses_in(chip); i++)
135dd7b254dSGiuliano Pochini 				set_monitor_gain(chip, o, i,
136dd7b254dSGiuliano Pochini 						 chip->monitor_gain[o][i]);
137dd7b254dSGiuliano Pochini 
138dd7b254dSGiuliano Pochini #ifdef ECHOCARD_HAS_INPUT_GAIN
139dd7b254dSGiuliano Pochini 		for (i = 0; i < num_busses_in(chip); i++)
140dd7b254dSGiuliano Pochini 			set_input_gain(chip, i, chip->input_gain[i]);
141dd7b254dSGiuliano Pochini 		update_input_line_level(chip);
142dd7b254dSGiuliano Pochini #endif
143dd7b254dSGiuliano Pochini 
144dd7b254dSGiuliano Pochini 		for (o = 0; o < num_busses_out(chip); o++)
145dd7b254dSGiuliano Pochini 			set_output_gain(chip, o, chip->output_gain[o]);
146dd7b254dSGiuliano Pochini 		update_output_line_level(chip);
147dd7b254dSGiuliano Pochini 		spin_unlock_irq(&chip->lock);
148dd7b254dSGiuliano Pochini 	}
149dd7b254dSGiuliano Pochini 
150dd7b254dSGiuliano Pochini 	return err;
151dd7b254dSGiuliano Pochini }
152dd7b254dSGiuliano Pochini 
153dd7b254dSGiuliano Pochini 
154dd7b254dSGiuliano Pochini 
155dd7b254dSGiuliano Pochini /* Set the S/PDIF output format */
156dd7b254dSGiuliano Pochini static int set_professional_spdif(struct echoaudio *chip, char prof)
157dd7b254dSGiuliano Pochini {
158dd7b254dSGiuliano Pochini 	u32 control_reg;
159dd7b254dSGiuliano Pochini 	int err;
160dd7b254dSGiuliano Pochini 
161dd7b254dSGiuliano Pochini 	/* Clear the current S/PDIF flags */
162dd7b254dSGiuliano Pochini 	control_reg = le32_to_cpu(chip->comm_page->control_register);
163dd7b254dSGiuliano Pochini 	control_reg &= GML_SPDIF_FORMAT_CLEAR_MASK;
164dd7b254dSGiuliano Pochini 
165dd7b254dSGiuliano Pochini 	/* Set the new S/PDIF flags depending on the mode */
166dd7b254dSGiuliano Pochini 	control_reg |= GML_SPDIF_TWO_CHANNEL | GML_SPDIF_24_BIT |
167dd7b254dSGiuliano Pochini 		GML_SPDIF_COPY_PERMIT;
168dd7b254dSGiuliano Pochini 	if (prof) {
169dd7b254dSGiuliano Pochini 		/* Professional mode */
170dd7b254dSGiuliano Pochini 		control_reg |= GML_SPDIF_PRO_MODE;
171dd7b254dSGiuliano Pochini 
172dd7b254dSGiuliano Pochini 		switch (chip->sample_rate) {
173dd7b254dSGiuliano Pochini 		case 32000:
174dd7b254dSGiuliano Pochini 			control_reg |= GML_SPDIF_SAMPLE_RATE0 |
175dd7b254dSGiuliano Pochini 				GML_SPDIF_SAMPLE_RATE1;
176dd7b254dSGiuliano Pochini 			break;
177dd7b254dSGiuliano Pochini 		case 44100:
178dd7b254dSGiuliano Pochini 			control_reg |= GML_SPDIF_SAMPLE_RATE0;
179dd7b254dSGiuliano Pochini 			break;
180dd7b254dSGiuliano Pochini 		case 48000:
181dd7b254dSGiuliano Pochini 			control_reg |= GML_SPDIF_SAMPLE_RATE1;
182dd7b254dSGiuliano Pochini 			break;
183dd7b254dSGiuliano Pochini 		}
184dd7b254dSGiuliano Pochini 	} else {
185dd7b254dSGiuliano Pochini 		/* Consumer mode */
186dd7b254dSGiuliano Pochini 		switch (chip->sample_rate) {
187dd7b254dSGiuliano Pochini 		case 32000:
188dd7b254dSGiuliano Pochini 			control_reg |= GML_SPDIF_SAMPLE_RATE0 |
189dd7b254dSGiuliano Pochini 				GML_SPDIF_SAMPLE_RATE1;
190dd7b254dSGiuliano Pochini 			break;
191dd7b254dSGiuliano Pochini 		case 48000:
192dd7b254dSGiuliano Pochini 			control_reg |= GML_SPDIF_SAMPLE_RATE1;
193dd7b254dSGiuliano Pochini 			break;
194dd7b254dSGiuliano Pochini 		}
195dd7b254dSGiuliano Pochini 	}
196dd7b254dSGiuliano Pochini 
197*549717fcSTakashi Iwai 	err = write_control_reg(chip, control_reg, false);
198*549717fcSTakashi Iwai 	if (err)
199dd7b254dSGiuliano Pochini 		return err;
200dd7b254dSGiuliano Pochini 	chip->professional_spdif = prof;
201b5b4a41bSSudip Mukherjee 	dev_dbg(chip->card->dev, "set_professional_spdif to %s\n",
202b5b4a41bSSudip Mukherjee 		prof ? "Professional" : "Consumer");
203dd7b254dSGiuliano Pochini 	return 0;
204dd7b254dSGiuliano Pochini }
205