Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Driver for Digigram miXart soundcards
0004  *
0005  * main file with alsa callbacks
0006  *
0007  * Copyright (c) 2003 by Digigram <alsa@digigram.com>
0008  */
0009 
0010 
0011 #include <linux/init.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/pci.h>
0014 #include <linux/dma-mapping.h>
0015 #include <linux/module.h>
0016 #include <linux/mutex.h>
0017 #include <linux/slab.h>
0018 
0019 #include <sound/core.h>
0020 #include <sound/initval.h>
0021 #include <sound/info.h>
0022 #include <sound/control.h>
0023 #include <sound/pcm.h>
0024 #include <sound/pcm_params.h>
0025 #include "mixart.h"
0026 #include "mixart_hwdep.h"
0027 #include "mixart_core.h"
0028 #include "mixart_mixer.h"
0029 
0030 #define CARD_NAME "miXart"
0031 
0032 MODULE_AUTHOR("Digigram <alsa@digigram.com>");
0033 MODULE_DESCRIPTION("Digigram " CARD_NAME);
0034 MODULE_LICENSE("GPL");
0035 
0036 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;             /* Index 0-MAX */
0037 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;              /* ID for this card */
0038 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;     /* Enable this card */
0039 
0040 module_param_array(index, int, NULL, 0444);
0041 MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard.");
0042 module_param_array(id, charp, NULL, 0444);
0043 MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard.");
0044 module_param_array(enable, bool, NULL, 0444);
0045 MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
0046 
0047 /*
0048  */
0049 
0050 static const struct pci_device_id snd_mixart_ids[] = {
0051     { PCI_VDEVICE(MOTOROLA, 0x0003), 0, }, /* MC8240 */
0052     { 0, }
0053 };
0054 
0055 MODULE_DEVICE_TABLE(pci, snd_mixart_ids);
0056 
0057 
0058 static int mixart_set_pipe_state(struct mixart_mgr *mgr,
0059                  struct mixart_pipe *pipe, int start)
0060 {
0061     struct mixart_group_state_req group_state;
0062     struct mixart_group_state_resp group_state_resp;
0063     struct mixart_msg request;
0064     int err;
0065     u32 system_msg_uid;
0066 
0067     switch(pipe->status) {
0068     case PIPE_RUNNING:
0069     case PIPE_CLOCK_SET:
0070         if(start) return 0; /* already started */
0071         break;
0072     case PIPE_STOPPED:
0073         if(!start) return 0; /* already stopped */
0074         break;
0075     default:
0076         dev_err(&mgr->pci->dev,
0077             "error mixart_set_pipe_state called with wrong pipe->status!\n");
0078         return -EINVAL;      /* function called with wrong pipe status */
0079     }
0080 
0081     system_msg_uid = 0x12345678; /* the event ! (take care: the MSB and two LSB's have to be 0) */
0082 
0083     /* wait on the last MSG_SYSTEM_SEND_SYNCHRO_CMD command to be really finished */
0084 
0085     request.message_id = MSG_SYSTEM_WAIT_SYNCHRO_CMD;
0086     request.uid = (struct mixart_uid){0,0};
0087     request.data = &system_msg_uid;
0088     request.size = sizeof(system_msg_uid);
0089 
0090     err = snd_mixart_send_msg_wait_notif(mgr, &request, system_msg_uid);
0091     if(err) {
0092         dev_err(&mgr->pci->dev,
0093             "error : MSG_SYSTEM_WAIT_SYNCHRO_CMD was not notified !\n");
0094         return err;
0095     }
0096 
0097     /* start or stop the pipe (1 pipe) */
0098 
0099     memset(&group_state, 0, sizeof(group_state));
0100     group_state.pipe_count = 1;
0101     group_state.pipe_uid[0] = pipe->group_uid;
0102 
0103     if(start)
0104         request.message_id = MSG_STREAM_START_STREAM_GRP_PACKET;
0105     else
0106         request.message_id = MSG_STREAM_STOP_STREAM_GRP_PACKET;
0107 
0108     request.uid = pipe->group_uid; /*(struct mixart_uid){0,0};*/
0109     request.data = &group_state;
0110     request.size = sizeof(group_state);
0111 
0112     err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp);
0113     if (err < 0 || group_state_resp.txx_status != 0) {
0114         dev_err(&mgr->pci->dev,
0115             "error MSG_STREAM_ST***_STREAM_GRP_PACKET err=%x stat=%x !\n",
0116             err, group_state_resp.txx_status);
0117         return -EINVAL;
0118     }
0119 
0120     if(start) {
0121         u32 stat = 0;
0122 
0123         group_state.pipe_count = 0; /* in case of start same command once again with pipe_count=0 */
0124 
0125         err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp);
0126         if (err < 0 || group_state_resp.txx_status != 0) {
0127             dev_err(&mgr->pci->dev,
0128                 "error MSG_STREAM_START_STREAM_GRP_PACKET err=%x stat=%x !\n",
0129                 err, group_state_resp.txx_status);
0130             return -EINVAL;
0131         }
0132 
0133         /* in case of start send a synchro top */
0134 
0135         request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD;
0136         request.uid = (struct mixart_uid){0,0};
0137         request.data = NULL;
0138         request.size = 0;
0139 
0140         err = snd_mixart_send_msg(mgr, &request, sizeof(stat), &stat);
0141         if (err < 0 || stat != 0) {
0142             dev_err(&mgr->pci->dev,
0143                 "error MSG_SYSTEM_SEND_SYNCHRO_CMD err=%x stat=%x !\n",
0144                 err, stat);
0145             return -EINVAL;
0146         }
0147 
0148         pipe->status = PIPE_RUNNING;
0149     }
0150     else /* !start */
0151         pipe->status = PIPE_STOPPED;
0152 
0153     return 0;
0154 }
0155 
0156 
0157 static int mixart_set_clock(struct mixart_mgr *mgr,
0158                 struct mixart_pipe *pipe, unsigned int rate)
0159 {
0160     struct mixart_msg request;
0161     struct mixart_clock_properties clock_properties;
0162     struct mixart_clock_properties_resp clock_prop_resp;
0163     int err;
0164 
0165     switch(pipe->status) {
0166     case PIPE_CLOCK_SET:
0167         break;
0168     case PIPE_RUNNING:
0169         if(rate != 0)
0170             break;
0171         fallthrough;
0172     default:
0173         if(rate == 0)
0174             return 0; /* nothing to do */
0175         else {
0176             dev_err(&mgr->pci->dev,
0177                 "error mixart_set_clock(%d) called with wrong pipe->status !\n",
0178                 rate);
0179             return -EINVAL;
0180         }
0181     }
0182 
0183     memset(&clock_properties, 0, sizeof(clock_properties));
0184     clock_properties.clock_generic_type = (rate != 0) ? CGT_INTERNAL_CLOCK : CGT_NO_CLOCK;
0185     clock_properties.clock_mode = CM_STANDALONE;
0186     clock_properties.frequency = rate;
0187     clock_properties.nb_callers = 1; /* only one entry in uid_caller ! */
0188     clock_properties.uid_caller[0] = pipe->group_uid;
0189 
0190     dev_dbg(&mgr->pci->dev, "mixart_set_clock to %d kHz\n", rate);
0191 
0192     request.message_id = MSG_CLOCK_SET_PROPERTIES;
0193     request.uid = mgr->uid_console_manager;
0194     request.data = &clock_properties;
0195     request.size = sizeof(clock_properties);
0196 
0197     err = snd_mixart_send_msg(mgr, &request, sizeof(clock_prop_resp), &clock_prop_resp);
0198     if (err < 0 || clock_prop_resp.status != 0 || clock_prop_resp.clock_mode != CM_STANDALONE) {
0199         dev_err(&mgr->pci->dev,
0200             "error MSG_CLOCK_SET_PROPERTIES err=%x stat=%x mod=%x !\n",
0201             err, clock_prop_resp.status, clock_prop_resp.clock_mode);
0202         return -EINVAL;
0203     }
0204 
0205     if(rate)  pipe->status = PIPE_CLOCK_SET;
0206     else      pipe->status = PIPE_RUNNING;
0207 
0208     return 0;
0209 }
0210 
0211 
0212 /*
0213  *  Allocate or reference output pipe for analog IOs (pcmp0/1)
0214  */
0215 struct mixart_pipe *
0216 snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture,
0217             int monitoring)
0218 {
0219     int stream_count;
0220     struct mixart_pipe *pipe;
0221     struct mixart_msg request;
0222 
0223     if(capture) {
0224         if (pcm_number == MIXART_PCM_ANALOG) {
0225             pipe = &(chip->pipe_in_ana);  /* analog inputs */
0226         } else {
0227             pipe = &(chip->pipe_in_dig); /* digital inputs */
0228         }
0229         request.message_id = MSG_STREAM_ADD_OUTPUT_GROUP;
0230         stream_count = MIXART_CAPTURE_STREAMS;
0231     } else {
0232         if (pcm_number == MIXART_PCM_ANALOG) {
0233             pipe = &(chip->pipe_out_ana);  /* analog outputs */
0234         } else {
0235             pipe = &(chip->pipe_out_dig);  /* digital outputs */
0236         }
0237         request.message_id = MSG_STREAM_ADD_INPUT_GROUP;
0238         stream_count = MIXART_PLAYBACK_STREAMS;
0239     }
0240 
0241     /* a new stream is opened and there are already all streams in use */
0242     if( (monitoring == 0) && (pipe->references >= stream_count) ) {
0243         return NULL;
0244     }
0245 
0246     /* pipe is not yet defined */
0247     if( pipe->status == PIPE_UNDEFINED ) {
0248         int err, i;
0249         struct {
0250             struct mixart_streaming_group_req sgroup_req;
0251             struct mixart_streaming_group sgroup_resp;
0252         } *buf;
0253 
0254         dev_dbg(chip->card->dev,
0255             "add_ref_pipe audio chip(%d) pcm(%d)\n",
0256             chip->chip_idx, pcm_number);
0257 
0258         buf = kmalloc(sizeof(*buf), GFP_KERNEL);
0259         if (!buf)
0260             return NULL;
0261 
0262         request.uid = (struct mixart_uid){0,0};      /* should be StreamManagerUID, but zero is OK if there is only one ! */
0263         request.data = &buf->sgroup_req;
0264         request.size = sizeof(buf->sgroup_req);
0265 
0266         memset(&buf->sgroup_req, 0, sizeof(buf->sgroup_req));
0267 
0268         buf->sgroup_req.stream_count = stream_count;
0269         buf->sgroup_req.channel_count = 2;
0270         buf->sgroup_req.latency = 256;
0271         buf->sgroup_req.connector = pipe->uid_left_connector;  /* the left connector */
0272 
0273         for (i=0; i<stream_count; i++) {
0274             int j;
0275             struct mixart_flowinfo *flowinfo;
0276             struct mixart_bufferinfo *bufferinfo;
0277             
0278             /* we don't yet know the format, so config 16 bit pcm audio for instance */
0279             buf->sgroup_req.stream_info[i].size_max_byte_frame = 1024;
0280             buf->sgroup_req.stream_info[i].size_max_sample_frame = 256;
0281             buf->sgroup_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */
0282 
0283             /* find the right bufferinfo_array */
0284             j = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (pcm_number * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS)) + i;
0285             if(capture) j += MIXART_PLAYBACK_STREAMS; /* in the array capture is behind playback */
0286 
0287             buf->sgroup_req.flow_entry[i] = j;
0288 
0289             flowinfo = (struct mixart_flowinfo *)chip->mgr->flowinfo.area;
0290             flowinfo[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo.addr + (j * sizeof(struct mixart_bufferinfo));
0291             flowinfo[j].bufferinfo_count = 1;               /* 1 will set the miXart to ring-buffer mode ! */
0292 
0293             bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area;
0294             bufferinfo[j].buffer_address = 0;               /* buffer is not yet allocated */
0295             bufferinfo[j].available_length = 0;             /* buffer is not yet allocated */
0296 
0297             /* construct the identifier of the stream buffer received in the interrupts ! */
0298             bufferinfo[j].buffer_id = (chip->chip_idx << MIXART_NOTIFY_CARD_OFFSET) + (pcm_number << MIXART_NOTIFY_PCM_OFFSET ) + i;
0299             if(capture) {
0300                 bufferinfo[j].buffer_id |= MIXART_NOTIFY_CAPT_MASK;
0301             }
0302         }
0303 
0304         err = snd_mixart_send_msg(chip->mgr, &request, sizeof(buf->sgroup_resp), &buf->sgroup_resp);
0305         if((err < 0) || (buf->sgroup_resp.status != 0)) {
0306             dev_err(chip->card->dev,
0307                 "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n",
0308                 err, buf->sgroup_resp.status);
0309             kfree(buf);
0310             return NULL;
0311         }
0312 
0313         pipe->group_uid = buf->sgroup_resp.group;     /* id of the pipe, as returned by embedded */
0314         pipe->stream_count = buf->sgroup_resp.stream_count;
0315         /* pipe->stream_uid[i] = buf->sgroup_resp.stream[i].stream_uid; */
0316 
0317         pipe->status = PIPE_STOPPED;
0318         kfree(buf);
0319     }
0320 
0321     if(monitoring)  pipe->monitoring = 1;
0322     else        pipe->references++;
0323 
0324     return pipe;
0325 }
0326 
0327 
0328 int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr,
0329                  struct mixart_pipe *pipe, int monitoring)
0330 {
0331     int err = 0;
0332 
0333     if(pipe->status == PIPE_UNDEFINED)
0334         return 0;
0335 
0336     if(monitoring)
0337         pipe->monitoring = 0;
0338     else
0339         pipe->references--;
0340 
0341     if((pipe->references <= 0) && (pipe->monitoring == 0)) {
0342 
0343         struct mixart_msg request;
0344         struct mixart_delete_group_resp delete_resp;
0345 
0346         /* release the clock */
0347         err = mixart_set_clock( mgr, pipe, 0);
0348         if( err < 0 ) {
0349             dev_err(&mgr->pci->dev,
0350                 "mixart_set_clock(0) return error!\n");
0351         }
0352 
0353         /* stop the pipe */
0354         err = mixart_set_pipe_state(mgr, pipe, 0);
0355         if( err < 0 ) {
0356             dev_err(&mgr->pci->dev, "error stopping pipe!\n");
0357         }
0358 
0359         request.message_id = MSG_STREAM_DELETE_GROUP;
0360         request.uid = (struct mixart_uid){0,0};
0361         request.data = &pipe->group_uid;            /* the streaming group ! */
0362         request.size = sizeof(pipe->group_uid);
0363 
0364         /* delete the pipe */
0365         err = snd_mixart_send_msg(mgr, &request, sizeof(delete_resp), &delete_resp);
0366         if ((err < 0) || (delete_resp.status != 0)) {
0367             dev_err(&mgr->pci->dev,
0368                 "error MSG_STREAM_DELETE_GROUP err(%x), status(%x)\n",
0369                 err, delete_resp.status);
0370         }
0371 
0372         pipe->group_uid = (struct mixart_uid){0,0};
0373         pipe->stream_count = 0;
0374         pipe->status = PIPE_UNDEFINED;
0375     }
0376 
0377     return err;
0378 }
0379 
0380 static int mixart_set_stream_state(struct mixart_stream *stream, int start)
0381 {
0382     struct snd_mixart *chip;
0383     struct mixart_stream_state_req stream_state_req;
0384     struct mixart_msg request;
0385 
0386     if(!stream->substream)
0387         return -EINVAL;
0388 
0389     memset(&stream_state_req, 0, sizeof(stream_state_req));
0390     stream_state_req.stream_count = 1;
0391     stream_state_req.stream_info.stream_desc.uid_pipe = stream->pipe->group_uid;
0392     stream_state_req.stream_info.stream_desc.stream_idx = stream->substream->number;
0393 
0394     if (stream->substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0395         request.message_id = start ? MSG_STREAM_START_INPUT_STAGE_PACKET : MSG_STREAM_STOP_INPUT_STAGE_PACKET;
0396     else
0397         request.message_id = start ? MSG_STREAM_START_OUTPUT_STAGE_PACKET : MSG_STREAM_STOP_OUTPUT_STAGE_PACKET;
0398 
0399     request.uid = (struct mixart_uid){0,0};
0400     request.data = &stream_state_req;
0401     request.size = sizeof(stream_state_req);
0402 
0403     stream->abs_period_elapsed = 0;            /* reset stream pos      */
0404     stream->buf_periods = 0;
0405     stream->buf_period_frag = 0;
0406 
0407     chip = snd_pcm_substream_chip(stream->substream);
0408 
0409     return snd_mixart_send_msg_nonblock(chip->mgr, &request);
0410 }
0411 
0412 /*
0413  *  Trigger callback
0414  */
0415 
0416 static int snd_mixart_trigger(struct snd_pcm_substream *subs, int cmd)
0417 {
0418     struct mixart_stream *stream = subs->runtime->private_data;
0419 
0420     switch (cmd) {
0421     case SNDRV_PCM_TRIGGER_START:
0422 
0423         dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_TRIGGER_START\n");
0424 
0425         /* START_STREAM */
0426         if( mixart_set_stream_state(stream, 1) )
0427             return -EINVAL;
0428 
0429         stream->status = MIXART_STREAM_STATUS_RUNNING;
0430 
0431         break;
0432     case SNDRV_PCM_TRIGGER_STOP:
0433 
0434         /* STOP_STREAM */
0435         if( mixart_set_stream_state(stream, 0) )
0436             return -EINVAL;
0437 
0438         stream->status = MIXART_STREAM_STATUS_OPEN;
0439 
0440         dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_TRIGGER_STOP\n");
0441 
0442         break;
0443 
0444     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0445         /* TODO */
0446         stream->status = MIXART_STREAM_STATUS_PAUSE;
0447         dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_PAUSE_PUSH\n");
0448         break;
0449     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0450         /* TODO */
0451         stream->status = MIXART_STREAM_STATUS_RUNNING;
0452         dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_PAUSE_RELEASE\n");
0453         break;
0454     default:
0455         return -EINVAL;
0456     }
0457     return 0;
0458 }
0459 
0460 static int mixart_sync_nonblock_events(struct mixart_mgr *mgr)
0461 {
0462     unsigned long timeout = jiffies + HZ;
0463     while (atomic_read(&mgr->msg_processed) > 0) {
0464         if (time_after(jiffies, timeout)) {
0465             dev_err(&mgr->pci->dev,
0466                 "mixart: cannot process nonblock events!\n");
0467             return -EBUSY;
0468         }
0469         schedule_timeout_uninterruptible(1);
0470     }
0471     return 0;
0472 }
0473 
0474 /*
0475  *  prepare callback for all pcms
0476  */
0477 static int snd_mixart_prepare(struct snd_pcm_substream *subs)
0478 {
0479     struct snd_mixart *chip = snd_pcm_substream_chip(subs);
0480     struct mixart_stream *stream = subs->runtime->private_data;
0481 
0482     /* TODO de façon non bloquante, réappliquer les hw_params (rate, bits, codec) */
0483 
0484     dev_dbg(chip->card->dev, "snd_mixart_prepare\n");
0485 
0486     mixart_sync_nonblock_events(chip->mgr);
0487 
0488     /* only the first stream can choose the sample rate */
0489     /* the further opened streams will be limited to its frequency (see open) */
0490     if(chip->mgr->ref_count_rate == 1)
0491         chip->mgr->sample_rate = subs->runtime->rate;
0492 
0493     /* set the clock only once (first stream) on the same pipe */
0494     if(stream->pipe->references == 1) {
0495         if( mixart_set_clock(chip->mgr, stream->pipe, subs->runtime->rate) )
0496             return -EINVAL;
0497     }
0498 
0499     return 0;
0500 }
0501 
0502 
0503 static int mixart_set_format(struct mixart_stream *stream, snd_pcm_format_t format)
0504 {
0505     int err;
0506     struct snd_mixart *chip;
0507     struct mixart_msg request;
0508     struct mixart_stream_param_desc stream_param;
0509     struct mixart_return_uid resp;
0510 
0511     chip = snd_pcm_substream_chip(stream->substream);
0512 
0513     memset(&stream_param, 0, sizeof(stream_param));
0514 
0515     stream_param.coding_type = CT_LINEAR;
0516     stream_param.number_of_channel = stream->channels;
0517 
0518     stream_param.sampling_freq = chip->mgr->sample_rate;
0519     if(stream_param.sampling_freq == 0)
0520         stream_param.sampling_freq = 44100; /* if frequency not yet defined, use some default */
0521 
0522     switch(format){
0523     case SNDRV_PCM_FORMAT_U8:
0524         stream_param.sample_type = ST_INTEGER_8;
0525         stream_param.sample_size = 8;
0526         break;
0527     case SNDRV_PCM_FORMAT_S16_LE:
0528         stream_param.sample_type = ST_INTEGER_16LE;
0529         stream_param.sample_size = 16;
0530         break;
0531     case SNDRV_PCM_FORMAT_S16_BE:
0532         stream_param.sample_type = ST_INTEGER_16BE;
0533         stream_param.sample_size = 16;
0534         break;
0535     case SNDRV_PCM_FORMAT_S24_3LE:
0536         stream_param.sample_type = ST_INTEGER_24LE;
0537         stream_param.sample_size = 24;
0538         break;
0539     case SNDRV_PCM_FORMAT_S24_3BE:
0540         stream_param.sample_type = ST_INTEGER_24BE;
0541         stream_param.sample_size = 24;
0542         break;
0543     case SNDRV_PCM_FORMAT_FLOAT_LE:
0544         stream_param.sample_type = ST_FLOATING_POINT_32LE;
0545         stream_param.sample_size = 32;
0546         break;
0547     case  SNDRV_PCM_FORMAT_FLOAT_BE:
0548         stream_param.sample_type = ST_FLOATING_POINT_32BE;
0549         stream_param.sample_size = 32;
0550         break;
0551     default:
0552         dev_err(chip->card->dev,
0553             "error mixart_set_format() : unknown format\n");
0554         return -EINVAL;
0555     }
0556 
0557     dev_dbg(chip->card->dev,
0558         "set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) channels(%d)\n",
0559            stream_param.sample_type, stream_param.sample_size, stream_param.sampling_freq, stream->channels);
0560 
0561     /* TODO: what else to configure ? */
0562     /* stream_param.samples_per_frame = 2; */
0563     /* stream_param.bytes_per_frame = 4; */
0564     /* stream_param.bytes_per_sample = 2; */
0565 
0566     stream_param.pipe_count = 1;      /* set to 1 */
0567     stream_param.stream_count = 1;    /* set to 1 */
0568     stream_param.stream_desc[0].uid_pipe = stream->pipe->group_uid;
0569     stream_param.stream_desc[0].stream_idx = stream->substream->number;
0570 
0571     request.message_id = MSG_STREAM_SET_INPUT_STAGE_PARAM;
0572     request.uid = (struct mixart_uid){0,0};
0573     request.data = &stream_param;
0574     request.size = sizeof(stream_param);
0575 
0576     err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp);
0577     if((err < 0) || resp.error_code) {
0578         dev_err(chip->card->dev,
0579             "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; resp=%x\n",
0580             err, resp.error_code);
0581         return -EINVAL;
0582     }
0583     return 0;
0584 }
0585 
0586 
0587 /*
0588  *  HW_PARAMS callback for all pcms
0589  */
0590 static int snd_mixart_hw_params(struct snd_pcm_substream *subs,
0591                                 struct snd_pcm_hw_params *hw)
0592 {
0593     struct snd_mixart *chip = snd_pcm_substream_chip(subs);
0594     struct mixart_mgr *mgr = chip->mgr;
0595     struct mixart_stream *stream = subs->runtime->private_data;
0596     snd_pcm_format_t format;
0597     int err;
0598     int channels;
0599 
0600     /* set up channels */
0601     channels = params_channels(hw);
0602 
0603     /*  set up format for the stream */
0604     format = params_format(hw);
0605 
0606     mutex_lock(&mgr->setup_mutex);
0607 
0608     /* update the stream levels */
0609     if( stream->pcm_number <= MIXART_PCM_DIGITAL ) {
0610         int is_aes = stream->pcm_number > MIXART_PCM_ANALOG;
0611         if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK )
0612             mixart_update_playback_stream_level(chip, is_aes, subs->number);
0613         else
0614             mixart_update_capture_stream_level( chip, is_aes);
0615     }
0616 
0617     stream->channels = channels;
0618 
0619     /* set the format to the board */
0620     err = mixart_set_format(stream, format);
0621     if(err < 0) {
0622         mutex_unlock(&mgr->setup_mutex);
0623         return err;
0624     }
0625 
0626     if (subs->runtime->buffer_changed) {
0627         struct mixart_bufferinfo *bufferinfo;
0628         int i = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (stream->pcm_number * (MIXART_PLAYBACK_STREAMS+MIXART_CAPTURE_STREAMS)) + subs->number;
0629         if( subs->stream == SNDRV_PCM_STREAM_CAPTURE ) {
0630             i += MIXART_PLAYBACK_STREAMS; /* in array capture is behind playback */
0631         }
0632         
0633         bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area;
0634         bufferinfo[i].buffer_address = subs->runtime->dma_addr;
0635         bufferinfo[i].available_length = subs->runtime->dma_bytes;
0636         /* bufferinfo[i].buffer_id  is already defined */
0637 
0638         dev_dbg(chip->card->dev,
0639             "snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n",
0640             i, bufferinfo[i].buffer_address,
0641                 bufferinfo[i].available_length,
0642                 subs->number);
0643     }
0644     mutex_unlock(&mgr->setup_mutex);
0645 
0646     return 0;
0647 }
0648 
0649 static int snd_mixart_hw_free(struct snd_pcm_substream *subs)
0650 {
0651     struct snd_mixart *chip = snd_pcm_substream_chip(subs);
0652     mixart_sync_nonblock_events(chip->mgr);
0653     return 0;
0654 }
0655 
0656 
0657 
0658 /*
0659  *  TODO CONFIGURATION SPACE for all pcms, mono pcm must update channels_max
0660  */
0661 static const struct snd_pcm_hardware snd_mixart_analog_caps =
0662 {
0663     .info             = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
0664                   SNDRV_PCM_INFO_MMAP_VALID |
0665                   SNDRV_PCM_INFO_PAUSE),
0666     .formats      = ( SNDRV_PCM_FMTBIT_U8 |
0667                   SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
0668                   SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
0669                   SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),
0670     .rates            = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
0671     .rate_min         = 8000,
0672     .rate_max         = 48000,
0673     .channels_min     = 1,
0674     .channels_max     = 2,
0675     .buffer_bytes_max = (32*1024),
0676     .period_bytes_min = 256,                  /* 256 frames U8 mono*/
0677     .period_bytes_max = (16*1024),
0678     .periods_min      = 2,
0679     .periods_max      = (32*1024/256),
0680 };
0681 
0682 static const struct snd_pcm_hardware snd_mixart_digital_caps =
0683 {
0684     .info             = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
0685                   SNDRV_PCM_INFO_MMAP_VALID |
0686                   SNDRV_PCM_INFO_PAUSE),
0687     .formats      = ( SNDRV_PCM_FMTBIT_U8 |
0688                   SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
0689                   SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
0690                   SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),
0691     .rates            = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
0692     .rate_min         = 32000,
0693     .rate_max         = 48000,
0694     .channels_min     = 1,
0695     .channels_max     = 2,
0696     .buffer_bytes_max = (32*1024),
0697     .period_bytes_min = 256,                  /* 256 frames U8 mono*/
0698     .period_bytes_max = (16*1024),
0699     .periods_min      = 2,
0700     .periods_max      = (32*1024/256),
0701 };
0702 
0703 
0704 static int snd_mixart_playback_open(struct snd_pcm_substream *subs)
0705 {
0706     struct snd_mixart            *chip = snd_pcm_substream_chip(subs);
0707     struct mixart_mgr        *mgr = chip->mgr;
0708     struct snd_pcm_runtime *runtime = subs->runtime;
0709     struct snd_pcm *pcm = subs->pcm;
0710     struct mixart_stream     *stream;
0711     struct mixart_pipe       *pipe;
0712     int err = 0;
0713     int pcm_number;
0714 
0715     mutex_lock(&mgr->setup_mutex);
0716 
0717     if ( pcm == chip->pcm ) {
0718         pcm_number = MIXART_PCM_ANALOG;
0719         runtime->hw = snd_mixart_analog_caps;
0720     } else {
0721         snd_BUG_ON(pcm != chip->pcm_dig);
0722         pcm_number = MIXART_PCM_DIGITAL;
0723         runtime->hw = snd_mixart_digital_caps;
0724     }
0725     dev_dbg(chip->card->dev,
0726         "snd_mixart_playback_open C%d/P%d/Sub%d\n",
0727         chip->chip_idx, pcm_number, subs->number);
0728 
0729     /* get stream info */
0730     stream = &(chip->playback_stream[pcm_number][subs->number]);
0731 
0732     if (stream->status != MIXART_STREAM_STATUS_FREE){
0733         /* streams in use */
0734         dev_err(chip->card->dev,
0735             "snd_mixart_playback_open C%d/P%d/Sub%d in use\n",
0736             chip->chip_idx, pcm_number, subs->number);
0737         err = -EBUSY;
0738         goto _exit_open;
0739     }
0740 
0741     /* get pipe pointer (out pipe) */
0742     pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 0, 0);
0743 
0744     if (pipe == NULL) {
0745         err = -EINVAL;
0746         goto _exit_open;
0747     }
0748 
0749     /* start the pipe if necessary */
0750     err = mixart_set_pipe_state(chip->mgr, pipe, 1);
0751     if( err < 0 ) {
0752         dev_err(chip->card->dev, "error starting pipe!\n");
0753         snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);
0754         err = -EINVAL;
0755         goto _exit_open;
0756     }
0757 
0758     stream->pipe        = pipe;
0759     stream->pcm_number  = pcm_number;
0760     stream->status      = MIXART_STREAM_STATUS_OPEN;
0761     stream->substream   = subs;
0762     stream->channels    = 0; /* not configured yet */
0763 
0764     runtime->private_data = stream;
0765 
0766     snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
0767     snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);
0768 
0769     /* if a sample rate is already used, another stream cannot change */
0770     if(mgr->ref_count_rate++) {
0771         if(mgr->sample_rate) {
0772             runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
0773         }
0774     }
0775 
0776  _exit_open:
0777     mutex_unlock(&mgr->setup_mutex);
0778 
0779     return err;
0780 }
0781 
0782 
0783 static int snd_mixart_capture_open(struct snd_pcm_substream *subs)
0784 {
0785     struct snd_mixart            *chip = snd_pcm_substream_chip(subs);
0786     struct mixart_mgr        *mgr = chip->mgr;
0787     struct snd_pcm_runtime *runtime = subs->runtime;
0788     struct snd_pcm *pcm = subs->pcm;
0789     struct mixart_stream     *stream;
0790     struct mixart_pipe       *pipe;
0791     int err = 0;
0792     int pcm_number;
0793 
0794     mutex_lock(&mgr->setup_mutex);
0795 
0796     if ( pcm == chip->pcm ) {
0797         pcm_number = MIXART_PCM_ANALOG;
0798         runtime->hw = snd_mixart_analog_caps;
0799     } else {
0800         snd_BUG_ON(pcm != chip->pcm_dig);
0801         pcm_number = MIXART_PCM_DIGITAL;
0802         runtime->hw = snd_mixart_digital_caps;
0803     }
0804 
0805     runtime->hw.channels_min = 2; /* for instance, no mono */
0806 
0807     dev_dbg(chip->card->dev, "snd_mixart_capture_open C%d/P%d/Sub%d\n",
0808         chip->chip_idx, pcm_number, subs->number);
0809 
0810     /* get stream info */
0811     stream = &(chip->capture_stream[pcm_number]);
0812 
0813     if (stream->status != MIXART_STREAM_STATUS_FREE){
0814         /* streams in use */
0815         dev_err(chip->card->dev,
0816             "snd_mixart_capture_open C%d/P%d/Sub%d in use\n",
0817             chip->chip_idx, pcm_number, subs->number);
0818         err = -EBUSY;
0819         goto _exit_open;
0820     }
0821 
0822     /* get pipe pointer (in pipe) */
0823     pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 1, 0);
0824 
0825     if (pipe == NULL) {
0826         err = -EINVAL;
0827         goto _exit_open;
0828     }
0829 
0830     /* start the pipe if necessary */
0831     err = mixart_set_pipe_state(chip->mgr, pipe, 1);
0832     if( err < 0 ) {
0833         dev_err(chip->card->dev, "error starting pipe!\n");
0834         snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);
0835         err = -EINVAL;
0836         goto _exit_open;
0837     }
0838 
0839     stream->pipe        = pipe;
0840     stream->pcm_number  = pcm_number;
0841     stream->status      = MIXART_STREAM_STATUS_OPEN;
0842     stream->substream   = subs;
0843     stream->channels    = 0; /* not configured yet */
0844 
0845     runtime->private_data = stream;
0846 
0847     snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
0848     snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);
0849 
0850     /* if a sample rate is already used, another stream cannot change */
0851     if(mgr->ref_count_rate++) {
0852         if(mgr->sample_rate) {
0853             runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
0854         }
0855     }
0856 
0857  _exit_open:
0858     mutex_unlock(&mgr->setup_mutex);
0859 
0860     return err;
0861 }
0862 
0863 
0864 
0865 static int snd_mixart_close(struct snd_pcm_substream *subs)
0866 {
0867     struct snd_mixart *chip = snd_pcm_substream_chip(subs);
0868     struct mixart_mgr *mgr = chip->mgr;
0869     struct mixart_stream *stream = subs->runtime->private_data;
0870 
0871     mutex_lock(&mgr->setup_mutex);
0872 
0873     dev_dbg(chip->card->dev, "snd_mixart_close C%d/P%d/Sub%d\n",
0874         chip->chip_idx, stream->pcm_number, subs->number);
0875 
0876     /* sample rate released */
0877     if(--mgr->ref_count_rate == 0) {
0878         mgr->sample_rate = 0;
0879     }
0880 
0881     /* delete pipe */
0882     if (snd_mixart_kill_ref_pipe(mgr, stream->pipe, 0 ) < 0) {
0883 
0884         dev_err(chip->card->dev,
0885             "error snd_mixart_kill_ref_pipe C%dP%d\n",
0886             chip->chip_idx, stream->pcm_number);
0887     }
0888 
0889     stream->pipe      = NULL;
0890     stream->status    = MIXART_STREAM_STATUS_FREE;
0891     stream->substream = NULL;
0892 
0893     mutex_unlock(&mgr->setup_mutex);
0894     return 0;
0895 }
0896 
0897 
0898 static snd_pcm_uframes_t snd_mixart_stream_pointer(struct snd_pcm_substream *subs)
0899 {
0900     struct snd_pcm_runtime *runtime = subs->runtime;
0901     struct mixart_stream   *stream  = runtime->private_data;
0902 
0903     return (snd_pcm_uframes_t)((stream->buf_periods * runtime->period_size) + stream->buf_period_frag);
0904 }
0905 
0906 
0907 
0908 static const struct snd_pcm_ops snd_mixart_playback_ops = {
0909     .open      = snd_mixart_playback_open,
0910     .close     = snd_mixart_close,
0911     .prepare   = snd_mixart_prepare,
0912     .hw_params = snd_mixart_hw_params,
0913     .hw_free   = snd_mixart_hw_free,
0914     .trigger   = snd_mixart_trigger,
0915     .pointer   = snd_mixart_stream_pointer,
0916 };
0917 
0918 static const struct snd_pcm_ops snd_mixart_capture_ops = {
0919     .open      = snd_mixart_capture_open,
0920     .close     = snd_mixart_close,
0921     .prepare   = snd_mixart_prepare,
0922     .hw_params = snd_mixart_hw_params,
0923     .hw_free   = snd_mixart_hw_free,
0924     .trigger   = snd_mixart_trigger,
0925     .pointer   = snd_mixart_stream_pointer,
0926 };
0927 
0928 static void preallocate_buffers(struct snd_mixart *chip, struct snd_pcm *pcm)
0929 {
0930 #if 0
0931     struct snd_pcm_substream *subs;
0932     int stream;
0933 
0934     for (stream = 0; stream < 2; stream++) {
0935         int idx = 0;
0936         for (subs = pcm->streams[stream].substream; subs; subs = subs->next, idx++)
0937             /* set up the unique device id with the chip index */
0938             subs->dma_device.id = subs->pcm->device << 16 |
0939                 subs->stream << 8 | (subs->number + 1) |
0940                 (chip->chip_idx + 1) << 24;
0941     }
0942 #endif
0943     snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
0944                        &chip->mgr->pci->dev,
0945                        32*1024, 32*1024);
0946 }
0947 
0948 /*
0949  */
0950 static int snd_mixart_pcm_analog(struct snd_mixart *chip)
0951 {
0952     int err;
0953     struct snd_pcm *pcm;
0954     char name[32];
0955 
0956     sprintf(name, "miXart analog %d", chip->chip_idx);
0957     err = snd_pcm_new(chip->card, name, MIXART_PCM_ANALOG,
0958               MIXART_PLAYBACK_STREAMS,
0959               MIXART_CAPTURE_STREAMS, &pcm);
0960     if (err < 0) {
0961         dev_err(chip->card->dev,
0962             "cannot create the analog pcm %d\n", chip->chip_idx);
0963         return err;
0964     }
0965 
0966     pcm->private_data = chip;
0967 
0968     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
0969     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
0970 
0971     pcm->info_flags = 0;
0972     pcm->nonatomic = true;
0973     strcpy(pcm->name, name);
0974 
0975     preallocate_buffers(chip, pcm);
0976 
0977     chip->pcm = pcm;
0978     return 0;
0979 }
0980 
0981 
0982 /*
0983  */
0984 static int snd_mixart_pcm_digital(struct snd_mixart *chip)
0985 {
0986     int err;
0987     struct snd_pcm *pcm;
0988     char name[32];
0989 
0990     sprintf(name, "miXart AES/EBU %d", chip->chip_idx);
0991     err = snd_pcm_new(chip->card, name, MIXART_PCM_DIGITAL,
0992               MIXART_PLAYBACK_STREAMS,
0993               MIXART_CAPTURE_STREAMS, &pcm);
0994     if (err < 0) {
0995         dev_err(chip->card->dev,
0996             "cannot create the digital pcm %d\n", chip->chip_idx);
0997         return err;
0998     }
0999 
1000     pcm->private_data = chip;
1001 
1002     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
1003     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
1004 
1005     pcm->info_flags = 0;
1006     pcm->nonatomic = true;
1007     strcpy(pcm->name, name);
1008 
1009     preallocate_buffers(chip, pcm);
1010 
1011     chip->pcm_dig = pcm;
1012     return 0;
1013 }
1014 
1015 static int snd_mixart_chip_free(struct snd_mixart *chip)
1016 {
1017     kfree(chip);
1018     return 0;
1019 }
1020 
1021 static int snd_mixart_chip_dev_free(struct snd_device *device)
1022 {
1023     struct snd_mixart *chip = device->device_data;
1024     return snd_mixart_chip_free(chip);
1025 }
1026 
1027 
1028 /*
1029  */
1030 static int snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx)
1031 {
1032     int err;
1033     struct snd_mixart *chip;
1034     static const struct snd_device_ops ops = {
1035         .dev_free = snd_mixart_chip_dev_free,
1036     };
1037 
1038     chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1039     if (!chip)
1040         return -ENOMEM;
1041 
1042     chip->card = card;
1043     chip->chip_idx = idx;
1044     chip->mgr = mgr;
1045     card->sync_irq = mgr->irq;
1046 
1047     err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
1048     if (err < 0) {
1049         snd_mixart_chip_free(chip);
1050         return err;
1051     }
1052 
1053     mgr->chip[idx] = chip;
1054     return 0;
1055 }
1056 
1057 int snd_mixart_create_pcm(struct snd_mixart* chip)
1058 {
1059     int err;
1060 
1061     err = snd_mixart_pcm_analog(chip);
1062     if (err < 0)
1063         return err;
1064 
1065     if(chip->mgr->board_type == MIXART_DAUGHTER_TYPE_AES) {
1066 
1067         err = snd_mixart_pcm_digital(chip);
1068         if (err < 0)
1069             return err;
1070     }
1071     return err;
1072 }
1073 
1074 
1075 /*
1076  * release all the cards assigned to a manager instance
1077  */
1078 static int snd_mixart_free(struct mixart_mgr *mgr)
1079 {
1080     unsigned int i;
1081 
1082     for (i = 0; i < mgr->num_cards; i++) {
1083         if (mgr->chip[i])
1084             snd_card_free(mgr->chip[i]->card);
1085     }
1086 
1087     /* stop mailbox */
1088     snd_mixart_exit_mailbox(mgr);
1089 
1090     /* release irq  */
1091     if (mgr->irq >= 0)
1092         free_irq(mgr->irq, mgr);
1093 
1094     /* reset board if some firmware was loaded */
1095     if(mgr->dsp_loaded) {
1096         snd_mixart_reset_board(mgr);
1097         dev_dbg(&mgr->pci->dev, "reset miXart !\n");
1098     }
1099 
1100     /* release the i/o ports */
1101     for (i = 0; i < 2; ++i)
1102         iounmap(mgr->mem[i].virt);
1103 
1104     pci_release_regions(mgr->pci);
1105 
1106     /* free flowarray */
1107     if(mgr->flowinfo.area) {
1108         snd_dma_free_pages(&mgr->flowinfo);
1109         mgr->flowinfo.area = NULL;
1110     }
1111     /* free bufferarray */
1112     if(mgr->bufferinfo.area) {
1113         snd_dma_free_pages(&mgr->bufferinfo);
1114         mgr->bufferinfo.area = NULL;
1115     }
1116 
1117     pci_disable_device(mgr->pci);
1118     kfree(mgr);
1119     return 0;
1120 }
1121 
1122 /*
1123  * proc interface
1124  */
1125 
1126 /*
1127   mixart_BA0 proc interface for BAR 0 - read callback
1128  */
1129 static ssize_t snd_mixart_BA0_read(struct snd_info_entry *entry,
1130                    void *file_private_data,
1131                    struct file *file, char __user *buf,
1132                    size_t count, loff_t pos)
1133 {
1134     struct mixart_mgr *mgr = entry->private_data;
1135 
1136     count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
1137     if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count))
1138         return -EFAULT;
1139     return count;
1140 }
1141 
1142 /*
1143   mixart_BA1 proc interface for BAR 1 - read callback
1144  */
1145 static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry,
1146                    void *file_private_data,
1147                    struct file *file, char __user *buf,
1148                    size_t count, loff_t pos)
1149 {
1150     struct mixart_mgr *mgr = entry->private_data;
1151 
1152     count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
1153     if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count))
1154         return -EFAULT;
1155     return count;
1156 }
1157 
1158 static const struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = {
1159     .read   = snd_mixart_BA0_read,
1160 };
1161 
1162 static const struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {
1163     .read   = snd_mixart_BA1_read,
1164 };
1165 
1166 
1167 static void snd_mixart_proc_read(struct snd_info_entry *entry, 
1168                                  struct snd_info_buffer *buffer)
1169 {
1170     struct snd_mixart *chip = entry->private_data;        
1171     u32 ref; 
1172 
1173     snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx);
1174 
1175     /* stats available when embedded OS is running */
1176     if (chip->mgr->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) {
1177         snd_iprintf(buffer, "- hardware -\n");
1178         switch (chip->mgr->board_type ) {
1179         case MIXART_DAUGHTER_TYPE_NONE     : snd_iprintf(buffer, "\tmiXart8 (no daughter board)\n\n"); break;
1180         case MIXART_DAUGHTER_TYPE_AES      : snd_iprintf(buffer, "\tmiXart8 AES/EBU\n\n"); break;
1181         case MIXART_DAUGHTER_TYPE_COBRANET : snd_iprintf(buffer, "\tmiXart8 Cobranet\n\n"); break;
1182         default:                             snd_iprintf(buffer, "\tUNKNOWN!\n\n"); break;
1183         }
1184 
1185         snd_iprintf(buffer, "- system load -\n");    
1186 
1187         /* get perf reference */
1188 
1189         ref = readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_SYSTEM_LOAD_OFFSET));
1190 
1191         if (ref) {
1192             u32 mailbox   = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_MAILBX_LOAD_OFFSET)) / ref;
1193             u32 streaming = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_STREAM_LOAD_OFFSET)) / ref;
1194             u32 interr    = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_INTERR_LOAD_OFFSET)) / ref;
1195 
1196             snd_iprintf(buffer, "\tstreaming          : %d\n", streaming);
1197             snd_iprintf(buffer, "\tmailbox            : %d\n", mailbox);
1198             snd_iprintf(buffer, "\tinterrupts handling : %d\n\n", interr);
1199         }
1200     } /* endif elf loaded */
1201 }
1202 
1203 static void snd_mixart_proc_init(struct snd_mixart *chip)
1204 {
1205     struct snd_info_entry *entry;
1206 
1207     /* text interface to read perf and temp meters */
1208     snd_card_ro_proc_new(chip->card, "board_info", chip,
1209                  snd_mixart_proc_read);
1210 
1211     if (! snd_card_proc_new(chip->card, "mixart_BA0", &entry)) {
1212         entry->content = SNDRV_INFO_CONTENT_DATA;
1213         entry->private_data = chip->mgr;    
1214         entry->c.ops = &snd_mixart_proc_ops_BA0;
1215         entry->size = MIXART_BA0_SIZE;
1216     }
1217     if (! snd_card_proc_new(chip->card, "mixart_BA1", &entry)) {
1218         entry->content = SNDRV_INFO_CONTENT_DATA;
1219         entry->private_data = chip->mgr;
1220         entry->c.ops = &snd_mixart_proc_ops_BA1;
1221         entry->size = MIXART_BA1_SIZE;
1222     }
1223 }
1224 /* end of proc interface */
1225 
1226 
1227 /*
1228  *    probe function - creates the card manager
1229  */
1230 static int snd_mixart_probe(struct pci_dev *pci,
1231                 const struct pci_device_id *pci_id)
1232 {
1233     static int dev;
1234     struct mixart_mgr *mgr;
1235     unsigned int i;
1236     int err;
1237     size_t size;
1238 
1239     /*
1240      */
1241     if (dev >= SNDRV_CARDS)
1242         return -ENODEV;
1243     if (! enable[dev]) {
1244         dev++;
1245         return -ENOENT;
1246     }
1247 
1248     /* enable PCI device */
1249     err = pci_enable_device(pci);
1250     if (err < 0)
1251         return err;
1252     pci_set_master(pci);
1253 
1254     /* check if we can restrict PCI DMA transfers to 32 bits */
1255     if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
1256         dev_err(&pci->dev,
1257             "architecture does not support 32bit PCI busmaster DMA\n");
1258         pci_disable_device(pci);
1259         return -ENXIO;
1260     }
1261 
1262     /*
1263      */
1264     mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1265     if (! mgr) {
1266         pci_disable_device(pci);
1267         return -ENOMEM;
1268     }
1269 
1270     mgr->pci = pci;
1271     mgr->irq = -1;
1272 
1273     /* resource assignment */
1274     err = pci_request_regions(pci, CARD_NAME);
1275     if (err < 0) {
1276         kfree(mgr);
1277         pci_disable_device(pci);
1278         return err;
1279     }
1280     for (i = 0; i < 2; i++) {
1281         mgr->mem[i].phys = pci_resource_start(pci, i);
1282         mgr->mem[i].virt = pci_ioremap_bar(pci, i);
1283         if (!mgr->mem[i].virt) {
1284             dev_err(&pci->dev, "unable to remap resource 0x%lx\n",
1285                    mgr->mem[i].phys);
1286             snd_mixart_free(mgr);
1287             return -EBUSY;
1288         }
1289     }
1290 
1291     if (request_threaded_irq(pci->irq, snd_mixart_interrupt,
1292                  snd_mixart_threaded_irq, IRQF_SHARED,
1293                  KBUILD_MODNAME, mgr)) {
1294         dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq);
1295         snd_mixart_free(mgr);
1296         return -EBUSY;
1297     }
1298     mgr->irq = pci->irq;
1299 
1300     /* init mailbox  */
1301     mgr->msg_fifo_readptr = 0;
1302     mgr->msg_fifo_writeptr = 0;
1303 
1304     mutex_init(&mgr->lock);
1305     mutex_init(&mgr->msg_lock);
1306     init_waitqueue_head(&mgr->msg_sleep);
1307     atomic_set(&mgr->msg_processed, 0);
1308 
1309     /* init setup mutex*/
1310     mutex_init(&mgr->setup_mutex);
1311 
1312     /* card assignment */
1313     mgr->num_cards = MIXART_MAX_CARDS; /* 4  FIXME: configurable? */
1314     for (i = 0; i < mgr->num_cards; i++) {
1315         struct snd_card *card;
1316         char tmpid[16];
1317         int idx;
1318 
1319         if (index[dev] < 0)
1320             idx = index[dev];
1321         else
1322             idx = index[dev] + i;
1323         snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i);
1324         err = snd_card_new(&pci->dev, idx, tmpid, THIS_MODULE,
1325                    0, &card);
1326 
1327         if (err < 0) {
1328             dev_err(&pci->dev, "cannot allocate the card %d\n", i);
1329             snd_mixart_free(mgr);
1330             return err;
1331         }
1332 
1333         strcpy(card->driver, CARD_NAME);
1334         snprintf(card->shortname, sizeof(card->shortname),
1335              "Digigram miXart [PCM #%d]", i);
1336         snprintf(card->longname, sizeof(card->longname),
1337             "Digigram miXart at 0x%lx & 0x%lx, irq %i [PCM #%d]",
1338             mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq, i);
1339 
1340         err = snd_mixart_create(mgr, card, i);
1341         if (err < 0) {
1342             snd_card_free(card);
1343             snd_mixart_free(mgr);
1344             return err;
1345         }
1346 
1347         if(i==0) {
1348             /* init proc interface only for chip0 */
1349             snd_mixart_proc_init(mgr->chip[i]);
1350         }
1351 
1352         err = snd_card_register(card);
1353         if (err < 0) {
1354             snd_mixart_free(mgr);
1355             return err;
1356         }
1357     }
1358 
1359     /* init firmware status (mgr->dsp_loaded reset in hwdep_new) */
1360     mgr->board_type = MIXART_DAUGHTER_TYPE_NONE;
1361 
1362     /* create array of streaminfo */
1363     size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS *
1364                 sizeof(struct mixart_flowinfo)) );
1365     if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
1366                 size, &mgr->flowinfo) < 0) {
1367         snd_mixart_free(mgr);
1368         return -ENOMEM;
1369     }
1370     /* init streaminfo_array */
1371     memset(mgr->flowinfo.area, 0, size);
1372 
1373     /* create array of bufferinfo */
1374     size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS *
1375                 sizeof(struct mixart_bufferinfo)) );
1376     if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
1377                 size, &mgr->bufferinfo) < 0) {
1378         snd_mixart_free(mgr);
1379         return -ENOMEM;
1380     }
1381     /* init bufferinfo_array */
1382     memset(mgr->bufferinfo.area, 0, size);
1383 
1384     /* set up firmware */
1385     err = snd_mixart_setup_firmware(mgr);
1386     if (err < 0) {
1387         snd_mixart_free(mgr);
1388         return err;
1389     }
1390 
1391     pci_set_drvdata(pci, mgr);
1392     dev++;
1393     return 0;
1394 }
1395 
1396 static void snd_mixart_remove(struct pci_dev *pci)
1397 {
1398     snd_mixart_free(pci_get_drvdata(pci));
1399 }
1400 
1401 static struct pci_driver mixart_driver = {
1402     .name = KBUILD_MODNAME,
1403     .id_table = snd_mixart_ids,
1404     .probe = snd_mixart_probe,
1405     .remove = snd_mixart_remove,
1406 };
1407 
1408 module_pci_driver(mixart_driver);