Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/echoaudio/mia_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 set_input_clock(struct echoaudio *chip, u16 clock);
33
static int set_professional_spdif(struct echoaudio *chip, char prof);
34
static int update_flags(struct echoaudio *chip);
35
static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
36
int gain);
37
static int update_vmixer_level(struct echoaudio *chip);
38
39
40
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
41
{
42
int err;
43
44
DE_INIT(("init_hw() - Mia\n"));
45
if (snd_BUG_ON((subdevice_id & 0xfff0) != MIA))
46
return -ENODEV;
47
48
if ((err = init_dsp_comm_page(chip))) {
49
DE_INIT(("init_hw - could not initialize DSP comm page\n"));
50
return err;
51
}
52
53
chip->device_id = device_id;
54
chip->subdevice_id = subdevice_id;
55
chip->bad_board = TRUE;
56
chip->dsp_code_to_load = FW_MIA_DSP;
57
/* Since this card has no ASIC, mark it as loaded so everything
58
works OK */
59
chip->asic_loaded = TRUE;
60
if ((subdevice_id & 0x0000f) == MIA_MIDI_REV)
61
chip->has_midi = TRUE;
62
chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
63
ECHO_CLOCK_BIT_SPDIF;
64
65
if ((err = load_firmware(chip)) < 0)
66
return err;
67
chip->bad_board = FALSE;
68
69
DE_INIT(("init_hw done\n"));
70
return err;
71
}
72
73
74
75
static int set_mixer_defaults(struct echoaudio *chip)
76
{
77
return init_line_levels(chip);
78
}
79
80
81
82
static u32 detect_input_clocks(const struct echoaudio *chip)
83
{
84
u32 clocks_from_dsp, clock_bits;
85
86
/* Map the DSP clock detect bits to the generic driver clock
87
detect bits */
88
clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
89
90
clock_bits = ECHO_CLOCK_BIT_INTERNAL;
91
92
if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
93
clock_bits |= ECHO_CLOCK_BIT_SPDIF;
94
95
return clock_bits;
96
}
97
98
99
100
/* The Mia has no ASIC. Just do nothing */
101
static int load_asic(struct echoaudio *chip)
102
{
103
return 0;
104
}
105
106
107
108
static int set_sample_rate(struct echoaudio *chip, u32 rate)
109
{
110
u32 control_reg;
111
112
switch (rate) {
113
case 96000:
114
control_reg = MIA_96000;
115
break;
116
case 88200:
117
control_reg = MIA_88200;
118
break;
119
case 48000:
120
control_reg = MIA_48000;
121
break;
122
case 44100:
123
control_reg = MIA_44100;
124
break;
125
case 32000:
126
control_reg = MIA_32000;
127
break;
128
default:
129
DE_ACT(("set_sample_rate: %d invalid!\n", rate));
130
return -EINVAL;
131
}
132
133
/* Override the clock setting if this Mia is set to S/PDIF clock */
134
if (chip->input_clock == ECHO_CLOCK_SPDIF)
135
control_reg |= MIA_SPDIF;
136
137
/* Set the control register if it has changed */
138
if (control_reg != le32_to_cpu(chip->comm_page->control_register)) {
139
if (wait_handshake(chip))
140
return -EIO;
141
142
chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */
143
chip->comm_page->control_register = cpu_to_le32(control_reg);
144
chip->sample_rate = rate;
145
146
clear_handshake(chip);
147
return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
148
}
149
return 0;
150
}
151
152
153
154
static int set_input_clock(struct echoaudio *chip, u16 clock)
155
{
156
DE_ACT(("set_input_clock(%d)\n", clock));
157
if (snd_BUG_ON(clock != ECHO_CLOCK_INTERNAL &&
158
clock != ECHO_CLOCK_SPDIF))
159
return -EINVAL;
160
161
chip->input_clock = clock;
162
return set_sample_rate(chip, chip->sample_rate);
163
}
164
165
166
167
/* This function routes the sound from a virtual channel to a real output */
168
static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
169
int gain)
170
{
171
int index;
172
173
if (snd_BUG_ON(pipe >= num_pipes_out(chip) ||
174
output >= num_busses_out(chip)))
175
return -EINVAL;
176
177
if (wait_handshake(chip))
178
return -EIO;
179
180
chip->vmixer_gain[output][pipe] = gain;
181
index = output * num_pipes_out(chip) + pipe;
182
chip->comm_page->vmixer[index] = gain;
183
184
DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain));
185
return 0;
186
}
187
188
189
190
/* Tell the DSP to read and update virtual mixer levels in comm page. */
191
static int update_vmixer_level(struct echoaudio *chip)
192
{
193
if (wait_handshake(chip))
194
return -EIO;
195
clear_handshake(chip);
196
return send_vector(chip, DSP_VC_SET_VMIXER_GAIN);
197
}
198
199
200
201
/* Tell the DSP to reread the flags from the comm page */
202
static int update_flags(struct echoaudio *chip)
203
{
204
if (wait_handshake(chip))
205
return -EIO;
206
clear_handshake(chip);
207
return send_vector(chip, DSP_VC_UPDATE_FLAGS);
208
}
209
210
211
212
static int set_professional_spdif(struct echoaudio *chip, char prof)
213
{
214
DE_ACT(("set_professional_spdif %d\n", prof));
215
if (prof)
216
chip->comm_page->flags |=
217
cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
218
else
219
chip->comm_page->flags &=
220
~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
221
chip->professional_spdif = prof;
222
return update_flags(chip);
223
}
224
225
226