Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/echoaudio/layla20_dsp.c
10817 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
static int read_dsp(struct echoaudio *chip, u32 *data);
33
static int set_professional_spdif(struct echoaudio *chip, char prof);
34
static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic);
35
static int check_asic_status(struct echoaudio *chip);
36
static int update_flags(struct echoaudio *chip);
37
38
39
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
40
{
41
int err;
42
43
DE_INIT(("init_hw() - Layla20\n"));
44
if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA20))
45
return -ENODEV;
46
47
if ((err = init_dsp_comm_page(chip))) {
48
DE_INIT(("init_hw - could not initialize DSP comm page\n"));
49
return err;
50
}
51
52
chip->device_id = device_id;
53
chip->subdevice_id = subdevice_id;
54
chip->bad_board = TRUE;
55
chip->has_midi = TRUE;
56
chip->dsp_code_to_load = FW_LAYLA20_DSP;
57
chip->input_clock_types =
58
ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |
59
ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER;
60
chip->output_clock_types =
61
ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER;
62
63
if ((err = load_firmware(chip)) < 0)
64
return err;
65
chip->bad_board = FALSE;
66
67
DE_INIT(("init_hw done\n"));
68
return err;
69
}
70
71
72
73
static int set_mixer_defaults(struct echoaudio *chip)
74
{
75
chip->professional_spdif = FALSE;
76
return init_line_levels(chip);
77
}
78
79
80
81
static u32 detect_input_clocks(const struct echoaudio *chip)
82
{
83
u32 clocks_from_dsp, clock_bits;
84
85
/* Map the DSP clock detect bits to the generic driver clock detect bits */
86
clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
87
88
clock_bits = ECHO_CLOCK_BIT_INTERNAL;
89
90
if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
91
clock_bits |= ECHO_CLOCK_BIT_SPDIF;
92
93
if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_WORD) {
94
if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SUPER)
95
clock_bits |= ECHO_CLOCK_BIT_SUPER;
96
else
97
clock_bits |= ECHO_CLOCK_BIT_WORD;
98
}
99
100
return clock_bits;
101
}
102
103
104
105
/* ASIC status check - some cards have one or two ASICs that need to be
106
loaded. Once that load is complete, this function is called to see if
107
the load was successful.
108
If this load fails, it does not necessarily mean that the hardware is
109
defective - the external box may be disconnected or turned off.
110
This routine sometimes fails for Layla20; for Layla20, the loop runs
111
5 times and succeeds if it wins on three of the loops. */
112
static int check_asic_status(struct echoaudio *chip)
113
{
114
u32 asic_status;
115
int goodcnt, i;
116
117
chip->asic_loaded = FALSE;
118
for (i = goodcnt = 0; i < 5; i++) {
119
send_vector(chip, DSP_VC_TEST_ASIC);
120
121
/* The DSP will return a value to indicate whether or not
122
the ASIC is currently loaded */
123
if (read_dsp(chip, &asic_status) < 0) {
124
DE_ACT(("check_asic_status: failed on read_dsp\n"));
125
return -EIO;
126
}
127
128
if (asic_status == ASIC_ALREADY_LOADED) {
129
if (++goodcnt == 3) {
130
chip->asic_loaded = TRUE;
131
return 0;
132
}
133
}
134
}
135
return -EIO;
136
}
137
138
139
140
/* Layla20 has an ASIC in the external box */
141
static int load_asic(struct echoaudio *chip)
142
{
143
int err;
144
145
if (chip->asic_loaded)
146
return 0;
147
148
err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA_ASIC,
149
FW_LAYLA20_ASIC);
150
if (err < 0)
151
return err;
152
153
/* Check if ASIC is alive and well. */
154
return check_asic_status(chip);
155
}
156
157
158
159
static int set_sample_rate(struct echoaudio *chip, u32 rate)
160
{
161
if (snd_BUG_ON(rate < 8000 || rate > 50000))
162
return -EINVAL;
163
164
/* Only set the clock for internal mode. Do not return failure,
165
simply treat it as a non-event. */
166
if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
167
DE_ACT(("set_sample_rate: Cannot set sample rate - "
168
"clock not set to CLK_CLOCKININTERNAL\n"));
169
chip->comm_page->sample_rate = cpu_to_le32(rate);
170
chip->sample_rate = rate;
171
return 0;
172
}
173
174
if (wait_handshake(chip))
175
return -EIO;
176
177
DE_ACT(("set_sample_rate(%d)\n", rate));
178
chip->sample_rate = rate;
179
chip->comm_page->sample_rate = cpu_to_le32(rate);
180
clear_handshake(chip);
181
return send_vector(chip, DSP_VC_SET_LAYLA_SAMPLE_RATE);
182
}
183
184
185
186
static int set_input_clock(struct echoaudio *chip, u16 clock_source)
187
{
188
u16 clock;
189
u32 rate;
190
191
DE_ACT(("set_input_clock:\n"));
192
rate = 0;
193
switch (clock_source) {
194
case ECHO_CLOCK_INTERNAL:
195
DE_ACT(("Set Layla20 clock to INTERNAL\n"));
196
rate = chip->sample_rate;
197
clock = LAYLA20_CLOCK_INTERNAL;
198
break;
199
case ECHO_CLOCK_SPDIF:
200
DE_ACT(("Set Layla20 clock to SPDIF\n"));
201
clock = LAYLA20_CLOCK_SPDIF;
202
break;
203
case ECHO_CLOCK_WORD:
204
DE_ACT(("Set Layla20 clock to WORD\n"));
205
clock = LAYLA20_CLOCK_WORD;
206
break;
207
case ECHO_CLOCK_SUPER:
208
DE_ACT(("Set Layla20 clock to SUPER\n"));
209
clock = LAYLA20_CLOCK_SUPER;
210
break;
211
default:
212
DE_ACT(("Input clock 0x%x not supported for Layla24\n",
213
clock_source));
214
return -EINVAL;
215
}
216
chip->input_clock = clock_source;
217
218
chip->comm_page->input_clock = cpu_to_le16(clock);
219
clear_handshake(chip);
220
send_vector(chip, DSP_VC_UPDATE_CLOCKS);
221
222
if (rate)
223
set_sample_rate(chip, rate);
224
225
return 0;
226
}
227
228
229
230
static int set_output_clock(struct echoaudio *chip, u16 clock)
231
{
232
DE_ACT(("set_output_clock: %d\n", clock));
233
switch (clock) {
234
case ECHO_CLOCK_SUPER:
235
clock = LAYLA20_OUTPUT_CLOCK_SUPER;
236
break;
237
case ECHO_CLOCK_WORD:
238
clock = LAYLA20_OUTPUT_CLOCK_WORD;
239
break;
240
default:
241
DE_ACT(("set_output_clock wrong clock\n"));
242
return -EINVAL;
243
}
244
245
if (wait_handshake(chip))
246
return -EIO;
247
248
chip->comm_page->output_clock = cpu_to_le16(clock);
249
chip->output_clock = clock;
250
clear_handshake(chip);
251
return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
252
}
253
254
255
256
/* Set input bus gain (one unit is 0.5dB !) */
257
static int set_input_gain(struct echoaudio *chip, u16 input, int gain)
258
{
259
if (snd_BUG_ON(input >= num_busses_in(chip)))
260
return -EINVAL;
261
262
if (wait_handshake(chip))
263
return -EIO;
264
265
chip->input_gain[input] = gain;
266
gain += GL20_INPUT_GAIN_MAGIC_NUMBER;
267
chip->comm_page->line_in_level[input] = gain;
268
return 0;
269
}
270
271
272
273
/* Tell the DSP to reread the flags from the comm page */
274
static int update_flags(struct echoaudio *chip)
275
{
276
if (wait_handshake(chip))
277
return -EIO;
278
clear_handshake(chip);
279
return send_vector(chip, DSP_VC_UPDATE_FLAGS);
280
}
281
282
283
284
static int set_professional_spdif(struct echoaudio *chip, char prof)
285
{
286
DE_ACT(("set_professional_spdif %d\n", prof));
287
if (prof)
288
chip->comm_page->flags |=
289
cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
290
else
291
chip->comm_page->flags &=
292
~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
293
chip->professional_spdif = prof;
294
return update_flags(chip);
295
}
296
297