linux/sound/drivers/vx/vx_pcm.c
<<
>>
Prefs
   1/*
   2 * Driver for Digigram VX soundcards
   3 *
   4 * PCM part
   5 *
   6 * Copyright (c) 2002,2003 by Takashi Iwai <tiwai@suse.de>
   7 *
   8 *   This program is free software; you can redistribute it and/or modify
   9 *   it under the terms of the GNU General Public License as published by
  10 *   the Free Software Foundation; either version 2 of the License, or
  11 *   (at your option) any later version.
  12 *
  13 *   This program is distributed in the hope that it will be useful,
  14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *   GNU General Public License for more details.
  17 *
  18 *   You should have received a copy of the GNU General Public License
  19 *   along with this program; if not, write to the Free Software
  20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  21 *
  22 *
  23 * STRATEGY
  24 *  for playback, we send series of "chunks", which size is equal with the
  25 *  IBL size, typically 126 samples.  at each end of chunk, the end-of-buffer
  26 *  interrupt is notified, and the interrupt handler will feed the next chunk.
  27 *
  28 *  the current position is calculated from the sample count RMH.
  29 *  pipe->transferred is the counter of data which has been already transferred.
  30 *  if this counter reaches to the period size, snd_pcm_period_elapsed() will
  31 *  be issued.
  32 *
  33 *  for capture, the situation is much easier.
  34 *  to get a low latency response, we'll check the capture streams at each
  35 *  interrupt (capture stream has no EOB notification).  if the pending
  36 *  data is accumulated to the period size, snd_pcm_period_elapsed() is
  37 *  called and the pointer is updated.
  38 *
  39 *  the current point of read buffer is kept in pipe->hw_ptr.  note that
  40 *  this is in bytes.
  41 *
  42 *
  43 * TODO
  44 *  - linked trigger for full-duplex mode.
  45 *  - scheduled action on the stream.
  46 */
  47
  48#include <linux/slab.h>
  49#include <linux/delay.h>
  50#include <sound/core.h>
  51#include <sound/asoundef.h>
  52#include <sound/pcm.h>
  53#include <sound/vx_core.h>
  54#include "vx_cmd.h"
  55
  56
  57/*
  58 * read three pending pcm bytes via inb()
  59 */
  60static void vx_pcm_read_per_bytes(struct vx_core *chip, struct snd_pcm_runtime *runtime,
  61                                  struct vx_pipe *pipe)
  62{
  63        int offset = pipe->hw_ptr;
  64        unsigned char *buf = (unsigned char *)(runtime->dma_area + offset);
  65        *buf++ = vx_inb(chip, RXH);
  66        if (++offset >= pipe->buffer_bytes) {
  67                offset = 0;
  68                buf = (unsigned char *)runtime->dma_area;
  69        }
  70        *buf++ = vx_inb(chip, RXM);
  71        if (++offset >= pipe->buffer_bytes) {
  72                offset = 0;
  73                buf = (unsigned char *)runtime->dma_area;
  74        }
  75        *buf++ = vx_inb(chip, RXL);
  76        if (++offset >= pipe->buffer_bytes) {
  77                offset = 0;
  78                buf = (unsigned char *)runtime->dma_area;
  79        }
  80        pipe->hw_ptr = offset;
  81}
  82
  83/*
  84 * vx_set_pcx_time - convert from the PC time to the RMH status time.
  85 * @pc_time: the pointer for the PC-time to set
  86 * @dsp_time: the pointer for RMH status time array
  87 */
  88static void vx_set_pcx_time(struct vx_core *chip, pcx_time_t *pc_time,
  89                            unsigned int *dsp_time)
  90{
  91        dsp_time[0] = (unsigned int)((*pc_time) >> 24) & PCX_TIME_HI_MASK;
  92        dsp_time[1] = (unsigned int)(*pc_time) &  MASK_DSP_WORD;
  93}
  94
  95/*
  96 * vx_set_differed_time - set the differed time if specified
  97 * @rmh: the rmh record to modify
  98 * @pipe: the pipe to be checked
  99 *
 100 * if the pipe is programmed with the differed time, set the DSP time
 101 * on the rmh and changes its command length.
 102 *
 103 * returns the increase of the command length.
 104 */
 105static int vx_set_differed_time(struct vx_core *chip, struct vx_rmh *rmh,
 106                                struct vx_pipe *pipe)
 107{
 108        /* Update The length added to the RMH command by the timestamp */
 109        if (! (pipe->differed_type & DC_DIFFERED_DELAY))
 110                return 0;
 111                
 112        /* Set the T bit */
 113        rmh->Cmd[0] |= DSP_DIFFERED_COMMAND_MASK;
 114
 115        /* Time stamp is the 1st following parameter */
 116        vx_set_pcx_time(chip, &pipe->pcx_time, &rmh->Cmd[1]);
 117
 118        /* Add the flags to a notified differed command */
 119        if (pipe->differed_type & DC_NOTIFY_DELAY)
 120                rmh->Cmd[1] |= NOTIFY_MASK_TIME_HIGH ;
 121
 122        /* Add the flags to a multiple differed command */
 123        if (pipe->differed_type & DC_MULTIPLE_DELAY)
 124                rmh->Cmd[1] |= MULTIPLE_MASK_TIME_HIGH;
 125
 126        /* Add the flags to a stream-time differed command */
 127        if (pipe->differed_type & DC_STREAM_TIME_DELAY)
 128                rmh->Cmd[1] |= STREAM_MASK_TIME_HIGH;
 129                
 130        rmh->LgCmd += 2;
 131        return 2;
 132}
 133
 134/*
 135 * vx_set_stream_format - send the stream format command
 136 * @pipe: the affected pipe
 137 * @data: format bitmask
 138 */
 139static int vx_set_stream_format(struct vx_core *chip, struct vx_pipe *pipe,
 140                                unsigned int data)
 141{
 142        struct vx_rmh rmh;
 143
 144        vx_init_rmh(&rmh, pipe->is_capture ?
 145                    CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
 146        rmh.Cmd[0] |= pipe->number << FIELD_SIZE;
 147
 148        /* Command might be longer since we may have to add a timestamp */
 149        vx_set_differed_time(chip, &rmh, pipe);
 150
 151        rmh.Cmd[rmh.LgCmd] = (data & 0xFFFFFF00) >> 8;
 152        rmh.Cmd[rmh.LgCmd + 1] = (data & 0xFF) << 16 /*| (datal & 0xFFFF00) >> 8*/;
 153        rmh.LgCmd += 2;
 154    
 155        return vx_send_msg(chip, &rmh);
 156}
 157
 158
 159/*
 160 * vx_set_format - set the format of a pipe
 161 * @pipe: the affected pipe
 162 * @runtime: pcm runtime instance to be referred
 163 *
 164 * returns 0 if successful, or a negative error code.
 165 */
 166static int vx_set_format(struct vx_core *chip, struct vx_pipe *pipe,
 167                         struct snd_pcm_runtime *runtime)
 168{
 169        unsigned int header = HEADER_FMT_BASE;
 170
 171        if (runtime->channels == 1)
 172                header |= HEADER_FMT_MONO;
 173        if (snd_pcm_format_little_endian(runtime->format))
 174                header |= HEADER_FMT_INTEL;
 175        if (runtime->rate < 32000 && runtime->rate > 11025)
 176                header |= HEADER_FMT_UPTO32;
 177        else if (runtime->rate <= 11025)
 178                header |= HEADER_FMT_UPTO11;
 179
 180        switch (snd_pcm_format_physical_width(runtime->format)) {
 181        // case 8: break;
 182        case 16: header |= HEADER_FMT_16BITS; break;
 183        case 24: header |= HEADER_FMT_24BITS; break;
 184        default : 
 185                snd_BUG();
 186                return -EINVAL;
 187        }
 188
 189        return vx_set_stream_format(chip, pipe, header);
 190}
 191
 192/*
 193 * set / query the IBL size
 194 */
 195static int vx_set_ibl(struct vx_core *chip, struct vx_ibl_info *info)
 196{
 197        int err;
 198        struct vx_rmh rmh;
 199
 200        vx_init_rmh(&rmh, CMD_IBL);
 201        rmh.Cmd[0] |= info->size & 0x03ffff;
 202        err = vx_send_msg(chip, &rmh);
 203        if (err < 0)
 204                return err;
 205        info->size = rmh.Stat[0];
 206        info->max_size = rmh.Stat[1];
 207        info->min_size = rmh.Stat[2];
 208        info->granularity = rmh.Stat[3];
 209        snd_printdd(KERN_DEBUG "vx_set_ibl: size = %d, max = %d, min = %d, gran = %d\n",
 210                   info->size, info->max_size, info->min_size, info->granularity);
 211        return 0;
 212}
 213
 214
 215/*
 216 * vx_get_pipe_state - get the state of a pipe
 217 * @pipe: the pipe to be checked
 218 * @state: the pointer for the returned state
 219 *
 220 * checks the state of a given pipe, and stores the state (1 = running,
 221 * 0 = paused) on the given pointer.
 222 *
 223 * called from trigger callback only
 224 */
 225static int vx_get_pipe_state(struct vx_core *chip, struct vx_pipe *pipe, int *state)
 226{
 227        int err;
 228        struct vx_rmh rmh;
 229
 230        vx_init_rmh(&rmh, CMD_PIPE_STATE);
 231        vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
 232        err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ 
 233        if (! err)
 234                *state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0;
 235        return err;
 236}
 237
 238
 239/*
 240 * vx_query_hbuffer_size - query available h-buffer size in bytes
 241 * @pipe: the pipe to be checked
 242 *
 243 * return the available size on h-buffer in bytes,
 244 * or a negative error code.
 245 *
 246 * NOTE: calling this function always switches to the stream mode.
 247 *       you'll need to disconnect the host to get back to the
 248 *       normal mode.
 249 */
 250static int vx_query_hbuffer_size(struct vx_core *chip, struct vx_pipe *pipe)
 251{
 252        int result;
 253        struct vx_rmh rmh;
 254
 255        vx_init_rmh(&rmh, CMD_SIZE_HBUFFER);
 256        vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
 257        if (pipe->is_capture)
 258                rmh.Cmd[0] |= 0x00000001;
 259        result = vx_send_msg(chip, &rmh);
 260        if (! result)
 261                result = rmh.Stat[0] & 0xffff;
 262        return result;
 263}
 264
 265
 266/*
 267 * vx_pipe_can_start - query whether a pipe is ready for start
 268 * @pipe: the pipe to be checked
 269 *
 270 * return 1 if ready, 0 if not ready, and negative value on error.
 271 *
 272 * called from trigger callback only
 273 */
 274static int vx_pipe_can_start(struct vx_core *chip, struct vx_pipe *pipe)
 275{
 276        int err;
 277        struct vx_rmh rmh;
 278        
 279        vx_init_rmh(&rmh, CMD_CAN_START_PIPE);
 280        vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
 281        rmh.Cmd[0] |= 1;
 282
 283        err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ 
 284        if (! err) {
 285                if (rmh.Stat[0])
 286                        err = 1;
 287        }
 288        return err;
 289}
 290
 291/*
 292 * vx_conf_pipe - tell the pipe to stand by and wait for IRQA.
 293 * @pipe: the pipe to be configured
 294 */
 295static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe)
 296{
 297        struct vx_rmh rmh;
 298
 299        vx_init_rmh(&rmh, CMD_CONF_PIPE);
 300        if (pipe->is_capture)
 301                rmh.Cmd[0] |= COMMAND_RECORD_MASK;
 302        rmh.Cmd[1] = 1 << pipe->number;
 303        return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
 304}
 305
 306/*
 307 * vx_send_irqa - trigger IRQA
 308 */
 309static int vx_send_irqa(struct vx_core *chip)
 310{
 311        struct vx_rmh rmh;
 312
 313        vx_init_rmh(&rmh, CMD_SEND_IRQA);
 314        return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ 
 315}
 316
 317
 318#define MAX_WAIT_FOR_DSP        250
 319/*
 320 * vx boards do not support inter-card sync, besides
 321 * only 126 samples require to be prepared before a pipe can start
 322 */
 323#define CAN_START_DELAY         2       /* wait 2ms only before asking if the pipe is ready*/
 324#define WAIT_STATE_DELAY        2       /* wait 2ms after irqA was requested and check if the pipe state toggled*/
 325
 326/*
 327 * vx_toggle_pipe - start / pause a pipe
 328 * @pipe: the pipe to be triggered
 329 * @state: start = 1, pause = 0
 330 *
 331 * called from trigger callback only
 332 *
 333 */
 334static int vx_toggle_pipe(struct vx_core *chip, struct vx_pipe *pipe, int state)
 335{
 336        int err, i, cur_state;
 337
 338        /* Check the pipe is not already in the requested state */
 339        if (vx_get_pipe_state(chip, pipe, &cur_state) < 0)
 340                return -EBADFD;
 341        if (state == cur_state)
 342                return 0;
 343
 344        /* If a start is requested, ask the DSP to get prepared
 345         * and wait for a positive acknowledge (when there are
 346         * enough sound buffer for this pipe)
 347         */
 348        if (state) {
 349                for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) {
 350                        err = vx_pipe_can_start(chip, pipe);
 351                        if (err > 0)
 352                                break;
 353                        /* Wait for a few, before asking again
 354                         * to avoid flooding the DSP with our requests
 355                         */
 356                        mdelay(1);
 357                }
 358        }
 359    
 360        if ((err = vx_conf_pipe(chip, pipe)) < 0)
 361                return err;
 362
 363        if ((err = vx_send_irqa(chip)) < 0)
 364                return err;
 365    
 366        /* If it completes successfully, wait for the pipes
 367         * reaching the expected state before returning
 368         * Check one pipe only (since they are synchronous)
 369         */
 370        for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
 371                err = vx_get_pipe_state(chip, pipe, &cur_state);
 372                if (err < 0 || cur_state == state)
 373                        break;
 374                err = -EIO;
 375                mdelay(1);
 376        }
 377        return err < 0 ? -EIO : 0;
 378}
 379
 380    
 381/*
 382 * vx_stop_pipe - stop a pipe
 383 * @pipe: the pipe to be stopped
 384 *
 385 * called from trigger callback only
 386 */
 387static int vx_stop_pipe(struct vx_core *chip, struct vx_pipe *pipe)
 388{
 389        struct vx_rmh rmh;
 390        vx_init_rmh(&rmh, CMD_STOP_PIPE);
 391        vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
 392        return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ 
 393}
 394
 395
 396/*
 397 * vx_alloc_pipe - allocate a pipe and initialize the pipe instance
 398 * @capture: 0 = playback, 1 = capture operation
 399 * @audioid: the audio id to be assigned
 400 * @num_audio: number of audio channels
 401 * @pipep: the returned pipe instance
 402 *
 403 * return 0 on success, or a negative error code.
 404 */
 405static int vx_alloc_pipe(struct vx_core *chip, int capture,
 406                         int audioid, int num_audio,
 407                         struct vx_pipe **pipep)
 408{
 409        int err;
 410        struct vx_pipe *pipe;
 411        struct vx_rmh rmh;
 412        int data_mode;
 413
 414        *pipep = NULL;
 415        vx_init_rmh(&rmh, CMD_RES_PIPE);
 416        vx_set_pipe_cmd_params(&rmh, capture, audioid, num_audio);
 417#if 0   // NYI
 418        if (underrun_skip_sound)
 419                rmh.Cmd[0] |= BIT_SKIP_SOUND;
 420#endif  // NYI
 421        data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;
 422        if (! capture && data_mode)
 423                rmh.Cmd[0] |= BIT_DATA_MODE;
 424        err = vx_send_msg(chip, &rmh);
 425        if (err < 0)
 426                return err;
 427
 428        /* initialize the pipe record */
 429        pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
 430        if (! pipe) {
 431                /* release the pipe */
 432                vx_init_rmh(&rmh, CMD_FREE_PIPE);
 433                vx_set_pipe_cmd_params(&rmh, capture, audioid, 0);
 434                vx_send_msg(chip, &rmh);
 435                return -ENOMEM;
 436        }
 437
 438        /* the pipe index should be identical with the audio index */
 439        pipe->number = audioid;
 440        pipe->is_capture = capture;
 441        pipe->channels = num_audio;
 442        pipe->differed_type = 0;
 443        pipe->pcx_time = 0;
 444        pipe->data_mode = data_mode;
 445        *pipep = pipe;
 446
 447        return 0;
 448}
 449
 450
 451/*
 452 * vx_free_pipe - release a pipe
 453 * @pipe: pipe to be released
 454 */
 455static int vx_free_pipe(struct vx_core *chip, struct vx_pipe *pipe)
 456{
 457        struct vx_rmh rmh;
 458
 459        vx_init_rmh(&rmh, CMD_FREE_PIPE);
 460        vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
 461        vx_send_msg(chip, &rmh);
 462
 463        kfree(pipe);
 464        return 0;
 465}
 466
 467
 468/*
 469 * vx_start_stream - start the stream
 470 *
 471 * called from trigger callback only
 472 */
 473static int vx_start_stream(struct vx_core *chip, struct vx_pipe *pipe)
 474{
 475        struct vx_rmh rmh;
 476
 477        vx_init_rmh(&rmh, CMD_START_ONE_STREAM);
 478        vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
 479        vx_set_differed_time(chip, &rmh, pipe);
 480        return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ 
 481}
 482
 483
 484/*
 485 * vx_stop_stream - stop the stream
 486 *
 487 * called from trigger callback only
 488 */
 489static int vx_stop_stream(struct vx_core *chip, struct vx_pipe *pipe)
 490{
 491        struct vx_rmh rmh;
 492
 493        vx_init_rmh(&rmh, CMD_STOP_STREAM);
 494        vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
 495        return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ 
 496}
 497
 498
 499/*
 500 * playback hw information
 501 */
 502
 503static struct snd_pcm_hardware vx_pcm_playback_hw = {
 504        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 505                                 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/
 506                                 /*SNDRV_PCM_INFO_RESUME*/),
 507        .formats =              (/*SNDRV_PCM_FMTBIT_U8 |*/
 508                                 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE),
 509        .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
 510        .rate_min =             5000,
 511        .rate_max =             48000,
 512        .channels_min =         1,
 513        .channels_max =         2,
 514        .buffer_bytes_max =     (128*1024),
 515        .period_bytes_min =     126,
 516        .period_bytes_max =     (128*1024),
 517        .periods_min =          2,
 518        .periods_max =          VX_MAX_PERIODS,
 519        .fifo_size =            126,
 520};
 521
 522
 523static void vx_pcm_delayed_start(unsigned long arg);
 524
 525/*
 526 * vx_pcm_playback_open - open callback for playback
 527 */
 528static int vx_pcm_playback_open(struct snd_pcm_substream *subs)
 529{
 530        struct snd_pcm_runtime *runtime = subs->runtime;
 531        struct vx_core *chip = snd_pcm_substream_chip(subs);
 532        struct vx_pipe *pipe = NULL;
 533        unsigned int audio;
 534        int err;
 535
 536        if (chip->chip_status & VX_STAT_IS_STALE)
 537                return -EBUSY;
 538
 539        audio = subs->pcm->device * 2;
 540        if (snd_BUG_ON(audio >= chip->audio_outs))
 541                return -EINVAL;
 542        
 543        /* playback pipe may have been already allocated for monitoring */
 544        pipe = chip->playback_pipes[audio];
 545        if (! pipe) {
 546                /* not allocated yet */
 547                err = vx_alloc_pipe(chip, 0, audio, 2, &pipe); /* stereo playback */
 548                if (err < 0)
 549                        return err;
 550                chip->playback_pipes[audio] = pipe;
 551        }
 552        /* open for playback */
 553        pipe->references++;
 554
 555        pipe->substream = subs;
 556        tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
 557        chip->playback_pipes[audio] = pipe;
 558
 559        runtime->hw = vx_pcm_playback_hw;
 560        runtime->hw.period_bytes_min = chip->ibl.size;
 561        runtime->private_data = pipe;
 562
 563        /* align to 4 bytes (otherwise will be problematic when 24bit is used) */ 
 564        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
 565        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
 566
 567        return 0;
 568}
 569
 570/*
 571 * vx_pcm_playback_close - close callback for playback
 572 */
 573static int vx_pcm_playback_close(struct snd_pcm_substream *subs)
 574{
 575        struct vx_core *chip = snd_pcm_substream_chip(subs);
 576        struct vx_pipe *pipe;
 577
 578        if (! subs->runtime->private_data)
 579                return -EINVAL;
 580
 581        pipe = subs->runtime->private_data;
 582
 583        if (--pipe->references == 0) {
 584                chip->playback_pipes[pipe->number] = NULL;
 585                vx_free_pipe(chip, pipe);
 586        }
 587
 588        return 0;
 589
 590}
 591
 592
 593/*
 594 * vx_notify_end_of_buffer - send "end-of-buffer" notifier at the given pipe
 595 * @pipe: the pipe to notify
 596 *
 597 * NB: call with a certain lock.
 598 */
 599static int vx_notify_end_of_buffer(struct vx_core *chip, struct vx_pipe *pipe)
 600{
 601        int err;
 602        struct vx_rmh rmh;  /* use a temporary rmh here */
 603
 604        /* Toggle Dsp Host Interface into Message mode */
 605        vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);
 606        vx_init_rmh(&rmh, CMD_NOTIFY_END_OF_BUFFER);
 607        vx_set_stream_cmd_params(&rmh, 0, pipe->number);
 608        err = vx_send_msg_nolock(chip, &rmh);
 609        if (err < 0)
 610                return err;
 611        /* Toggle Dsp Host Interface back to sound transfer mode */
 612        vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);
 613        return 0;
 614}
 615
 616/*
 617 * vx_pcm_playback_transfer_chunk - transfer a single chunk
 618 * @subs: substream
 619 * @pipe: the pipe to transfer
 620 * @size: chunk size in bytes
 621 *
 622 * transfer a single buffer chunk.  EOB notificaton is added after that.
 623 * called from the interrupt handler, too.
 624 *
 625 * return 0 if ok.
 626 */
 627static int vx_pcm_playback_transfer_chunk(struct vx_core *chip,
 628                                          struct snd_pcm_runtime *runtime,
 629                                          struct vx_pipe *pipe, int size)
 630{
 631        int space, err = 0;
 632
 633        space = vx_query_hbuffer_size(chip, pipe);
 634        if (space < 0) {
 635                /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
 636                vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
 637                snd_printd("error hbuffer\n");
 638                return space;
 639        }
 640        if (space < size) {
 641                vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
 642                snd_printd("no enough hbuffer space %d\n", space);
 643                return -EIO; /* XRUN */
 644        }
 645                
 646        /* we don't need irqsave here, because this function
 647         * is called from either trigger callback or irq handler
 648         */
 649        spin_lock(&chip->lock); 
 650        vx_pseudo_dma_write(chip, runtime, pipe, size);
 651        err = vx_notify_end_of_buffer(chip, pipe);
 652        /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
 653        vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
 654        spin_unlock(&chip->lock);
 655        return err;
 656}
 657
 658/*
 659 * update the position of the given pipe.
 660 * pipe->position is updated and wrapped within the buffer size.
 661 * pipe->transferred is updated, too, but the size is not wrapped,
 662 * so that the caller can check the total transferred size later
 663 * (to call snd_pcm_period_elapsed).
 664 */
 665static int vx_update_pipe_position(struct vx_core *chip,
 666                                   struct snd_pcm_runtime *runtime,
 667                                   struct vx_pipe *pipe)
 668{
 669        struct vx_rmh rmh;
 670        int err, update;
 671        u64 count;
 672
 673        vx_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT);
 674        vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
 675        err = vx_send_msg(chip, &rmh);
 676        if (err < 0)
 677                return err;
 678
 679        count = ((u64)(rmh.Stat[0] & 0xfffff) << 24) | (u64)rmh.Stat[1];
 680        update = (int)(count - pipe->cur_count);
 681        pipe->cur_count = count;
 682        pipe->position += update;
 683        if (pipe->position >= (int)runtime->buffer_size)
 684                pipe->position %= runtime->buffer_size;
 685        pipe->transferred += update;
 686        return 0;
 687}
 688
 689/*
 690 * transfer the pending playback buffer data to DSP
 691 * called from interrupt handler
 692 */
 693static void vx_pcm_playback_transfer(struct vx_core *chip,
 694                                     struct snd_pcm_substream *subs,
 695                                     struct vx_pipe *pipe, int nchunks)
 696{
 697        int i, err;
 698        struct snd_pcm_runtime *runtime = subs->runtime;
 699
 700        if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))
 701                return;
 702        for (i = 0; i < nchunks; i++) {
 703                if ((err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe,
 704                                                          chip->ibl.size)) < 0)
 705                        return;
 706        }
 707}
 708
 709/*
 710 * update the playback position and call snd_pcm_period_elapsed() if necessary
 711 * called from interrupt handler
 712 */
 713static void vx_pcm_playback_update(struct vx_core *chip,
 714                                   struct snd_pcm_substream *subs,
 715                                   struct vx_pipe *pipe)
 716{
 717        int err;
 718        struct snd_pcm_runtime *runtime = subs->runtime;
 719
 720        if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) {
 721                if ((err = vx_update_pipe_position(chip, runtime, pipe)) < 0)
 722                        return;
 723                if (pipe->transferred >= (int)runtime->period_size) {
 724                        pipe->transferred %= runtime->period_size;
 725                        snd_pcm_period_elapsed(subs);
 726                }
 727        }
 728}
 729
 730/*
 731 * start the stream and pipe.
 732 * this function is called from tasklet, which is invoked by the trigger
 733 * START callback.
 734 */
 735static void vx_pcm_delayed_start(unsigned long arg)
 736{
 737        struct snd_pcm_substream *subs = (struct snd_pcm_substream *)arg;
 738        struct vx_core *chip = subs->pcm->private_data;
 739        struct vx_pipe *pipe = subs->runtime->private_data;
 740        int err;
 741
 742        /*  printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/
 743
 744        if ((err = vx_start_stream(chip, pipe)) < 0) {
 745                snd_printk(KERN_ERR "vx: cannot start stream\n");
 746                return;
 747        }
 748        if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) {
 749                snd_printk(KERN_ERR "vx: cannot start pipe\n");
 750                return;
 751        }
 752        /*   printk( KERN_DEBUG "dddd tasklet delayed start jiffies = %ld \n", jiffies);*/
 753}
 754
 755/*
 756 * vx_pcm_playback_trigger - trigger callback for playback
 757 */
 758static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
 759{
 760        struct vx_core *chip = snd_pcm_substream_chip(subs);
 761        struct vx_pipe *pipe = subs->runtime->private_data;
 762        int err;
 763
 764        if (chip->chip_status & VX_STAT_IS_STALE)
 765                return -EBUSY;
 766                
 767        switch (cmd) {
 768        case SNDRV_PCM_TRIGGER_START:
 769        case SNDRV_PCM_TRIGGER_RESUME:
 770                if (! pipe->is_capture)
 771                        vx_pcm_playback_transfer(chip, subs, pipe, 2);
 772                /* FIXME:
 773                 * we trigger the pipe using tasklet, so that the interrupts are
 774                 * issued surely after the trigger is completed.
 775                 */ 
 776                tasklet_schedule(&pipe->start_tq);
 777                chip->pcm_running++;
 778                pipe->running = 1;
 779                break;
 780        case SNDRV_PCM_TRIGGER_STOP:
 781        case SNDRV_PCM_TRIGGER_SUSPEND:
 782                vx_toggle_pipe(chip, pipe, 0);
 783                vx_stop_pipe(chip, pipe);
 784                vx_stop_stream(chip, pipe);
 785                chip->pcm_running--;
 786                pipe->running = 0;
 787                break;
 788        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 789                if ((err = vx_toggle_pipe(chip, pipe, 0)) < 0)
 790                        return err;
 791                break;
 792        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 793                if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0)
 794                        return err;
 795                break;
 796        default:
 797                return -EINVAL;
 798        }
 799        return 0;
 800}
 801
 802/*
 803 * vx_pcm_playback_pointer - pointer callback for playback
 804 */
 805static snd_pcm_uframes_t vx_pcm_playback_pointer(struct snd_pcm_substream *subs)
 806{
 807        struct snd_pcm_runtime *runtime = subs->runtime;
 808        struct vx_pipe *pipe = runtime->private_data;
 809        return pipe->position;
 810}
 811
 812/*
 813 * vx_pcm_hw_params - hw_params callback for playback and capture
 814 */
 815static int vx_pcm_hw_params(struct snd_pcm_substream *subs,
 816                                     struct snd_pcm_hw_params *hw_params)
 817{
 818        return snd_pcm_lib_alloc_vmalloc_32_buffer
 819                                        (subs, params_buffer_bytes(hw_params));
 820}
 821
 822/*
 823 * vx_pcm_hw_free - hw_free callback for playback and capture
 824 */
 825static int vx_pcm_hw_free(struct snd_pcm_substream *subs)
 826{
 827        return snd_pcm_lib_free_vmalloc_buffer(subs);
 828}
 829
 830/*
 831 * vx_pcm_prepare - prepare callback for playback and capture
 832 */
 833static int vx_pcm_prepare(struct snd_pcm_substream *subs)
 834{
 835        struct vx_core *chip = snd_pcm_substream_chip(subs);
 836        struct snd_pcm_runtime *runtime = subs->runtime;
 837        struct vx_pipe *pipe = runtime->private_data;
 838        int err, data_mode;
 839        // int max_size, nchunks;
 840
 841        if (chip->chip_status & VX_STAT_IS_STALE)
 842                return -EBUSY;
 843
 844        data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;
 845        if (data_mode != pipe->data_mode && ! pipe->is_capture) {
 846                /* IEC958 status (raw-mode) was changed */
 847                /* we reopen the pipe */
 848                struct vx_rmh rmh;
 849                snd_printdd(KERN_DEBUG "reopen the pipe with data_mode = %d\n", data_mode);
 850                vx_init_rmh(&rmh, CMD_FREE_PIPE);
 851                vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0);
 852                if ((err = vx_send_msg(chip, &rmh)) < 0)
 853                        return err;
 854                vx_init_rmh(&rmh, CMD_RES_PIPE);
 855                vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels);
 856                if (data_mode)
 857                        rmh.Cmd[0] |= BIT_DATA_MODE;
 858                if ((err = vx_send_msg(chip, &rmh)) < 0)
 859                        return err;
 860                pipe->data_mode = data_mode;
 861        }
 862
 863        if (chip->pcm_running && chip->freq != runtime->rate) {
 864                snd_printk(KERN_ERR "vx: cannot set different clock %d "
 865                           "from the current %d\n", runtime->rate, chip->freq);
 866                return -EINVAL;
 867        }
 868        vx_set_clock(chip, runtime->rate);
 869
 870        if ((err = vx_set_format(chip, pipe, runtime)) < 0)
 871                return err;
 872
 873        if (vx_is_pcmcia(chip)) {
 874                pipe->align = 2; /* 16bit word */
 875        } else {
 876                pipe->align = 4; /* 32bit word */
 877        }
 878
 879        pipe->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size);
 880        pipe->period_bytes = frames_to_bytes(runtime, runtime->period_size);
 881        pipe->hw_ptr = 0;
 882
 883        /* set the timestamp */
 884        vx_update_pipe_position(chip, runtime, pipe);
 885        /* clear again */
 886        pipe->transferred = 0;
 887        pipe->position = 0;
 888
 889        pipe->prepared = 1;
 890
 891        return 0;
 892}
 893
 894
 895/*
 896 * operators for PCM playback
 897 */
 898static struct snd_pcm_ops vx_pcm_playback_ops = {
 899        .open =         vx_pcm_playback_open,
 900        .close =        vx_pcm_playback_close,
 901        .ioctl =        snd_pcm_lib_ioctl,
 902        .hw_params =    vx_pcm_hw_params,
 903        .hw_free =      vx_pcm_hw_free,
 904        .prepare =      vx_pcm_prepare,
 905        .trigger =      vx_pcm_trigger,
 906        .pointer =      vx_pcm_playback_pointer,
 907        .page =         snd_pcm_lib_get_vmalloc_page,
 908        .mmap =         snd_pcm_lib_mmap_vmalloc,
 909};
 910
 911
 912/*
 913 * playback hw information
 914 */
 915
 916static struct snd_pcm_hardware vx_pcm_capture_hw = {
 917        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 918                                 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/
 919                                 /*SNDRV_PCM_INFO_RESUME*/),
 920        .formats =              (/*SNDRV_PCM_FMTBIT_U8 |*/
 921                                 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE),
 922        .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
 923        .rate_min =             5000,
 924        .rate_max =             48000,
 925        .channels_min =         1,
 926        .channels_max =         2,
 927        .buffer_bytes_max =     (128*1024),
 928        .period_bytes_min =     126,
 929        .period_bytes_max =     (128*1024),
 930        .periods_min =          2,
 931        .periods_max =          VX_MAX_PERIODS,
 932        .fifo_size =            126,
 933};
 934
 935
 936/*
 937 * vx_pcm_capture_open - open callback for capture
 938 */
 939static int vx_pcm_capture_open(struct snd_pcm_substream *subs)
 940{
 941        struct snd_pcm_runtime *runtime = subs->runtime;
 942        struct vx_core *chip = snd_pcm_substream_chip(subs);
 943        struct vx_pipe *pipe;
 944        struct vx_pipe *pipe_out_monitoring = NULL;
 945        unsigned int audio;
 946        int err;
 947
 948        if (chip->chip_status & VX_STAT_IS_STALE)
 949                return -EBUSY;
 950
 951        audio = subs->pcm->device * 2;
 952        if (snd_BUG_ON(audio >= chip->audio_ins))
 953                return -EINVAL;
 954        err = vx_alloc_pipe(chip, 1, audio, 2, &pipe);
 955        if (err < 0)
 956                return err;
 957        pipe->substream = subs;
 958        tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
 959        chip->capture_pipes[audio] = pipe;
 960
 961        /* check if monitoring is needed */
 962        if (chip->audio_monitor_active[audio]) {
 963                pipe_out_monitoring = chip->playback_pipes[audio];
 964                if (! pipe_out_monitoring) {
 965                        /* allocate a pipe */
 966                        err = vx_alloc_pipe(chip, 0, audio, 2, &pipe_out_monitoring);
 967                        if (err < 0)
 968                                return err;
 969                        chip->playback_pipes[audio] = pipe_out_monitoring;
 970                }
 971                pipe_out_monitoring->references++;
 972                /* 
 973                   if an output pipe is available, it's audios still may need to be 
 974                   unmuted. hence we'll have to call a mixer entry point.
 975                */
 976                vx_set_monitor_level(chip, audio, chip->audio_monitor[audio],
 977                                     chip->audio_monitor_active[audio]);
 978                /* assuming stereo */
 979                vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1],
 980                                     chip->audio_monitor_active[audio+1]); 
 981        }
 982
 983        pipe->monitoring_pipe = pipe_out_monitoring; /* default value NULL */
 984
 985        runtime->hw = vx_pcm_capture_hw;
 986        runtime->hw.period_bytes_min = chip->ibl.size;
 987        runtime->private_data = pipe;
 988
 989        /* align to 4 bytes (otherwise will be problematic when 24bit is used) */ 
 990        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
 991        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
 992
 993        return 0;
 994}
 995
 996/*
 997 * vx_pcm_capture_close - close callback for capture
 998 */
 999static int vx_pcm_capture_close(struct snd_pcm_substream *subs)
1000{
1001        struct vx_core *chip = snd_pcm_substream_chip(subs);
1002        struct vx_pipe *pipe;
1003        struct vx_pipe *pipe_out_monitoring;
1004        
1005        if (! subs->runtime->private_data)
1006                return -EINVAL;
1007        pipe = subs->runtime->private_data;
1008        chip->capture_pipes[pipe->number] = NULL;
1009
1010        pipe_out_monitoring = pipe->monitoring_pipe;
1011
1012        /*
1013          if an output pipe is attached to this input, 
1014          check if it needs to be released.
1015        */
1016        if (pipe_out_monitoring) {
1017                if (--pipe_out_monitoring->references == 0) {
1018                        vx_free_pipe(chip, pipe_out_monitoring);
1019                        chip->playback_pipes[pipe->number] = NULL;
1020                        pipe->monitoring_pipe = NULL;
1021                }
1022        }
1023        
1024        vx_free_pipe(chip, pipe);
1025        return 0;
1026}
1027
1028
1029
1030#define DMA_READ_ALIGN  6       /* hardware alignment for read */
1031
1032/*
1033 * vx_pcm_capture_update - update the capture buffer
1034 */
1035static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream *subs,
1036                                  struct vx_pipe *pipe)
1037{
1038        int size, space, count;
1039        struct snd_pcm_runtime *runtime = subs->runtime;
1040
1041        if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))
1042                return;
1043
1044        size = runtime->buffer_size - snd_pcm_capture_avail(runtime);
1045        if (! size)
1046                return;
1047        size = frames_to_bytes(runtime, size);
1048        space = vx_query_hbuffer_size(chip, pipe);
1049        if (space < 0)
1050                goto _error;
1051        if (size > space)
1052                size = space;
1053        size = (size / 3) * 3; /* align to 3 bytes */
1054        if (size < DMA_READ_ALIGN)
1055                goto _error;
1056
1057        /* keep the last 6 bytes, they will be read after disconnection */
1058        count = size - DMA_READ_ALIGN;
1059        /* read bytes until the current pointer reaches to the aligned position
1060         * for word-transfer
1061         */
1062        while (count > 0) {
1063                if ((pipe->hw_ptr % pipe->align) == 0)
1064                        break;
1065                if (vx_wait_for_rx_full(chip) < 0)
1066                        goto _error;
1067                vx_pcm_read_per_bytes(chip, runtime, pipe);
1068                count -= 3;
1069        }
1070        if (count > 0) {
1071                /* ok, let's accelerate! */
1072                int align = pipe->align * 3;
1073                space = (count / align) * align;
1074                vx_pseudo_dma_read(chip, runtime, pipe, space);
1075                count -= space;
1076        }
1077        /* read the rest of bytes */
1078        while (count > 0) {
1079                if (vx_wait_for_rx_full(chip) < 0)
1080                        goto _error;
1081                vx_pcm_read_per_bytes(chip, runtime, pipe);
1082                count -= 3;
1083        }
1084        /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
1085        vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
1086        /* read the last pending 6 bytes */
1087        count = DMA_READ_ALIGN;
1088        while (count > 0) {
1089                vx_pcm_read_per_bytes(chip, runtime, pipe);
1090                count -= 3;
1091        }
1092        /* update the position */
1093        pipe->transferred += size;
1094        if (pipe->transferred >= pipe->period_bytes) {
1095                pipe->transferred %= pipe->period_bytes;
1096                snd_pcm_period_elapsed(subs);
1097        }
1098        return;
1099
1100 _error:
1101        /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
1102        vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
1103        return;
1104}
1105
1106/*
1107 * vx_pcm_capture_pointer - pointer callback for capture
1108 */
1109static snd_pcm_uframes_t vx_pcm_capture_pointer(struct snd_pcm_substream *subs)
1110{
1111        struct snd_pcm_runtime *runtime = subs->runtime;
1112        struct vx_pipe *pipe = runtime->private_data;
1113        return bytes_to_frames(runtime, pipe->hw_ptr);
1114}
1115
1116/*
1117 * operators for PCM capture
1118 */
1119static struct snd_pcm_ops vx_pcm_capture_ops = {
1120        .open =         vx_pcm_capture_open,
1121        .close =        vx_pcm_capture_close,
1122        .ioctl =        snd_pcm_lib_ioctl,
1123        .hw_params =    vx_pcm_hw_params,
1124        .hw_free =      vx_pcm_hw_free,
1125        .prepare =      vx_pcm_prepare,
1126        .trigger =      vx_pcm_trigger,
1127        .pointer =      vx_pcm_capture_pointer,
1128        .page =         snd_pcm_lib_get_vmalloc_page,
1129        .mmap =         snd_pcm_lib_mmap_vmalloc,
1130};
1131
1132
1133/*
1134 * interrupt handler for pcm streams
1135 */
1136void vx_pcm_update_intr(struct vx_core *chip, unsigned int events)
1137{
1138        unsigned int i;
1139        struct vx_pipe *pipe;
1140
1141#define EVENT_MASK      (END_OF_BUFFER_EVENTS_PENDING|ASYNC_EVENTS_PENDING)
1142
1143        if (events & EVENT_MASK) {
1144                vx_init_rmh(&chip->irq_rmh, CMD_ASYNC);
1145                if (events & ASYNC_EVENTS_PENDING)
1146                        chip->irq_rmh.Cmd[0] |= 0x00000001;     /* SEL_ASYNC_EVENTS */
1147                if (events & END_OF_BUFFER_EVENTS_PENDING)
1148                        chip->irq_rmh.Cmd[0] |= 0x00000002;     /* SEL_END_OF_BUF_EVENTS */
1149
1150                if (vx_send_msg(chip, &chip->irq_rmh) < 0) {
1151                        snd_printdd(KERN_ERR "msg send error!!\n");
1152                        return;
1153                }
1154
1155                i = 1;
1156                while (i < chip->irq_rmh.LgStat) {
1157                        int p, buf, capture, eob;
1158                        p = chip->irq_rmh.Stat[i] & MASK_FIRST_FIELD;
1159                        capture = (chip->irq_rmh.Stat[i] & 0x400000) ? 1 : 0;
1160                        eob = (chip->irq_rmh.Stat[i] & 0x800000) ? 1 : 0;
1161                        i++;
1162                        if (events & ASYNC_EVENTS_PENDING)
1163                                i++;
1164                        buf = 1; /* force to transfer */
1165                        if (events & END_OF_BUFFER_EVENTS_PENDING) {
1166                                if (eob)
1167                                        buf = chip->irq_rmh.Stat[i];
1168                                i++;
1169                        }
1170                        if (capture)
1171                                continue;
1172                        if (snd_BUG_ON(p < 0 || p >= chip->audio_outs))
1173                                continue;
1174                        pipe = chip->playback_pipes[p];
1175                        if (pipe && pipe->substream) {
1176                                vx_pcm_playback_update(chip, pipe->substream, pipe);
1177                                vx_pcm_playback_transfer(chip, pipe->substream, pipe, buf);
1178                        }
1179                }
1180        }
1181
1182        /* update the capture pcm pointers as frequently as possible */
1183        for (i = 0; i < chip->audio_ins; i++) {
1184                pipe = chip->capture_pipes[i];
1185                if (pipe && pipe->substream)
1186                        vx_pcm_capture_update(chip, pipe->substream, pipe);
1187        }
1188}
1189
1190
1191/*
1192 * vx_init_audio_io - check the available audio i/o and allocate pipe arrays
1193 */
1194static int vx_init_audio_io(struct vx_core *chip)
1195{
1196        struct vx_rmh rmh;
1197        int preferred;
1198
1199        vx_init_rmh(&rmh, CMD_SUPPORTED);
1200        if (vx_send_msg(chip, &rmh) < 0) {
1201                snd_printk(KERN_ERR "vx: cannot get the supported audio data\n");
1202                return -ENXIO;
1203        }
1204
1205        chip->audio_outs = rmh.Stat[0] & MASK_FIRST_FIELD;
1206        chip->audio_ins = (rmh.Stat[0] >> (FIELD_SIZE*2)) & MASK_FIRST_FIELD;
1207        chip->audio_info = rmh.Stat[1];
1208
1209        /* allocate pipes */
1210        chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL);
1211        if (!chip->playback_pipes)
1212                return -ENOMEM;
1213        chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL);
1214        if (!chip->capture_pipes) {
1215                kfree(chip->playback_pipes);
1216                return -ENOMEM;
1217        }
1218
1219        preferred = chip->ibl.size;
1220        chip->ibl.size = 0;
1221        vx_set_ibl(chip, &chip->ibl); /* query the info */
1222        if (preferred > 0) {
1223                chip->ibl.size = ((preferred + chip->ibl.granularity - 1) /
1224                                  chip->ibl.granularity) * chip->ibl.granularity;
1225                if (chip->ibl.size > chip->ibl.max_size)
1226                        chip->ibl.size = chip->ibl.max_size;
1227        } else
1228                chip->ibl.size = chip->ibl.min_size; /* set to the minimum */
1229        vx_set_ibl(chip, &chip->ibl);
1230
1231        return 0;
1232}
1233
1234
1235/*
1236 * free callback for pcm
1237 */
1238static void snd_vx_pcm_free(struct snd_pcm *pcm)
1239{
1240        struct vx_core *chip = pcm->private_data;
1241        chip->pcm[pcm->device] = NULL;
1242        kfree(chip->playback_pipes);
1243        chip->playback_pipes = NULL;
1244        kfree(chip->capture_pipes);
1245        chip->capture_pipes = NULL;
1246}
1247
1248/*
1249 * snd_vx_pcm_new - create and initialize a pcm
1250 */
1251int snd_vx_pcm_new(struct vx_core *chip)
1252{
1253        struct snd_pcm *pcm;
1254        unsigned int i;
1255        int err;
1256
1257        if ((err = vx_init_audio_io(chip)) < 0)
1258                return err;
1259
1260        for (i = 0; i < chip->hw->num_codecs; i++) {
1261                unsigned int outs, ins;
1262                outs = chip->audio_outs > i * 2 ? 1 : 0;
1263                ins = chip->audio_ins > i * 2 ? 1 : 0;
1264                if (! outs && ! ins)
1265                        break;
1266                err = snd_pcm_new(chip->card, "VX PCM", i,
1267                                  outs, ins, &pcm);
1268                if (err < 0)
1269                        return err;
1270                if (outs)
1271                        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &vx_pcm_playback_ops);
1272                if (ins)
1273                        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops);
1274
1275                pcm->private_data = chip;
1276                pcm->private_free = snd_vx_pcm_free;
1277                pcm->info_flags = 0;
1278                strcpy(pcm->name, chip->card->shortname);
1279                chip->pcm[i] = pcm;
1280        }
1281
1282        return 0;
1283}
1284