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