Lines Matching +full:assigned +full:- +full:clock +full:- +full:rates +full:- +full:u64
1 // SPDX-License-Identifier: GPL-2.0-or-later
11 * IBL size, typically 126 samples. at each end of chunk, the end-of-buffer
15 * pipe->transferred is the counter of data which has been already transferred.
25 * the current point of read buffer is kept in pipe->hw_ptr. note that
29 * - linked trigger for full-duplex mode.
30 * - scheduled action on the stream.
48 int offset = pipe->hw_ptr; in vx_pcm_read_per_bytes()
49 unsigned char *buf = (unsigned char *)(runtime->dma_area + offset); in vx_pcm_read_per_bytes()
51 if (++offset >= pipe->buffer_bytes) { in vx_pcm_read_per_bytes()
53 buf = (unsigned char *)runtime->dma_area; in vx_pcm_read_per_bytes()
56 if (++offset >= pipe->buffer_bytes) { in vx_pcm_read_per_bytes()
58 buf = (unsigned char *)runtime->dma_area; in vx_pcm_read_per_bytes()
61 if (++offset >= pipe->buffer_bytes) { in vx_pcm_read_per_bytes()
64 pipe->hw_ptr = offset; in vx_pcm_read_per_bytes()
68 * vx_set_pcx_time - convert from the PC time to the RMH status time.
69 * @pc_time: the pointer for the PC-time to set
80 * vx_set_differed_time - set the differed time if specified
93 if (! (pipe->differed_type & DC_DIFFERED_DELAY)) in vx_set_differed_time()
97 rmh->Cmd[0] |= DSP_DIFFERED_COMMAND_MASK; in vx_set_differed_time()
100 vx_set_pcx_time(chip, &pipe->pcx_time, &rmh->Cmd[1]); in vx_set_differed_time()
103 if (pipe->differed_type & DC_NOTIFY_DELAY) in vx_set_differed_time()
104 rmh->Cmd[1] |= NOTIFY_MASK_TIME_HIGH ; in vx_set_differed_time()
107 if (pipe->differed_type & DC_MULTIPLE_DELAY) in vx_set_differed_time()
108 rmh->Cmd[1] |= MULTIPLE_MASK_TIME_HIGH; in vx_set_differed_time()
110 /* Add the flags to a stream-time differed command */ in vx_set_differed_time()
111 if (pipe->differed_type & DC_STREAM_TIME_DELAY) in vx_set_differed_time()
112 rmh->Cmd[1] |= STREAM_MASK_TIME_HIGH; in vx_set_differed_time()
114 rmh->LgCmd += 2; in vx_set_differed_time()
119 * vx_set_stream_format - send the stream format command
128 vx_init_rmh(&rmh, pipe->is_capture ? in vx_set_stream_format()
130 rmh.Cmd[0] |= pipe->number << FIELD_SIZE; in vx_set_stream_format()
144 * vx_set_format - set the format of a pipe
155 if (runtime->channels == 1) in vx_set_format()
157 if (snd_pcm_format_little_endian(runtime->format)) in vx_set_format()
159 if (runtime->rate < 32000 && runtime->rate > 11025) in vx_set_format()
161 else if (runtime->rate <= 11025) in vx_set_format()
164 switch (snd_pcm_format_physical_width(runtime->format)) { in vx_set_format()
170 return -EINVAL; in vx_set_format()
185 rmh.Cmd[0] |= info->size & 0x03ffff; in vx_set_ibl()
189 info->size = rmh.Stat[0]; in vx_set_ibl()
190 info->max_size = rmh.Stat[1]; in vx_set_ibl()
191 info->min_size = rmh.Stat[2]; in vx_set_ibl()
192 info->granularity = rmh.Stat[3]; in vx_set_ibl()
193 dev_dbg(chip->card->dev, in vx_set_ibl()
195 __func__, info->size, info->max_size, info->min_size, in vx_set_ibl()
196 info->granularity); in vx_set_ibl()
202 * vx_get_pipe_state - get the state of a pipe
217 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_get_pipe_state()
220 *state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0; in vx_get_pipe_state()
226 * vx_query_hbuffer_size - query available h-buffer size in bytes
229 * return the available size on h-buffer in bytes,
242 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_query_hbuffer_size()
243 if (pipe->is_capture) in vx_query_hbuffer_size()
253 * vx_pipe_can_start - query whether a pipe is ready for start
266 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_pipe_can_start()
278 * vx_conf_pipe - tell the pipe to stand by and wait for IRQA.
286 if (pipe->is_capture) in vx_conf_pipe()
288 rmh.Cmd[1] = 1 << pipe->number; in vx_conf_pipe()
293 * vx_send_irqa - trigger IRQA
306 * vx boards do not support inter-card sync, besides
313 * vx_toggle_pipe - start / pause a pipe
326 return -EBADFD; in vx_toggle_pipe()
362 err = -EIO; in vx_toggle_pipe()
365 return err < 0 ? -EIO : 0; in vx_toggle_pipe()
370 * vx_stop_pipe - stop a pipe
379 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_stop_pipe()
385 * vx_alloc_pipe - allocate a pipe and initialize the pipe instance
387 * @audioid: the audio id to be assigned
409 data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0; in vx_alloc_pipe()
423 return -ENOMEM; in vx_alloc_pipe()
427 pipe->number = audioid; in vx_alloc_pipe()
428 pipe->is_capture = capture; in vx_alloc_pipe()
429 pipe->channels = num_audio; in vx_alloc_pipe()
430 pipe->differed_type = 0; in vx_alloc_pipe()
431 pipe->pcx_time = 0; in vx_alloc_pipe()
432 pipe->data_mode = data_mode; in vx_alloc_pipe()
440 * vx_free_pipe - release a pipe
448 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_free_pipe()
457 * vx_start_stream - start the stream
466 vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); in vx_start_stream()
473 * vx_stop_stream - stop the stream
482 vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); in vx_stop_stream()
497 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
512 * vx_pcm_playback_open - open callback for playback
516 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_playback_open()
522 if (chip->chip_status & VX_STAT_IS_STALE) in vx_pcm_playback_open()
523 return -EBUSY; in vx_pcm_playback_open()
525 audio = subs->pcm->device * 2; in vx_pcm_playback_open()
526 if (snd_BUG_ON(audio >= chip->audio_outs)) in vx_pcm_playback_open()
527 return -EINVAL; in vx_pcm_playback_open()
530 pipe = chip->playback_pipes[audio]; in vx_pcm_playback_open()
538 pipe->references++; in vx_pcm_playback_open()
540 pipe->substream = subs; in vx_pcm_playback_open()
541 chip->playback_pipes[audio] = pipe; in vx_pcm_playback_open()
543 runtime->hw = vx_pcm_playback_hw; in vx_pcm_playback_open()
544 runtime->hw.period_bytes_min = chip->ibl.size; in vx_pcm_playback_open()
545 runtime->private_data = pipe; in vx_pcm_playback_open()
555 * vx_pcm_playback_close - close callback for playback
562 if (! subs->runtime->private_data) in vx_pcm_playback_close()
563 return -EINVAL; in vx_pcm_playback_close()
565 pipe = subs->runtime->private_data; in vx_pcm_playback_close()
567 if (--pipe->references == 0) { in vx_pcm_playback_close()
568 chip->playback_pipes[pipe->number] = NULL; in vx_pcm_playback_close()
578 * vx_notify_end_of_buffer - send "end-of-buffer" notifier at the given pipe
591 vx_set_stream_cmd_params(&rmh, 0, pipe->number); in vx_notify_end_of_buffer()
601 * vx_pcm_playback_transfer_chunk - transfer a single chunk
621 dev_dbg(chip->card->dev, "error hbuffer\n"); in vx_pcm_playback_transfer_chunk()
626 dev_dbg(chip->card->dev, "no enough hbuffer space %d\n", space); in vx_pcm_playback_transfer_chunk()
627 return -EIO; /* XRUN */ in vx_pcm_playback_transfer_chunk()
633 mutex_lock(&chip->lock); in vx_pcm_playback_transfer_chunk()
638 mutex_unlock(&chip->lock); in vx_pcm_playback_transfer_chunk()
644 * pipe->position is updated and wrapped within the buffer size.
645 * pipe->transferred is updated, too, but the size is not wrapped,
655 u64 count; in vx_update_pipe_position()
658 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); in vx_update_pipe_position()
663 count = ((u64)(rmh.Stat[0] & 0xfffff) << 24) | (u64)rmh.Stat[1]; in vx_update_pipe_position()
664 update = (int)(count - pipe->cur_count); in vx_update_pipe_position()
665 pipe->cur_count = count; in vx_update_pipe_position()
666 pipe->position += update; in vx_update_pipe_position()
667 if (pipe->position >= (int)runtime->buffer_size) in vx_update_pipe_position()
668 pipe->position %= runtime->buffer_size; in vx_update_pipe_position()
669 pipe->transferred += update; in vx_update_pipe_position()
682 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_playback_transfer()
684 if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE)) in vx_pcm_playback_transfer()
688 chip->ibl.size); in vx_pcm_playback_transfer()
703 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_playback_update()
705 if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) { in vx_pcm_playback_update()
709 if (pipe->transferred >= (int)runtime->period_size) { in vx_pcm_playback_update()
710 pipe->transferred %= runtime->period_size; in vx_pcm_playback_update()
717 * vx_pcm_playback_trigger - trigger callback for playback
722 struct vx_pipe *pipe = subs->runtime->private_data; in vx_pcm_trigger()
725 if (chip->chip_status & VX_STAT_IS_STALE) in vx_pcm_trigger()
726 return -EBUSY; in vx_pcm_trigger()
731 if (! pipe->is_capture) in vx_pcm_trigger()
744 chip->pcm_running++; in vx_pcm_trigger()
745 pipe->running = 1; in vx_pcm_trigger()
752 chip->pcm_running--; in vx_pcm_trigger()
753 pipe->running = 0; in vx_pcm_trigger()
766 return -EINVAL; in vx_pcm_trigger()
772 * vx_pcm_playback_pointer - pointer callback for playback
776 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_playback_pointer()
777 struct vx_pipe *pipe = runtime->private_data; in vx_pcm_playback_pointer()
778 return pipe->position; in vx_pcm_playback_pointer()
782 * vx_pcm_prepare - prepare callback for playback and capture
787 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_prepare()
788 struct vx_pipe *pipe = runtime->private_data; in vx_pcm_prepare()
792 if (chip->chip_status & VX_STAT_IS_STALE) in vx_pcm_prepare()
793 return -EBUSY; in vx_pcm_prepare()
795 data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0; in vx_pcm_prepare()
796 if (data_mode != pipe->data_mode && ! pipe->is_capture) { in vx_pcm_prepare()
797 /* IEC958 status (raw-mode) was changed */ in vx_pcm_prepare()
800 dev_dbg(chip->card->dev, in vx_pcm_prepare()
803 vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0); in vx_pcm_prepare()
808 vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels); in vx_pcm_prepare()
814 pipe->data_mode = data_mode; in vx_pcm_prepare()
817 if (chip->pcm_running && chip->freq != runtime->rate) { in vx_pcm_prepare()
818 dev_err(chip->card->dev, in vx_pcm_prepare()
819 "vx: cannot set different clock %d from the current %d\n", in vx_pcm_prepare()
820 runtime->rate, chip->freq); in vx_pcm_prepare()
821 return -EINVAL; in vx_pcm_prepare()
823 vx_set_clock(chip, runtime->rate); in vx_pcm_prepare()
830 pipe->align = 2; /* 16bit word */ in vx_pcm_prepare()
832 pipe->align = 4; /* 32bit word */ in vx_pcm_prepare()
835 pipe->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); in vx_pcm_prepare()
836 pipe->period_bytes = frames_to_bytes(runtime, runtime->period_size); in vx_pcm_prepare()
837 pipe->hw_ptr = 0; in vx_pcm_prepare()
842 pipe->transferred = 0; in vx_pcm_prepare()
843 pipe->position = 0; in vx_pcm_prepare()
845 pipe->prepared = 1; in vx_pcm_prepare()
873 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
888 * vx_pcm_capture_open - open callback for capture
892 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_capture_open()
899 if (chip->chip_status & VX_STAT_IS_STALE) in vx_pcm_capture_open()
900 return -EBUSY; in vx_pcm_capture_open()
902 audio = subs->pcm->device * 2; in vx_pcm_capture_open()
903 if (snd_BUG_ON(audio >= chip->audio_ins)) in vx_pcm_capture_open()
904 return -EINVAL; in vx_pcm_capture_open()
908 pipe->substream = subs; in vx_pcm_capture_open()
909 chip->capture_pipes[audio] = pipe; in vx_pcm_capture_open()
912 if (chip->audio_monitor_active[audio]) { in vx_pcm_capture_open()
913 pipe_out_monitoring = chip->playback_pipes[audio]; in vx_pcm_capture_open()
919 chip->playback_pipes[audio] = pipe_out_monitoring; in vx_pcm_capture_open()
921 pipe_out_monitoring->references++; in vx_pcm_capture_open()
926 vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], in vx_pcm_capture_open()
927 chip->audio_monitor_active[audio]); in vx_pcm_capture_open()
929 vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], in vx_pcm_capture_open()
930 chip->audio_monitor_active[audio+1]); in vx_pcm_capture_open()
933 pipe->monitoring_pipe = pipe_out_monitoring; /* default value NULL */ in vx_pcm_capture_open()
935 runtime->hw = vx_pcm_capture_hw; in vx_pcm_capture_open()
936 runtime->hw.period_bytes_min = chip->ibl.size; in vx_pcm_capture_open()
937 runtime->private_data = pipe; in vx_pcm_capture_open()
947 * vx_pcm_capture_close - close callback for capture
955 if (! subs->runtime->private_data) in vx_pcm_capture_close()
956 return -EINVAL; in vx_pcm_capture_close()
957 pipe = subs->runtime->private_data; in vx_pcm_capture_close()
958 chip->capture_pipes[pipe->number] = NULL; in vx_pcm_capture_close()
960 pipe_out_monitoring = pipe->monitoring_pipe; in vx_pcm_capture_close()
967 if (--pipe_out_monitoring->references == 0) { in vx_pcm_capture_close()
969 chip->playback_pipes[pipe->number] = NULL; in vx_pcm_capture_close()
970 pipe->monitoring_pipe = NULL; in vx_pcm_capture_close()
983 * vx_pcm_capture_update - update the capture buffer
989 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_capture_update()
991 if (!pipe->running || (chip->chip_status & VX_STAT_IS_STALE)) in vx_pcm_capture_update()
994 size = runtime->buffer_size - snd_pcm_capture_avail(runtime); in vx_pcm_capture_update()
1008 count = size - DMA_READ_ALIGN; in vx_pcm_capture_update()
1010 * for word-transfer in vx_pcm_capture_update()
1013 if ((pipe->hw_ptr % pipe->align) == 0) in vx_pcm_capture_update()
1018 count -= 3; in vx_pcm_capture_update()
1022 int align = pipe->align * 3; in vx_pcm_capture_update()
1026 count -= space; in vx_pcm_capture_update()
1034 count -= 3; in vx_pcm_capture_update()
1042 count -= 3; in vx_pcm_capture_update()
1045 pipe->transferred += size; in vx_pcm_capture_update()
1046 if (pipe->transferred >= pipe->period_bytes) { in vx_pcm_capture_update()
1047 pipe->transferred %= pipe->period_bytes; in vx_pcm_capture_update()
1059 * vx_pcm_capture_pointer - pointer callback for capture
1063 struct snd_pcm_runtime *runtime = subs->runtime; in vx_pcm_capture_pointer()
1064 struct vx_pipe *pipe = runtime->private_data; in vx_pcm_capture_pointer()
1065 return bytes_to_frames(runtime, pipe->hw_ptr); in vx_pcm_capture_pointer()
1091 vx_init_rmh(&chip->irq_rmh, CMD_ASYNC); in vx_pcm_update_intr()
1093 chip->irq_rmh.Cmd[0] |= 0x00000001; /* SEL_ASYNC_EVENTS */ in vx_pcm_update_intr()
1095 chip->irq_rmh.Cmd[0] |= 0x00000002; /* SEL_END_OF_BUF_EVENTS */ in vx_pcm_update_intr()
1097 if (vx_send_msg(chip, &chip->irq_rmh) < 0) { in vx_pcm_update_intr()
1098 dev_dbg(chip->card->dev, "msg send error!!\n"); in vx_pcm_update_intr()
1103 while (i < chip->irq_rmh.LgStat) { in vx_pcm_update_intr()
1105 p = chip->irq_rmh.Stat[i] & MASK_FIRST_FIELD; in vx_pcm_update_intr()
1106 capture = (chip->irq_rmh.Stat[i] & 0x400000) ? 1 : 0; in vx_pcm_update_intr()
1107 eob = (chip->irq_rmh.Stat[i] & 0x800000) ? 1 : 0; in vx_pcm_update_intr()
1114 buf = chip->irq_rmh.Stat[i]; in vx_pcm_update_intr()
1119 if (snd_BUG_ON(p < 0 || p >= chip->audio_outs)) in vx_pcm_update_intr()
1121 pipe = chip->playback_pipes[p]; in vx_pcm_update_intr()
1122 if (pipe && pipe->substream) { in vx_pcm_update_intr()
1123 vx_pcm_playback_update(chip, pipe->substream, pipe); in vx_pcm_update_intr()
1124 vx_pcm_playback_transfer(chip, pipe->substream, pipe, buf); in vx_pcm_update_intr()
1130 for (i = 0; i < chip->audio_ins; i++) { in vx_pcm_update_intr()
1131 pipe = chip->capture_pipes[i]; in vx_pcm_update_intr()
1132 if (pipe && pipe->substream) in vx_pcm_update_intr()
1133 vx_pcm_capture_update(chip, pipe->substream, pipe); in vx_pcm_update_intr()
1139 * vx_init_audio_io - check the available audio i/o and allocate pipe arrays
1148 dev_err(chip->card->dev, in vx_init_audio_io()
1150 return -ENXIO; in vx_init_audio_io()
1153 chip->audio_outs = rmh.Stat[0] & MASK_FIRST_FIELD; in vx_init_audio_io()
1154 chip->audio_ins = (rmh.Stat[0] >> (FIELD_SIZE*2)) & MASK_FIRST_FIELD; in vx_init_audio_io()
1155 chip->audio_info = rmh.Stat[1]; in vx_init_audio_io()
1158 chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL); in vx_init_audio_io()
1159 if (!chip->playback_pipes) in vx_init_audio_io()
1160 return -ENOMEM; in vx_init_audio_io()
1161 chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL); in vx_init_audio_io()
1162 if (!chip->capture_pipes) { in vx_init_audio_io()
1163 kfree(chip->playback_pipes); in vx_init_audio_io()
1164 return -ENOMEM; in vx_init_audio_io()
1167 preferred = chip->ibl.size; in vx_init_audio_io()
1168 chip->ibl.size = 0; in vx_init_audio_io()
1169 vx_set_ibl(chip, &chip->ibl); /* query the info */ in vx_init_audio_io()
1171 chip->ibl.size = roundup(preferred, chip->ibl.granularity); in vx_init_audio_io()
1172 if (chip->ibl.size > chip->ibl.max_size) in vx_init_audio_io()
1173 chip->ibl.size = chip->ibl.max_size; in vx_init_audio_io()
1175 chip->ibl.size = chip->ibl.min_size; /* set to the minimum */ in vx_init_audio_io()
1176 vx_set_ibl(chip, &chip->ibl); in vx_init_audio_io()
1187 struct vx_core *chip = pcm->private_data; in snd_vx_pcm_free()
1188 chip->pcm[pcm->device] = NULL; in snd_vx_pcm_free()
1189 kfree(chip->playback_pipes); in snd_vx_pcm_free()
1190 chip->playback_pipes = NULL; in snd_vx_pcm_free()
1191 kfree(chip->capture_pipes); in snd_vx_pcm_free()
1192 chip->capture_pipes = NULL; in snd_vx_pcm_free()
1196 * snd_vx_pcm_new - create and initialize a pcm
1208 for (i = 0; i < chip->hw->num_codecs; i++) { in snd_vx_pcm_new()
1210 outs = chip->audio_outs > i * 2 ? 1 : 0; in snd_vx_pcm_new()
1211 ins = chip->audio_ins > i * 2 ? 1 : 0; in snd_vx_pcm_new()
1214 err = snd_pcm_new(chip->card, "VX PCM", i, in snd_vx_pcm_new()
1225 pcm->private_data = chip; in snd_vx_pcm_new()
1226 pcm->private_free = snd_vx_pcm_free; in snd_vx_pcm_new()
1227 pcm->info_flags = 0; in snd_vx_pcm_new()
1228 pcm->nonatomic = true; in snd_vx_pcm_new()
1229 strcpy(pcm->name, chip->card->shortname); in snd_vx_pcm_new()
1230 chip->pcm[i] = pcm; in snd_vx_pcm_new()