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