1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* -*- linux-c -*- * |
3 | * |
4 | * ALSA driver for the digigram lx6464es interface |
5 | * |
6 | * Copyright (c) 2008, 2009 Tim Blechmann <tim@klingt.org> |
7 | */ |
8 | |
9 | #include <linux/module.h> |
10 | #include <linux/init.h> |
11 | #include <linux/pci.h> |
12 | #include <linux/delay.h> |
13 | #include <linux/slab.h> |
14 | |
15 | #include <sound/initval.h> |
16 | #include <sound/control.h> |
17 | #include <sound/info.h> |
18 | |
19 | #include "lx6464es.h" |
20 | |
21 | MODULE_AUTHOR("Tim Blechmann" ); |
22 | MODULE_LICENSE("GPL" ); |
23 | MODULE_DESCRIPTION("digigram lx6464es" ); |
24 | |
25 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
26 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
27 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; |
28 | |
29 | module_param_array(index, int, NULL, 0444); |
30 | MODULE_PARM_DESC(index, "Index value for Digigram LX6464ES interface." ); |
31 | module_param_array(id, charp, NULL, 0444); |
32 | MODULE_PARM_DESC(id, "ID string for Digigram LX6464ES interface." ); |
33 | module_param_array(enable, bool, NULL, 0444); |
34 | MODULE_PARM_DESC(enable, "Enable/disable specific Digigram LX6464ES soundcards." ); |
35 | |
36 | static const char card_name[] = "LX6464ES" ; |
37 | |
38 | |
39 | #define PCI_DEVICE_ID_PLX_LX6464ES PCI_DEVICE_ID_PLX_9056 |
40 | |
41 | static const struct pci_device_id snd_lx6464es_ids[] = { |
42 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES, |
43 | PCI_VENDOR_ID_DIGIGRAM, |
44 | PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_SERIAL_SUBSYSTEM), |
45 | }, /* LX6464ES */ |
46 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES, |
47 | PCI_VENDOR_ID_DIGIGRAM, |
48 | PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_CAE_SERIAL_SUBSYSTEM), |
49 | }, /* LX6464ES-CAE */ |
50 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES, |
51 | PCI_VENDOR_ID_DIGIGRAM, |
52 | PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ESE_SERIAL_SUBSYSTEM), |
53 | }, /* LX6464ESe */ |
54 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES, |
55 | PCI_VENDOR_ID_DIGIGRAM, |
56 | PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ESE_CAE_SERIAL_SUBSYSTEM), |
57 | }, /* LX6464ESe-CAE */ |
58 | { 0, }, |
59 | }; |
60 | |
61 | MODULE_DEVICE_TABLE(pci, snd_lx6464es_ids); |
62 | |
63 | |
64 | |
65 | /* PGO pour USERo dans le registre pci_0x06/loc_0xEC */ |
66 | #define CHIPSC_RESET_XILINX (1L<<16) |
67 | |
68 | |
69 | /* alsa callbacks */ |
70 | static const struct snd_pcm_hardware lx_caps = { |
71 | .info = (SNDRV_PCM_INFO_MMAP | |
72 | SNDRV_PCM_INFO_INTERLEAVED | |
73 | SNDRV_PCM_INFO_MMAP_VALID | |
74 | SNDRV_PCM_INFO_SYNC_START), |
75 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
76 | SNDRV_PCM_FMTBIT_S16_BE | |
77 | SNDRV_PCM_FMTBIT_S24_3LE | |
78 | SNDRV_PCM_FMTBIT_S24_3BE), |
79 | .rates = (SNDRV_PCM_RATE_CONTINUOUS | |
80 | SNDRV_PCM_RATE_8000_192000), |
81 | .rate_min = 8000, |
82 | .rate_max = 192000, |
83 | .channels_min = 2, |
84 | .channels_max = 64, |
85 | .buffer_bytes_max = 64*2*3*MICROBLAZE_IBL_MAX*MAX_STREAM_BUFFER, |
86 | .period_bytes_min = (2*2*MICROBLAZE_IBL_MIN*2), |
87 | .period_bytes_max = (4*64*MICROBLAZE_IBL_MAX*MAX_STREAM_BUFFER), |
88 | .periods_min = 2, |
89 | .periods_max = MAX_STREAM_BUFFER, |
90 | }; |
91 | |
92 | static int lx_set_granularity(struct lx6464es *chip, u32 gran); |
93 | |
94 | |
95 | static int lx_hardware_open(struct lx6464es *chip, |
96 | struct snd_pcm_substream *substream) |
97 | { |
98 | int err = 0; |
99 | struct snd_pcm_runtime *runtime = substream->runtime; |
100 | int channels = runtime->channels; |
101 | int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
102 | |
103 | snd_pcm_uframes_t period_size = runtime->period_size; |
104 | |
105 | dev_dbg(chip->card->dev, "allocating pipe for %d channels\n" , channels); |
106 | err = lx_pipe_allocate(chip, pipe: 0, is_capture, channels); |
107 | if (err < 0) { |
108 | dev_err(chip->card->dev, LXP "allocating pipe failed\n" ); |
109 | return err; |
110 | } |
111 | |
112 | err = lx_set_granularity(chip, gran: period_size); |
113 | if (err < 0) { |
114 | dev_err(chip->card->dev, "setting granularity to %ld failed\n" , |
115 | period_size); |
116 | return err; |
117 | } |
118 | |
119 | return 0; |
120 | } |
121 | |
122 | static int lx_hardware_start(struct lx6464es *chip, |
123 | struct snd_pcm_substream *substream) |
124 | { |
125 | int err = 0; |
126 | struct snd_pcm_runtime *runtime = substream->runtime; |
127 | int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
128 | |
129 | dev_dbg(chip->card->dev, "setting stream format\n" ); |
130 | err = lx_stream_set_format(chip, runtime, pipe: 0, is_capture); |
131 | if (err < 0) { |
132 | dev_err(chip->card->dev, "setting stream format failed\n" ); |
133 | return err; |
134 | } |
135 | |
136 | dev_dbg(chip->card->dev, "starting pipe\n" ); |
137 | err = lx_pipe_start(chip, pipe: 0, is_capture); |
138 | if (err < 0) { |
139 | dev_err(chip->card->dev, "starting pipe failed\n" ); |
140 | return err; |
141 | } |
142 | |
143 | dev_dbg(chip->card->dev, "waiting for pipe to start\n" ); |
144 | err = lx_pipe_wait_for_start(chip, pipe: 0, is_capture); |
145 | if (err < 0) { |
146 | dev_err(chip->card->dev, "waiting for pipe failed\n" ); |
147 | return err; |
148 | } |
149 | |
150 | return err; |
151 | } |
152 | |
153 | |
154 | static int lx_hardware_stop(struct lx6464es *chip, |
155 | struct snd_pcm_substream *substream) |
156 | { |
157 | int err = 0; |
158 | int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
159 | |
160 | dev_dbg(chip->card->dev, "pausing pipe\n" ); |
161 | err = lx_pipe_pause(chip, pipe: 0, is_capture); |
162 | if (err < 0) { |
163 | dev_err(chip->card->dev, "pausing pipe failed\n" ); |
164 | return err; |
165 | } |
166 | |
167 | dev_dbg(chip->card->dev, "waiting for pipe to become idle\n" ); |
168 | err = lx_pipe_wait_for_idle(chip, pipe: 0, is_capture); |
169 | if (err < 0) { |
170 | dev_err(chip->card->dev, "waiting for pipe failed\n" ); |
171 | return err; |
172 | } |
173 | |
174 | dev_dbg(chip->card->dev, "stopping pipe\n" ); |
175 | err = lx_pipe_stop(chip, pipe: 0, is_capture); |
176 | if (err < 0) { |
177 | dev_err(chip->card->dev, "stopping pipe failed\n" ); |
178 | return err; |
179 | } |
180 | |
181 | return err; |
182 | } |
183 | |
184 | |
185 | static int lx_hardware_close(struct lx6464es *chip, |
186 | struct snd_pcm_substream *substream) |
187 | { |
188 | int err = 0; |
189 | int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
190 | |
191 | dev_dbg(chip->card->dev, "releasing pipe\n" ); |
192 | err = lx_pipe_release(chip, pipe: 0, is_capture); |
193 | if (err < 0) { |
194 | dev_err(chip->card->dev, "releasing pipe failed\n" ); |
195 | return err; |
196 | } |
197 | |
198 | return err; |
199 | } |
200 | |
201 | |
202 | static int lx_pcm_open(struct snd_pcm_substream *substream) |
203 | { |
204 | struct lx6464es *chip = snd_pcm_substream_chip(substream); |
205 | struct snd_pcm_runtime *runtime = substream->runtime; |
206 | int err = 0; |
207 | int board_rate; |
208 | |
209 | dev_dbg(chip->card->dev, "->lx_pcm_open\n" ); |
210 | mutex_lock(&chip->setup_mutex); |
211 | |
212 | /* copy the struct snd_pcm_hardware struct */ |
213 | runtime->hw = lx_caps; |
214 | |
215 | #if 0 |
216 | /* buffer-size should better be multiple of period-size */ |
217 | err = snd_pcm_hw_constraint_integer(runtime, |
218 | SNDRV_PCM_HW_PARAM_PERIODS); |
219 | if (err < 0) { |
220 | dev_warn(chip->card->dev, "could not constrain periods\n" ); |
221 | goto exit; |
222 | } |
223 | #endif |
224 | |
225 | /* the clock rate cannot be changed */ |
226 | board_rate = chip->board_sample_rate; |
227 | err = snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_RATE, |
228 | val: board_rate); |
229 | |
230 | if (err < 0) { |
231 | dev_warn(chip->card->dev, "could not constrain periods\n" ); |
232 | goto exit; |
233 | } |
234 | |
235 | /* constrain period size */ |
236 | err = snd_pcm_hw_constraint_minmax(runtime, |
237 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, |
238 | MICROBLAZE_IBL_MIN, |
239 | MICROBLAZE_IBL_MAX); |
240 | if (err < 0) { |
241 | dev_warn(chip->card->dev, |
242 | "could not constrain period size\n" ); |
243 | goto exit; |
244 | } |
245 | |
246 | snd_pcm_hw_constraint_step(runtime, cond: 0, |
247 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, step: 32); |
248 | |
249 | snd_pcm_set_sync(substream); |
250 | err = 0; |
251 | |
252 | exit: |
253 | runtime->private_data = chip; |
254 | |
255 | mutex_unlock(lock: &chip->setup_mutex); |
256 | dev_dbg(chip->card->dev, "<-lx_pcm_open, %d\n" , err); |
257 | return err; |
258 | } |
259 | |
260 | static int lx_pcm_close(struct snd_pcm_substream *substream) |
261 | { |
262 | dev_dbg(substream->pcm->card->dev, "->lx_pcm_close\n" ); |
263 | return 0; |
264 | } |
265 | |
266 | static snd_pcm_uframes_t lx_pcm_stream_pointer(struct snd_pcm_substream |
267 | *substream) |
268 | { |
269 | struct lx6464es *chip = snd_pcm_substream_chip(substream); |
270 | snd_pcm_uframes_t pos; |
271 | int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
272 | |
273 | struct lx_stream *lx_stream = is_capture ? &chip->capture_stream : |
274 | &chip->playback_stream; |
275 | |
276 | dev_dbg(chip->card->dev, "->lx_pcm_stream_pointer\n" ); |
277 | |
278 | mutex_lock(&chip->lock); |
279 | pos = lx_stream->frame_pos * substream->runtime->period_size; |
280 | mutex_unlock(lock: &chip->lock); |
281 | |
282 | dev_dbg(chip->card->dev, "stream_pointer at %ld\n" , pos); |
283 | return pos; |
284 | } |
285 | |
286 | static int lx_pcm_prepare(struct snd_pcm_substream *substream) |
287 | { |
288 | struct lx6464es *chip = snd_pcm_substream_chip(substream); |
289 | int err = 0; |
290 | const int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
291 | |
292 | dev_dbg(chip->card->dev, "->lx_pcm_prepare\n" ); |
293 | |
294 | mutex_lock(&chip->setup_mutex); |
295 | |
296 | if (chip->hardware_running[is_capture]) { |
297 | err = lx_hardware_stop(chip, substream); |
298 | if (err < 0) { |
299 | dev_err(chip->card->dev, "failed to stop hardware. " |
300 | "Error code %d\n" , err); |
301 | goto exit; |
302 | } |
303 | |
304 | err = lx_hardware_close(chip, substream); |
305 | if (err < 0) { |
306 | dev_err(chip->card->dev, "failed to close hardware. " |
307 | "Error code %d\n" , err); |
308 | goto exit; |
309 | } |
310 | } |
311 | |
312 | dev_dbg(chip->card->dev, "opening hardware\n" ); |
313 | err = lx_hardware_open(chip, substream); |
314 | if (err < 0) { |
315 | dev_err(chip->card->dev, "failed to open hardware. " |
316 | "Error code %d\n" , err); |
317 | goto exit; |
318 | } |
319 | |
320 | err = lx_hardware_start(chip, substream); |
321 | if (err < 0) { |
322 | dev_err(chip->card->dev, "failed to start hardware. " |
323 | "Error code %d\n" , err); |
324 | goto exit; |
325 | } |
326 | |
327 | chip->hardware_running[is_capture] = 1; |
328 | |
329 | if (chip->board_sample_rate != substream->runtime->rate) { |
330 | if (!err) |
331 | chip->board_sample_rate = substream->runtime->rate; |
332 | } |
333 | |
334 | exit: |
335 | mutex_unlock(lock: &chip->setup_mutex); |
336 | return err; |
337 | } |
338 | |
339 | static int lx_pcm_hw_params(struct snd_pcm_substream *substream, |
340 | struct snd_pcm_hw_params *hw_params, int is_capture) |
341 | { |
342 | struct lx6464es *chip = snd_pcm_substream_chip(substream); |
343 | |
344 | dev_dbg(chip->card->dev, "->lx_pcm_hw_params\n" ); |
345 | |
346 | mutex_lock(&chip->setup_mutex); |
347 | |
348 | if (is_capture) |
349 | chip->capture_stream.stream = substream; |
350 | else |
351 | chip->playback_stream.stream = substream; |
352 | |
353 | mutex_unlock(lock: &chip->setup_mutex); |
354 | return 0; |
355 | } |
356 | |
357 | static int lx_pcm_hw_params_playback(struct snd_pcm_substream *substream, |
358 | struct snd_pcm_hw_params *hw_params) |
359 | { |
360 | return lx_pcm_hw_params(substream, hw_params, is_capture: 0); |
361 | } |
362 | |
363 | static int lx_pcm_hw_params_capture(struct snd_pcm_substream *substream, |
364 | struct snd_pcm_hw_params *hw_params) |
365 | { |
366 | return lx_pcm_hw_params(substream, hw_params, is_capture: 1); |
367 | } |
368 | |
369 | static int lx_pcm_hw_free(struct snd_pcm_substream *substream) |
370 | { |
371 | struct lx6464es *chip = snd_pcm_substream_chip(substream); |
372 | int err = 0; |
373 | int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
374 | |
375 | dev_dbg(chip->card->dev, "->lx_pcm_hw_free\n" ); |
376 | mutex_lock(&chip->setup_mutex); |
377 | |
378 | if (chip->hardware_running[is_capture]) { |
379 | err = lx_hardware_stop(chip, substream); |
380 | if (err < 0) { |
381 | dev_err(chip->card->dev, "failed to stop hardware. " |
382 | "Error code %d\n" , err); |
383 | goto exit; |
384 | } |
385 | |
386 | err = lx_hardware_close(chip, substream); |
387 | if (err < 0) { |
388 | dev_err(chip->card->dev, "failed to close hardware. " |
389 | "Error code %d\n" , err); |
390 | goto exit; |
391 | } |
392 | |
393 | chip->hardware_running[is_capture] = 0; |
394 | } |
395 | |
396 | if (is_capture) |
397 | chip->capture_stream.stream = NULL; |
398 | else |
399 | chip->playback_stream.stream = NULL; |
400 | |
401 | exit: |
402 | mutex_unlock(lock: &chip->setup_mutex); |
403 | return err; |
404 | } |
405 | |
406 | static void lx_trigger_start(struct lx6464es *chip, struct lx_stream *lx_stream) |
407 | { |
408 | struct snd_pcm_substream *substream = lx_stream->stream; |
409 | const unsigned int is_capture = lx_stream->is_capture; |
410 | |
411 | int err; |
412 | |
413 | const u32 channels = substream->runtime->channels; |
414 | const u32 bytes_per_frame = channels * 3; |
415 | const u32 period_size = substream->runtime->period_size; |
416 | const u32 periods = substream->runtime->periods; |
417 | const u32 period_bytes = period_size * bytes_per_frame; |
418 | |
419 | dma_addr_t buf = substream->dma_buffer.addr; |
420 | int i; |
421 | |
422 | u32 needed, freed; |
423 | u32 size_array[5]; |
424 | |
425 | for (i = 0; i != periods; ++i) { |
426 | u32 buffer_index = 0; |
427 | |
428 | err = lx_buffer_ask(chip, pipe: 0, is_capture, r_needed: &needed, r_freed: &freed, |
429 | size_array); |
430 | dev_dbg(chip->card->dev, "starting: needed %d, freed %d\n" , |
431 | needed, freed); |
432 | |
433 | err = lx_buffer_give(chip, pipe: 0, is_capture, buffer_size: period_bytes, |
434 | lower_32_bits(buf), upper_32_bits(buf), |
435 | r_buffer_index: &buffer_index); |
436 | |
437 | dev_dbg(chip->card->dev, "starting: buffer index %x on 0x%lx (%d bytes)\n" , |
438 | buffer_index, (unsigned long)buf, period_bytes); |
439 | buf += period_bytes; |
440 | } |
441 | |
442 | err = lx_buffer_ask(chip, pipe: 0, is_capture, r_needed: &needed, r_freed: &freed, size_array); |
443 | dev_dbg(chip->card->dev, "starting: needed %d, freed %d\n" , needed, freed); |
444 | |
445 | dev_dbg(chip->card->dev, "starting: starting stream\n" ); |
446 | err = lx_stream_start(chip, pipe: 0, is_capture); |
447 | if (err < 0) |
448 | dev_err(chip->card->dev, "couldn't start stream\n" ); |
449 | else |
450 | lx_stream->status = LX_STREAM_STATUS_RUNNING; |
451 | |
452 | lx_stream->frame_pos = 0; |
453 | } |
454 | |
455 | static void lx_trigger_stop(struct lx6464es *chip, struct lx_stream *lx_stream) |
456 | { |
457 | const unsigned int is_capture = lx_stream->is_capture; |
458 | int err; |
459 | |
460 | dev_dbg(chip->card->dev, "stopping: stopping stream\n" ); |
461 | err = lx_stream_stop(chip, pipe: 0, is_capture); |
462 | if (err < 0) |
463 | dev_err(chip->card->dev, "couldn't stop stream\n" ); |
464 | else |
465 | lx_stream->status = LX_STREAM_STATUS_FREE; |
466 | |
467 | } |
468 | |
469 | static void lx_trigger_dispatch_stream(struct lx6464es *chip, |
470 | struct lx_stream *lx_stream) |
471 | { |
472 | switch (lx_stream->status) { |
473 | case LX_STREAM_STATUS_SCHEDULE_RUN: |
474 | lx_trigger_start(chip, lx_stream); |
475 | break; |
476 | |
477 | case LX_STREAM_STATUS_SCHEDULE_STOP: |
478 | lx_trigger_stop(chip, lx_stream); |
479 | break; |
480 | |
481 | default: |
482 | break; |
483 | } |
484 | } |
485 | |
486 | static int lx_pcm_trigger_dispatch(struct lx6464es *chip, |
487 | struct lx_stream *lx_stream, int cmd) |
488 | { |
489 | int err = 0; |
490 | |
491 | mutex_lock(&chip->lock); |
492 | switch (cmd) { |
493 | case SNDRV_PCM_TRIGGER_START: |
494 | lx_stream->status = LX_STREAM_STATUS_SCHEDULE_RUN; |
495 | break; |
496 | |
497 | case SNDRV_PCM_TRIGGER_STOP: |
498 | lx_stream->status = LX_STREAM_STATUS_SCHEDULE_STOP; |
499 | break; |
500 | |
501 | default: |
502 | err = -EINVAL; |
503 | goto exit; |
504 | } |
505 | |
506 | lx_trigger_dispatch_stream(chip, lx_stream: &chip->capture_stream); |
507 | lx_trigger_dispatch_stream(chip, lx_stream: &chip->playback_stream); |
508 | |
509 | exit: |
510 | mutex_unlock(lock: &chip->lock); |
511 | return err; |
512 | } |
513 | |
514 | |
515 | static int lx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
516 | { |
517 | struct lx6464es *chip = snd_pcm_substream_chip(substream); |
518 | const int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
519 | struct lx_stream *stream = is_capture ? &chip->capture_stream : |
520 | &chip->playback_stream; |
521 | |
522 | dev_dbg(chip->card->dev, "->lx_pcm_trigger\n" ); |
523 | |
524 | return lx_pcm_trigger_dispatch(chip, lx_stream: stream, cmd); |
525 | } |
526 | |
527 | static void snd_lx6464es_free(struct snd_card *card) |
528 | { |
529 | struct lx6464es *chip = card->private_data; |
530 | |
531 | lx_irq_disable(chip); |
532 | } |
533 | |
534 | /* reset the dsp during initialization */ |
535 | static int lx_init_xilinx_reset(struct lx6464es *chip) |
536 | { |
537 | int i; |
538 | u32 plx_reg = lx_plx_reg_read(chip, port: ePLX_CHIPSC); |
539 | |
540 | dev_dbg(chip->card->dev, "->lx_init_xilinx_reset\n" ); |
541 | |
542 | /* activate reset of xilinx */ |
543 | plx_reg &= ~CHIPSC_RESET_XILINX; |
544 | |
545 | lx_plx_reg_write(chip, port: ePLX_CHIPSC, data: plx_reg); |
546 | msleep(msecs: 1); |
547 | |
548 | lx_plx_reg_write(chip, port: ePLX_MBOX3, data: 0); |
549 | msleep(msecs: 1); |
550 | |
551 | plx_reg |= CHIPSC_RESET_XILINX; |
552 | lx_plx_reg_write(chip, port: ePLX_CHIPSC, data: plx_reg); |
553 | |
554 | /* deactivate reset of xilinx */ |
555 | for (i = 0; i != 100; ++i) { |
556 | u32 reg_mbox3; |
557 | msleep(msecs: 10); |
558 | reg_mbox3 = lx_plx_reg_read(chip, port: ePLX_MBOX3); |
559 | if (reg_mbox3) { |
560 | dev_dbg(chip->card->dev, "xilinx reset done\n" ); |
561 | dev_dbg(chip->card->dev, "xilinx took %d loops\n" , i); |
562 | break; |
563 | } |
564 | } |
565 | |
566 | /* todo: add some error handling? */ |
567 | |
568 | /* clear mr */ |
569 | lx_dsp_reg_write(chip, port: eReg_CSM, data: 0); |
570 | |
571 | /* le xilinx ES peut ne pas etre encore pret, on attend. */ |
572 | msleep(msecs: 600); |
573 | |
574 | return 0; |
575 | } |
576 | |
577 | static int lx_init_xilinx_test(struct lx6464es *chip) |
578 | { |
579 | u32 reg; |
580 | |
581 | dev_dbg(chip->card->dev, "->lx_init_xilinx_test\n" ); |
582 | |
583 | /* TEST if we have access to Xilinx/MicroBlaze */ |
584 | lx_dsp_reg_write(chip, port: eReg_CSM, data: 0); |
585 | |
586 | reg = lx_dsp_reg_read(chip, port: eReg_CSM); |
587 | |
588 | if (reg) { |
589 | dev_err(chip->card->dev, "Problem: Reg_CSM %x.\n" , reg); |
590 | |
591 | /* PCI9056_SPACE0_REMAP */ |
592 | lx_plx_reg_write(chip, port: ePLX_PCICR, data: 1); |
593 | |
594 | reg = lx_dsp_reg_read(chip, port: eReg_CSM); |
595 | if (reg) { |
596 | dev_err(chip->card->dev, "Error: Reg_CSM %x.\n" , reg); |
597 | return -EAGAIN; /* seems to be appropriate */ |
598 | } |
599 | } |
600 | |
601 | dev_dbg(chip->card->dev, "Xilinx/MicroBlaze access test successful\n" ); |
602 | |
603 | return 0; |
604 | } |
605 | |
606 | /* initialize ethersound */ |
607 | static int lx_init_ethersound_config(struct lx6464es *chip) |
608 | { |
609 | int i; |
610 | u32 orig_conf_es = lx_dsp_reg_read(chip, port: eReg_CONFES); |
611 | |
612 | /* configure 64 io channels */ |
613 | u32 conf_es = (orig_conf_es & CONFES_READ_PART_MASK) | |
614 | (64 << IOCR_INPUTS_OFFSET) | |
615 | (64 << IOCR_OUTPUTS_OFFSET) | |
616 | (FREQ_RATIO_SINGLE_MODE << FREQ_RATIO_OFFSET); |
617 | |
618 | dev_dbg(chip->card->dev, "->lx_init_ethersound\n" ); |
619 | |
620 | chip->freq_ratio = FREQ_RATIO_SINGLE_MODE; |
621 | |
622 | /* |
623 | * write it to the card ! |
624 | * this actually kicks the ES xilinx, the first time since poweron. |
625 | * the MAC address in the Reg_ADMACESMSB Reg_ADMACESLSB registers |
626 | * is not ready before this is done, and the bit 2 in Reg_CSES is set. |
627 | * */ |
628 | lx_dsp_reg_write(chip, port: eReg_CONFES, data: conf_es); |
629 | |
630 | for (i = 0; i != 1000; ++i) { |
631 | if (lx_dsp_reg_read(chip, port: eReg_CSES) & 4) { |
632 | dev_dbg(chip->card->dev, "ethersound initialized after %dms\n" , |
633 | i); |
634 | goto ethersound_initialized; |
635 | } |
636 | msleep(msecs: 1); |
637 | } |
638 | dev_warn(chip->card->dev, |
639 | "ethersound could not be initialized after %dms\n" , i); |
640 | return -ETIMEDOUT; |
641 | |
642 | ethersound_initialized: |
643 | dev_dbg(chip->card->dev, "ethersound initialized\n" ); |
644 | return 0; |
645 | } |
646 | |
647 | static int lx_init_get_version_features(struct lx6464es *chip) |
648 | { |
649 | u32 dsp_version; |
650 | |
651 | int err; |
652 | |
653 | dev_dbg(chip->card->dev, "->lx_init_get_version_features\n" ); |
654 | |
655 | err = lx_dsp_get_version(chip, rdsp_version: &dsp_version); |
656 | |
657 | if (err == 0) { |
658 | u32 freq; |
659 | |
660 | dev_info(chip->card->dev, "DSP version: V%02d.%02d #%d\n" , |
661 | (dsp_version>>16) & 0xff, (dsp_version>>8) & 0xff, |
662 | dsp_version & 0xff); |
663 | |
664 | /* later: what firmware version do we expect? */ |
665 | |
666 | /* retrieve Play/Rec features */ |
667 | /* done here because we may have to handle alternate |
668 | * DSP files. */ |
669 | /* later */ |
670 | |
671 | /* init the EtherSound sample rate */ |
672 | err = lx_dsp_get_clock_frequency(chip, rfreq: &freq); |
673 | if (err == 0) |
674 | chip->board_sample_rate = freq; |
675 | dev_dbg(chip->card->dev, "actual clock frequency %d\n" , freq); |
676 | } else { |
677 | dev_err(chip->card->dev, "DSP corrupted \n" ); |
678 | err = -EAGAIN; |
679 | } |
680 | |
681 | return err; |
682 | } |
683 | |
684 | static int lx_set_granularity(struct lx6464es *chip, u32 gran) |
685 | { |
686 | int err = 0; |
687 | u32 snapped_gran = MICROBLAZE_IBL_MIN; |
688 | |
689 | dev_dbg(chip->card->dev, "->lx_set_granularity\n" ); |
690 | |
691 | /* blocksize is a power of 2 */ |
692 | while ((snapped_gran < gran) && |
693 | (snapped_gran < MICROBLAZE_IBL_MAX)) { |
694 | snapped_gran *= 2; |
695 | } |
696 | |
697 | if (snapped_gran == chip->pcm_granularity) |
698 | return 0; |
699 | |
700 | err = lx_dsp_set_granularity(chip, gran: snapped_gran); |
701 | if (err < 0) { |
702 | dev_warn(chip->card->dev, "could not set granularity\n" ); |
703 | err = -EAGAIN; |
704 | } |
705 | |
706 | if (snapped_gran != gran) |
707 | dev_err(chip->card->dev, "snapped blocksize to %d\n" , snapped_gran); |
708 | |
709 | dev_dbg(chip->card->dev, "set blocksize on board %d\n" , snapped_gran); |
710 | chip->pcm_granularity = snapped_gran; |
711 | |
712 | return err; |
713 | } |
714 | |
715 | /* initialize and test the xilinx dsp chip */ |
716 | static int lx_init_dsp(struct lx6464es *chip) |
717 | { |
718 | int err; |
719 | int i; |
720 | |
721 | dev_dbg(chip->card->dev, "->lx_init_dsp\n" ); |
722 | |
723 | dev_dbg(chip->card->dev, "initialize board\n" ); |
724 | err = lx_init_xilinx_reset(chip); |
725 | if (err) |
726 | return err; |
727 | |
728 | dev_dbg(chip->card->dev, "testing board\n" ); |
729 | err = lx_init_xilinx_test(chip); |
730 | if (err) |
731 | return err; |
732 | |
733 | dev_dbg(chip->card->dev, "initialize ethersound configuration\n" ); |
734 | err = lx_init_ethersound_config(chip); |
735 | if (err) |
736 | return err; |
737 | |
738 | lx_irq_enable(chip); |
739 | |
740 | /** \todo the mac address should be ready by not, but it isn't, |
741 | * so we wait for it */ |
742 | for (i = 0; i != 1000; ++i) { |
743 | err = lx_dsp_get_mac(chip); |
744 | if (err) |
745 | return err; |
746 | if (chip->mac_address[0] || chip->mac_address[1] || chip->mac_address[2] || |
747 | chip->mac_address[3] || chip->mac_address[4] || chip->mac_address[5]) |
748 | goto mac_ready; |
749 | msleep(msecs: 1); |
750 | } |
751 | return -ETIMEDOUT; |
752 | |
753 | mac_ready: |
754 | dev_dbg(chip->card->dev, "mac address ready read after: %dms\n" , i); |
755 | dev_info(chip->card->dev, |
756 | "mac address: %02X.%02X.%02X.%02X.%02X.%02X\n" , |
757 | chip->mac_address[0], chip->mac_address[1], chip->mac_address[2], |
758 | chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]); |
759 | |
760 | err = lx_init_get_version_features(chip); |
761 | if (err) |
762 | return err; |
763 | |
764 | lx_set_granularity(chip, MICROBLAZE_IBL_DEFAULT); |
765 | |
766 | chip->playback_mute = 0; |
767 | |
768 | return err; |
769 | } |
770 | |
771 | static const struct snd_pcm_ops lx_ops_playback = { |
772 | .open = lx_pcm_open, |
773 | .close = lx_pcm_close, |
774 | .prepare = lx_pcm_prepare, |
775 | .hw_params = lx_pcm_hw_params_playback, |
776 | .hw_free = lx_pcm_hw_free, |
777 | .trigger = lx_pcm_trigger, |
778 | .pointer = lx_pcm_stream_pointer, |
779 | }; |
780 | |
781 | static const struct snd_pcm_ops lx_ops_capture = { |
782 | .open = lx_pcm_open, |
783 | .close = lx_pcm_close, |
784 | .prepare = lx_pcm_prepare, |
785 | .hw_params = lx_pcm_hw_params_capture, |
786 | .hw_free = lx_pcm_hw_free, |
787 | .trigger = lx_pcm_trigger, |
788 | .pointer = lx_pcm_stream_pointer, |
789 | }; |
790 | |
791 | static int lx_pcm_create(struct lx6464es *chip) |
792 | { |
793 | int err; |
794 | struct snd_pcm *pcm; |
795 | |
796 | u32 size = 64 * /* channels */ |
797 | 3 * /* 24 bit samples */ |
798 | MAX_STREAM_BUFFER * /* periods */ |
799 | MICROBLAZE_IBL_MAX * /* frames per period */ |
800 | 2; /* duplex */ |
801 | |
802 | size = PAGE_ALIGN(size); |
803 | |
804 | /* hardcoded device name & channel count */ |
805 | err = snd_pcm_new(card: chip->card, id: (char *)card_name, device: 0, |
806 | playback_count: 1, capture_count: 1, rpcm: &pcm); |
807 | if (err < 0) |
808 | return err; |
809 | |
810 | pcm->private_data = chip; |
811 | |
812 | snd_pcm_set_ops(pcm, direction: SNDRV_PCM_STREAM_PLAYBACK, ops: &lx_ops_playback); |
813 | snd_pcm_set_ops(pcm, direction: SNDRV_PCM_STREAM_CAPTURE, ops: &lx_ops_capture); |
814 | |
815 | pcm->info_flags = 0; |
816 | pcm->nonatomic = true; |
817 | strcpy(p: pcm->name, q: card_name); |
818 | |
819 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, |
820 | data: &chip->pci->dev, size, max: size); |
821 | |
822 | chip->pcm = pcm; |
823 | chip->capture_stream.is_capture = 1; |
824 | |
825 | return 0; |
826 | } |
827 | |
828 | static int lx_control_playback_info(struct snd_kcontrol *kcontrol, |
829 | struct snd_ctl_elem_info *uinfo) |
830 | { |
831 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
832 | uinfo->count = 1; |
833 | uinfo->value.integer.min = 0; |
834 | uinfo->value.integer.max = 1; |
835 | return 0; |
836 | } |
837 | |
838 | static int lx_control_playback_get(struct snd_kcontrol *kcontrol, |
839 | struct snd_ctl_elem_value *ucontrol) |
840 | { |
841 | struct lx6464es *chip = snd_kcontrol_chip(kcontrol); |
842 | ucontrol->value.integer.value[0] = chip->playback_mute; |
843 | return 0; |
844 | } |
845 | |
846 | static int lx_control_playback_put(struct snd_kcontrol *kcontrol, |
847 | struct snd_ctl_elem_value *ucontrol) |
848 | { |
849 | struct lx6464es *chip = snd_kcontrol_chip(kcontrol); |
850 | int changed = 0; |
851 | int current_value = chip->playback_mute; |
852 | |
853 | if (current_value != ucontrol->value.integer.value[0]) { |
854 | lx_level_unmute(chip, is_capture: 0, unmute: !current_value); |
855 | chip->playback_mute = !current_value; |
856 | changed = 1; |
857 | } |
858 | return changed; |
859 | } |
860 | |
861 | static const struct snd_kcontrol_new lx_control_playback_switch = { |
862 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
863 | .name = "PCM Playback Switch" , |
864 | .index = 0, |
865 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
866 | .private_value = 0, |
867 | .info = lx_control_playback_info, |
868 | .get = lx_control_playback_get, |
869 | .put = lx_control_playback_put |
870 | }; |
871 | |
872 | |
873 | |
874 | static void lx_proc_levels_read(struct snd_info_entry *entry, |
875 | struct snd_info_buffer *buffer) |
876 | { |
877 | u32 levels[64]; |
878 | int err; |
879 | int i, j; |
880 | struct lx6464es *chip = entry->private_data; |
881 | |
882 | snd_iprintf(buffer, "capture levels:\n" ); |
883 | err = lx_level_peaks(chip, is_capture: 1, channels: 64, r_levels: levels); |
884 | if (err < 0) |
885 | return; |
886 | |
887 | for (i = 0; i != 8; ++i) { |
888 | for (j = 0; j != 8; ++j) |
889 | snd_iprintf(buffer, "%08x " , levels[i*8+j]); |
890 | snd_iprintf(buffer, "\n" ); |
891 | } |
892 | |
893 | snd_iprintf(buffer, "\nplayback levels:\n" ); |
894 | |
895 | err = lx_level_peaks(chip, is_capture: 0, channels: 64, r_levels: levels); |
896 | if (err < 0) |
897 | return; |
898 | |
899 | for (i = 0; i != 8; ++i) { |
900 | for (j = 0; j != 8; ++j) |
901 | snd_iprintf(buffer, "%08x " , levels[i*8+j]); |
902 | snd_iprintf(buffer, "\n" ); |
903 | } |
904 | |
905 | snd_iprintf(buffer, "\n" ); |
906 | } |
907 | |
908 | static int lx_proc_create(struct snd_card *card, struct lx6464es *chip) |
909 | { |
910 | return snd_card_ro_proc_new(card, name: "levels" , private_data: chip, read: lx_proc_levels_read); |
911 | } |
912 | |
913 | |
914 | static int snd_lx6464es_create(struct snd_card *card, |
915 | struct pci_dev *pci) |
916 | { |
917 | struct lx6464es *chip = card->private_data; |
918 | int err; |
919 | |
920 | dev_dbg(card->dev, "->snd_lx6464es_create\n" ); |
921 | |
922 | /* enable PCI device */ |
923 | err = pcim_enable_device(pdev: pci); |
924 | if (err < 0) |
925 | return err; |
926 | |
927 | pci_set_master(dev: pci); |
928 | |
929 | /* check if we can restrict PCI DMA transfers to 32 bits */ |
930 | err = dma_set_mask(dev: &pci->dev, DMA_BIT_MASK(32)); |
931 | if (err < 0) { |
932 | dev_err(card->dev, |
933 | "architecture does not support 32bit PCI busmaster DMA\n" ); |
934 | return -ENXIO; |
935 | } |
936 | |
937 | chip->card = card; |
938 | chip->pci = pci; |
939 | chip->irq = -1; |
940 | |
941 | /* initialize synchronization structs */ |
942 | mutex_init(&chip->lock); |
943 | mutex_init(&chip->msg_lock); |
944 | mutex_init(&chip->setup_mutex); |
945 | |
946 | /* request resources */ |
947 | err = pci_request_regions(pci, card_name); |
948 | if (err < 0) |
949 | return err; |
950 | |
951 | /* plx port */ |
952 | chip->port_plx = pci_resource_start(pci, 1); |
953 | chip->port_plx_remapped = devm_ioport_map(dev: &pci->dev, port: chip->port_plx, |
954 | pci_resource_len(pci, 1)); |
955 | if (!chip->port_plx_remapped) |
956 | return -ENOMEM; |
957 | |
958 | /* dsp port */ |
959 | chip->port_dsp_bar = pcim_iomap(pdev: pci, bar: 2, maxlen: 0); |
960 | if (!chip->port_dsp_bar) |
961 | return -ENOMEM; |
962 | |
963 | err = devm_request_threaded_irq(dev: &pci->dev, irq: pci->irq, handler: lx_interrupt, |
964 | thread_fn: lx_threaded_irq, IRQF_SHARED, |
965 | KBUILD_MODNAME, dev_id: chip); |
966 | if (err) { |
967 | dev_err(card->dev, "unable to grab IRQ %d\n" , pci->irq); |
968 | return err; |
969 | } |
970 | chip->irq = pci->irq; |
971 | card->sync_irq = chip->irq; |
972 | card->private_free = snd_lx6464es_free; |
973 | |
974 | err = lx_init_dsp(chip); |
975 | if (err < 0) { |
976 | dev_err(card->dev, "error during DSP initialization\n" ); |
977 | return err; |
978 | } |
979 | |
980 | err = lx_pcm_create(chip); |
981 | if (err < 0) |
982 | return err; |
983 | |
984 | err = lx_proc_create(card, chip); |
985 | if (err < 0) |
986 | return err; |
987 | |
988 | err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &lx_control_playback_switch, |
989 | private_data: chip)); |
990 | if (err < 0) |
991 | return err; |
992 | |
993 | return 0; |
994 | } |
995 | |
996 | static int snd_lx6464es_probe(struct pci_dev *pci, |
997 | const struct pci_device_id *pci_id) |
998 | { |
999 | static int dev; |
1000 | struct snd_card *card; |
1001 | struct lx6464es *chip; |
1002 | int err; |
1003 | |
1004 | dev_dbg(&pci->dev, "->snd_lx6464es_probe\n" ); |
1005 | |
1006 | if (dev >= SNDRV_CARDS) |
1007 | return -ENODEV; |
1008 | if (!enable[dev]) { |
1009 | dev++; |
1010 | return -ENOENT; |
1011 | } |
1012 | |
1013 | err = snd_devm_card_new(parent: &pci->dev, idx: index[dev], xid: id[dev], THIS_MODULE, |
1014 | extra_size: sizeof(*chip), card_ret: &card); |
1015 | if (err < 0) |
1016 | return err; |
1017 | chip = card->private_data; |
1018 | |
1019 | err = snd_lx6464es_create(card, pci); |
1020 | if (err < 0) { |
1021 | dev_err(card->dev, "error during snd_lx6464es_create\n" ); |
1022 | goto error; |
1023 | } |
1024 | |
1025 | strcpy(p: card->driver, q: "LX6464ES" ); |
1026 | sprintf(buf: card->id, fmt: "LX6464ES_%02X%02X%02X" , |
1027 | chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]); |
1028 | |
1029 | sprintf(buf: card->shortname, fmt: "LX6464ES %02X.%02X.%02X.%02X.%02X.%02X" , |
1030 | chip->mac_address[0], chip->mac_address[1], chip->mac_address[2], |
1031 | chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]); |
1032 | |
1033 | sprintf(buf: card->longname, fmt: "%s at 0x%lx, 0x%p, irq %i" , |
1034 | card->shortname, chip->port_plx, |
1035 | chip->port_dsp_bar, chip->irq); |
1036 | |
1037 | err = snd_card_register(card); |
1038 | if (err < 0) |
1039 | goto error; |
1040 | |
1041 | dev_dbg(chip->card->dev, "initialization successful\n" ); |
1042 | pci_set_drvdata(pdev: pci, data: card); |
1043 | dev++; |
1044 | return 0; |
1045 | |
1046 | error: |
1047 | snd_card_free(card); |
1048 | return err; |
1049 | } |
1050 | |
1051 | static struct pci_driver lx6464es_driver = { |
1052 | .name = KBUILD_MODNAME, |
1053 | .id_table = snd_lx6464es_ids, |
1054 | .probe = snd_lx6464es_probe, |
1055 | }; |
1056 | |
1057 | module_pci_driver(lx6464es_driver); |
1058 | |