linux/sound/pci/mixart/mixart.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Driver for Digigram miXart soundcards
   4 *
   5 * main file with alsa callbacks
   6 *
   7 * Copyright (c) 2003 by Digigram <alsa@digigram.com>
   8 */
   9
  10
  11#include <linux/init.h>
  12#include <linux/interrupt.h>
  13#include <linux/pci.h>
  14#include <linux/dma-mapping.h>
  15#include <linux/module.h>
  16#include <linux/mutex.h>
  17#include <linux/slab.h>
  18
  19#include <sound/core.h>
  20#include <sound/initval.h>
  21#include <sound/info.h>
  22#include <sound/control.h>
  23#include <sound/pcm.h>
  24#include <sound/pcm_params.h>
  25#include "mixart.h"
  26#include "mixart_hwdep.h"
  27#include "mixart_core.h"
  28#include "mixart_mixer.h"
  29
  30#define CARD_NAME "miXart"
  31
  32MODULE_AUTHOR("Digigram <alsa@digigram.com>");
  33MODULE_DESCRIPTION("Digigram " CARD_NAME);
  34MODULE_LICENSE("GPL");
  35
  36static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;             /* Index 0-MAX */
  37static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;              /* ID for this card */
  38static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;     /* Enable this card */
  39
  40module_param_array(index, int, NULL, 0444);
  41MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard.");
  42module_param_array(id, charp, NULL, 0444);
  43MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard.");
  44module_param_array(enable, bool, NULL, 0444);
  45MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
  46
  47/*
  48 */
  49
  50static const struct pci_device_id snd_mixart_ids[] = {
  51        { PCI_VDEVICE(MOTOROLA, 0x0003), 0, }, /* MC8240 */
  52        { 0, }
  53};
  54
  55MODULE_DEVICE_TABLE(pci, snd_mixart_ids);
  56
  57
  58static int mixart_set_pipe_state(struct mixart_mgr *mgr,
  59                                 struct mixart_pipe *pipe, int start)
  60{
  61        struct mixart_group_state_req group_state;
  62        struct mixart_group_state_resp group_state_resp;
  63        struct mixart_msg request;
  64        int err;
  65        u32 system_msg_uid;
  66
  67        switch(pipe->status) {
  68        case PIPE_RUNNING:
  69        case PIPE_CLOCK_SET:
  70                if(start) return 0; /* already started */
  71                break;
  72        case PIPE_STOPPED:
  73                if(!start) return 0; /* already stopped */
  74                break;
  75        default:
  76                dev_err(&mgr->pci->dev,
  77                        "error mixart_set_pipe_state called with wrong pipe->status!\n");
  78                return -EINVAL;      /* function called with wrong pipe status */
  79        }
  80
  81        system_msg_uid = 0x12345678; /* the event ! (take care: the MSB and two LSB's have to be 0) */
  82
  83        /* wait on the last MSG_SYSTEM_SEND_SYNCHRO_CMD command to be really finished */
  84
  85        request.message_id = MSG_SYSTEM_WAIT_SYNCHRO_CMD;
  86        request.uid = (struct mixart_uid){0,0};
  87        request.data = &system_msg_uid;
  88        request.size = sizeof(system_msg_uid);
  89
  90        err = snd_mixart_send_msg_wait_notif(mgr, &request, system_msg_uid);
  91        if(err) {
  92                dev_err(&mgr->pci->dev,
  93                        "error : MSG_SYSTEM_WAIT_SYNCHRO_CMD was not notified !\n");
  94                return err;
  95        }
  96
  97        /* start or stop the pipe (1 pipe) */
  98
  99        memset(&group_state, 0, sizeof(group_state));
 100        group_state.pipe_count = 1;
 101        group_state.pipe_uid[0] = pipe->group_uid;
 102
 103        if(start)
 104                request.message_id = MSG_STREAM_START_STREAM_GRP_PACKET;
 105        else
 106                request.message_id = MSG_STREAM_STOP_STREAM_GRP_PACKET;
 107
 108        request.uid = pipe->group_uid; /*(struct mixart_uid){0,0};*/
 109        request.data = &group_state;
 110        request.size = sizeof(group_state);
 111
 112        err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp);
 113        if (err < 0 || group_state_resp.txx_status != 0) {
 114                dev_err(&mgr->pci->dev,
 115                        "error MSG_STREAM_ST***_STREAM_GRP_PACKET err=%x stat=%x !\n",
 116                        err, group_state_resp.txx_status);
 117                return -EINVAL;
 118        }
 119
 120        if(start) {
 121                u32 stat = 0;
 122
 123                group_state.pipe_count = 0; /* in case of start same command once again with pipe_count=0 */
 124
 125                err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp);
 126                if (err < 0 || group_state_resp.txx_status != 0) {
 127                        dev_err(&mgr->pci->dev,
 128                                "error MSG_STREAM_START_STREAM_GRP_PACKET err=%x stat=%x !\n",
 129                                err, group_state_resp.txx_status);
 130                        return -EINVAL;
 131                }
 132
 133                /* in case of start send a synchro top */
 134
 135                request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD;
 136                request.uid = (struct mixart_uid){0,0};
 137                request.data = NULL;
 138                request.size = 0;
 139
 140                err = snd_mixart_send_msg(mgr, &request, sizeof(stat), &stat);
 141                if (err < 0 || stat != 0) {
 142                        dev_err(&mgr->pci->dev,
 143                                "error MSG_SYSTEM_SEND_SYNCHRO_CMD err=%x stat=%x !\n",
 144                                err, stat);
 145                        return -EINVAL;
 146                }
 147
 148                pipe->status = PIPE_RUNNING;
 149        }
 150        else /* !start */
 151                pipe->status = PIPE_STOPPED;
 152
 153        return 0;
 154}
 155
 156
 157static int mixart_set_clock(struct mixart_mgr *mgr,
 158                            struct mixart_pipe *pipe, unsigned int rate)
 159{
 160        struct mixart_msg request;
 161        struct mixart_clock_properties clock_properties;
 162        struct mixart_clock_properties_resp clock_prop_resp;
 163        int err;
 164
 165        switch(pipe->status) {
 166        case PIPE_CLOCK_SET:
 167                break;
 168        case PIPE_RUNNING:
 169                if(rate != 0)
 170                        break;
 171                fallthrough;
 172        default:
 173                if(rate == 0)
 174                        return 0; /* nothing to do */
 175                else {
 176                        dev_err(&mgr->pci->dev,
 177                                "error mixart_set_clock(%d) called with wrong pipe->status !\n",
 178                                rate);
 179                        return -EINVAL;
 180                }
 181        }
 182
 183        memset(&clock_properties, 0, sizeof(clock_properties));
 184        clock_properties.clock_generic_type = (rate != 0) ? CGT_INTERNAL_CLOCK : CGT_NO_CLOCK;
 185        clock_properties.clock_mode = CM_STANDALONE;
 186        clock_properties.frequency = rate;
 187        clock_properties.nb_callers = 1; /* only one entry in uid_caller ! */
 188        clock_properties.uid_caller[0] = pipe->group_uid;
 189
 190        dev_dbg(&mgr->pci->dev, "mixart_set_clock to %d kHz\n", rate);
 191
 192        request.message_id = MSG_CLOCK_SET_PROPERTIES;
 193        request.uid = mgr->uid_console_manager;
 194        request.data = &clock_properties;
 195        request.size = sizeof(clock_properties);
 196
 197        err = snd_mixart_send_msg(mgr, &request, sizeof(clock_prop_resp), &clock_prop_resp);
 198        if (err < 0 || clock_prop_resp.status != 0 || clock_prop_resp.clock_mode != CM_STANDALONE) {
 199                dev_err(&mgr->pci->dev,
 200                        "error MSG_CLOCK_SET_PROPERTIES err=%x stat=%x mod=%x !\n",
 201                        err, clock_prop_resp.status, clock_prop_resp.clock_mode);
 202                return -EINVAL;
 203        }
 204
 205        if(rate)  pipe->status = PIPE_CLOCK_SET;
 206        else      pipe->status = PIPE_RUNNING;
 207
 208        return 0;
 209}
 210
 211
 212/*
 213 *  Allocate or reference output pipe for analog IOs (pcmp0/1)
 214 */
 215struct mixart_pipe *
 216snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture,
 217                        int monitoring)
 218{
 219        int stream_count;
 220        struct mixart_pipe *pipe;
 221        struct mixart_msg request;
 222
 223        if(capture) {
 224                if (pcm_number == MIXART_PCM_ANALOG) {
 225                        pipe = &(chip->pipe_in_ana);  /* analog inputs */
 226                } else {
 227                        pipe = &(chip->pipe_in_dig); /* digital inputs */
 228                }
 229                request.message_id = MSG_STREAM_ADD_OUTPUT_GROUP;
 230                stream_count = MIXART_CAPTURE_STREAMS;
 231        } else {
 232                if (pcm_number == MIXART_PCM_ANALOG) {
 233                        pipe = &(chip->pipe_out_ana);  /* analog outputs */
 234                } else {
 235                        pipe = &(chip->pipe_out_dig);  /* digital outputs */
 236                }
 237                request.message_id = MSG_STREAM_ADD_INPUT_GROUP;
 238                stream_count = MIXART_PLAYBACK_STREAMS;
 239        }
 240
 241        /* a new stream is opened and there are already all streams in use */
 242        if( (monitoring == 0) && (pipe->references >= stream_count) ) {
 243                return NULL;
 244        }
 245
 246        /* pipe is not yet defined */
 247        if( pipe->status == PIPE_UNDEFINED ) {
 248                int err, i;
 249                struct {
 250                        struct mixart_streaming_group_req sgroup_req;
 251                        struct mixart_streaming_group sgroup_resp;
 252                } *buf;
 253
 254                dev_dbg(chip->card->dev,
 255                        "add_ref_pipe audio chip(%d) pcm(%d)\n",
 256                        chip->chip_idx, pcm_number);
 257
 258                buf = kmalloc(sizeof(*buf), GFP_KERNEL);
 259                if (!buf)
 260                        return NULL;
 261
 262                request.uid = (struct mixart_uid){0,0};      /* should be StreamManagerUID, but zero is OK if there is only one ! */
 263                request.data = &buf->sgroup_req;
 264                request.size = sizeof(buf->sgroup_req);
 265
 266                memset(&buf->sgroup_req, 0, sizeof(buf->sgroup_req));
 267
 268                buf->sgroup_req.stream_count = stream_count;
 269                buf->sgroup_req.channel_count = 2;
 270                buf->sgroup_req.latency = 256;
 271                buf->sgroup_req.connector = pipe->uid_left_connector;  /* the left connector */
 272
 273                for (i=0; i<stream_count; i++) {
 274                        int j;
 275                        struct mixart_flowinfo *flowinfo;
 276                        struct mixart_bufferinfo *bufferinfo;
 277                        
 278                        /* we don't yet know the format, so config 16 bit pcm audio for instance */
 279                        buf->sgroup_req.stream_info[i].size_max_byte_frame = 1024;
 280                        buf->sgroup_req.stream_info[i].size_max_sample_frame = 256;
 281                        buf->sgroup_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */
 282
 283                        /* find the right bufferinfo_array */
 284                        j = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (pcm_number * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS)) + i;
 285                        if(capture) j += MIXART_PLAYBACK_STREAMS; /* in the array capture is behind playback */
 286
 287                        buf->sgroup_req.flow_entry[i] = j;
 288
 289                        flowinfo = (struct mixart_flowinfo *)chip->mgr->flowinfo.area;
 290                        flowinfo[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo.addr + (j * sizeof(struct mixart_bufferinfo));
 291                        flowinfo[j].bufferinfo_count = 1;               /* 1 will set the miXart to ring-buffer mode ! */
 292
 293                        bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area;
 294                        bufferinfo[j].buffer_address = 0;               /* buffer is not yet allocated */
 295                        bufferinfo[j].available_length = 0;             /* buffer is not yet allocated */
 296
 297                        /* construct the identifier of the stream buffer received in the interrupts ! */
 298                        bufferinfo[j].buffer_id = (chip->chip_idx << MIXART_NOTIFY_CARD_OFFSET) + (pcm_number << MIXART_NOTIFY_PCM_OFFSET ) + i;
 299                        if(capture) {
 300                                bufferinfo[j].buffer_id |= MIXART_NOTIFY_CAPT_MASK;
 301                        }
 302                }
 303
 304                err = snd_mixart_send_msg(chip->mgr, &request, sizeof(buf->sgroup_resp), &buf->sgroup_resp);
 305                if((err < 0) || (buf->sgroup_resp.status != 0)) {
 306                        dev_err(chip->card->dev,
 307                                "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n",
 308                                err, buf->sgroup_resp.status);
 309                        kfree(buf);
 310                        return NULL;
 311                }
 312
 313                pipe->group_uid = buf->sgroup_resp.group;     /* id of the pipe, as returned by embedded */
 314                pipe->stream_count = buf->sgroup_resp.stream_count;
 315                /* pipe->stream_uid[i] = buf->sgroup_resp.stream[i].stream_uid; */
 316
 317                pipe->status = PIPE_STOPPED;
 318                kfree(buf);
 319        }
 320
 321        if(monitoring)  pipe->monitoring = 1;
 322        else            pipe->references++;
 323
 324        return pipe;
 325}
 326
 327
 328int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr,
 329                             struct mixart_pipe *pipe, int monitoring)
 330{
 331        int err = 0;
 332
 333        if(pipe->status == PIPE_UNDEFINED)
 334                return 0;
 335
 336        if(monitoring)
 337                pipe->monitoring = 0;
 338        else
 339                pipe->references--;
 340
 341        if((pipe->references <= 0) && (pipe->monitoring == 0)) {
 342
 343                struct mixart_msg request;
 344                struct mixart_delete_group_resp delete_resp;
 345
 346                /* release the clock */
 347                err = mixart_set_clock( mgr, pipe, 0);
 348                if( err < 0 ) {
 349                        dev_err(&mgr->pci->dev,
 350                                "mixart_set_clock(0) return error!\n");
 351                }
 352
 353                /* stop the pipe */
 354                err = mixart_set_pipe_state(mgr, pipe, 0);
 355                if( err < 0 ) {
 356                        dev_err(&mgr->pci->dev, "error stopping pipe!\n");
 357                }
 358
 359                request.message_id = MSG_STREAM_DELETE_GROUP;
 360                request.uid = (struct mixart_uid){0,0};
 361                request.data = &pipe->group_uid;            /* the streaming group ! */
 362                request.size = sizeof(pipe->group_uid);
 363
 364                /* delete the pipe */
 365                err = snd_mixart_send_msg(mgr, &request, sizeof(delete_resp), &delete_resp);
 366                if ((err < 0) || (delete_resp.status != 0)) {
 367                        dev_err(&mgr->pci->dev,
 368                                "error MSG_STREAM_DELETE_GROUP err(%x), status(%x)\n",
 369                                err, delete_resp.status);
 370                }
 371
 372                pipe->group_uid = (struct mixart_uid){0,0};
 373                pipe->stream_count = 0;
 374                pipe->status = PIPE_UNDEFINED;
 375        }
 376
 377        return err;
 378}
 379
 380static int mixart_set_stream_state(struct mixart_stream *stream, int start)
 381{
 382        struct snd_mixart *chip;
 383        struct mixart_stream_state_req stream_state_req;
 384        struct mixart_msg request;
 385
 386        if(!stream->substream)
 387                return -EINVAL;
 388
 389        memset(&stream_state_req, 0, sizeof(stream_state_req));
 390        stream_state_req.stream_count = 1;
 391        stream_state_req.stream_info.stream_desc.uid_pipe = stream->pipe->group_uid;
 392        stream_state_req.stream_info.stream_desc.stream_idx = stream->substream->number;
 393
 394        if (stream->substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 395                request.message_id = start ? MSG_STREAM_START_INPUT_STAGE_PACKET : MSG_STREAM_STOP_INPUT_STAGE_PACKET;
 396        else
 397                request.message_id = start ? MSG_STREAM_START_OUTPUT_STAGE_PACKET : MSG_STREAM_STOP_OUTPUT_STAGE_PACKET;
 398
 399        request.uid = (struct mixart_uid){0,0};
 400        request.data = &stream_state_req;
 401        request.size = sizeof(stream_state_req);
 402
 403        stream->abs_period_elapsed = 0;            /* reset stream pos      */
 404        stream->buf_periods = 0;
 405        stream->buf_period_frag = 0;
 406
 407        chip = snd_pcm_substream_chip(stream->substream);
 408
 409        return snd_mixart_send_msg_nonblock(chip->mgr, &request);
 410}
 411
 412/*
 413 *  Trigger callback
 414 */
 415
 416static int snd_mixart_trigger(struct snd_pcm_substream *subs, int cmd)
 417{
 418        struct mixart_stream *stream = subs->runtime->private_data;
 419
 420        switch (cmd) {
 421        case SNDRV_PCM_TRIGGER_START:
 422
 423                dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_TRIGGER_START\n");
 424
 425                /* START_STREAM */
 426                if( mixart_set_stream_state(stream, 1) )
 427                        return -EINVAL;
 428
 429                stream->status = MIXART_STREAM_STATUS_RUNNING;
 430
 431                break;
 432        case SNDRV_PCM_TRIGGER_STOP:
 433
 434                /* STOP_STREAM */
 435                if( mixart_set_stream_state(stream, 0) )
 436                        return -EINVAL;
 437
 438                stream->status = MIXART_STREAM_STATUS_OPEN;
 439
 440                dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_TRIGGER_STOP\n");
 441
 442                break;
 443
 444        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 445                /* TODO */
 446                stream->status = MIXART_STREAM_STATUS_PAUSE;
 447                dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_PAUSE_PUSH\n");
 448                break;
 449        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 450                /* TODO */
 451                stream->status = MIXART_STREAM_STATUS_RUNNING;
 452                dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_PAUSE_RELEASE\n");
 453                break;
 454        default:
 455                return -EINVAL;
 456        }
 457        return 0;
 458}
 459
 460static int mixart_sync_nonblock_events(struct mixart_mgr *mgr)
 461{
 462        unsigned long timeout = jiffies + HZ;
 463        while (atomic_read(&mgr->msg_processed) > 0) {
 464                if (time_after(jiffies, timeout)) {
 465                        dev_err(&mgr->pci->dev,
 466                                "mixart: cannot process nonblock events!\n");
 467                        return -EBUSY;
 468                }
 469                schedule_timeout_uninterruptible(1);
 470        }
 471        return 0;
 472}
 473
 474/*
 475 *  prepare callback for all pcms
 476 */
 477static int snd_mixart_prepare(struct snd_pcm_substream *subs)
 478{
 479        struct snd_mixart *chip = snd_pcm_substream_chip(subs);
 480        struct mixart_stream *stream = subs->runtime->private_data;
 481
 482        /* TODO de façon non bloquante, réappliquer les hw_params (rate, bits, codec) */
 483
 484        dev_dbg(chip->card->dev, "snd_mixart_prepare\n");
 485
 486        mixart_sync_nonblock_events(chip->mgr);
 487
 488        /* only the first stream can choose the sample rate */
 489        /* the further opened streams will be limited to its frequency (see open) */
 490        if(chip->mgr->ref_count_rate == 1)
 491                chip->mgr->sample_rate = subs->runtime->rate;
 492
 493        /* set the clock only once (first stream) on the same pipe */
 494        if(stream->pipe->references == 1) {
 495                if( mixart_set_clock(chip->mgr, stream->pipe, subs->runtime->rate) )
 496                        return -EINVAL;
 497        }
 498
 499        return 0;
 500}
 501
 502
 503static int mixart_set_format(struct mixart_stream *stream, snd_pcm_format_t format)
 504{
 505        int err;
 506        struct snd_mixart *chip;
 507        struct mixart_msg request;
 508        struct mixart_stream_param_desc stream_param;
 509        struct mixart_return_uid resp;
 510
 511        chip = snd_pcm_substream_chip(stream->substream);
 512
 513        memset(&stream_param, 0, sizeof(stream_param));
 514
 515        stream_param.coding_type = CT_LINEAR;
 516        stream_param.number_of_channel = stream->channels;
 517
 518        stream_param.sampling_freq = chip->mgr->sample_rate;
 519        if(stream_param.sampling_freq == 0)
 520                stream_param.sampling_freq = 44100; /* if frequency not yet defined, use some default */
 521
 522        switch(format){
 523        case SNDRV_PCM_FORMAT_U8:
 524                stream_param.sample_type = ST_INTEGER_8;
 525                stream_param.sample_size = 8;
 526                break;
 527        case SNDRV_PCM_FORMAT_S16_LE:
 528                stream_param.sample_type = ST_INTEGER_16LE;
 529                stream_param.sample_size = 16;
 530                break;
 531        case SNDRV_PCM_FORMAT_S16_BE:
 532                stream_param.sample_type = ST_INTEGER_16BE;
 533                stream_param.sample_size = 16;
 534                break;
 535        case SNDRV_PCM_FORMAT_S24_3LE:
 536                stream_param.sample_type = ST_INTEGER_24LE;
 537                stream_param.sample_size = 24;
 538                break;
 539        case SNDRV_PCM_FORMAT_S24_3BE:
 540                stream_param.sample_type = ST_INTEGER_24BE;
 541                stream_param.sample_size = 24;
 542                break;
 543        case SNDRV_PCM_FORMAT_FLOAT_LE:
 544                stream_param.sample_type = ST_FLOATING_POINT_32LE;
 545                stream_param.sample_size = 32;
 546                break;
 547        case  SNDRV_PCM_FORMAT_FLOAT_BE:
 548                stream_param.sample_type = ST_FLOATING_POINT_32BE;
 549                stream_param.sample_size = 32;
 550                break;
 551        default:
 552                dev_err(chip->card->dev,
 553                        "error mixart_set_format() : unknown format\n");
 554                return -EINVAL;
 555        }
 556
 557        dev_dbg(chip->card->dev,
 558                "set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) channels(%d)\n",
 559                   stream_param.sample_type, stream_param.sample_size, stream_param.sampling_freq, stream->channels);
 560
 561        /* TODO: what else to configure ? */
 562        /* stream_param.samples_per_frame = 2; */
 563        /* stream_param.bytes_per_frame = 4; */
 564        /* stream_param.bytes_per_sample = 2; */
 565
 566        stream_param.pipe_count = 1;      /* set to 1 */
 567        stream_param.stream_count = 1;    /* set to 1 */
 568        stream_param.stream_desc[0].uid_pipe = stream->pipe->group_uid;
 569        stream_param.stream_desc[0].stream_idx = stream->substream->number;
 570
 571        request.message_id = MSG_STREAM_SET_INPUT_STAGE_PARAM;
 572        request.uid = (struct mixart_uid){0,0};
 573        request.data = &stream_param;
 574        request.size = sizeof(stream_param);
 575
 576        err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp);
 577        if((err < 0) || resp.error_code) {
 578                dev_err(chip->card->dev,
 579                        "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; resp=%x\n",
 580                        err, resp.error_code);
 581                return -EINVAL;
 582        }
 583        return 0;
 584}
 585
 586
 587/*
 588 *  HW_PARAMS callback for all pcms
 589 */
 590static int snd_mixart_hw_params(struct snd_pcm_substream *subs,
 591                                struct snd_pcm_hw_params *hw)
 592{
 593        struct snd_mixart *chip = snd_pcm_substream_chip(subs);
 594        struct mixart_mgr *mgr = chip->mgr;
 595        struct mixart_stream *stream = subs->runtime->private_data;
 596        snd_pcm_format_t format;
 597        int err;
 598        int channels;
 599
 600        /* set up channels */
 601        channels = params_channels(hw);
 602
 603        /*  set up format for the stream */
 604        format = params_format(hw);
 605
 606        mutex_lock(&mgr->setup_mutex);
 607
 608        /* update the stream levels */
 609        if( stream->pcm_number <= MIXART_PCM_DIGITAL ) {
 610                int is_aes = stream->pcm_number > MIXART_PCM_ANALOG;
 611                if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK )
 612                        mixart_update_playback_stream_level(chip, is_aes, subs->number);
 613                else
 614                        mixart_update_capture_stream_level( chip, is_aes);
 615        }
 616
 617        stream->channels = channels;
 618
 619        /* set the format to the board */
 620        err = mixart_set_format(stream, format);
 621        if(err < 0) {
 622                mutex_unlock(&mgr->setup_mutex);
 623                return err;
 624        }
 625
 626        if (subs->runtime->buffer_changed) {
 627                struct mixart_bufferinfo *bufferinfo;
 628                int i = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (stream->pcm_number * (MIXART_PLAYBACK_STREAMS+MIXART_CAPTURE_STREAMS)) + subs->number;
 629                if( subs->stream == SNDRV_PCM_STREAM_CAPTURE ) {
 630                        i += MIXART_PLAYBACK_STREAMS; /* in array capture is behind playback */
 631                }
 632                
 633                bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area;
 634                bufferinfo[i].buffer_address = subs->runtime->dma_addr;
 635                bufferinfo[i].available_length = subs->runtime->dma_bytes;
 636                /* bufferinfo[i].buffer_id  is already defined */
 637
 638                dev_dbg(chip->card->dev,
 639                        "snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n",
 640                        i, bufferinfo[i].buffer_address,
 641                                bufferinfo[i].available_length,
 642                                subs->number);
 643        }
 644        mutex_unlock(&mgr->setup_mutex);
 645
 646        return 0;
 647}
 648
 649static int snd_mixart_hw_free(struct snd_pcm_substream *subs)
 650{
 651        struct snd_mixart *chip = snd_pcm_substream_chip(subs);
 652        mixart_sync_nonblock_events(chip->mgr);
 653        return 0;
 654}
 655
 656
 657
 658/*
 659 *  TODO CONFIGURATION SPACE for all pcms, mono pcm must update channels_max
 660 */
 661static const struct snd_pcm_hardware snd_mixart_analog_caps =
 662{
 663        .info             = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 664                              SNDRV_PCM_INFO_MMAP_VALID |
 665                              SNDRV_PCM_INFO_PAUSE),
 666        .formats          = ( SNDRV_PCM_FMTBIT_U8 |
 667                              SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
 668                              SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
 669                              SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),
 670        .rates            = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
 671        .rate_min         = 8000,
 672        .rate_max         = 48000,
 673        .channels_min     = 1,
 674        .channels_max     = 2,
 675        .buffer_bytes_max = (32*1024),
 676        .period_bytes_min = 256,                  /* 256 frames U8 mono*/
 677        .period_bytes_max = (16*1024),
 678        .periods_min      = 2,
 679        .periods_max      = (32*1024/256),
 680};
 681
 682static const struct snd_pcm_hardware snd_mixart_digital_caps =
 683{
 684        .info             = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 685                              SNDRV_PCM_INFO_MMAP_VALID |
 686                              SNDRV_PCM_INFO_PAUSE),
 687        .formats          = ( SNDRV_PCM_FMTBIT_U8 |
 688                              SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
 689                              SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
 690                              SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),
 691        .rates            = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
 692        .rate_min         = 32000,
 693        .rate_max         = 48000,
 694        .channels_min     = 1,
 695        .channels_max     = 2,
 696        .buffer_bytes_max = (32*1024),
 697        .period_bytes_min = 256,                  /* 256 frames U8 mono*/
 698        .period_bytes_max = (16*1024),
 699        .periods_min      = 2,
 700        .periods_max      = (32*1024/256),
 701};
 702
 703
 704static int snd_mixart_playback_open(struct snd_pcm_substream *subs)
 705{
 706        struct snd_mixart            *chip = snd_pcm_substream_chip(subs);
 707        struct mixart_mgr        *mgr = chip->mgr;
 708        struct snd_pcm_runtime *runtime = subs->runtime;
 709        struct snd_pcm *pcm = subs->pcm;
 710        struct mixart_stream     *stream;
 711        struct mixart_pipe       *pipe;
 712        int err = 0;
 713        int pcm_number;
 714
 715        mutex_lock(&mgr->setup_mutex);
 716
 717        if ( pcm == chip->pcm ) {
 718                pcm_number = MIXART_PCM_ANALOG;
 719                runtime->hw = snd_mixart_analog_caps;
 720        } else {
 721                snd_BUG_ON(pcm != chip->pcm_dig);
 722                pcm_number = MIXART_PCM_DIGITAL;
 723                runtime->hw = snd_mixart_digital_caps;
 724        }
 725        dev_dbg(chip->card->dev,
 726                "snd_mixart_playback_open C%d/P%d/Sub%d\n",
 727                chip->chip_idx, pcm_number, subs->number);
 728
 729        /* get stream info */
 730        stream = &(chip->playback_stream[pcm_number][subs->number]);
 731
 732        if (stream->status != MIXART_STREAM_STATUS_FREE){
 733                /* streams in use */
 734                dev_err(chip->card->dev,
 735                        "snd_mixart_playback_open C%d/P%d/Sub%d in use\n",
 736                        chip->chip_idx, pcm_number, subs->number);
 737                err = -EBUSY;
 738                goto _exit_open;
 739        }
 740
 741        /* get pipe pointer (out pipe) */
 742        pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 0, 0);
 743
 744        if (pipe == NULL) {
 745                err = -EINVAL;
 746                goto _exit_open;
 747        }
 748
 749        /* start the pipe if necessary */
 750        err = mixart_set_pipe_state(chip->mgr, pipe, 1);
 751        if( err < 0 ) {
 752                dev_err(chip->card->dev, "error starting pipe!\n");
 753                snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);
 754                err = -EINVAL;
 755                goto _exit_open;
 756        }
 757
 758        stream->pipe        = pipe;
 759        stream->pcm_number  = pcm_number;
 760        stream->status      = MIXART_STREAM_STATUS_OPEN;
 761        stream->substream   = subs;
 762        stream->channels    = 0; /* not configured yet */
 763
 764        runtime->private_data = stream;
 765
 766        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
 767        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);
 768
 769        /* if a sample rate is already used, another stream cannot change */
 770        if(mgr->ref_count_rate++) {
 771                if(mgr->sample_rate) {
 772                        runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
 773                }
 774        }
 775
 776 _exit_open:
 777        mutex_unlock(&mgr->setup_mutex);
 778
 779        return err;
 780}
 781
 782
 783static int snd_mixart_capture_open(struct snd_pcm_substream *subs)
 784{
 785        struct snd_mixart            *chip = snd_pcm_substream_chip(subs);
 786        struct mixart_mgr        *mgr = chip->mgr;
 787        struct snd_pcm_runtime *runtime = subs->runtime;
 788        struct snd_pcm *pcm = subs->pcm;
 789        struct mixart_stream     *stream;
 790        struct mixart_pipe       *pipe;
 791        int err = 0;
 792        int pcm_number;
 793
 794        mutex_lock(&mgr->setup_mutex);
 795
 796        if ( pcm == chip->pcm ) {
 797                pcm_number = MIXART_PCM_ANALOG;
 798                runtime->hw = snd_mixart_analog_caps;
 799        } else {
 800                snd_BUG_ON(pcm != chip->pcm_dig);
 801                pcm_number = MIXART_PCM_DIGITAL;
 802                runtime->hw = snd_mixart_digital_caps;
 803        }
 804
 805        runtime->hw.channels_min = 2; /* for instance, no mono */
 806
 807        dev_dbg(chip->card->dev, "snd_mixart_capture_open C%d/P%d/Sub%d\n",
 808                chip->chip_idx, pcm_number, subs->number);
 809
 810        /* get stream info */
 811        stream = &(chip->capture_stream[pcm_number]);
 812
 813        if (stream->status != MIXART_STREAM_STATUS_FREE){
 814                /* streams in use */
 815                dev_err(chip->card->dev,
 816                        "snd_mixart_capture_open C%d/P%d/Sub%d in use\n",
 817                        chip->chip_idx, pcm_number, subs->number);
 818                err = -EBUSY;
 819                goto _exit_open;
 820        }
 821
 822        /* get pipe pointer (in pipe) */
 823        pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 1, 0);
 824
 825        if (pipe == NULL) {
 826                err = -EINVAL;
 827                goto _exit_open;
 828        }
 829
 830        /* start the pipe if necessary */
 831        err = mixart_set_pipe_state(chip->mgr, pipe, 1);
 832        if( err < 0 ) {
 833                dev_err(chip->card->dev, "error starting pipe!\n");
 834                snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);
 835                err = -EINVAL;
 836                goto _exit_open;
 837        }
 838
 839        stream->pipe        = pipe;
 840        stream->pcm_number  = pcm_number;
 841        stream->status      = MIXART_STREAM_STATUS_OPEN;
 842        stream->substream   = subs;
 843        stream->channels    = 0; /* not configured yet */
 844
 845        runtime->private_data = stream;
 846
 847        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
 848        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);
 849
 850        /* if a sample rate is already used, another stream cannot change */
 851        if(mgr->ref_count_rate++) {
 852                if(mgr->sample_rate) {
 853                        runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
 854                }
 855        }
 856
 857 _exit_open:
 858        mutex_unlock(&mgr->setup_mutex);
 859
 860        return err;
 861}
 862
 863
 864
 865static int snd_mixart_close(struct snd_pcm_substream *subs)
 866{
 867        struct snd_mixart *chip = snd_pcm_substream_chip(subs);
 868        struct mixart_mgr *mgr = chip->mgr;
 869        struct mixart_stream *stream = subs->runtime->private_data;
 870
 871        mutex_lock(&mgr->setup_mutex);
 872
 873        dev_dbg(chip->card->dev, "snd_mixart_close C%d/P%d/Sub%d\n",
 874                chip->chip_idx, stream->pcm_number, subs->number);
 875
 876        /* sample rate released */
 877        if(--mgr->ref_count_rate == 0) {
 878                mgr->sample_rate = 0;
 879        }
 880
 881        /* delete pipe */
 882        if (snd_mixart_kill_ref_pipe(mgr, stream->pipe, 0 ) < 0) {
 883
 884                dev_err(chip->card->dev,
 885                        "error snd_mixart_kill_ref_pipe C%dP%d\n",
 886                        chip->chip_idx, stream->pcm_number);
 887        }
 888
 889        stream->pipe      = NULL;
 890        stream->status    = MIXART_STREAM_STATUS_FREE;
 891        stream->substream = NULL;
 892
 893        mutex_unlock(&mgr->setup_mutex);
 894        return 0;
 895}
 896
 897
 898static snd_pcm_uframes_t snd_mixart_stream_pointer(struct snd_pcm_substream *subs)
 899{
 900        struct snd_pcm_runtime *runtime = subs->runtime;
 901        struct mixart_stream   *stream  = runtime->private_data;
 902
 903        return (snd_pcm_uframes_t)((stream->buf_periods * runtime->period_size) + stream->buf_period_frag);
 904}
 905
 906
 907
 908static const struct snd_pcm_ops snd_mixart_playback_ops = {
 909        .open      = snd_mixart_playback_open,
 910        .close     = snd_mixart_close,
 911        .prepare   = snd_mixart_prepare,
 912        .hw_params = snd_mixart_hw_params,
 913        .hw_free   = snd_mixart_hw_free,
 914        .trigger   = snd_mixart_trigger,
 915        .pointer   = snd_mixart_stream_pointer,
 916};
 917
 918static const struct snd_pcm_ops snd_mixart_capture_ops = {
 919        .open      = snd_mixart_capture_open,
 920        .close     = snd_mixart_close,
 921        .prepare   = snd_mixart_prepare,
 922        .hw_params = snd_mixart_hw_params,
 923        .hw_free   = snd_mixart_hw_free,
 924        .trigger   = snd_mixart_trigger,
 925        .pointer   = snd_mixart_stream_pointer,
 926};
 927
 928static void preallocate_buffers(struct snd_mixart *chip, struct snd_pcm *pcm)
 929{
 930#if 0
 931        struct snd_pcm_substream *subs;
 932        int stream;
 933
 934        for (stream = 0; stream < 2; stream++) {
 935                int idx = 0;
 936                for (subs = pcm->streams[stream].substream; subs; subs = subs->next, idx++)
 937                        /* set up the unique device id with the chip index */
 938                        subs->dma_device.id = subs->pcm->device << 16 |
 939                                subs->stream << 8 | (subs->number + 1) |
 940                                (chip->chip_idx + 1) << 24;
 941        }
 942#endif
 943        snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
 944                                       &chip->mgr->pci->dev,
 945                                       32*1024, 32*1024);
 946}
 947
 948/*
 949 */
 950static int snd_mixart_pcm_analog(struct snd_mixart *chip)
 951{
 952        int err;
 953        struct snd_pcm *pcm;
 954        char name[32];
 955
 956        sprintf(name, "miXart analog %d", chip->chip_idx);
 957        err = snd_pcm_new(chip->card, name, MIXART_PCM_ANALOG,
 958                          MIXART_PLAYBACK_STREAMS,
 959                          MIXART_CAPTURE_STREAMS, &pcm);
 960        if (err < 0) {
 961                dev_err(chip->card->dev,
 962                        "cannot create the analog pcm %d\n", chip->chip_idx);
 963                return err;
 964        }
 965
 966        pcm->private_data = chip;
 967
 968        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
 969        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
 970
 971        pcm->info_flags = 0;
 972        pcm->nonatomic = true;
 973        strcpy(pcm->name, name);
 974
 975        preallocate_buffers(chip, pcm);
 976
 977        chip->pcm = pcm;
 978        return 0;
 979}
 980
 981
 982/*
 983 */
 984static int snd_mixart_pcm_digital(struct snd_mixart *chip)
 985{
 986        int err;
 987        struct snd_pcm *pcm;
 988        char name[32];
 989
 990        sprintf(name, "miXart AES/EBU %d", chip->chip_idx);
 991        err = snd_pcm_new(chip->card, name, MIXART_PCM_DIGITAL,
 992                          MIXART_PLAYBACK_STREAMS,
 993                          MIXART_CAPTURE_STREAMS, &pcm);
 994        if (err < 0) {
 995                dev_err(chip->card->dev,
 996                        "cannot create the digital pcm %d\n", chip->chip_idx);
 997                return err;
 998        }
 999
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
1015static int snd_mixart_chip_free(struct snd_mixart *chip)
1016{
1017        kfree(chip);
1018        return 0;
1019}
1020
1021static 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 */
1030static 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
1057int 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 */
1078static 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 */
1129static 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 */
1145static 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
1158static const struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = {
1159        .read   = snd_mixart_BA0_read,
1160};
1161
1162static const struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {
1163        .read   = snd_mixart_BA1_read,
1164};
1165
1166
1167static 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
1203static 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 */
1230static 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
1396static void snd_mixart_remove(struct pci_dev *pci)
1397{
1398        snd_mixart_free(pci_get_drvdata(pci));
1399}
1400
1401static 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
1408module_pci_driver(mixart_driver);
1409
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.