Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/echoaudio/echoaudio_gml.c
10818 views
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 <[email protected]>
28
29
****************************************************************************/
30
31
32
/* These functions are common for Gina24, Layla24 and Mona cards */
33
34
35
/* ASIC status check - some cards have one or two ASICs that need to be
36
loaded. Once that load is complete, this function is called to see if
37
the load was successful.
38
If this load fails, it does not necessarily mean that the hardware is
39
defective - the external box may be disconnected or turned off. */
40
static int check_asic_status(struct echoaudio *chip)
41
{
42
u32 asic_status;
43
44
send_vector(chip, DSP_VC_TEST_ASIC);
45
46
/* The DSP will return a value to indicate whether or not the
47
ASIC is currently loaded */
48
if (read_dsp(chip, &asic_status) < 0) {
49
DE_INIT(("check_asic_status: failed on read_dsp\n"));
50
chip->asic_loaded = FALSE;
51
return -EIO;
52
}
53
54
chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED);
55
return chip->asic_loaded ? 0 : -EIO;
56
}
57
58
59
60
/* Most configuration of Gina24, Layla24, or Mona is accomplished by writing
61
the control register. write_control_reg sends the new control register
62
value to the DSP. */
63
static int write_control_reg(struct echoaudio *chip, u32 value, char force)
64
{
65
/* Handle the digital input auto-mute */
66
if (chip->digital_in_automute)
67
value |= GML_DIGITAL_IN_AUTO_MUTE;
68
else
69
value &= ~GML_DIGITAL_IN_AUTO_MUTE;
70
71
DE_ACT(("write_control_reg: 0x%x\n", value));
72
73
/* Write the control register */
74
value = cpu_to_le32(value);
75
if (value != chip->comm_page->control_register || force) {
76
if (wait_handshake(chip))
77
return -EIO;
78
chip->comm_page->control_register = value;
79
clear_handshake(chip);
80
return send_vector(chip, DSP_VC_WRITE_CONTROL_REG);
81
}
82
return 0;
83
}
84
85
86
87
/* Gina24, Layla24, and Mona support digital input auto-mute. If the digital
88
input auto-mute is enabled, the DSP will only enable the digital inputs if
89
the card is syncing to a valid clock on the ADAT or S/PDIF inputs.
90
If the auto-mute is disabled, the digital inputs are enabled regardless of
91
what the input clock is set or what is connected. */
92
static int set_input_auto_mute(struct echoaudio *chip, int automute)
93
{
94
DE_ACT(("set_input_auto_mute %d\n", automute));
95
96
chip->digital_in_automute = automute;
97
98
/* Re-set the input clock to the current value - indirectly causes
99
the auto-mute flag to be sent to the DSP */
100
return set_input_clock(chip, chip->input_clock);
101
}
102
103
104
105
/* S/PDIF coax / S/PDIF optical / ADAT - switch */
106
static int set_digital_mode(struct echoaudio *chip, u8 mode)
107
{
108
u8 previous_mode;
109
int err, i, o;
110
111
if (chip->bad_board)
112
return -EIO;
113
114
/* All audio channels must be closed before changing the digital mode */
115
if (snd_BUG_ON(chip->pipe_alloc_mask))
116
return -EAGAIN;
117
118
if (snd_BUG_ON(!(chip->digital_modes & (1 << mode))))
119
return -EINVAL;
120
121
previous_mode = chip->digital_mode;
122
err = dsp_set_digital_mode(chip, mode);
123
124
/* If we successfully changed the digital mode from or to ADAT,
125
then make sure all output, input and monitor levels are
126
updated by the DSP comm object. */
127
if (err >= 0 && previous_mode != mode &&
128
(previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) {
129
spin_lock_irq(&chip->lock);
130
for (o = 0; o < num_busses_out(chip); o++)
131
for (i = 0; i < num_busses_in(chip); i++)
132
set_monitor_gain(chip, o, i,
133
chip->monitor_gain[o][i]);
134
135
#ifdef ECHOCARD_HAS_INPUT_GAIN
136
for (i = 0; i < num_busses_in(chip); i++)
137
set_input_gain(chip, i, chip->input_gain[i]);
138
update_input_line_level(chip);
139
#endif
140
141
for (o = 0; o < num_busses_out(chip); o++)
142
set_output_gain(chip, o, chip->output_gain[o]);
143
update_output_line_level(chip);
144
spin_unlock_irq(&chip->lock);
145
}
146
147
return err;
148
}
149
150
151
152
/* Set the S/PDIF output format */
153
static int set_professional_spdif(struct echoaudio *chip, char prof)
154
{
155
u32 control_reg;
156
int err;
157
158
/* Clear the current S/PDIF flags */
159
control_reg = le32_to_cpu(chip->comm_page->control_register);
160
control_reg &= GML_SPDIF_FORMAT_CLEAR_MASK;
161
162
/* Set the new S/PDIF flags depending on the mode */
163
control_reg |= GML_SPDIF_TWO_CHANNEL | GML_SPDIF_24_BIT |
164
GML_SPDIF_COPY_PERMIT;
165
if (prof) {
166
/* Professional mode */
167
control_reg |= GML_SPDIF_PRO_MODE;
168
169
switch (chip->sample_rate) {
170
case 32000:
171
control_reg |= GML_SPDIF_SAMPLE_RATE0 |
172
GML_SPDIF_SAMPLE_RATE1;
173
break;
174
case 44100:
175
control_reg |= GML_SPDIF_SAMPLE_RATE0;
176
break;
177
case 48000:
178
control_reg |= GML_SPDIF_SAMPLE_RATE1;
179
break;
180
}
181
} else {
182
/* Consumer mode */
183
switch (chip->sample_rate) {
184
case 32000:
185
control_reg |= GML_SPDIF_SAMPLE_RATE0 |
186
GML_SPDIF_SAMPLE_RATE1;
187
break;
188
case 48000:
189
control_reg |= GML_SPDIF_SAMPLE_RATE1;
190
break;
191
}
192
}
193
194
if ((err = write_control_reg(chip, control_reg, FALSE)))
195
return err;
196
chip->professional_spdif = prof;
197
DE_ACT(("set_professional_spdif to %s\n",
198
prof ? "Professional" : "Consumer"));
199
return 0;
200
}
201
202