• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/sound/pci/mixart/
1/*
2 * Driver for Digigram miXart soundcards
3 *
4 * main file with alsa callbacks
5 *
6 * Copyright (c) 2003 by Digigram <alsa@digigram.com>
7 *
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.
12 *
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.
17 *
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
21 */
22
23
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include <linux/pci.h>
27#include <linux/dma-mapping.h>
28#include <linux/moduleparam.h>
29#include <linux/mutex.h>
30#include <linux/slab.h>
31
32#include <sound/core.h>
33#include <sound/initval.h>
34#include <sound/info.h>
35#include <sound/control.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include "mixart.h"
39#include "mixart_hwdep.h"
40#include "mixart_core.h"
41#include "mixart_mixer.h"
42
43#define CARD_NAME "miXart"
44
45MODULE_AUTHOR("Digigram <alsa@digigram.com>");
46MODULE_DESCRIPTION("Digigram " CARD_NAME);
47MODULE_LICENSE("GPL");
48MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}");
49
50static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;             /* Index 0-MAX */
51static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;              /* ID for this card */
52static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;     /* Enable this card */
53
54module_param_array(index, int, NULL, 0444);
55MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard.");
56module_param_array(id, charp, NULL, 0444);
57MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard.");
58module_param_array(enable, bool, NULL, 0444);
59MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
60
61/*
62 */
63
64static DEFINE_PCI_DEVICE_TABLE(snd_mixart_ids) = {
65	{ PCI_VDEVICE(MOTOROLA, 0x0003), 0, }, /* MC8240 */
66	{ 0, }
67};
68
69MODULE_DEVICE_TABLE(pci, snd_mixart_ids);
70
71
72static int mixart_set_pipe_state(struct mixart_mgr *mgr,
73				 struct mixart_pipe *pipe, int start)
74{
75	struct mixart_group_state_req group_state;
76	struct mixart_group_state_resp group_state_resp;
77	struct mixart_msg request;
78	int err;
79	u32 system_msg_uid;
80
81	switch(pipe->status) {
82	case PIPE_RUNNING:
83	case PIPE_CLOCK_SET:
84		if(start) return 0; /* already started */
85		break;
86	case PIPE_STOPPED:
87		if(!start) return 0; /* already stopped */
88		break;
89	default:
90		snd_printk(KERN_ERR "error mixart_set_pipe_state called with wrong pipe->status!\n");
91		return -EINVAL;      /* function called with wrong pipe status */
92	}
93
94	system_msg_uid = 0x12345678; /* the event ! (take care: the MSB and two LSB's have to be 0) */
95
96	/* wait on the last MSG_SYSTEM_SEND_SYNCHRO_CMD command to be really finished */
97
98	request.message_id = MSG_SYSTEM_WAIT_SYNCHRO_CMD;
99	request.uid = (struct mixart_uid){0,0};
100	request.data = &system_msg_uid;
101	request.size = sizeof(system_msg_uid);
102
103	err = snd_mixart_send_msg_wait_notif(mgr, &request, system_msg_uid);
104	if(err) {
105		snd_printk(KERN_ERR "error : MSG_SYSTEM_WAIT_SYNCHRO_CMD was not notified !\n");
106		return err;
107	}
108
109	/* start or stop the pipe (1 pipe) */
110
111	memset(&group_state, 0, sizeof(group_state));
112	group_state.pipe_count = 1;
113	group_state.pipe_uid[0] = pipe->group_uid;
114
115	if(start)
116		request.message_id = MSG_STREAM_START_STREAM_GRP_PACKET;
117	else
118		request.message_id = MSG_STREAM_STOP_STREAM_GRP_PACKET;
119
120	request.uid = pipe->group_uid; /*(struct mixart_uid){0,0};*/
121	request.data = &group_state;
122	request.size = sizeof(group_state);
123
124	err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp);
125	if (err < 0 || group_state_resp.txx_status != 0) {
126		snd_printk(KERN_ERR "error MSG_STREAM_ST***_STREAM_GRP_PACKET err=%x stat=%x !\n", err, group_state_resp.txx_status);
127		return -EINVAL;
128	}
129
130	if(start) {
131		u32 stat;
132
133		group_state.pipe_count = 0; /* in case of start same command once again with pipe_count=0 */
134
135		err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp);
136		if (err < 0 || group_state_resp.txx_status != 0) {
137			snd_printk(KERN_ERR "error MSG_STREAM_START_STREAM_GRP_PACKET err=%x stat=%x !\n", err, group_state_resp.txx_status);
138 			return -EINVAL;
139		}
140
141		/* in case of start send a synchro top */
142
143		request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD;
144		request.uid = (struct mixart_uid){0,0};
145		request.data = NULL;
146		request.size = 0;
147
148		err = snd_mixart_send_msg(mgr, &request, sizeof(stat), &stat);
149		if (err < 0 || stat != 0) {
150			snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD err=%x stat=%x !\n", err, stat);
151			return -EINVAL;
152		}
153
154		pipe->status = PIPE_RUNNING;
155	}
156	else /* !start */
157		pipe->status = PIPE_STOPPED;
158
159	return 0;
160}
161
162
163static int mixart_set_clock(struct mixart_mgr *mgr,
164			    struct mixart_pipe *pipe, unsigned int rate)
165{
166	struct mixart_msg request;
167	struct mixart_clock_properties clock_properties;
168	struct mixart_clock_properties_resp clock_prop_resp;
169	int err;
170
171	switch(pipe->status) {
172	case PIPE_CLOCK_SET:
173		break;
174	case PIPE_RUNNING:
175		if(rate != 0)
176			break;
177	default:
178		if(rate == 0)
179			return 0; /* nothing to do */
180		else {
181			snd_printk(KERN_ERR "error mixart_set_clock(%d) called with wrong pipe->status !\n", rate);
182			return -EINVAL;
183		}
184	}
185
186	memset(&clock_properties, 0, sizeof(clock_properties));
187	clock_properties.clock_generic_type = (rate != 0) ? CGT_INTERNAL_CLOCK : CGT_NO_CLOCK;
188	clock_properties.clock_mode = CM_STANDALONE;
189	clock_properties.frequency = rate;
190	clock_properties.nb_callers = 1; /* only one entry in uid_caller ! */
191	clock_properties.uid_caller[0] = pipe->group_uid;
192
193	snd_printdd("mixart_set_clock to %d kHz\n", rate);
194
195	request.message_id = MSG_CLOCK_SET_PROPERTIES;
196	request.uid = mgr->uid_console_manager;
197	request.data = &clock_properties;
198	request.size = sizeof(clock_properties);
199
200	err = snd_mixart_send_msg(mgr, &request, sizeof(clock_prop_resp), &clock_prop_resp);
201	if (err < 0 || clock_prop_resp.status != 0 || clock_prop_resp.clock_mode != CM_STANDALONE) {
202		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);
203		return -EINVAL;
204	}
205
206	if(rate)  pipe->status = PIPE_CLOCK_SET;
207	else      pipe->status = PIPE_RUNNING;
208
209	return 0;
210}
211
212
213/*
214 *  Allocate or reference output pipe for analog IOs (pcmp0/1)
215 */
216struct mixart_pipe *
217snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture,
218			int monitoring)
219{
220	int stream_count;
221	struct mixart_pipe *pipe;
222	struct mixart_msg request;
223
224	if(capture) {
225		if (pcm_number == MIXART_PCM_ANALOG) {
226			pipe = &(chip->pipe_in_ana);  /* analog inputs */
227		} else {
228			pipe = &(chip->pipe_in_dig); /* digital inputs */
229		}
230		request.message_id = MSG_STREAM_ADD_OUTPUT_GROUP;
231		stream_count = MIXART_CAPTURE_STREAMS;
232	} else {
233		if (pcm_number == MIXART_PCM_ANALOG) {
234			pipe = &(chip->pipe_out_ana);  /* analog outputs */
235		} else {
236			pipe = &(chip->pipe_out_dig);  /* digital outputs */
237		}
238		request.message_id = MSG_STREAM_ADD_INPUT_GROUP;
239		stream_count = MIXART_PLAYBACK_STREAMS;
240	}
241
242	/* a new stream is opened and there are already all streams in use */
243	if( (monitoring == 0) && (pipe->references >= stream_count) ) {
244		return NULL;
245	}
246
247	/* pipe is not yet defined */
248	if( pipe->status == PIPE_UNDEFINED ) {
249		int err, i;
250		struct {
251			struct mixart_streaming_group_req sgroup_req;
252			struct mixart_streaming_group sgroup_resp;
253		} *buf;
254
255		snd_printdd("add_ref_pipe audio chip(%d) pcm(%d)\n", chip->chip_idx, pcm_number);
256
257		buf = kmalloc(sizeof(*buf), GFP_KERNEL);
258		if (!buf)
259			return NULL;
260
261		request.uid = (struct mixart_uid){0,0};      /* should be StreamManagerUID, but zero is OK if there is only one ! */
262		request.data = &buf->sgroup_req;
263		request.size = sizeof(buf->sgroup_req);
264
265		memset(&buf->sgroup_req, 0, sizeof(buf->sgroup_req));
266
267		buf->sgroup_req.stream_count = stream_count;
268		buf->sgroup_req.channel_count = 2;
269		buf->sgroup_req.latency = 256;
270		buf->sgroup_req.connector = pipe->uid_left_connector;  /* the left connector */
271
272		for (i=0; i<stream_count; i++) {
273			int j;
274			struct mixart_flowinfo *flowinfo;
275			struct mixart_bufferinfo *bufferinfo;
276
277			/* we don't yet know the format, so config 16 bit pcm audio for instance */
278			buf->sgroup_req.stream_info[i].size_max_byte_frame = 1024;
279			buf->sgroup_req.stream_info[i].size_max_sample_frame = 256;
280			buf->sgroup_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */
281
282			/* find the right bufferinfo_array */
283			j = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (pcm_number * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS)) + i;
284			if(capture) j += MIXART_PLAYBACK_STREAMS; /* in the array capture is behind playback */
285
286			buf->sgroup_req.flow_entry[i] = j;
287
288			flowinfo = (struct mixart_flowinfo *)chip->mgr->flowinfo.area;
289			flowinfo[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo.addr + (j * sizeof(struct mixart_bufferinfo));
290			flowinfo[j].bufferinfo_count = 1;               /* 1 will set the miXart to ring-buffer mode ! */
291
292			bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area;
293			bufferinfo[j].buffer_address = 0;               /* buffer is not yet allocated */
294			bufferinfo[j].available_length = 0;             /* buffer is not yet allocated */
295
296			/* construct the identifier of the stream buffer received in the interrupts ! */
297			bufferinfo[j].buffer_id = (chip->chip_idx << MIXART_NOTIFY_CARD_OFFSET) + (pcm_number << MIXART_NOTIFY_PCM_OFFSET ) + i;
298			if(capture) {
299				bufferinfo[j].buffer_id |= MIXART_NOTIFY_CAPT_MASK;
300			}
301		}
302
303		err = snd_mixart_send_msg(chip->mgr, &request, sizeof(buf->sgroup_resp), &buf->sgroup_resp);
304		if((err < 0) || (buf->sgroup_resp.status != 0)) {
305			snd_printk(KERN_ERR "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", err, buf->sgroup_resp.status);
306			kfree(buf);
307			return NULL;
308		}
309
310		pipe->group_uid = buf->sgroup_resp.group;     /* id of the pipe, as returned by embedded */
311		pipe->stream_count = buf->sgroup_resp.stream_count;
312		/* pipe->stream_uid[i] = buf->sgroup_resp.stream[i].stream_uid; */
313
314		pipe->status = PIPE_STOPPED;
315		kfree(buf);
316	}
317
318	if(monitoring)	pipe->monitoring = 1;
319	else		pipe->references++;
320
321	return pipe;
322}
323
324
325int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr,
326			     struct mixart_pipe *pipe, int monitoring)
327{
328	int err = 0;
329
330	if(pipe->status == PIPE_UNDEFINED)
331		return 0;
332
333	if(monitoring)
334		pipe->monitoring = 0;
335	else
336		pipe->references--;
337
338	if((pipe->references <= 0) && (pipe->monitoring == 0)) {
339
340		struct mixart_msg request;
341		struct mixart_delete_group_resp delete_resp;
342
343		/* release the clock */
344		err = mixart_set_clock( mgr, pipe, 0);
345		if( err < 0 ) {
346			snd_printk(KERN_ERR "mixart_set_clock(0) return error!\n");
347		}
348
349		/* stop the pipe */
350		err = mixart_set_pipe_state(mgr, pipe, 0);
351		if( err < 0 ) {
352			snd_printk(KERN_ERR "error stopping pipe!\n");
353		}
354
355		request.message_id = MSG_STREAM_DELETE_GROUP;
356		request.uid = (struct mixart_uid){0,0};
357		request.data = &pipe->group_uid;            /* the streaming group ! */
358		request.size = sizeof(pipe->group_uid);
359
360		/* delete the pipe */
361		err = snd_mixart_send_msg(mgr, &request, sizeof(delete_resp), &delete_resp);
362		if ((err < 0) || (delete_resp.status != 0)) {
363			snd_printk(KERN_ERR "error MSG_STREAM_DELETE_GROUP err(%x), status(%x)\n", err, delete_resp.status);
364		}
365
366		pipe->group_uid = (struct mixart_uid){0,0};
367		pipe->stream_count = 0;
368		pipe->status = PIPE_UNDEFINED;
369	}
370
371	return err;
372}
373
374static int mixart_set_stream_state(struct mixart_stream *stream, int start)
375{
376	struct snd_mixart *chip;
377	struct mixart_stream_state_req stream_state_req;
378	struct mixart_msg request;
379
380	if(!stream->substream)
381		return -EINVAL;
382
383	memset(&stream_state_req, 0, sizeof(stream_state_req));
384	stream_state_req.stream_count = 1;
385	stream_state_req.stream_info.stream_desc.uid_pipe = stream->pipe->group_uid;
386	stream_state_req.stream_info.stream_desc.stream_idx = stream->substream->number;
387
388	if (stream->substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
389		request.message_id = start ? MSG_STREAM_START_INPUT_STAGE_PACKET : MSG_STREAM_STOP_INPUT_STAGE_PACKET;
390	else
391		request.message_id = start ? MSG_STREAM_START_OUTPUT_STAGE_PACKET : MSG_STREAM_STOP_OUTPUT_STAGE_PACKET;
392
393	request.uid = (struct mixart_uid){0,0};
394	request.data = &stream_state_req;
395	request.size = sizeof(stream_state_req);
396
397	stream->abs_period_elapsed = 0;            /* reset stream pos      */
398	stream->buf_periods = 0;
399	stream->buf_period_frag = 0;
400
401	chip = snd_pcm_substream_chip(stream->substream);
402
403	return snd_mixart_send_msg_nonblock(chip->mgr, &request);
404}
405
406/*
407 *  Trigger callback
408 */
409
410static int snd_mixart_trigger(struct snd_pcm_substream *subs, int cmd)
411{
412	struct mixart_stream *stream = subs->runtime->private_data;
413
414	switch (cmd) {
415	case SNDRV_PCM_TRIGGER_START:
416
417		snd_printdd("SNDRV_PCM_TRIGGER_START\n");
418
419		/* START_STREAM */
420		if( mixart_set_stream_state(stream, 1) )
421			return -EINVAL;
422
423		stream->status = MIXART_STREAM_STATUS_RUNNING;
424
425		break;
426	case SNDRV_PCM_TRIGGER_STOP:
427
428		/* STOP_STREAM */
429		if( mixart_set_stream_state(stream, 0) )
430			return -EINVAL;
431
432		stream->status = MIXART_STREAM_STATUS_OPEN;
433
434		snd_printdd("SNDRV_PCM_TRIGGER_STOP\n");
435
436		break;
437
438	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
439		/* TODO */
440		stream->status = MIXART_STREAM_STATUS_PAUSE;
441		snd_printdd("SNDRV_PCM_PAUSE_PUSH\n");
442		break;
443	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
444		/* TODO */
445		stream->status = MIXART_STREAM_STATUS_RUNNING;
446		snd_printdd("SNDRV_PCM_PAUSE_RELEASE\n");
447		break;
448	default:
449		return -EINVAL;
450	}
451	return 0;
452}
453
454static int mixart_sync_nonblock_events(struct mixart_mgr *mgr)
455{
456	unsigned long timeout = jiffies + HZ;
457	while (atomic_read(&mgr->msg_processed) > 0) {
458		if (time_after(jiffies, timeout)) {
459			snd_printk(KERN_ERR "mixart: cannot process nonblock events!\n");
460			return -EBUSY;
461		}
462		schedule_timeout_uninterruptible(1);
463	}
464	return 0;
465}
466
467/*
468 *  prepare callback for all pcms
469 */
470static int snd_mixart_prepare(struct snd_pcm_substream *subs)
471{
472	struct snd_mixart *chip = snd_pcm_substream_chip(subs);
473	struct mixart_stream *stream = subs->runtime->private_data;
474
475	/* TODO de fa��on non bloquante, r��appliquer les hw_params (rate, bits, codec) */
476
477	snd_printdd("snd_mixart_prepare\n");
478
479	mixart_sync_nonblock_events(chip->mgr);
480
481	/* only the first stream can choose the sample rate */
482	/* the further opened streams will be limited to its frequency (see open) */
483	if(chip->mgr->ref_count_rate == 1)
484		chip->mgr->sample_rate = subs->runtime->rate;
485
486	/* set the clock only once (first stream) on the same pipe */
487	if(stream->pipe->references == 1) {
488		if( mixart_set_clock(chip->mgr, stream->pipe, subs->runtime->rate) )
489			return -EINVAL;
490	}
491
492	return 0;
493}
494
495
496static int mixart_set_format(struct mixart_stream *stream, snd_pcm_format_t format)
497{
498	int err;
499	struct snd_mixart *chip;
500	struct mixart_msg request;
501	struct mixart_stream_param_desc stream_param;
502	struct mixart_return_uid resp;
503
504	chip = snd_pcm_substream_chip(stream->substream);
505
506	memset(&stream_param, 0, sizeof(stream_param));
507
508	stream_param.coding_type = CT_LINEAR;
509	stream_param.number_of_channel = stream->channels;
510
511	stream_param.sampling_freq = chip->mgr->sample_rate;
512	if(stream_param.sampling_freq == 0)
513		stream_param.sampling_freq = 44100; /* if frequency not yet defined, use some default */
514
515	switch(format){
516	case SNDRV_PCM_FORMAT_U8:
517		stream_param.sample_type = ST_INTEGER_8;
518		stream_param.sample_size = 8;
519		break;
520	case SNDRV_PCM_FORMAT_S16_LE:
521		stream_param.sample_type = ST_INTEGER_16LE;
522		stream_param.sample_size = 16;
523		break;
524	case SNDRV_PCM_FORMAT_S16_BE:
525		stream_param.sample_type = ST_INTEGER_16BE;
526		stream_param.sample_size = 16;
527		break;
528	case SNDRV_PCM_FORMAT_S24_3LE:
529		stream_param.sample_type = ST_INTEGER_24LE;
530		stream_param.sample_size = 24;
531		break;
532	case SNDRV_PCM_FORMAT_S24_3BE:
533		stream_param.sample_type = ST_INTEGER_24BE;
534		stream_param.sample_size = 24;
535		break;
536	case SNDRV_PCM_FORMAT_FLOAT_LE:
537		stream_param.sample_type = ST_FLOATING_POINT_32LE;
538		stream_param.sample_size = 32;
539		break;
540	case  SNDRV_PCM_FORMAT_FLOAT_BE:
541		stream_param.sample_type = ST_FLOATING_POINT_32BE;
542		stream_param.sample_size = 32;
543		break;
544	default:
545		snd_printk(KERN_ERR "error mixart_set_format() : unknown format\n");
546		return -EINVAL;
547	}
548
549	snd_printdd("set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) channels(%d)\n",
550		   stream_param.sample_type, stream_param.sample_size, stream_param.sampling_freq, stream->channels);
551
552	/* TODO: what else to configure ? */
553	/* stream_param.samples_per_frame = 2; */
554	/* stream_param.bytes_per_frame = 4; */
555	/* stream_param.bytes_per_sample = 2; */
556
557	stream_param.pipe_count = 1;      /* set to 1 */
558	stream_param.stream_count = 1;    /* set to 1 */
559	stream_param.stream_desc[0].uid_pipe = stream->pipe->group_uid;
560	stream_param.stream_desc[0].stream_idx = stream->substream->number;
561
562	request.message_id = MSG_STREAM_SET_INPUT_STAGE_PARAM;
563	request.uid = (struct mixart_uid){0,0};
564	request.data = &stream_param;
565	request.size = sizeof(stream_param);
566
567	err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp);
568	if((err < 0) || resp.error_code) {
569		snd_printk(KERN_ERR "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; resp=%x\n", err, resp.error_code);
570		return -EINVAL;
571	}
572	return 0;
573}
574
575
576/*
577 *  HW_PARAMS callback for all pcms
578 */
579static int snd_mixart_hw_params(struct snd_pcm_substream *subs,
580                                struct snd_pcm_hw_params *hw)
581{
582	struct snd_mixart *chip = snd_pcm_substream_chip(subs);
583	struct mixart_mgr *mgr = chip->mgr;
584	struct mixart_stream *stream = subs->runtime->private_data;
585	snd_pcm_format_t format;
586	int err;
587	int channels;
588
589	/* set up channels */
590	channels = params_channels(hw);
591
592	/*  set up format for the stream */
593	format = params_format(hw);
594
595	mutex_lock(&mgr->setup_mutex);
596
597	/* update the stream levels */
598	if( stream->pcm_number <= MIXART_PCM_DIGITAL ) {
599		int is_aes = stream->pcm_number > MIXART_PCM_ANALOG;
600		if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK )
601			mixart_update_playback_stream_level(chip, is_aes, subs->number);
602		else
603			mixart_update_capture_stream_level( chip, is_aes);
604	}
605
606	stream->channels = channels;
607
608	/* set the format to the board */
609	err = mixart_set_format(stream, format);
610	if(err < 0) {
611		mutex_unlock(&mgr->setup_mutex);
612		return err;
613	}
614
615	/* allocate buffer */
616	err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw));
617
618	if (err > 0) {
619		struct mixart_bufferinfo *bufferinfo;
620		int i = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (stream->pcm_number * (MIXART_PLAYBACK_STREAMS+MIXART_CAPTURE_STREAMS)) + subs->number;
621		if( subs->stream == SNDRV_PCM_STREAM_CAPTURE ) {
622			i += MIXART_PLAYBACK_STREAMS; /* in array capture is behind playback */
623		}
624
625		bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area;
626		bufferinfo[i].buffer_address = subs->runtime->dma_addr;
627		bufferinfo[i].available_length = subs->runtime->dma_bytes;
628		/* bufferinfo[i].buffer_id  is already defined */
629
630		snd_printdd("snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", i,
631				bufferinfo[i].buffer_address,
632				bufferinfo[i].available_length,
633				subs->number);
634	}
635	mutex_unlock(&mgr->setup_mutex);
636
637	return err;
638}
639
640static int snd_mixart_hw_free(struct snd_pcm_substream *subs)
641{
642	struct snd_mixart *chip = snd_pcm_substream_chip(subs);
643	snd_pcm_lib_free_pages(subs);
644	mixart_sync_nonblock_events(chip->mgr);
645	return 0;
646}
647
648
649
650/*
651 *  TODO CONFIGURATION SPACE for all pcms, mono pcm must update channels_max
652 */
653static struct snd_pcm_hardware snd_mixart_analog_caps =
654{
655	.info             = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
656			      SNDRV_PCM_INFO_MMAP_VALID |
657			      SNDRV_PCM_INFO_PAUSE),
658	.formats	  = ( SNDRV_PCM_FMTBIT_U8 |
659			      SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
660			      SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
661			      SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),
662	.rates            = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
663	.rate_min         = 8000,
664	.rate_max         = 48000,
665	.channels_min     = 1,
666	.channels_max     = 2,
667	.buffer_bytes_max = (32*1024),
668	.period_bytes_min = 256,                  /* 256 frames U8 mono*/
669	.period_bytes_max = (16*1024),
670	.periods_min      = 2,
671	.periods_max      = (32*1024/256),
672};
673
674static struct snd_pcm_hardware snd_mixart_digital_caps =
675{
676	.info             = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
677			      SNDRV_PCM_INFO_MMAP_VALID |
678			      SNDRV_PCM_INFO_PAUSE),
679	.formats	  = ( SNDRV_PCM_FMTBIT_U8 |
680			      SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
681			      SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
682			      SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),
683	.rates            = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
684	.rate_min         = 32000,
685	.rate_max         = 48000,
686	.channels_min     = 1,
687	.channels_max     = 2,
688	.buffer_bytes_max = (32*1024),
689	.period_bytes_min = 256,                  /* 256 frames U8 mono*/
690	.period_bytes_max = (16*1024),
691	.periods_min      = 2,
692	.periods_max      = (32*1024/256),
693};
694
695
696static int snd_mixart_playback_open(struct snd_pcm_substream *subs)
697{
698	struct snd_mixart            *chip = snd_pcm_substream_chip(subs);
699	struct mixart_mgr        *mgr = chip->mgr;
700	struct snd_pcm_runtime *runtime = subs->runtime;
701	struct snd_pcm *pcm = subs->pcm;
702	struct mixart_stream     *stream;
703	struct mixart_pipe       *pipe;
704	int err = 0;
705	int pcm_number;
706
707	mutex_lock(&mgr->setup_mutex);
708
709	if ( pcm == chip->pcm ) {
710		pcm_number = MIXART_PCM_ANALOG;
711		runtime->hw = snd_mixart_analog_caps;
712	} else {
713		snd_BUG_ON(pcm != chip->pcm_dig);
714		pcm_number = MIXART_PCM_DIGITAL;
715		runtime->hw = snd_mixart_digital_caps;
716	}
717	snd_printdd("snd_mixart_playback_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number);
718
719	/* get stream info */
720	stream = &(chip->playback_stream[pcm_number][subs->number]);
721
722	if (stream->status != MIXART_STREAM_STATUS_FREE){
723		/* streams in use */
724		snd_printk(KERN_ERR "snd_mixart_playback_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number);
725		err = -EBUSY;
726		goto _exit_open;
727	}
728
729	/* get pipe pointer (out pipe) */
730	pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 0, 0);
731
732	if (pipe == NULL) {
733		err = -EINVAL;
734		goto _exit_open;
735	}
736
737	/* start the pipe if necessary */
738	err = mixart_set_pipe_state(chip->mgr, pipe, 1);
739	if( err < 0 ) {
740		snd_printk(KERN_ERR "error starting pipe!\n");
741		snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);
742		err = -EINVAL;
743		goto _exit_open;
744	}
745
746	stream->pipe        = pipe;
747	stream->pcm_number  = pcm_number;
748	stream->status      = MIXART_STREAM_STATUS_OPEN;
749	stream->substream   = subs;
750	stream->channels    = 0; /* not configured yet */
751
752	runtime->private_data = stream;
753
754	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
755	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);
756
757	/* if a sample rate is already used, another stream cannot change */
758	if(mgr->ref_count_rate++) {
759		if(mgr->sample_rate) {
760			runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
761		}
762	}
763
764 _exit_open:
765	mutex_unlock(&mgr->setup_mutex);
766
767	return err;
768}
769
770
771static int snd_mixart_capture_open(struct snd_pcm_substream *subs)
772{
773	struct snd_mixart            *chip = snd_pcm_substream_chip(subs);
774	struct mixart_mgr        *mgr = chip->mgr;
775	struct snd_pcm_runtime *runtime = subs->runtime;
776	struct snd_pcm *pcm = subs->pcm;
777	struct mixart_stream     *stream;
778	struct mixart_pipe       *pipe;
779	int err = 0;
780	int pcm_number;
781
782	mutex_lock(&mgr->setup_mutex);
783
784	if ( pcm == chip->pcm ) {
785		pcm_number = MIXART_PCM_ANALOG;
786		runtime->hw = snd_mixart_analog_caps;
787	} else {
788		snd_BUG_ON(pcm != chip->pcm_dig);
789		pcm_number = MIXART_PCM_DIGITAL;
790		runtime->hw = snd_mixart_digital_caps;
791	}
792
793	runtime->hw.channels_min = 2; /* for instance, no mono */
794
795	snd_printdd("snd_mixart_capture_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number);
796
797	/* get stream info */
798	stream = &(chip->capture_stream[pcm_number]);
799
800	if (stream->status != MIXART_STREAM_STATUS_FREE){
801		/* streams in use */
802		snd_printk(KERN_ERR "snd_mixart_capture_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number);
803		err = -EBUSY;
804		goto _exit_open;
805	}
806
807	/* get pipe pointer (in pipe) */
808	pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 1, 0);
809
810	if (pipe == NULL) {
811		err = -EINVAL;
812		goto _exit_open;
813	}
814
815	/* start the pipe if necessary */
816	err = mixart_set_pipe_state(chip->mgr, pipe, 1);
817	if( err < 0 ) {
818		snd_printk(KERN_ERR "error starting pipe!\n");
819		snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);
820		err = -EINVAL;
821		goto _exit_open;
822	}
823
824	stream->pipe        = pipe;
825	stream->pcm_number  = pcm_number;
826	stream->status      = MIXART_STREAM_STATUS_OPEN;
827	stream->substream   = subs;
828	stream->channels    = 0; /* not configured yet */
829
830	runtime->private_data = stream;
831
832	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
833	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);
834
835	/* if a sample rate is already used, another stream cannot change */
836	if(mgr->ref_count_rate++) {
837		if(mgr->sample_rate) {
838			runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
839		}
840	}
841
842 _exit_open:
843	mutex_unlock(&mgr->setup_mutex);
844
845	return err;
846}
847
848
849
850static int snd_mixart_close(struct snd_pcm_substream *subs)
851{
852	struct snd_mixart *chip = snd_pcm_substream_chip(subs);
853	struct mixart_mgr *mgr = chip->mgr;
854	struct mixart_stream *stream = subs->runtime->private_data;
855
856	mutex_lock(&mgr->setup_mutex);
857
858	snd_printdd("snd_mixart_close C%d/P%d/Sub%d\n", chip->chip_idx, stream->pcm_number, subs->number);
859
860	/* sample rate released */
861	if(--mgr->ref_count_rate == 0) {
862		mgr->sample_rate = 0;
863	}
864
865	/* delete pipe */
866	if (snd_mixart_kill_ref_pipe(mgr, stream->pipe, 0 ) < 0) {
867
868		snd_printk(KERN_ERR "error snd_mixart_kill_ref_pipe C%dP%d\n", chip->chip_idx, stream->pcm_number);
869	}
870
871	stream->pipe      = NULL;
872	stream->status    = MIXART_STREAM_STATUS_FREE;
873	stream->substream = NULL;
874
875	mutex_unlock(&mgr->setup_mutex);
876	return 0;
877}
878
879
880static snd_pcm_uframes_t snd_mixart_stream_pointer(struct snd_pcm_substream *subs)
881{
882	struct snd_pcm_runtime *runtime = subs->runtime;
883	struct mixart_stream   *stream  = runtime->private_data;
884
885	return (snd_pcm_uframes_t)((stream->buf_periods * runtime->period_size) + stream->buf_period_frag);
886}
887
888
889
890static struct snd_pcm_ops snd_mixart_playback_ops = {
891	.open      = snd_mixart_playback_open,
892	.close     = snd_mixart_close,
893	.ioctl     = snd_pcm_lib_ioctl,
894	.prepare   = snd_mixart_prepare,
895	.hw_params = snd_mixart_hw_params,
896	.hw_free   = snd_mixart_hw_free,
897	.trigger   = snd_mixart_trigger,
898	.pointer   = snd_mixart_stream_pointer,
899};
900
901static struct snd_pcm_ops snd_mixart_capture_ops = {
902	.open      = snd_mixart_capture_open,
903	.close     = snd_mixart_close,
904	.ioctl     = snd_pcm_lib_ioctl,
905	.prepare   = snd_mixart_prepare,
906	.hw_params = snd_mixart_hw_params,
907	.hw_free   = snd_mixart_hw_free,
908	.trigger   = snd_mixart_trigger,
909	.pointer   = snd_mixart_stream_pointer,
910};
911
912static void preallocate_buffers(struct snd_mixart *chip, struct snd_pcm *pcm)
913{
914	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
915					      snd_dma_pci_data(chip->mgr->pci), 32*1024, 32*1024);
916}
917
918/*
919 */
920static int snd_mixart_pcm_analog(struct snd_mixart *chip)
921{
922	int err;
923	struct snd_pcm *pcm;
924	char name[32];
925
926	sprintf(name, "miXart analog %d", chip->chip_idx);
927	if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_ANALOG,
928			       MIXART_PLAYBACK_STREAMS,
929			       MIXART_CAPTURE_STREAMS, &pcm)) < 0) {
930		snd_printk(KERN_ERR "cannot create the analog pcm %d\n", chip->chip_idx);
931		return err;
932	}
933
934	pcm->private_data = chip;
935
936	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
937	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
938
939	pcm->info_flags = 0;
940	strcpy(pcm->name, name);
941
942	preallocate_buffers(chip, pcm);
943
944	chip->pcm = pcm;
945	return 0;
946}
947
948
949/*
950 */
951static int snd_mixart_pcm_digital(struct snd_mixart *chip)
952{
953	int err;
954	struct snd_pcm *pcm;
955	char name[32];
956
957	sprintf(name, "miXart AES/EBU %d", chip->chip_idx);
958	if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_DIGITAL,
959			       MIXART_PLAYBACK_STREAMS,
960			       MIXART_CAPTURE_STREAMS, &pcm)) < 0) {
961		snd_printk(KERN_ERR "cannot create the digital pcm %d\n", chip->chip_idx);
962		return err;
963	}
964
965	pcm->private_data = chip;
966
967	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
968	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
969
970	pcm->info_flags = 0;
971	strcpy(pcm->name, name);
972
973	preallocate_buffers(chip, pcm);
974
975	chip->pcm_dig = pcm;
976	return 0;
977}
978
979static int snd_mixart_chip_free(struct snd_mixart *chip)
980{
981	kfree(chip);
982	return 0;
983}
984
985static int snd_mixart_chip_dev_free(struct snd_device *device)
986{
987	struct snd_mixart *chip = device->device_data;
988	return snd_mixart_chip_free(chip);
989}
990
991
992/*
993 */
994static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx)
995{
996	int err;
997	struct snd_mixart *chip;
998	static struct snd_device_ops ops = {
999		.dev_free = snd_mixart_chip_dev_free,
1000	};
1001
1002	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1003	if (! chip) {
1004		snd_printk(KERN_ERR "cannot allocate chip\n");
1005		return -ENOMEM;
1006	}
1007
1008	chip->card = card;
1009	chip->chip_idx = idx;
1010	chip->mgr = mgr;
1011
1012	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
1013		snd_mixart_chip_free(chip);
1014		return err;
1015	}
1016
1017	mgr->chip[idx] = chip;
1018	snd_card_set_dev(card, &mgr->pci->dev);
1019
1020	return 0;
1021}
1022
1023int snd_mixart_create_pcm(struct snd_mixart* chip)
1024{
1025	int err;
1026
1027	err = snd_mixart_pcm_analog(chip);
1028	if (err < 0)
1029		return err;
1030
1031	if(chip->mgr->board_type == MIXART_DAUGHTER_TYPE_AES) {
1032
1033		err = snd_mixart_pcm_digital(chip);
1034		if (err < 0)
1035			return err;
1036	}
1037	return err;
1038}
1039
1040
1041/*
1042 * release all the cards assigned to a manager instance
1043 */
1044static int snd_mixart_free(struct mixart_mgr *mgr)
1045{
1046	unsigned int i;
1047
1048	for (i = 0; i < mgr->num_cards; i++) {
1049		if (mgr->chip[i])
1050			snd_card_free(mgr->chip[i]->card);
1051	}
1052
1053	/* stop mailbox */
1054	snd_mixart_exit_mailbox(mgr);
1055
1056	/* release irq  */
1057	if (mgr->irq >= 0)
1058		free_irq(mgr->irq, mgr);
1059
1060	/* reset board if some firmware was loaded */
1061	if(mgr->dsp_loaded) {
1062		snd_mixart_reset_board(mgr);
1063		snd_printdd("reset miXart !\n");
1064	}
1065
1066	/* release the i/o ports */
1067	for (i = 0; i < 2; i++) {
1068		if (mgr->mem[i].virt)
1069			iounmap(mgr->mem[i].virt);
1070	}
1071	pci_release_regions(mgr->pci);
1072
1073	/* free flowarray */
1074	if(mgr->flowinfo.area) {
1075		snd_dma_free_pages(&mgr->flowinfo);
1076		mgr->flowinfo.area = NULL;
1077	}
1078	/* free bufferarray */
1079	if(mgr->bufferinfo.area) {
1080		snd_dma_free_pages(&mgr->bufferinfo);
1081		mgr->bufferinfo.area = NULL;
1082	}
1083
1084	pci_disable_device(mgr->pci);
1085	kfree(mgr);
1086	return 0;
1087}
1088
1089/*
1090 * proc interface
1091 */
1092
1093/*
1094  mixart_BA0 proc interface for BAR 0 - read callback
1095 */
1096static ssize_t snd_mixart_BA0_read(struct snd_info_entry *entry,
1097				   void *file_private_data,
1098				   struct file *file, char __user *buf,
1099				   size_t count, loff_t pos)
1100{
1101	struct mixart_mgr *mgr = entry->private_data;
1102
1103	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
1104	if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count))
1105		return -EFAULT;
1106	return count;
1107}
1108
1109/*
1110  mixart_BA1 proc interface for BAR 1 - read callback
1111 */
1112static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry,
1113				   void *file_private_data,
1114				   struct file *file, char __user *buf,
1115				   size_t count, loff_t pos)
1116{
1117	struct mixart_mgr *mgr = entry->private_data;
1118
1119	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
1120	if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count))
1121		return -EFAULT;
1122	return count;
1123}
1124
1125static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = {
1126	.read   = snd_mixart_BA0_read,
1127};
1128
1129static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {
1130	.read   = snd_mixart_BA1_read,
1131};
1132
1133
1134static void snd_mixart_proc_read(struct snd_info_entry *entry,
1135                                 struct snd_info_buffer *buffer)
1136{
1137	struct snd_mixart *chip = entry->private_data;
1138	u32 ref;
1139
1140	snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx);
1141
1142	/* stats available when embedded OS is running */
1143	if (chip->mgr->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) {
1144		snd_iprintf(buffer, "- hardware -\n");
1145		switch (chip->mgr->board_type ) {
1146		case MIXART_DAUGHTER_TYPE_NONE     : snd_iprintf(buffer, "\tmiXart8 (no daughter board)\n\n"); break;
1147		case MIXART_DAUGHTER_TYPE_AES      : snd_iprintf(buffer, "\tmiXart8 AES/EBU\n\n"); break;
1148		case MIXART_DAUGHTER_TYPE_COBRANET : snd_iprintf(buffer, "\tmiXart8 Cobranet\n\n"); break;
1149		default:                             snd_iprintf(buffer, "\tUNKNOWN!\n\n"); break;
1150		}
1151
1152		snd_iprintf(buffer, "- system load -\n");
1153
1154		/* get perf reference */
1155
1156		ref = readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_SYSTEM_LOAD_OFFSET));
1157
1158		if (ref) {
1159			u32 mailbox   = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_MAILBX_LOAD_OFFSET)) / ref;
1160			u32 streaming = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_STREAM_LOAD_OFFSET)) / ref;
1161			u32 interr    = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_INTERR_LOAD_OFFSET)) / ref;
1162
1163			snd_iprintf(buffer, "\tstreaming          : %d\n", streaming);
1164			snd_iprintf(buffer, "\tmailbox            : %d\n", mailbox);
1165			snd_iprintf(buffer, "\tinterrups handling : %d\n\n", interr);
1166		}
1167	} /* endif elf loaded */
1168}
1169
1170static void __devinit snd_mixart_proc_init(struct snd_mixart *chip)
1171{
1172	struct snd_info_entry *entry;
1173
1174	/* text interface to read perf and temp meters */
1175	if (! snd_card_proc_new(chip->card, "board_info", &entry)) {
1176		entry->private_data = chip;
1177		entry->c.text.read = snd_mixart_proc_read;
1178	}
1179
1180	if (! snd_card_proc_new(chip->card, "mixart_BA0", &entry)) {
1181		entry->content = SNDRV_INFO_CONTENT_DATA;
1182		entry->private_data = chip->mgr;
1183		entry->c.ops = &snd_mixart_proc_ops_BA0;
1184		entry->size = MIXART_BA0_SIZE;
1185	}
1186	if (! snd_card_proc_new(chip->card, "mixart_BA1", &entry)) {
1187		entry->content = SNDRV_INFO_CONTENT_DATA;
1188		entry->private_data = chip->mgr;
1189		entry->c.ops = &snd_mixart_proc_ops_BA1;
1190		entry->size = MIXART_BA1_SIZE;
1191	}
1192}
1193/* end of proc interface */
1194
1195
1196/*
1197 *    probe function - creates the card manager
1198 */
1199static int __devinit snd_mixart_probe(struct pci_dev *pci,
1200				      const struct pci_device_id *pci_id)
1201{
1202	static int dev;
1203	struct mixart_mgr *mgr;
1204	unsigned int i;
1205	int err;
1206	size_t size;
1207
1208	/*
1209	 */
1210	if (dev >= SNDRV_CARDS)
1211		return -ENODEV;
1212	if (! enable[dev]) {
1213		dev++;
1214		return -ENOENT;
1215	}
1216
1217	/* enable PCI device */
1218	if ((err = pci_enable_device(pci)) < 0)
1219		return err;
1220	pci_set_master(pci);
1221
1222	/* check if we can restrict PCI DMA transfers to 32 bits */
1223	if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0) {
1224		snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n");
1225		pci_disable_device(pci);
1226		return -ENXIO;
1227	}
1228
1229	/*
1230	 */
1231	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1232	if (! mgr) {
1233		pci_disable_device(pci);
1234		return -ENOMEM;
1235	}
1236
1237	mgr->pci = pci;
1238	mgr->irq = -1;
1239
1240	/* resource assignment */
1241	if ((err = pci_request_regions(pci, CARD_NAME)) < 0) {
1242		kfree(mgr);
1243		pci_disable_device(pci);
1244		return err;
1245	}
1246	for (i = 0; i < 2; i++) {
1247		mgr->mem[i].phys = pci_resource_start(pci, i);
1248		mgr->mem[i].virt = pci_ioremap_bar(pci, i);
1249		if (!mgr->mem[i].virt) {
1250		        printk(KERN_ERR "unable to remap resource 0x%lx\n",
1251			       mgr->mem[i].phys);
1252			snd_mixart_free(mgr);
1253			return -EBUSY;
1254		}
1255	}
1256
1257	if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED,
1258			CARD_NAME, mgr)) {
1259		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
1260		snd_mixart_free(mgr);
1261		return -EBUSY;
1262	}
1263	mgr->irq = pci->irq;
1264
1265	sprintf(mgr->shortname, "Digigram miXart");
1266	sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq);
1267
1268	/* ISR spinlock  */
1269	spin_lock_init(&mgr->lock);
1270
1271	/* init mailbox  */
1272	mgr->msg_fifo_readptr = 0;
1273	mgr->msg_fifo_writeptr = 0;
1274
1275	spin_lock_init(&mgr->msg_lock);
1276	mutex_init(&mgr->msg_mutex);
1277	init_waitqueue_head(&mgr->msg_sleep);
1278	atomic_set(&mgr->msg_processed, 0);
1279
1280	/* init setup mutex*/
1281	mutex_init(&mgr->setup_mutex);
1282
1283	/* init message taslket */
1284	tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr);
1285
1286	/* card assignment */
1287	mgr->num_cards = MIXART_MAX_CARDS;
1288	for (i = 0; i < mgr->num_cards; i++) {
1289		struct snd_card *card;
1290		char tmpid[16];
1291		int idx;
1292
1293		if (index[dev] < 0)
1294			idx = index[dev];
1295		else
1296			idx = index[dev] + i;
1297		snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i);
1298		err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card);
1299
1300		if (err < 0) {
1301			snd_printk(KERN_ERR "cannot allocate the card %d\n", i);
1302			snd_mixart_free(mgr);
1303			return err;
1304		}
1305
1306		strcpy(card->driver, CARD_NAME);
1307		sprintf(card->shortname, "%s [PCM #%d]", mgr->shortname, i);
1308		sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i);
1309
1310		if ((err = snd_mixart_create(mgr, card, i)) < 0) {
1311			snd_card_free(card);
1312			snd_mixart_free(mgr);
1313			return err;
1314		}
1315
1316		if(i==0) {
1317			/* init proc interface only for chip0 */
1318			snd_mixart_proc_init(mgr->chip[i]);
1319		}
1320
1321		if ((err = snd_card_register(card)) < 0) {
1322			snd_mixart_free(mgr);
1323			return err;
1324		}
1325	}
1326
1327	/* init firmware status (mgr->dsp_loaded reset in hwdep_new) */
1328	mgr->board_type = MIXART_DAUGHTER_TYPE_NONE;
1329
1330	/* create array of streaminfo */
1331	size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS *
1332			    sizeof(struct mixart_flowinfo)) );
1333	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
1334				size, &mgr->flowinfo) < 0) {
1335		snd_mixart_free(mgr);
1336		return -ENOMEM;
1337	}
1338	/* init streaminfo_array */
1339	memset(mgr->flowinfo.area, 0, size);
1340
1341	/* create array of bufferinfo */
1342	size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS *
1343			    sizeof(struct mixart_bufferinfo)) );
1344	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
1345				size, &mgr->bufferinfo) < 0) {
1346		snd_mixart_free(mgr);
1347		return -ENOMEM;
1348	}
1349	/* init bufferinfo_array */
1350	memset(mgr->bufferinfo.area, 0, size);
1351
1352	/* set up firmware */
1353	err = snd_mixart_setup_firmware(mgr);
1354	if (err < 0) {
1355		snd_mixart_free(mgr);
1356		return err;
1357	}
1358
1359	pci_set_drvdata(pci, mgr);
1360	dev++;
1361	return 0;
1362}
1363
1364static void __devexit snd_mixart_remove(struct pci_dev *pci)
1365{
1366	snd_mixart_free(pci_get_drvdata(pci));
1367	pci_set_drvdata(pci, NULL);
1368}
1369
1370static struct pci_driver driver = {
1371	.name = "Digigram miXart",
1372	.id_table = snd_mixart_ids,
1373	.probe = snd_mixart_probe,
1374	.remove = __devexit_p(snd_mixart_remove),
1375};
1376
1377static int __init alsa_card_mixart_init(void)
1378{
1379	return pci_register_driver(&driver);
1380}
1381
1382static void __exit alsa_card_mixart_exit(void)
1383{
1384	pci_unregister_driver(&driver);
1385}
1386
1387module_init(alsa_card_mixart_init)
1388module_exit(alsa_card_mixart_exit)
1389