2 * Driver for Digigram miXart soundcards
4 * main file with alsa callbacks
6 * Copyright (c) 2003 by Digigram <alsa@digigram.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sound/driver.h>
25 #include <linux/init.h>
26 #include <linux/interrupt.h>
27 #include <linux/pci.h>
28 #include <linux/moduleparam.h>
29 #include <sound/core.h>
30 #include <sound/initval.h>
31 #include <sound/info.h>
32 #include <sound/control.h>
33 #include <sound/pcm.h>
34 #include <sound/pcm_params.h>
36 #include "mixart_hwdep.h"
37 #include "mixart_core.h"
38 #include "mixart_mixer.h"
40 #define CARD_NAME "miXart"
42 MODULE_AUTHOR("Digigram <alsa@digigram.com>");
43 MODULE_DESCRIPTION("Digigram " CARD_NAME
);
44 MODULE_LICENSE("GPL");
45 MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME
"}}");
47 static int index
[SNDRV_CARDS
] = SNDRV_DEFAULT_IDX
; /* Index 0-MAX */
48 static char *id
[SNDRV_CARDS
] = SNDRV_DEFAULT_STR
; /* ID for this card */
49 static int enable
[SNDRV_CARDS
] = SNDRV_DEFAULT_ENABLE_PNP
; /* Enable this card */
51 module_param_array(index
, int, NULL
, 0444);
52 MODULE_PARM_DESC(index
, "Index value for Digigram " CARD_NAME
" soundcard.");
53 module_param_array(id
, charp
, NULL
, 0444);
54 MODULE_PARM_DESC(id
, "ID string for Digigram " CARD_NAME
" soundcard.");
55 module_param_array(enable
, bool, NULL
, 0444);
56 MODULE_PARM_DESC(enable
, "Enable Digigram " CARD_NAME
" soundcard.");
61 static struct pci_device_id snd_mixart_ids
[] = {
62 { 0x1057, 0x0003, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0, }, /* MC8240 */
66 MODULE_DEVICE_TABLE(pci
, snd_mixart_ids
);
69 static int mixart_set_pipe_state(mixart_mgr_t
*mgr
, mixart_pipe_t
* pipe
, int start
)
71 mixart_group_state_req_t group_state
;
72 mixart_group_state_resp_t group_state_resp
;
77 switch(pipe
->status
) {
80 if(start
) return 0; /* already started */
83 if(!start
) return 0; /* already stopped */
86 snd_printk(KERN_ERR
"error mixart_set_pipe_state called with wrong pipe->status!\n");
87 return -EINVAL
; /* function called with wrong pipe status */
90 system_msg_uid
= 0x12345678; /* the event ! (take care: the MSB and two LSB's have to be 0) */
92 /* wait on the last MSG_SYSTEM_SEND_SYNCHRO_CMD command to be really finished */
94 request
.message_id
= MSG_SYSTEM_WAIT_SYNCHRO_CMD
;
95 request
.uid
= (mixart_uid_t
){0,0};
96 request
.data
= &system_msg_uid
;
97 request
.size
= sizeof(system_msg_uid
);
99 err
= snd_mixart_send_msg_wait_notif(mgr
, &request
, system_msg_uid
);
101 snd_printk(KERN_ERR
"error : MSG_SYSTEM_WAIT_SYNCHRO_CMD was not notified !\n");
105 /* start or stop the pipe (1 pipe) */
107 memset(&group_state
, 0, sizeof(group_state
));
108 group_state
.pipe_count
= 1;
109 group_state
.pipe_uid
[0] = pipe
->group_uid
;
112 request
.message_id
= MSG_STREAM_START_STREAM_GRP_PACKET
;
114 request
.message_id
= MSG_STREAM_STOP_STREAM_GRP_PACKET
;
116 request
.uid
= pipe
->group_uid
; /*(mixart_uid_t){0,0};*/
117 request
.data
= &group_state
;
118 request
.size
= sizeof(group_state
);
120 err
= snd_mixart_send_msg(mgr
, &request
, sizeof(group_state_resp
), &group_state_resp
);
121 if (err
< 0 || group_state_resp
.txx_status
!= 0) {
122 snd_printk(KERN_ERR
"error MSG_STREAM_ST***_STREAM_GRP_PACKET err=%x stat=%x !\n", err
, group_state_resp
.txx_status
);
129 group_state
.pipe_count
= 0; /* in case of start same command once again with pipe_count=0 */
131 err
= snd_mixart_send_msg(mgr
, &request
, sizeof(group_state_resp
), &group_state_resp
);
132 if (err
< 0 || group_state_resp
.txx_status
!= 0) {
133 snd_printk(KERN_ERR
"error MSG_STREAM_START_STREAM_GRP_PACKET err=%x stat=%x !\n", err
, group_state_resp
.txx_status
);
137 /* in case of start send a synchro top */
139 request
.message_id
= MSG_SYSTEM_SEND_SYNCHRO_CMD
;
140 request
.uid
= (mixart_uid_t
){0,0};
144 err
= snd_mixart_send_msg(mgr
, &request
, sizeof(stat
), &stat
);
145 if (err
< 0 || stat
!= 0) {
146 snd_printk(KERN_ERR
"error MSG_SYSTEM_SEND_SYNCHRO_CMD err=%x stat=%x !\n", err
, stat
);
150 pipe
->status
= PIPE_RUNNING
;
153 pipe
->status
= PIPE_STOPPED
;
159 static int mixart_set_clock(mixart_mgr_t
*mgr
, mixart_pipe_t
*pipe
, unsigned int rate
)
161 mixart_msg_t request
;
162 mixart_clock_properties_t clock_properties
;
163 mixart_clock_properties_resp_t clock_prop_resp
;
166 switch(pipe
->status
) {
174 return 0; /* nothing to do */
176 snd_printk(KERN_ERR
"error mixart_set_clock(%d) called with wrong pipe->status !\n", rate
);
181 memset(&clock_properties
, 0, sizeof(clock_properties
));
182 clock_properties
.clock_generic_type
= (rate
!= 0) ? CGT_INTERNAL_CLOCK
: CGT_NO_CLOCK
;
183 clock_properties
.clock_mode
= CM_STANDALONE
;
184 clock_properties
.frequency
= rate
;
185 clock_properties
.nb_callers
= 1; /* only one entry in uid_caller ! */
186 clock_properties
.uid_caller
[0] = pipe
->group_uid
;
188 snd_printdd("mixart_set_clock to %d kHz\n", rate
);
190 request
.message_id
= MSG_CLOCK_SET_PROPERTIES
;
191 request
.uid
= mgr
->uid_console_manager
;
192 request
.data
= &clock_properties
;
193 request
.size
= sizeof(clock_properties
);
195 err
= snd_mixart_send_msg(mgr
, &request
, sizeof(clock_prop_resp
), &clock_prop_resp
);
196 if (err
< 0 || clock_prop_resp
.status
!= 0 || clock_prop_resp
.clock_mode
!= CM_STANDALONE
) {
197 snd_printk(KERN_ERR
"error MSG_CLOCK_SET_PROPERTIES err=%x stat=%x mod=%x !\n", err
, clock_prop_resp
.status
, clock_prop_resp
.clock_mode
);
201 if(rate
) pipe
->status
= PIPE_CLOCK_SET
;
202 else pipe
->status
= PIPE_RUNNING
;
209 * Allocate or reference output pipe for analog IOs (pcmp0/1)
211 mixart_pipe_t
* snd_mixart_add_ref_pipe( mixart_t
*chip
, int pcm_number
, int capture
, int monitoring
)
215 mixart_msg_t request
;
218 if (pcm_number
== MIXART_PCM_ANALOG
) {
219 pipe
= &(chip
->pipe_in_ana
); /* analog inputs */
221 pipe
= &(chip
->pipe_in_dig
); /* digital inputs */
223 request
.message_id
= MSG_STREAM_ADD_OUTPUT_GROUP
;
224 stream_count
= MIXART_CAPTURE_STREAMS
;
226 if (pcm_number
== MIXART_PCM_ANALOG
) {
227 pipe
= &(chip
->pipe_out_ana
); /* analog outputs */
229 pipe
= &(chip
->pipe_out_dig
); /* digital outputs */
231 request
.message_id
= MSG_STREAM_ADD_INPUT_GROUP
;
232 stream_count
= MIXART_PLAYBACK_STREAMS
;
235 /* a new stream is opened and there are already all streams in use */
236 if( (monitoring
== 0) && (pipe
->references
>= stream_count
) ) {
240 /* pipe is not yet defined */
241 if( pipe
->status
== PIPE_UNDEFINED
) {
244 mixart_streaming_group_req_t sgroup_req
;
245 mixart_streaming_group_t sgroup_resp
;
248 snd_printdd("add_ref_pipe audio chip(%d) pcm(%d)\n", chip
->chip_idx
, pcm_number
);
250 buf
= kmalloc(sizeof(*buf
), GFP_KERNEL
);
254 request
.uid
= (mixart_uid_t
){0,0}; /* should be StreamManagerUID, but zero is OK if there is only one ! */
255 request
.data
= &buf
->sgroup_req
;
256 request
.size
= sizeof(buf
->sgroup_req
);
258 memset(&buf
->sgroup_req
, 0, sizeof(buf
->sgroup_req
));
260 buf
->sgroup_req
.stream_count
= stream_count
;
261 buf
->sgroup_req
.channel_count
= 2;
262 buf
->sgroup_req
.latency
= 256;
263 buf
->sgroup_req
.connector
= pipe
->uid_left_connector
; /* the left connector */
265 for (i
=0; i
<stream_count
; i
++) {
267 struct mixart_flowinfo
*flowinfo
;
268 struct mixart_bufferinfo
*bufferinfo
;
270 /* we don't yet know the format, so config 16 bit pcm audio for instance */
271 buf
->sgroup_req
.stream_info
[i
].size_max_byte_frame
= 1024;
272 buf
->sgroup_req
.stream_info
[i
].size_max_sample_frame
= 256;
273 buf
->sgroup_req
.stream_info
[i
].nb_bytes_max_per_sample
= MIXART_FLOAT_P__4_0_TO_HEX
; /* is 4.0f */
275 /* find the right bufferinfo_array */
276 j
= (chip
->chip_idx
* MIXART_MAX_STREAM_PER_CARD
) + (pcm_number
* (MIXART_PLAYBACK_STREAMS
+ MIXART_CAPTURE_STREAMS
)) + i
;
277 if(capture
) j
+= MIXART_PLAYBACK_STREAMS
; /* in the array capture is behind playback */
279 buf
->sgroup_req
.flow_entry
[i
] = j
;
281 flowinfo
= (struct mixart_flowinfo
*)chip
->mgr
->flowinfo
.area
;
282 flowinfo
[j
].bufferinfo_array_phy_address
= (u32
)chip
->mgr
->bufferinfo
.addr
+ (j
* sizeof(mixart_bufferinfo_t
));
283 flowinfo
[j
].bufferinfo_count
= 1; /* 1 will set the miXart to ring-buffer mode ! */
285 bufferinfo
= (struct mixart_bufferinfo
*)chip
->mgr
->bufferinfo
.area
;
286 bufferinfo
[j
].buffer_address
= 0; /* buffer is not yet allocated */
287 bufferinfo
[j
].available_length
= 0; /* buffer is not yet allocated */
289 /* construct the identifier of the stream buffer received in the interrupts ! */
290 bufferinfo
[j
].buffer_id
= (chip
->chip_idx
<< MIXART_NOTIFY_CARD_OFFSET
) + (pcm_number
<< MIXART_NOTIFY_PCM_OFFSET
) + i
;
292 bufferinfo
[j
].buffer_id
|= MIXART_NOTIFY_CAPT_MASK
;
296 err
= snd_mixart_send_msg(chip
->mgr
, &request
, sizeof(buf
->sgroup_resp
), &buf
->sgroup_resp
);
297 if((err
< 0) || (buf
->sgroup_resp
.status
!= 0)) {
298 snd_printk(KERN_ERR
"error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", err
, buf
->sgroup_resp
.status
);
303 pipe
->group_uid
= buf
->sgroup_resp
.group
; /* id of the pipe, as returned by embedded */
304 pipe
->stream_count
= buf
->sgroup_resp
.stream_count
;
305 /* pipe->stream_uid[i] = buf->sgroup_resp.stream[i].stream_uid; */
307 pipe
->status
= PIPE_STOPPED
;
311 if(monitoring
) pipe
->monitoring
= 1;
312 else pipe
->references
++;
318 int snd_mixart_kill_ref_pipe( mixart_mgr_t
*mgr
, mixart_pipe_t
*pipe
, int monitoring
)
322 if(pipe
->status
== PIPE_UNDEFINED
)
326 pipe
->monitoring
= 0;
330 if((pipe
->references
<= 0) && (pipe
->monitoring
== 0)) {
332 mixart_msg_t request
;
333 mixart_delete_group_resp_t delete_resp
;
335 /* release the clock */
336 err
= mixart_set_clock( mgr
, pipe
, 0);
338 snd_printk(KERN_ERR
"mixart_set_clock(0) return error!\n");
342 err
= mixart_set_pipe_state(mgr
, pipe
, 0);
344 snd_printk(KERN_ERR
"error stopping pipe!\n");
347 request
.message_id
= MSG_STREAM_DELETE_GROUP
;
348 request
.uid
= (mixart_uid_t
){0,0};
349 request
.data
= &pipe
->group_uid
; /* the streaming group ! */
350 request
.size
= sizeof(pipe
->group_uid
);
352 /* delete the pipe */
353 err
= snd_mixart_send_msg(mgr
, &request
, sizeof(delete_resp
), &delete_resp
);
354 if ((err
< 0) || (delete_resp
.status
!= 0)) {
355 snd_printk(KERN_ERR
"error MSG_STREAM_DELETE_GROUP err(%x), status(%x)\n", err
, delete_resp
.status
);
358 pipe
->group_uid
= (mixart_uid_t
){0,0};
359 pipe
->stream_count
= 0;
360 pipe
->status
= PIPE_UNDEFINED
;
366 static int mixart_set_stream_state(mixart_stream_t
*stream
, int start
)
369 mixart_stream_state_req_t stream_state_req
;
370 mixart_msg_t request
;
372 if(!stream
->substream
)
375 memset(&stream_state_req
, 0, sizeof(stream_state_req
));
376 stream_state_req
.stream_count
= 1;
377 stream_state_req
.stream_info
.stream_desc
.uid_pipe
= stream
->pipe
->group_uid
;
378 stream_state_req
.stream_info
.stream_desc
.stream_idx
= stream
->substream
->number
;
380 if (stream
->substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
381 request
.message_id
= start
? MSG_STREAM_START_INPUT_STAGE_PACKET
: MSG_STREAM_STOP_INPUT_STAGE_PACKET
;
383 request
.message_id
= start
? MSG_STREAM_START_OUTPUT_STAGE_PACKET
: MSG_STREAM_STOP_OUTPUT_STAGE_PACKET
;
385 request
.uid
= (mixart_uid_t
){0,0};
386 request
.data
= &stream_state_req
;
387 request
.size
= sizeof(stream_state_req
);
389 stream
->abs_period_elapsed
= 0; /* reset stream pos */
390 stream
->buf_periods
= 0;
391 stream
->buf_period_frag
= 0;
393 chip
= snd_pcm_substream_chip(stream
->substream
);
395 return snd_mixart_send_msg_nonblock(chip
->mgr
, &request
);
402 static int snd_mixart_trigger(snd_pcm_substream_t
*subs
, int cmd
)
404 mixart_stream_t
*stream
= (mixart_stream_t
*)subs
->runtime
->private_data
;
407 case SNDRV_PCM_TRIGGER_START
:
409 snd_printdd("SNDRV_PCM_TRIGGER_START\n");
412 if( mixart_set_stream_state(stream
, 1) )
415 stream
->status
= MIXART_STREAM_STATUS_RUNNING
;
418 case SNDRV_PCM_TRIGGER_STOP
:
421 if( mixart_set_stream_state(stream
, 0) )
424 stream
->status
= MIXART_STREAM_STATUS_OPEN
;
426 snd_printdd("SNDRV_PCM_TRIGGER_STOP\n");
430 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
432 stream
->status
= MIXART_STREAM_STATUS_PAUSE
;
433 snd_printdd("SNDRV_PCM_PAUSE_PUSH\n");
435 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
437 stream
->status
= MIXART_STREAM_STATUS_RUNNING
;
438 snd_printdd("SNDRV_PCM_PAUSE_RELEASE\n");
446 static int mixart_sync_nonblock_events(mixart_mgr_t
*mgr
)
448 unsigned long timeout
= jiffies
+ HZ
;
449 while (atomic_read(&mgr
->msg_processed
) > 0) {
450 if (time_after(jiffies
, timeout
)) {
451 snd_printk(KERN_ERR
"mixart: cannot process nonblock events!\n");
454 schedule_timeout_uninterruptible(1);
460 * prepare callback for all pcms
462 static int snd_mixart_prepare(snd_pcm_substream_t
*subs
)
464 mixart_t
*chip
= snd_pcm_substream_chip(subs
);
465 mixart_stream_t
*stream
= (mixart_stream_t
*)subs
->runtime
->private_data
;
467 /* TODO de façon non bloquante, réappliquer les hw_params (rate, bits, codec) */
469 snd_printdd("snd_mixart_prepare\n");
471 mixart_sync_nonblock_events(chip
->mgr
);
473 /* only the first stream can choose the sample rate */
474 /* the further opened streams will be limited to its frequency (see open) */
475 if(chip
->mgr
->ref_count_rate
== 1)
476 chip
->mgr
->sample_rate
= subs
->runtime
->rate
;
478 /* set the clock only once (first stream) on the same pipe */
479 if(stream
->pipe
->references
== 1) {
480 if( mixart_set_clock(chip
->mgr
, stream
->pipe
, subs
->runtime
->rate
) )
488 static int mixart_set_format(mixart_stream_t
*stream
, snd_pcm_format_t format
)
492 mixart_msg_t request
;
493 mixart_stream_param_desc_t stream_param
;
494 mixart_return_uid_t resp
;
496 chip
= snd_pcm_substream_chip(stream
->substream
);
498 memset(&stream_param
, 0, sizeof(stream_param
));
500 stream_param
.coding_type
= CT_LINEAR
;
501 stream_param
.number_of_channel
= stream
->channels
;
503 stream_param
.sampling_freq
= chip
->mgr
->sample_rate
;
504 if(stream_param
.sampling_freq
== 0)
505 stream_param
.sampling_freq
= 44100; /* if frequency not yet defined, use some default */
508 case SNDRV_PCM_FORMAT_U8
:
509 stream_param
.sample_type
= ST_INTEGER_8
;
510 stream_param
.sample_size
= 8;
512 case SNDRV_PCM_FORMAT_S16_LE
:
513 stream_param
.sample_type
= ST_INTEGER_16LE
;
514 stream_param
.sample_size
= 16;
516 case SNDRV_PCM_FORMAT_S16_BE
:
517 stream_param
.sample_type
= ST_INTEGER_16BE
;
518 stream_param
.sample_size
= 16;
520 case SNDRV_PCM_FORMAT_S24_3LE
:
521 stream_param
.sample_type
= ST_INTEGER_24LE
;
522 stream_param
.sample_size
= 24;
524 case SNDRV_PCM_FORMAT_S24_3BE
:
525 stream_param
.sample_type
= ST_INTEGER_24BE
;
526 stream_param
.sample_size
= 24;
528 case SNDRV_PCM_FORMAT_FLOAT_LE
:
529 stream_param
.sample_type
= ST_FLOATING_POINT_32LE
;
530 stream_param
.sample_size
= 32;
532 case SNDRV_PCM_FORMAT_FLOAT_BE
:
533 stream_param
.sample_type
= ST_FLOATING_POINT_32BE
;
534 stream_param
.sample_size
= 32;
537 snd_printk(KERN_ERR
"error mixart_set_format() : unknown format\n");
541 snd_printdd("set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) channels(%d)\n",
542 stream_param
.sample_type
, stream_param
.sample_size
, stream_param
.sampling_freq
, stream
->channels
);
544 /* TODO: what else to configure ? */
545 /* stream_param.samples_per_frame = 2; */
546 /* stream_param.bytes_per_frame = 4; */
547 /* stream_param.bytes_per_sample = 2; */
549 stream_param
.pipe_count
= 1; /* set to 1 */
550 stream_param
.stream_count
= 1; /* set to 1 */
551 stream_param
.stream_desc
[0].uid_pipe
= stream
->pipe
->group_uid
;
552 stream_param
.stream_desc
[0].stream_idx
= stream
->substream
->number
;
554 request
.message_id
= MSG_STREAM_SET_INPUT_STAGE_PARAM
;
555 request
.uid
= (mixart_uid_t
){0,0};
556 request
.data
= &stream_param
;
557 request
.size
= sizeof(stream_param
);
559 err
= snd_mixart_send_msg(chip
->mgr
, &request
, sizeof(resp
), &resp
);
560 if((err
< 0) || resp
.error_code
) {
561 snd_printk(KERN_ERR
"MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; resp=%x\n", err
, resp
.error_code
);
569 * HW_PARAMS callback for all pcms
571 static int snd_mixart_hw_params(snd_pcm_substream_t
*subs
,
572 snd_pcm_hw_params_t
*hw
)
574 mixart_t
*chip
= snd_pcm_substream_chip(subs
);
575 mixart_mgr_t
*mgr
= chip
->mgr
;
576 mixart_stream_t
*stream
= (mixart_stream_t
*)subs
->runtime
->private_data
;
577 snd_pcm_format_t format
;
581 /* set up channels */
582 channels
= params_channels(hw
);
584 /* set up format for the stream */
585 format
= params_format(hw
);
587 down(&mgr
->setup_mutex
);
589 /* update the stream levels */
590 if( stream
->pcm_number
<= MIXART_PCM_DIGITAL
) {
591 int is_aes
= stream
->pcm_number
> MIXART_PCM_ANALOG
;
592 if( subs
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
593 mixart_update_playback_stream_level(chip
, is_aes
, subs
->number
);
595 mixart_update_capture_stream_level( chip
, is_aes
);
598 stream
->channels
= channels
;
600 /* set the format to the board */
601 err
= mixart_set_format(stream
, format
);
606 /* allocate buffer */
607 err
= snd_pcm_lib_malloc_pages(subs
, params_buffer_bytes(hw
));
610 struct mixart_bufferinfo
*bufferinfo
;
611 int i
= (chip
->chip_idx
* MIXART_MAX_STREAM_PER_CARD
) + (stream
->pcm_number
* (MIXART_PLAYBACK_STREAMS
+MIXART_CAPTURE_STREAMS
)) + subs
->number
;
612 if( subs
->stream
== SNDRV_PCM_STREAM_CAPTURE
) {
613 i
+= MIXART_PLAYBACK_STREAMS
; /* in array capture is behind playback */
616 bufferinfo
= (struct mixart_bufferinfo
*)chip
->mgr
->bufferinfo
.area
;
617 bufferinfo
[i
].buffer_address
= subs
->runtime
->dma_addr
;
618 bufferinfo
[i
].available_length
= subs
->runtime
->dma_bytes
;
619 /* bufferinfo[i].buffer_id is already defined */
621 snd_printdd("snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", i
,
622 bufferinfo
[i
].buffer_address
,
623 bufferinfo
[i
].available_length
,
626 up(&mgr
->setup_mutex
);
631 static int snd_mixart_hw_free(snd_pcm_substream_t
*subs
)
633 mixart_t
*chip
= snd_pcm_substream_chip(subs
);
634 snd_pcm_lib_free_pages(subs
);
635 mixart_sync_nonblock_events(chip
->mgr
);
642 * TODO CONFIGURATION SPACE for all pcms, mono pcm must update channels_max
644 static snd_pcm_hardware_t snd_mixart_analog_caps
=
646 .info
= ( SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_INTERLEAVED
|
647 SNDRV_PCM_INFO_MMAP_VALID
| SNDRV_PCM_INFO_SYNC_START
|
648 SNDRV_PCM_INFO_PAUSE
),
649 .formats
= ( SNDRV_PCM_FMTBIT_U8
|
650 SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S16_BE
|
651 SNDRV_PCM_FMTBIT_S24_3LE
| SNDRV_PCM_FMTBIT_S24_3BE
|
652 SNDRV_PCM_FMTBIT_FLOAT_LE
| SNDRV_PCM_FMTBIT_FLOAT_BE
),
653 .rates
= SNDRV_PCM_RATE_CONTINUOUS
| SNDRV_PCM_RATE_8000_48000
,
658 .buffer_bytes_max
= (32*1024),
659 .period_bytes_min
= 256, /* 256 frames U8 mono*/
660 .period_bytes_max
= (16*1024),
662 .periods_max
= (32*1024/256),
665 static snd_pcm_hardware_t snd_mixart_digital_caps
=
667 .info
= ( SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_INTERLEAVED
|
668 SNDRV_PCM_INFO_MMAP_VALID
| SNDRV_PCM_INFO_SYNC_START
|
669 SNDRV_PCM_INFO_PAUSE
),
670 .formats
= ( SNDRV_PCM_FMTBIT_U8
|
671 SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S16_BE
|
672 SNDRV_PCM_FMTBIT_S24_3LE
| SNDRV_PCM_FMTBIT_S24_3BE
|
673 SNDRV_PCM_FMTBIT_FLOAT_LE
| SNDRV_PCM_FMTBIT_FLOAT_BE
),
674 .rates
= SNDRV_PCM_RATE_32000
| SNDRV_PCM_RATE_44100
| SNDRV_PCM_RATE_48000
,
679 .buffer_bytes_max
= (32*1024),
680 .period_bytes_min
= 256, /* 256 frames U8 mono*/
681 .period_bytes_max
= (16*1024),
683 .periods_max
= (32*1024/256),
687 static int snd_mixart_playback_open(snd_pcm_substream_t
*subs
)
689 mixart_t
*chip
= snd_pcm_substream_chip(subs
);
690 mixart_mgr_t
*mgr
= chip
->mgr
;
691 snd_pcm_runtime_t
*runtime
= subs
->runtime
;
692 snd_pcm_t
*pcm
= subs
->pcm
;
693 mixart_stream_t
*stream
;
698 down(&mgr
->setup_mutex
);
700 if ( pcm
== chip
->pcm
) {
701 pcm_number
= MIXART_PCM_ANALOG
;
702 runtime
->hw
= snd_mixart_analog_caps
;
704 snd_assert ( pcm
== chip
->pcm_dig
);
705 pcm_number
= MIXART_PCM_DIGITAL
;
706 runtime
->hw
= snd_mixart_digital_caps
;
708 snd_printdd("snd_mixart_playback_open C%d/P%d/Sub%d\n", chip
->chip_idx
, pcm_number
, subs
->number
);
710 /* get stream info */
711 stream
= &(chip
->playback_stream
[pcm_number
][subs
->number
]);
713 if (stream
->status
!= MIXART_STREAM_STATUS_FREE
){
715 snd_printk(KERN_ERR
"snd_mixart_playback_open C%d/P%d/Sub%d in use\n", chip
->chip_idx
, pcm_number
, subs
->number
);
720 /* get pipe pointer (out pipe) */
721 pipe
= snd_mixart_add_ref_pipe(chip
, pcm_number
, 0, 0);
728 /* start the pipe if necessary */
729 err
= mixart_set_pipe_state(chip
->mgr
, pipe
, 1);
731 snd_printk(KERN_ERR
"error starting pipe!\n");
732 snd_mixart_kill_ref_pipe(chip
->mgr
, pipe
, 0);
738 stream
->pcm_number
= pcm_number
;
739 stream
->status
= MIXART_STREAM_STATUS_OPEN
;
740 stream
->substream
= subs
;
741 stream
->channels
= 0; /* not configured yet */
743 runtime
->private_data
= stream
;
745 snd_pcm_hw_constraint_step(runtime
, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES
, 32);
746 snd_pcm_hw_constraint_step(runtime
, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE
, 64);
748 /* if a sample rate is already used, another stream cannot change */
749 if(mgr
->ref_count_rate
++) {
750 if(mgr
->sample_rate
) {
751 runtime
->hw
.rate_min
= runtime
->hw
.rate_max
= mgr
->sample_rate
;
756 up(&mgr
->setup_mutex
);
762 static int snd_mixart_capture_open(snd_pcm_substream_t
*subs
)
764 mixart_t
*chip
= snd_pcm_substream_chip(subs
);
765 mixart_mgr_t
*mgr
= chip
->mgr
;
766 snd_pcm_runtime_t
*runtime
= subs
->runtime
;
767 snd_pcm_t
*pcm
= subs
->pcm
;
768 mixart_stream_t
*stream
;
773 down(&mgr
->setup_mutex
);
775 if ( pcm
== chip
->pcm
) {
776 pcm_number
= MIXART_PCM_ANALOG
;
777 runtime
->hw
= snd_mixart_analog_caps
;
779 snd_assert ( pcm
== chip
->pcm_dig
);
780 pcm_number
= MIXART_PCM_DIGITAL
;
781 runtime
->hw
= snd_mixart_digital_caps
;
784 runtime
->hw
.channels_min
= 2; /* for instance, no mono */
786 snd_printdd("snd_mixart_capture_open C%d/P%d/Sub%d\n", chip
->chip_idx
, pcm_number
, subs
->number
);
788 /* get stream info */
789 stream
= &(chip
->capture_stream
[pcm_number
]);
791 if (stream
->status
!= MIXART_STREAM_STATUS_FREE
){
793 snd_printk(KERN_ERR
"snd_mixart_capture_open C%d/P%d/Sub%d in use\n", chip
->chip_idx
, pcm_number
, subs
->number
);
798 /* get pipe pointer (in pipe) */
799 pipe
= snd_mixart_add_ref_pipe(chip
, pcm_number
, 1, 0);
806 /* start the pipe if necessary */
807 err
= mixart_set_pipe_state(chip
->mgr
, pipe
, 1);
809 snd_printk(KERN_ERR
"error starting pipe!\n");
810 snd_mixart_kill_ref_pipe(chip
->mgr
, pipe
, 0);
816 stream
->pcm_number
= pcm_number
;
817 stream
->status
= MIXART_STREAM_STATUS_OPEN
;
818 stream
->substream
= subs
;
819 stream
->channels
= 0; /* not configured yet */
821 runtime
->private_data
= stream
;
823 snd_pcm_hw_constraint_step(runtime
, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES
, 32);
824 snd_pcm_hw_constraint_step(runtime
, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE
, 64);
826 /* if a sample rate is already used, another stream cannot change */
827 if(mgr
->ref_count_rate
++) {
828 if(mgr
->sample_rate
) {
829 runtime
->hw
.rate_min
= runtime
->hw
.rate_max
= mgr
->sample_rate
;
834 up(&mgr
->setup_mutex
);
841 static int snd_mixart_close(snd_pcm_substream_t
*subs
)
843 mixart_t
*chip
= snd_pcm_substream_chip(subs
);
844 mixart_mgr_t
*mgr
= chip
->mgr
;
845 mixart_stream_t
*stream
= (mixart_stream_t
*)subs
->runtime
->private_data
;
847 down(&mgr
->setup_mutex
);
849 snd_printdd("snd_mixart_close C%d/P%d/Sub%d\n", chip
->chip_idx
, stream
->pcm_number
, subs
->number
);
851 /* sample rate released */
852 if(--mgr
->ref_count_rate
== 0) {
853 mgr
->sample_rate
= 0;
857 if (snd_mixart_kill_ref_pipe(mgr
, stream
->pipe
, 0 ) < 0) {
859 snd_printk(KERN_ERR
"error snd_mixart_kill_ref_pipe C%dP%d\n", chip
->chip_idx
, stream
->pcm_number
);
863 stream
->status
= MIXART_STREAM_STATUS_FREE
;
864 stream
->substream
= NULL
;
866 up(&mgr
->setup_mutex
);
871 static snd_pcm_uframes_t
snd_mixart_stream_pointer(snd_pcm_substream_t
* subs
)
873 snd_pcm_runtime_t
*runtime
= subs
->runtime
;
874 mixart_stream_t
*stream
= (mixart_stream_t
*)runtime
->private_data
;
876 return (snd_pcm_uframes_t
)((stream
->buf_periods
* runtime
->period_size
) + stream
->buf_period_frag
);
881 static snd_pcm_ops_t snd_mixart_playback_ops
= {
882 .open
= snd_mixart_playback_open
,
883 .close
= snd_mixart_close
,
884 .ioctl
= snd_pcm_lib_ioctl
,
885 .prepare
= snd_mixart_prepare
,
886 .hw_params
= snd_mixart_hw_params
,
887 .hw_free
= snd_mixart_hw_free
,
888 .trigger
= snd_mixart_trigger
,
889 .pointer
= snd_mixart_stream_pointer
,
892 static snd_pcm_ops_t snd_mixart_capture_ops
= {
893 .open
= snd_mixart_capture_open
,
894 .close
= snd_mixart_close
,
895 .ioctl
= snd_pcm_lib_ioctl
,
896 .prepare
= snd_mixart_prepare
,
897 .hw_params
= snd_mixart_hw_params
,
898 .hw_free
= snd_mixart_hw_free
,
899 .trigger
= snd_mixart_trigger
,
900 .pointer
= snd_mixart_stream_pointer
,
903 static void preallocate_buffers(mixart_t
*chip
, snd_pcm_t
*pcm
)
906 snd_pcm_substream_t
*subs
;
909 for (stream
= 0; stream
< 2; stream
++) {
911 for (subs
= pcm
->streams
[stream
].substream
; subs
; subs
= subs
->next
, idx
++)
912 /* set up the unique device id with the chip index */
913 subs
->dma_device
.id
= subs
->pcm
->device
<< 16 |
914 subs
->stream
<< 8 | (subs
->number
+ 1) |
915 (chip
->chip_idx
+ 1) << 24;
918 snd_pcm_lib_preallocate_pages_for_all(pcm
, SNDRV_DMA_TYPE_DEV
,
919 snd_dma_pci_data(chip
->mgr
->pci
), 32*1024, 32*1024);
924 static int snd_mixart_pcm_analog(mixart_t
*chip
)
930 sprintf(name
, "miXart analog %d", chip
->chip_idx
);
931 if ((err
= snd_pcm_new(chip
->card
, name
, MIXART_PCM_ANALOG
,
932 MIXART_PLAYBACK_STREAMS
,
933 MIXART_CAPTURE_STREAMS
, &pcm
)) < 0) {
934 snd_printk(KERN_ERR
"cannot create the analog pcm %d\n", chip
->chip_idx
);
938 pcm
->private_data
= chip
;
940 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &snd_mixart_playback_ops
);
941 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
, &snd_mixart_capture_ops
);
944 strcpy(pcm
->name
, name
);
946 preallocate_buffers(chip
, pcm
);
955 static int snd_mixart_pcm_digital(mixart_t
*chip
)
961 sprintf(name
, "miXart AES/EBU %d", chip
->chip_idx
);
962 if ((err
= snd_pcm_new(chip
->card
, name
, MIXART_PCM_DIGITAL
,
963 MIXART_PLAYBACK_STREAMS
,
964 MIXART_CAPTURE_STREAMS
, &pcm
)) < 0) {
965 snd_printk(KERN_ERR
"cannot create the digital pcm %d\n", chip
->chip_idx
);
969 pcm
->private_data
= chip
;
971 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &snd_mixart_playback_ops
);
972 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
, &snd_mixart_capture_ops
);
975 strcpy(pcm
->name
, name
);
977 preallocate_buffers(chip
, pcm
);
983 static int snd_mixart_chip_free(mixart_t
*chip
)
989 static int snd_mixart_chip_dev_free(snd_device_t
*device
)
991 mixart_t
*chip
= device
->device_data
;
992 return snd_mixart_chip_free(chip
);
998 static int __devinit
snd_mixart_create(mixart_mgr_t
*mgr
, snd_card_t
*card
, int idx
)
1002 static snd_device_ops_t ops
= {
1003 .dev_free
= snd_mixart_chip_dev_free
,
1006 mgr
->chip
[idx
] = chip
= kzalloc(sizeof(*chip
), GFP_KERNEL
);
1008 snd_printk(KERN_ERR
"cannot allocate chip\n");
1013 chip
->chip_idx
= idx
;
1016 if ((err
= snd_device_new(card
, SNDRV_DEV_LOWLEVEL
, chip
, &ops
)) < 0) {
1017 snd_mixart_chip_free(chip
);
1021 snd_card_set_dev(card
, &mgr
->pci
->dev
);
1026 int snd_mixart_create_pcm(mixart_t
* chip
)
1030 err
= snd_mixart_pcm_analog(chip
);
1034 if(chip
->mgr
->board_type
== MIXART_DAUGHTER_TYPE_AES
) {
1036 err
= snd_mixart_pcm_digital(chip
);
1045 * release all the cards assigned to a manager instance
1047 static int snd_mixart_free(mixart_mgr_t
*mgr
)
1051 for (i
= 0; i
< mgr
->num_cards
; i
++) {
1053 snd_card_free(mgr
->chip
[i
]->card
);
1057 snd_mixart_exit_mailbox(mgr
);
1061 free_irq(mgr
->irq
, (void *)mgr
);
1063 /* reset board if some firmware was loaded */
1064 if(mgr
->dsp_loaded
) {
1065 snd_mixart_reset_board(mgr
);
1066 snd_printdd("reset miXart !\n");
1069 /* release the i/o ports */
1070 for (i
= 0; i
< 2; i
++) {
1071 if (mgr
->mem
[i
].virt
)
1072 iounmap(mgr
->mem
[i
].virt
);
1074 pci_release_regions(mgr
->pci
);
1076 /* free flowarray */
1077 if(mgr
->flowinfo
.area
) {
1078 snd_dma_free_pages(&mgr
->flowinfo
);
1079 mgr
->flowinfo
.area
= NULL
;
1081 /* free bufferarray */
1082 if(mgr
->bufferinfo
.area
) {
1083 snd_dma_free_pages(&mgr
->bufferinfo
);
1084 mgr
->bufferinfo
.area
= NULL
;
1087 pci_disable_device(mgr
->pci
);
1095 static long long snd_mixart_BA0_llseek(snd_info_entry_t
*entry
,
1096 void *private_file_data
,
1101 offset
= offset
& ~3; /* 4 bytes aligned */
1104 case 0: /* SEEK_SET */
1105 file
->f_pos
= offset
;
1107 case 1: /* SEEK_CUR */
1108 file
->f_pos
+= offset
;
1110 case 2: /* SEEK_END, offset is negative */
1111 file
->f_pos
= MIXART_BA0_SIZE
+ offset
;
1116 if(file
->f_pos
> MIXART_BA0_SIZE
)
1117 file
->f_pos
= MIXART_BA0_SIZE
;
1121 static long long snd_mixart_BA1_llseek(snd_info_entry_t
*entry
,
1122 void *private_file_data
,
1127 offset
= offset
& ~3; /* 4 bytes aligned */
1130 case 0: /* SEEK_SET */
1131 file
->f_pos
= offset
;
1133 case 1: /* SEEK_CUR */
1134 file
->f_pos
+= offset
;
1136 case 2: /* SEEK_END, offset is negative */
1137 file
->f_pos
= MIXART_BA1_SIZE
+ offset
;
1142 if(file
->f_pos
> MIXART_BA1_SIZE
)
1143 file
->f_pos
= MIXART_BA1_SIZE
;
1148 mixart_BA0 proc interface for BAR 0 - read callback
1150 static long snd_mixart_BA0_read(snd_info_entry_t
*entry
, void *file_private_data
,
1151 struct file
*file
, char __user
*buf
,
1152 unsigned long count
, unsigned long pos
)
1154 mixart_mgr_t
*mgr
= entry
->private_data
;
1156 count
= count
& ~3; /* make sure the read size is a multiple of 4 bytes */
1159 if(pos
+ count
> MIXART_BA0_SIZE
)
1160 count
= (long)(MIXART_BA0_SIZE
- pos
);
1161 if(copy_to_user_fromio(buf
, MIXART_MEM( mgr
, pos
), count
))
1167 mixart_BA1 proc interface for BAR 1 - read callback
1169 static long snd_mixart_BA1_read(snd_info_entry_t
*entry
, void *file_private_data
,
1170 struct file
*file
, char __user
*buf
,
1171 unsigned long count
, unsigned long pos
)
1173 mixart_mgr_t
*mgr
= entry
->private_data
;
1175 count
= count
& ~3; /* make sure the read size is a multiple of 4 bytes */
1178 if(pos
+ count
> MIXART_BA1_SIZE
)
1179 count
= (long)(MIXART_BA1_SIZE
- pos
);
1180 if(copy_to_user_fromio(buf
, MIXART_REG( mgr
, pos
), count
))
1185 static struct snd_info_entry_ops snd_mixart_proc_ops_BA0
= {
1186 .read
= snd_mixart_BA0_read
,
1187 .llseek
= snd_mixart_BA0_llseek
1190 static struct snd_info_entry_ops snd_mixart_proc_ops_BA1
= {
1191 .read
= snd_mixart_BA1_read
,
1192 .llseek
= snd_mixart_BA1_llseek
1196 static void snd_mixart_proc_read(snd_info_entry_t
*entry
,
1197 snd_info_buffer_t
* buffer
)
1199 mixart_t
*chip
= entry
->private_data
;
1202 snd_iprintf(buffer
, "Digigram miXart (alsa card %d)\n\n", chip
->chip_idx
);
1204 /* stats available when embedded OS is running */
1205 if (chip
->mgr
->dsp_loaded
& ( 1 << MIXART_MOTHERBOARD_ELF_INDEX
)) {
1206 snd_iprintf(buffer
, "- hardware -\n");
1207 switch (chip
->mgr
->board_type
) {
1208 case MIXART_DAUGHTER_TYPE_NONE
: snd_iprintf(buffer
, "\tmiXart8 (no daughter board)\n\n"); break;
1209 case MIXART_DAUGHTER_TYPE_AES
: snd_iprintf(buffer
, "\tmiXart8 AES/EBU\n\n"); break;
1210 case MIXART_DAUGHTER_TYPE_COBRANET
: snd_iprintf(buffer
, "\tmiXart8 Cobranet\n\n"); break;
1211 default: snd_iprintf(buffer
, "\tUNKNOWN!\n\n"); break;
1214 snd_iprintf(buffer
, "- system load -\n");
1216 /* get perf reference */
1218 ref
= readl_be( MIXART_MEM( chip
->mgr
, MIXART_PSEUDOREG_PERF_SYSTEM_LOAD_OFFSET
));
1221 u32 mailbox
= 100 * readl_be( MIXART_MEM( chip
->mgr
, MIXART_PSEUDOREG_PERF_MAILBX_LOAD_OFFSET
)) / ref
;
1222 u32 streaming
= 100 * readl_be( MIXART_MEM( chip
->mgr
, MIXART_PSEUDOREG_PERF_STREAM_LOAD_OFFSET
)) / ref
;
1223 u32 interr
= 100 * readl_be( MIXART_MEM( chip
->mgr
, MIXART_PSEUDOREG_PERF_INTERR_LOAD_OFFSET
)) / ref
;
1225 snd_iprintf(buffer
, "\tstreaming : %d\n", streaming
);
1226 snd_iprintf(buffer
, "\tmailbox : %d\n", mailbox
);
1227 snd_iprintf(buffer
, "\tinterrups handling : %d\n\n", interr
);
1229 } /* endif elf loaded */
1232 static void __devinit
snd_mixart_proc_init(mixart_t
*chip
)
1234 snd_info_entry_t
*entry
;
1236 /* text interface to read perf and temp meters */
1237 if (! snd_card_proc_new(chip
->card
, "board_info", &entry
)) {
1238 entry
->private_data
= chip
;
1239 entry
->c
.text
.read_size
= 1024;
1240 entry
->c
.text
.read
= snd_mixart_proc_read
;
1243 if (! snd_card_proc_new(chip
->card
, "mixart_BA0", &entry
)) {
1244 entry
->content
= SNDRV_INFO_CONTENT_DATA
;
1245 entry
->private_data
= chip
->mgr
;
1246 entry
->c
.ops
= &snd_mixart_proc_ops_BA0
;
1247 entry
->size
= MIXART_BA0_SIZE
;
1249 if (! snd_card_proc_new(chip
->card
, "mixart_BA1", &entry
)) {
1250 entry
->content
= SNDRV_INFO_CONTENT_DATA
;
1251 entry
->private_data
= chip
->mgr
;
1252 entry
->c
.ops
= &snd_mixart_proc_ops_BA1
;
1253 entry
->size
= MIXART_BA1_SIZE
;
1256 /* end of proc interface */
1260 * probe function - creates the card manager
1262 static int __devinit
snd_mixart_probe(struct pci_dev
*pci
,
1263 const struct pci_device_id
*pci_id
)
1273 if (dev
>= SNDRV_CARDS
)
1275 if (! enable
[dev
]) {
1280 /* enable PCI device */
1281 if ((err
= pci_enable_device(pci
)) < 0)
1283 pci_set_master(pci
);
1285 /* check if we can restrict PCI DMA transfers to 32 bits */
1286 if (pci_set_dma_mask(pci
, 0xffffffff) < 0) {
1287 snd_printk(KERN_ERR
"architecture does not support 32bit PCI busmaster DMA\n");
1288 pci_disable_device(pci
);
1294 mgr
= kzalloc(sizeof(*mgr
), GFP_KERNEL
);
1296 pci_disable_device(pci
);
1303 /* resource assignment */
1304 if ((err
= pci_request_regions(pci
, CARD_NAME
)) < 0) {
1306 pci_disable_device(pci
);
1309 for (i
= 0; i
< 2; i
++) {
1310 mgr
->mem
[i
].phys
= pci_resource_start(pci
, i
);
1311 mgr
->mem
[i
].virt
= ioremap_nocache(mgr
->mem
[i
].phys
,
1312 pci_resource_len(pci
, i
));
1315 if (request_irq(pci
->irq
, snd_mixart_interrupt
, SA_INTERRUPT
|SA_SHIRQ
, CARD_NAME
, (void *)mgr
)) {
1316 snd_printk(KERN_ERR
"unable to grab IRQ %d\n", pci
->irq
);
1317 snd_mixart_free(mgr
);
1320 mgr
->irq
= pci
->irq
;
1322 sprintf(mgr
->shortname
, "Digigram miXart");
1323 sprintf(mgr
->longname
, "%s at 0x%lx & 0x%lx, irq %i", mgr
->shortname
, mgr
->mem
[0].phys
, mgr
->mem
[1].phys
, mgr
->irq
);
1326 spin_lock_init(&mgr
->lock
);
1329 mgr
->msg_fifo_readptr
= 0;
1330 mgr
->msg_fifo_writeptr
= 0;
1332 spin_lock_init(&mgr
->msg_lock
);
1333 init_MUTEX(&mgr
->msg_mutex
);
1334 init_waitqueue_head(&mgr
->msg_sleep
);
1335 atomic_set(&mgr
->msg_processed
, 0);
1337 /* init setup mutex*/
1338 init_MUTEX(&mgr
->setup_mutex
);
1340 /* init message taslket */
1341 tasklet_init( &mgr
->msg_taskq
, snd_mixart_msg_tasklet
, (unsigned long) mgr
);
1343 /* card assignment */
1344 mgr
->num_cards
= MIXART_MAX_CARDS
; /* 4 FIXME: configurable? */
1345 for (i
= 0; i
< mgr
->num_cards
; i
++) {
1353 idx
= index
[dev
] + i
;
1354 snprintf(tmpid
, sizeof(tmpid
), "%s-%d", id
[dev
] ? id
[dev
] : "MIXART", i
);
1355 card
= snd_card_new(idx
, tmpid
, THIS_MODULE
, 0);
1358 snd_printk(KERN_ERR
"cannot allocate the card %d\n", i
);
1359 snd_mixart_free(mgr
);
1363 strcpy(card
->driver
, CARD_NAME
);
1364 sprintf(card
->shortname
, "%s [PCM #%d]", mgr
->shortname
, i
);
1365 sprintf(card
->longname
, "%s [PCM #%d]", mgr
->longname
, i
);
1367 if ((err
= snd_mixart_create(mgr
, card
, i
)) < 0) {
1368 snd_mixart_free(mgr
);
1373 /* init proc interface only for chip0 */
1374 snd_mixart_proc_init(mgr
->chip
[i
]);
1377 if ((err
= snd_card_register(card
)) < 0) {
1378 snd_mixart_free(mgr
);
1383 /* init firmware status (mgr->dsp_loaded reset in hwdep_new) */
1384 mgr
->board_type
= MIXART_DAUGHTER_TYPE_NONE
;
1386 /* create array of streaminfo */
1387 size
= PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD
* MIXART_MAX_CARDS
* sizeof(mixart_flowinfo_t
)) );
1388 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV
, snd_dma_pci_data(pci
),
1389 size
, &mgr
->flowinfo
) < 0) {
1390 snd_mixart_free(mgr
);
1393 /* init streaminfo_array */
1394 memset(mgr
->flowinfo
.area
, 0, size
);
1396 /* create array of bufferinfo */
1397 size
= PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD
* MIXART_MAX_CARDS
* sizeof(mixart_bufferinfo_t
)) );
1398 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV
, snd_dma_pci_data(pci
),
1399 size
, &mgr
->bufferinfo
) < 0) {
1400 snd_mixart_free(mgr
);
1403 /* init bufferinfo_array */
1404 memset(mgr
->bufferinfo
.area
, 0, size
);
1406 /* set up firmware */
1407 err
= snd_mixart_setup_firmware(mgr
);
1409 snd_mixart_free(mgr
);
1413 pci_set_drvdata(pci
, mgr
);
1418 static void __devexit
snd_mixart_remove(struct pci_dev
*pci
)
1420 snd_mixart_free(pci_get_drvdata(pci
));
1421 pci_set_drvdata(pci
, NULL
);
1424 static struct pci_driver driver
= {
1425 .name
= "Digigram miXart",
1426 .id_table
= snd_mixart_ids
,
1427 .probe
= snd_mixart_probe
,
1428 .remove
= __devexit_p(snd_mixart_remove
),
1431 static int __init
alsa_card_mixart_init(void)
1433 return pci_register_driver(&driver
);
1436 static void __exit
alsa_card_mixart_exit(void)
1438 pci_unregister_driver(&driver
);
1441 module_init(alsa_card_mixart_init
)
1442 module_exit(alsa_card_mixart_exit
)