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