1235 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for Digigram VX soundcards4 *5 * PCM part6 *7 * Copyright (c) 2002,2003 by Takashi Iwai <tiwai@suse.de>8 *9 * STRATEGY10 * for playback, we send series of "chunks", which size is equal with the11 * IBL size, typically 126 samples. at each end of chunk, the end-of-buffer12 * 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() will17 * 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 each21 * interrupt (capture stream has no EOB notification). if the pending22 * data is accumulated to the period size, snd_pcm_period_elapsed() is23 * called and the pointer is updated.24 *25 * the current point of read buffer is kept in pipe->hw_ptr. note that26 * this is in bytes.27 *28 * TODO29 * - 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 set70 * @dsp_time: the pointer for RMH status time array71 */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 specified81 * @rmh: the rmh record to modify82 * @pipe: the pipe to be checked83 *84 * if the pipe is programmed with the differed time, set the DSP time85 * 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 command120 * @pipe: the affected pipe121 * @data: format bitmask122 */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 pipe145 * @pipe: the affected pipe146 * @runtime: pcm runtime instance to be referred147 *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 size178 */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 dev_dbg(chip->card->dev,194 "%s: size = %d, max = %d, min = %d, gran = %d\n",195 __func__, info->size, info->max_size, info->min_size,196 info->granularity);197 return 0;198}199 200 201/*202 * vx_get_pipe_state - get the state of a pipe203 * @pipe: the pipe to be checked204 * @state: the pointer for the returned state205 *206 * checks the state of a given pipe, and stores the state (1 = running,207 * 0 = paused) on the given pointer.208 *209 * called from trigger callback only210 */211static int vx_get_pipe_state(struct vx_core *chip, struct vx_pipe *pipe, int *state)212{213 int err;214 struct vx_rmh rmh;215 216 vx_init_rmh(&rmh, CMD_PIPE_STATE);217 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);218 err = vx_send_msg(chip, &rmh);219 if (! err)220 *state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0;221 return err;222}223 224 225/*226 * vx_query_hbuffer_size - query available h-buffer size in bytes227 * @pipe: the pipe to be checked228 *229 * return the available size on h-buffer in bytes,230 * or a negative error code.231 *232 * NOTE: calling this function always switches to the stream mode.233 * you'll need to disconnect the host to get back to the234 * normal mode.235 */236static int vx_query_hbuffer_size(struct vx_core *chip, struct vx_pipe *pipe)237{238 int result;239 struct vx_rmh rmh;240 241 vx_init_rmh(&rmh, CMD_SIZE_HBUFFER);242 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);243 if (pipe->is_capture)244 rmh.Cmd[0] |= 0x00000001;245 result = vx_send_msg(chip, &rmh);246 if (! result)247 result = rmh.Stat[0] & 0xffff;248 return result;249}250 251 252/*253 * vx_pipe_can_start - query whether a pipe is ready for start254 * @pipe: the pipe to be checked255 *256 * return 1 if ready, 0 if not ready, and negative value on error.257 *258 * called from trigger callback only259 */260static int vx_pipe_can_start(struct vx_core *chip, struct vx_pipe *pipe)261{262 int err;263 struct vx_rmh rmh;264 265 vx_init_rmh(&rmh, CMD_CAN_START_PIPE);266 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);267 rmh.Cmd[0] |= 1;268 269 err = vx_send_msg(chip, &rmh);270 if (! err) {271 if (rmh.Stat[0])272 err = 1;273 }274 return err;275}276 277/*278 * vx_conf_pipe - tell the pipe to stand by and wait for IRQA.279 * @pipe: the pipe to be configured280 */281static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe)282{283 struct vx_rmh rmh;284 285 vx_init_rmh(&rmh, CMD_CONF_PIPE);286 if (pipe->is_capture)287 rmh.Cmd[0] |= COMMAND_RECORD_MASK;288 rmh.Cmd[1] = 1 << pipe->number;289 return vx_send_msg(chip, &rmh);290}291 292/*293 * vx_send_irqa - trigger IRQA294 */295static int vx_send_irqa(struct vx_core *chip)296{297 struct vx_rmh rmh;298 299 vx_init_rmh(&rmh, CMD_SEND_IRQA);300 return vx_send_msg(chip, &rmh);301}302 303 304#define MAX_WAIT_FOR_DSP 250305/*306 * vx boards do not support inter-card sync, besides307 * only 126 samples require to be prepared before a pipe can start308 */309#define CAN_START_DELAY 2 /* wait 2ms only before asking if the pipe is ready*/310#define WAIT_STATE_DELAY 2 /* wait 2ms after irqA was requested and check if the pipe state toggled*/311 312/*313 * vx_toggle_pipe - start / pause a pipe314 * @pipe: the pipe to be triggered315 * @state: start = 1, pause = 0316 *317 * called from trigger callback only318 *319 */320static int vx_toggle_pipe(struct vx_core *chip, struct vx_pipe *pipe, int state)321{322 int err, i, cur_state;323 324 /* Check the pipe is not already in the requested state */325 if (vx_get_pipe_state(chip, pipe, &cur_state) < 0)326 return -EBADFD;327 if (state == cur_state)328 return 0;329 330 /* If a start is requested, ask the DSP to get prepared331 * and wait for a positive acknowledge (when there are332 * enough sound buffer for this pipe)333 */334 if (state) {335 for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) {336 err = vx_pipe_can_start(chip, pipe);337 if (err > 0)338 break;339 /* Wait for a few, before asking again340 * to avoid flooding the DSP with our requests341 */342 mdelay(1);343 }344 }345 346 err = vx_conf_pipe(chip, pipe);347 if (err < 0)348 return err;349 350 err = vx_send_irqa(chip);351 if (err < 0)352 return err;353 354 /* If it completes successfully, wait for the pipes355 * reaching the expected state before returning356 * Check one pipe only (since they are synchronous)357 */358 for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {359 err = vx_get_pipe_state(chip, pipe, &cur_state);360 if (err < 0 || cur_state == state)361 break;362 err = -EIO;363 mdelay(1);364 }365 return err < 0 ? -EIO : 0;366}367 368 369/*370 * vx_stop_pipe - stop a pipe371 * @pipe: the pipe to be stopped372 *373 * called from trigger callback only374 */375static int vx_stop_pipe(struct vx_core *chip, struct vx_pipe *pipe)376{377 struct vx_rmh rmh;378 vx_init_rmh(&rmh, CMD_STOP_PIPE);379 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);380 return vx_send_msg(chip, &rmh);381}382 383 384/*385 * vx_alloc_pipe - allocate a pipe and initialize the pipe instance386 * @capture: 0 = playback, 1 = capture operation387 * @audioid: the audio id to be assigned388 * @num_audio: number of audio channels389 * @pipep: the returned pipe instance390 *391 * return 0 on success, or a negative error code.392 */393static int vx_alloc_pipe(struct vx_core *chip, int capture,394 int audioid, int num_audio,395 struct vx_pipe **pipep)396{397 int err;398 struct vx_pipe *pipe;399 struct vx_rmh rmh;400 int data_mode;401 402 *pipep = NULL;403 vx_init_rmh(&rmh, CMD_RES_PIPE);404 vx_set_pipe_cmd_params(&rmh, capture, audioid, num_audio);405#if 0 // NYI406 if (underrun_skip_sound)407 rmh.Cmd[0] |= BIT_SKIP_SOUND;408#endif // NYI409 data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;410 if (! capture && data_mode)411 rmh.Cmd[0] |= BIT_DATA_MODE;412 err = vx_send_msg(chip, &rmh);413 if (err < 0)414 return err;415 416 /* initialize the pipe record */417 pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);418 if (! pipe) {419 /* release the pipe */420 vx_init_rmh(&rmh, CMD_FREE_PIPE);421 vx_set_pipe_cmd_params(&rmh, capture, audioid, 0);422 vx_send_msg(chip, &rmh);423 return -ENOMEM;424 }425 426 /* the pipe index should be identical with the audio index */427 pipe->number = audioid;428 pipe->is_capture = capture;429 pipe->channels = num_audio;430 pipe->differed_type = 0;431 pipe->pcx_time = 0;432 pipe->data_mode = data_mode;433 *pipep = pipe;434 435 return 0;436}437 438 439/*440 * vx_free_pipe - release a pipe441 * @pipe: pipe to be released442 */443static int vx_free_pipe(struct vx_core *chip, struct vx_pipe *pipe)444{445 struct vx_rmh rmh;446 447 vx_init_rmh(&rmh, CMD_FREE_PIPE);448 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);449 vx_send_msg(chip, &rmh);450 451 kfree(pipe);452 return 0;453}454 455 456/*457 * vx_start_stream - start the stream458 *459 * called from trigger callback only460 */461static int vx_start_stream(struct vx_core *chip, struct vx_pipe *pipe)462{463 struct vx_rmh rmh;464 465 vx_init_rmh(&rmh, CMD_START_ONE_STREAM);466 vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);467 vx_set_differed_time(chip, &rmh, pipe);468 return vx_send_msg(chip, &rmh);469}470 471 472/*473 * vx_stop_stream - stop the stream474 *475 * called from trigger callback only476 */477static int vx_stop_stream(struct vx_core *chip, struct vx_pipe *pipe)478{479 struct vx_rmh rmh;480 481 vx_init_rmh(&rmh, CMD_STOP_STREAM);482 vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);483 return vx_send_msg(chip, &rmh);484}485 486 487/*488 * playback hw information489 */490 491static const struct snd_pcm_hardware vx_pcm_playback_hw = {492 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |493 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/494 /*SNDRV_PCM_INFO_RESUME*/),495 .formats = (/*SNDRV_PCM_FMTBIT_U8 |*/496 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE),497 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,498 .rate_min = 5000,499 .rate_max = 48000,500 .channels_min = 1,501 .channels_max = 2,502 .buffer_bytes_max = (128*1024),503 .period_bytes_min = 126,504 .period_bytes_max = (128*1024),505 .periods_min = 2,506 .periods_max = VX_MAX_PERIODS,507 .fifo_size = 126,508};509 510 511/*512 * vx_pcm_playback_open - open callback for playback513 */514static int vx_pcm_playback_open(struct snd_pcm_substream *subs)515{516 struct snd_pcm_runtime *runtime = subs->runtime;517 struct vx_core *chip = snd_pcm_substream_chip(subs);518 struct vx_pipe *pipe = NULL;519 unsigned int audio;520 int err;521 522 if (chip->chip_status & VX_STAT_IS_STALE)523 return -EBUSY;524 525 audio = subs->pcm->device * 2;526 if (snd_BUG_ON(audio >= chip->audio_outs))527 return -EINVAL;528 529 /* playback pipe may have been already allocated for monitoring */530 pipe = chip->playback_pipes[audio];531 if (! pipe) {532 /* not allocated yet */533 err = vx_alloc_pipe(chip, 0, audio, 2, &pipe); /* stereo playback */534 if (err < 0)535 return err;536 }537 /* open for playback */538 pipe->references++;539 540 pipe->substream = subs;541 chip->playback_pipes[audio] = pipe;542 543 runtime->hw = vx_pcm_playback_hw;544 runtime->hw.period_bytes_min = chip->ibl.size;545 runtime->private_data = pipe;546 547 /* align to 4 bytes (otherwise will be problematic when 24bit is used) */ 548 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);549 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);550 551 return 0;552}553 554/*555 * vx_pcm_playback_close - close callback for playback556 */557static int vx_pcm_playback_close(struct snd_pcm_substream *subs)558{559 struct vx_core *chip = snd_pcm_substream_chip(subs);560 struct vx_pipe *pipe;561 562 if (! subs->runtime->private_data)563 return -EINVAL;564 565 pipe = subs->runtime->private_data;566 567 if (--pipe->references == 0) {568 chip->playback_pipes[pipe->number] = NULL;569 vx_free_pipe(chip, pipe);570 }571 572 return 0;573 574}575 576 577/*578 * vx_notify_end_of_buffer - send "end-of-buffer" notifier at the given pipe579 * @pipe: the pipe to notify580 *581 * NB: call with a certain lock.582 */583static int vx_notify_end_of_buffer(struct vx_core *chip, struct vx_pipe *pipe)584{585 int err;586 struct vx_rmh rmh; /* use a temporary rmh here */587 588 /* Toggle Dsp Host Interface into Message mode */589 vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);590 vx_init_rmh(&rmh, CMD_NOTIFY_END_OF_BUFFER);591 vx_set_stream_cmd_params(&rmh, 0, pipe->number);592 err = vx_send_msg_nolock(chip, &rmh);593 if (err < 0)594 return err;595 /* Toggle Dsp Host Interface back to sound transfer mode */596 vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);597 return 0;598}599 600/*601 * vx_pcm_playback_transfer_chunk - transfer a single chunk602 * @subs: substream603 * @pipe: the pipe to transfer604 * @size: chunk size in bytes605 *606 * transfer a single buffer chunk. EOB notificaton is added after that.607 * called from the interrupt handler, too.608 *609 * return 0 if ok.610 */611static int vx_pcm_playback_transfer_chunk(struct vx_core *chip,612 struct snd_pcm_runtime *runtime,613 struct vx_pipe *pipe, int size)614{615 int space, err = 0;616 617 space = vx_query_hbuffer_size(chip, pipe);618 if (space < 0) {619 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */620 vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);621 dev_dbg(chip->card->dev, "error hbuffer\n");622 return space;623 }624 if (space < size) {625 vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);626 dev_dbg(chip->card->dev, "no enough hbuffer space %d\n", space);627 return -EIO; /* XRUN */628 }629 630 /* we don't need irqsave here, because this function631 * is called from either trigger callback or irq handler632 */633 mutex_lock(&chip->lock);634 vx_pseudo_dma_write(chip, runtime, pipe, size);635 err = vx_notify_end_of_buffer(chip, pipe);636 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */637 vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);638 mutex_unlock(&chip->lock);639 return err;640}641 642/*643 * update the position of the given pipe.644 * pipe->position is updated and wrapped within the buffer size.645 * pipe->transferred is updated, too, but the size is not wrapped,646 * so that the caller can check the total transferred size later647 * (to call snd_pcm_period_elapsed).648 */649static int vx_update_pipe_position(struct vx_core *chip,650 struct snd_pcm_runtime *runtime,651 struct vx_pipe *pipe)652{653 struct vx_rmh rmh;654 int err, update;655 u64 count;656 657 vx_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT);658 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);659 err = vx_send_msg(chip, &rmh);660 if (err < 0)661 return err;662 663 count = ((u64)(rmh.Stat[0] & 0xfffff) << 24) | (u64)rmh.Stat[1];664 update = (int)(count - pipe->cur_count);665 pipe->cur_count = count;666 pipe->position += update;667 if (pipe->position >= (int)runtime->buffer_size)668 pipe->position %= runtime->buffer_size;669 pipe->transferred += update;670 return 0;671}672 673/*674 * transfer the pending playback buffer data to DSP675 * called from interrupt handler676 */677static void vx_pcm_playback_transfer(struct vx_core *chip,678 struct snd_pcm_substream *subs,679 struct vx_pipe *pipe, int nchunks)680{681 int i, err;682 struct snd_pcm_runtime *runtime = subs->runtime;683 684 if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))685 return;686 for (i = 0; i < nchunks; i++) {687 err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe,688 chip->ibl.size);689 if (err < 0)690 return;691 }692}693 694/*695 * update the playback position and call snd_pcm_period_elapsed() if necessary696 * called from interrupt handler697 */698static void vx_pcm_playback_update(struct vx_core *chip,699 struct snd_pcm_substream *subs,700 struct vx_pipe *pipe)701{702 int err;703 struct snd_pcm_runtime *runtime = subs->runtime;704 705 if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) {706 err = vx_update_pipe_position(chip, runtime, pipe);707 if (err < 0)708 return;709 if (pipe->transferred >= (int)runtime->period_size) {710 pipe->transferred %= runtime->period_size;711 snd_pcm_period_elapsed(subs);712 }713 }714}715 716/*717 * vx_pcm_playback_trigger - trigger callback for playback718 */719static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)720{721 struct vx_core *chip = snd_pcm_substream_chip(subs);722 struct vx_pipe *pipe = subs->runtime->private_data;723 int err;724 725 if (chip->chip_status & VX_STAT_IS_STALE)726 return -EBUSY;727 728 switch (cmd) {729 case SNDRV_PCM_TRIGGER_START:730 case SNDRV_PCM_TRIGGER_RESUME:731 if (! pipe->is_capture)732 vx_pcm_playback_transfer(chip, subs, pipe, 2);733 err = vx_start_stream(chip, pipe);734 if (err < 0) {735 pr_debug("vx: cannot start stream\n");736 return err;737 }738 err = vx_toggle_pipe(chip, pipe, 1);739 if (err < 0) {740 pr_debug("vx: cannot start pipe\n");741 vx_stop_stream(chip, pipe);742 return err;743 }744 chip->pcm_running++;745 pipe->running = 1;746 break;747 case SNDRV_PCM_TRIGGER_STOP:748 case SNDRV_PCM_TRIGGER_SUSPEND:749 vx_toggle_pipe(chip, pipe, 0);750 vx_stop_pipe(chip, pipe);751 vx_stop_stream(chip, pipe);752 chip->pcm_running--;753 pipe->running = 0;754 break;755 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:756 err = vx_toggle_pipe(chip, pipe, 0);757 if (err < 0)758 return err;759 break;760 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:761 err = vx_toggle_pipe(chip, pipe, 1);762 if (err < 0)763 return err;764 break;765 default:766 return -EINVAL;767 }768 return 0;769}770 771/*772 * vx_pcm_playback_pointer - pointer callback for playback773 */774static snd_pcm_uframes_t vx_pcm_playback_pointer(struct snd_pcm_substream *subs)775{776 struct snd_pcm_runtime *runtime = subs->runtime;777 struct vx_pipe *pipe = runtime->private_data;778 return pipe->position;779}780 781/*782 * vx_pcm_prepare - prepare callback for playback and capture783 */784static int vx_pcm_prepare(struct snd_pcm_substream *subs)785{786 struct vx_core *chip = snd_pcm_substream_chip(subs);787 struct snd_pcm_runtime *runtime = subs->runtime;788 struct vx_pipe *pipe = runtime->private_data;789 int err, data_mode;790 // int max_size, nchunks;791 792 if (chip->chip_status & VX_STAT_IS_STALE)793 return -EBUSY;794 795 data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;796 if (data_mode != pipe->data_mode && ! pipe->is_capture) {797 /* IEC958 status (raw-mode) was changed */798 /* we reopen the pipe */799 struct vx_rmh rmh;800 dev_dbg(chip->card->dev,801 "reopen the pipe with data_mode = %d\n", data_mode);802 vx_init_rmh(&rmh, CMD_FREE_PIPE);803 vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0);804 err = vx_send_msg(chip, &rmh);805 if (err < 0)806 return err;807 vx_init_rmh(&rmh, CMD_RES_PIPE);808 vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels);809 if (data_mode)810 rmh.Cmd[0] |= BIT_DATA_MODE;811 err = vx_send_msg(chip, &rmh);812 if (err < 0)813 return err;814 pipe->data_mode = data_mode;815 }816 817 if (chip->pcm_running && chip->freq != runtime->rate) {818 dev_err(chip->card->dev,819 "vx: cannot set different clock %d from the current %d\n",820 runtime->rate, chip->freq);821 return -EINVAL;822 }823 vx_set_clock(chip, runtime->rate);824 825 err = vx_set_format(chip, pipe, runtime);826 if (err < 0)827 return err;828 829 if (vx_is_pcmcia(chip)) {830 pipe->align = 2; /* 16bit word */831 } else {832 pipe->align = 4; /* 32bit word */833 }834 835 pipe->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size);836 pipe->period_bytes = frames_to_bytes(runtime, runtime->period_size);837 pipe->hw_ptr = 0;838 839 /* set the timestamp */840 vx_update_pipe_position(chip, runtime, pipe);841 /* clear again */842 pipe->transferred = 0;843 pipe->position = 0;844 845 pipe->prepared = 1;846 847 return 0;848}849 850 851/*852 * operators for PCM playback853 */854static const struct snd_pcm_ops vx_pcm_playback_ops = {855 .open = vx_pcm_playback_open,856 .close = vx_pcm_playback_close,857 .prepare = vx_pcm_prepare,858 .trigger = vx_pcm_trigger,859 .pointer = vx_pcm_playback_pointer,860};861 862 863/*864 * playback hw information865 */866 867static const struct snd_pcm_hardware vx_pcm_capture_hw = {868 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |869 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/870 /*SNDRV_PCM_INFO_RESUME*/),871 .formats = (/*SNDRV_PCM_FMTBIT_U8 |*/872 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE),873 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,874 .rate_min = 5000,875 .rate_max = 48000,876 .channels_min = 1,877 .channels_max = 2,878 .buffer_bytes_max = (128*1024),879 .period_bytes_min = 126,880 .period_bytes_max = (128*1024),881 .periods_min = 2,882 .periods_max = VX_MAX_PERIODS,883 .fifo_size = 126,884};885 886 887/*888 * vx_pcm_capture_open - open callback for capture889 */890static int vx_pcm_capture_open(struct snd_pcm_substream *subs)891{892 struct snd_pcm_runtime *runtime = subs->runtime;893 struct vx_core *chip = snd_pcm_substream_chip(subs);894 struct vx_pipe *pipe;895 struct vx_pipe *pipe_out_monitoring = NULL;896 unsigned int audio;897 int err;898 899 if (chip->chip_status & VX_STAT_IS_STALE)900 return -EBUSY;901 902 audio = subs->pcm->device * 2;903 if (snd_BUG_ON(audio >= chip->audio_ins))904 return -EINVAL;905 err = vx_alloc_pipe(chip, 1, audio, 2, &pipe);906 if (err < 0)907 return err;908 pipe->substream = subs;909 chip->capture_pipes[audio] = pipe;910 911 /* check if monitoring is needed */912 if (chip->audio_monitor_active[audio]) {913 pipe_out_monitoring = chip->playback_pipes[audio];914 if (! pipe_out_monitoring) {915 /* allocate a pipe */916 err = vx_alloc_pipe(chip, 0, audio, 2, &pipe_out_monitoring);917 if (err < 0)918 return err;919 chip->playback_pipes[audio] = pipe_out_monitoring;920 }921 pipe_out_monitoring->references++;922 /* 923 if an output pipe is available, it's audios still may need to be 924 unmuted. hence we'll have to call a mixer entry point.925 */926 vx_set_monitor_level(chip, audio, chip->audio_monitor[audio],927 chip->audio_monitor_active[audio]);928 /* assuming stereo */929 vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1],930 chip->audio_monitor_active[audio+1]); 931 }932 933 pipe->monitoring_pipe = pipe_out_monitoring; /* default value NULL */934 935 runtime->hw = vx_pcm_capture_hw;936 runtime->hw.period_bytes_min = chip->ibl.size;937 runtime->private_data = pipe;938 939 /* align to 4 bytes (otherwise will be problematic when 24bit is used) */ 940 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);941 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);942 943 return 0;944}945 946/*947 * vx_pcm_capture_close - close callback for capture948 */949static int vx_pcm_capture_close(struct snd_pcm_substream *subs)950{951 struct vx_core *chip = snd_pcm_substream_chip(subs);952 struct vx_pipe *pipe;953 struct vx_pipe *pipe_out_monitoring;954 955 if (! subs->runtime->private_data)956 return -EINVAL;957 pipe = subs->runtime->private_data;958 chip->capture_pipes[pipe->number] = NULL;959 960 pipe_out_monitoring = pipe->monitoring_pipe;961 962 /*963 if an output pipe is attached to this input, 964 check if it needs to be released.965 */966 if (pipe_out_monitoring) {967 if (--pipe_out_monitoring->references == 0) {968 vx_free_pipe(chip, pipe_out_monitoring);969 chip->playback_pipes[pipe->number] = NULL;970 pipe->monitoring_pipe = NULL;971 }972 }973 974 vx_free_pipe(chip, pipe);975 return 0;976}977 978 979 980#define DMA_READ_ALIGN 6 /* hardware alignment for read */981 982/*983 * vx_pcm_capture_update - update the capture buffer984 */985static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream *subs,986 struct vx_pipe *pipe)987{988 int size, space, count;989 struct snd_pcm_runtime *runtime = subs->runtime;990 991 if (!pipe->running || (chip->chip_status & VX_STAT_IS_STALE))992 return;993 994 size = runtime->buffer_size - snd_pcm_capture_avail(runtime);995 if (! size)996 return;997 size = frames_to_bytes(runtime, size);998 space = vx_query_hbuffer_size(chip, pipe);999 if (space < 0)1000 goto _error;1001 if (size > space)1002 size = space;1003 size = (size / 3) * 3; /* align to 3 bytes */1004 if (size < DMA_READ_ALIGN)1005 goto _error;1006 1007 /* keep the last 6 bytes, they will be read after disconnection */1008 count = size - DMA_READ_ALIGN;1009 /* read bytes until the current pointer reaches to the aligned position1010 * for word-transfer1011 */1012 while (count > 0) {1013 if ((pipe->hw_ptr % pipe->align) == 0)1014 break;1015 if (vx_wait_for_rx_full(chip) < 0)1016 goto _error;1017 vx_pcm_read_per_bytes(chip, runtime, pipe);1018 count -= 3;1019 }1020 if (count > 0) {1021 /* ok, let's accelerate! */1022 int align = pipe->align * 3;1023 space = (count / align) * align;1024 if (space > 0) {1025 vx_pseudo_dma_read(chip, runtime, pipe, space);1026 count -= space;1027 }1028 }1029 /* read the rest of bytes */1030 while (count > 0) {1031 if (vx_wait_for_rx_full(chip) < 0)1032 goto _error;1033 vx_pcm_read_per_bytes(chip, runtime, pipe);1034 count -= 3;1035 }1036 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */1037 vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);1038 /* read the last pending 6 bytes */1039 count = DMA_READ_ALIGN;1040 while (count > 0) {1041 vx_pcm_read_per_bytes(chip, runtime, pipe);1042 count -= 3;1043 }1044 /* update the position */1045 pipe->transferred += size;1046 if (pipe->transferred >= pipe->period_bytes) {1047 pipe->transferred %= pipe->period_bytes;1048 snd_pcm_period_elapsed(subs);1049 }1050 return;1051 1052 _error:1053 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */1054 vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);1055 return;1056}1057 1058/*1059 * vx_pcm_capture_pointer - pointer callback for capture1060 */1061static snd_pcm_uframes_t vx_pcm_capture_pointer(struct snd_pcm_substream *subs)1062{1063 struct snd_pcm_runtime *runtime = subs->runtime;1064 struct vx_pipe *pipe = runtime->private_data;1065 return bytes_to_frames(runtime, pipe->hw_ptr);1066}1067 1068/*1069 * operators for PCM capture1070 */1071static const struct snd_pcm_ops vx_pcm_capture_ops = {1072 .open = vx_pcm_capture_open,1073 .close = vx_pcm_capture_close,1074 .prepare = vx_pcm_prepare,1075 .trigger = vx_pcm_trigger,1076 .pointer = vx_pcm_capture_pointer,1077};1078 1079 1080/*1081 * interrupt handler for pcm streams1082 */1083void vx_pcm_update_intr(struct vx_core *chip, unsigned int events)1084{1085 unsigned int i;1086 struct vx_pipe *pipe;1087 1088#define EVENT_MASK (END_OF_BUFFER_EVENTS_PENDING|ASYNC_EVENTS_PENDING)1089 1090 if (events & EVENT_MASK) {1091 vx_init_rmh(&chip->irq_rmh, CMD_ASYNC);1092 if (events & ASYNC_EVENTS_PENDING)1093 chip->irq_rmh.Cmd[0] |= 0x00000001; /* SEL_ASYNC_EVENTS */1094 if (events & END_OF_BUFFER_EVENTS_PENDING)1095 chip->irq_rmh.Cmd[0] |= 0x00000002; /* SEL_END_OF_BUF_EVENTS */1096 1097 if (vx_send_msg(chip, &chip->irq_rmh) < 0) {1098 dev_dbg(chip->card->dev, "msg send error!!\n");1099 return;1100 }1101 1102 i = 1;1103 while (i < chip->irq_rmh.LgStat) {1104 int p, buf, capture, eob;1105 p = chip->irq_rmh.Stat[i] & MASK_FIRST_FIELD;1106 capture = (chip->irq_rmh.Stat[i] & 0x400000) ? 1 : 0;1107 eob = (chip->irq_rmh.Stat[i] & 0x800000) ? 1 : 0;1108 i++;1109 if (events & ASYNC_EVENTS_PENDING)1110 i++;1111 buf = 1; /* force to transfer */1112 if (events & END_OF_BUFFER_EVENTS_PENDING) {1113 if (eob)1114 buf = chip->irq_rmh.Stat[i];1115 i++;1116 }1117 if (capture)1118 continue;1119 if (snd_BUG_ON(p < 0 || p >= chip->audio_outs))1120 continue;1121 pipe = chip->playback_pipes[p];1122 if (pipe && pipe->substream) {1123 vx_pcm_playback_update(chip, pipe->substream, pipe);1124 vx_pcm_playback_transfer(chip, pipe->substream, pipe, buf);1125 }1126 }1127 }1128 1129 /* update the capture pcm pointers as frequently as possible */1130 for (i = 0; i < chip->audio_ins; i++) {1131 pipe = chip->capture_pipes[i];1132 if (pipe && pipe->substream)1133 vx_pcm_capture_update(chip, pipe->substream, pipe);1134 }1135}1136 1137 1138/*1139 * vx_init_audio_io - check the available audio i/o and allocate pipe arrays1140 */1141static int vx_init_audio_io(struct vx_core *chip)1142{1143 struct vx_rmh rmh;1144 int preferred;1145 1146 vx_init_rmh(&rmh, CMD_SUPPORTED);1147 if (vx_send_msg(chip, &rmh) < 0) {1148 dev_err(chip->card->dev,1149 "vx: cannot get the supported audio data\n");1150 return -ENXIO;1151 }1152 1153 chip->audio_outs = rmh.Stat[0] & MASK_FIRST_FIELD;1154 chip->audio_ins = (rmh.Stat[0] >> (FIELD_SIZE*2)) & MASK_FIRST_FIELD;1155 chip->audio_info = rmh.Stat[1];1156 1157 /* allocate pipes */1158 chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL);1159 if (!chip->playback_pipes)1160 return -ENOMEM;1161 chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL);1162 if (!chip->capture_pipes) {1163 kfree(chip->playback_pipes);1164 return -ENOMEM;1165 }1166 1167 preferred = chip->ibl.size;1168 chip->ibl.size = 0;1169 vx_set_ibl(chip, &chip->ibl); /* query the info */1170 if (preferred > 0) {1171 chip->ibl.size = roundup(preferred, chip->ibl.granularity);1172 if (chip->ibl.size > chip->ibl.max_size)1173 chip->ibl.size = chip->ibl.max_size;1174 } else1175 chip->ibl.size = chip->ibl.min_size; /* set to the minimum */1176 vx_set_ibl(chip, &chip->ibl);1177 1178 return 0;1179}1180 1181 1182/*1183 * free callback for pcm1184 */1185static void snd_vx_pcm_free(struct snd_pcm *pcm)1186{1187 struct vx_core *chip = pcm->private_data;1188 chip->pcm[pcm->device] = NULL;1189 kfree(chip->playback_pipes);1190 chip->playback_pipes = NULL;1191 kfree(chip->capture_pipes);1192 chip->capture_pipes = NULL;1193}1194 1195/*1196 * snd_vx_pcm_new - create and initialize a pcm1197 */1198int snd_vx_pcm_new(struct vx_core *chip)1199{1200 struct snd_pcm *pcm;1201 unsigned int i;1202 int err;1203 1204 err = vx_init_audio_io(chip);1205 if (err < 0)1206 return err;1207 1208 for (i = 0; i < chip->hw->num_codecs; i++) {1209 unsigned int outs, ins;1210 outs = chip->audio_outs > i * 2 ? 1 : 0;1211 ins = chip->audio_ins > i * 2 ? 1 : 0;1212 if (! outs && ! ins)1213 break;1214 err = snd_pcm_new(chip->card, "VX PCM", i,1215 outs, ins, &pcm);1216 if (err < 0)1217 return err;1218 if (outs)1219 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &vx_pcm_playback_ops);1220 if (ins)1221 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops);1222 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,1223 NULL, 0, 0);1224 1225 pcm->private_data = chip;1226 pcm->private_free = snd_vx_pcm_free;1227 pcm->info_flags = 0;1228 pcm->nonatomic = true;1229 strcpy(pcm->name, chip->card->shortname);1230 chip->pcm[i] = pcm;1231 }1232 1233 return 0;1234}1235