1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32static int read_dsp(struct echoaudio *chip, u32 *data);
33static int set_professional_spdif(struct echoaudio *chip, char prof);
34static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic);
35static int check_asic_status(struct echoaudio *chip);
36static int update_flags(struct echoaudio *chip);
37
38
39static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
40{
41 int err;
42
43 if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA20))
44 return -ENODEV;
45
46 err = init_dsp_comm_page(chip);
47 if (err) {
48 dev_err(chip->card->dev,
49 "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 = 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 err = load_firmware(chip);
65 if (err < 0)
66 return err;
67 chip->bad_board = false;
68
69 return err;
70}
71
72
73
74static int set_mixer_defaults(struct echoaudio *chip)
75{
76 chip->professional_spdif = false;
77 return init_line_levels(chip);
78}
79
80
81
82static u32 detect_input_clocks(const struct echoaudio *chip)
83{
84 u32 clocks_from_dsp, clock_bits;
85
86
87 clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
88
89 clock_bits = ECHO_CLOCK_BIT_INTERNAL;
90
91 if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
92 clock_bits |= ECHO_CLOCK_BIT_SPDIF;
93
94 if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_WORD) {
95 if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SUPER)
96 clock_bits |= ECHO_CLOCK_BIT_SUPER;
97 else
98 clock_bits |= ECHO_CLOCK_BIT_WORD;
99 }
100
101 return clock_bits;
102}
103
104
105
106
107
108
109
110
111
112
113static int check_asic_status(struct echoaudio *chip)
114{
115 u32 asic_status;
116 int goodcnt, i;
117
118 chip->asic_loaded = false;
119 for (i = goodcnt = 0; i < 5; i++) {
120 send_vector(chip, DSP_VC_TEST_ASIC);
121
122
123
124 if (read_dsp(chip, &asic_status) < 0) {
125 dev_err(chip->card->dev,
126 "check_asic_status: failed on read_dsp\n");
127 return -EIO;
128 }
129
130 if (asic_status == ASIC_ALREADY_LOADED) {
131 if (++goodcnt == 3) {
132 chip->asic_loaded = true;
133 return 0;
134 }
135 }
136 }
137 return -EIO;
138}
139
140
141
142
143static int load_asic(struct echoaudio *chip)
144{
145 int err;
146
147 if (chip->asic_loaded)
148 return 0;
149
150 err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA_ASIC,
151 FW_LAYLA20_ASIC);
152 if (err < 0)
153 return err;
154
155
156 return check_asic_status(chip);
157}
158
159
160
161static int set_sample_rate(struct echoaudio *chip, u32 rate)
162{
163 if (snd_BUG_ON(rate < 8000 || rate > 50000))
164 return -EINVAL;
165
166
167
168 if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
169 dev_warn(chip->card->dev,
170 "Cannot set sample rate - clock not set to CLK_CLOCKININTERNAL\n");
171 chip->comm_page->sample_rate = cpu_to_le32(rate);
172 chip->sample_rate = rate;
173 return 0;
174 }
175
176 if (wait_handshake(chip))
177 return -EIO;
178
179 dev_dbg(chip->card->dev, "set_sample_rate(%d)\n", rate);
180 chip->sample_rate = rate;
181 chip->comm_page->sample_rate = cpu_to_le32(rate);
182 clear_handshake(chip);
183 return send_vector(chip, DSP_VC_SET_LAYLA_SAMPLE_RATE);
184}
185
186
187
188static int set_input_clock(struct echoaudio *chip, u16 clock_source)
189{
190 u16 clock;
191 u32 rate;
192
193 rate = 0;
194 switch (clock_source) {
195 case ECHO_CLOCK_INTERNAL:
196 rate = chip->sample_rate;
197 clock = LAYLA20_CLOCK_INTERNAL;
198 break;
199 case ECHO_CLOCK_SPDIF:
200 clock = LAYLA20_CLOCK_SPDIF;
201 break;
202 case ECHO_CLOCK_WORD:
203 clock = LAYLA20_CLOCK_WORD;
204 break;
205 case ECHO_CLOCK_SUPER:
206 clock = LAYLA20_CLOCK_SUPER;
207 break;
208 default:
209 dev_err(chip->card->dev,
210 "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
228static int set_output_clock(struct echoaudio *chip, u16 clock)
229{
230 switch (clock) {
231 case ECHO_CLOCK_SUPER:
232 clock = LAYLA20_OUTPUT_CLOCK_SUPER;
233 break;
234 case ECHO_CLOCK_WORD:
235 clock = LAYLA20_OUTPUT_CLOCK_WORD;
236 break;
237 default:
238 dev_err(chip->card->dev, "set_output_clock wrong clock\n");
239 return -EINVAL;
240 }
241
242 if (wait_handshake(chip))
243 return -EIO;
244
245 chip->comm_page->output_clock = cpu_to_le16(clock);
246 chip->output_clock = clock;
247 clear_handshake(chip);
248 return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
249}
250
251
252
253
254static int set_input_gain(struct echoaudio *chip, u16 input, int gain)
255{
256 if (snd_BUG_ON(input >= num_busses_in(chip)))
257 return -EINVAL;
258
259 if (wait_handshake(chip))
260 return -EIO;
261
262 chip->input_gain[input] = gain;
263 gain += GL20_INPUT_GAIN_MAGIC_NUMBER;
264 chip->comm_page->line_in_level[input] = gain;
265 return 0;
266}
267
268
269
270
271static int update_flags(struct echoaudio *chip)
272{
273 if (wait_handshake(chip))
274 return -EIO;
275 clear_handshake(chip);
276 return send_vector(chip, DSP_VC_UPDATE_FLAGS);
277}
278
279
280
281static int set_professional_spdif(struct echoaudio *chip, char prof)
282{
283 if (prof)
284 chip->comm_page->flags |=
285 cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
286 else
287 chip->comm_page->flags &=
288 ~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
289 chip->professional_spdif = prof;
290 return update_flags(chip);
291}
292