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