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