Lines Matching +full:- +full:- +full:-
8 * <https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-52900014>
15 * top-level directory.
21 #include "qemu/error-report.h"
26 #include "hw/audio/virtio-snd.h"
97 s->snd_conf.jacks, in virtio_snd_get_config()
98 s->snd_conf.streams, in virtio_snd_get_config()
99 s->snd_conf.chmaps); in virtio_snd_get_config()
101 memcpy(sndconfig, &s->snd_conf, sizeof(s->snd_conf)); in virtio_snd_get_config()
102 cpu_to_le32s(&sndconfig->jacks); in virtio_snd_get_config()
103 cpu_to_le32s(&sndconfig->streams); in virtio_snd_get_config()
104 cpu_to_le32s(&sndconfig->chmaps); in virtio_snd_get_config()
111 g_free(buffer->elem); in virtio_snd_pcm_buffer_free()
118 g_free(cmd->elem); in virtio_snd_ctrl_cmd_free()
132 return stream_id >= s->snd_conf.streams ? NULL : in virtio_snd_pcm_get_stream()
133 s->pcm->streams[stream_id]; in virtio_snd_pcm_get_stream()
145 return stream_id >= s->snd_conf.streams ? NULL in virtio_snd_pcm_get_params()
146 : &s->pcm->pcm_params[stream_id]; in virtio_snd_pcm_get_params()
164 size_t msg_sz = iov_to_buf(cmd->elem->out_sg, in virtio_snd_handle_pcm_info()
165 cmd->elem->out_num, in virtio_snd_handle_pcm_info()
175 "%s: virtio-snd command size incorrect %zu vs \ in virtio_snd_handle_pcm_info()
177 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); in virtio_snd_handle_pcm_info()
185 if (iov_size(cmd->elem->in_sg, cmd->elem->in_num) < in virtio_snd_handle_pcm_info()
191 iov_size(cmd->elem->in_sg, cmd->elem->in_num), in virtio_snd_handle_pcm_info()
193 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); in virtio_snd_handle_pcm_info()
204 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); in virtio_snd_handle_pcm_info()
207 val = stream->info; in virtio_snd_handle_pcm_info()
221 cmd->payload_size = sizeof(virtio_snd_pcm_info) * count; in virtio_snd_handle_pcm_info()
222 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK); in virtio_snd_handle_pcm_info()
223 iov_from_buf(cmd->elem->in_sg, in virtio_snd_handle_pcm_info()
224 cmd->elem->in_num, in virtio_snd_handle_pcm_info()
227 cmd->payload_size); in virtio_snd_handle_pcm_info()
246 if (stream_id >= s->snd_conf.streams || s->pcm->pcm_params == NULL) { in virtio_snd_set_pcm_params()
256 if (params->channels < 1 || params->channels > AUDIO_MAX_CHANNELS) { in virtio_snd_set_pcm_params()
260 if (params->format >= sizeof(supported_formats) * BITS_PER_BYTE || in virtio_snd_set_pcm_params()
261 !(supported_formats & BIT(params->format))) { in virtio_snd_set_pcm_params()
265 if (params->rate >= sizeof(supported_rates) * BITS_PER_BYTE || in virtio_snd_set_pcm_params()
266 !(supported_rates & BIT(params->rate))) { in virtio_snd_set_pcm_params()
271 st_params->buffer_bytes = le32_to_cpu(params->buffer_bytes); in virtio_snd_set_pcm_params()
272 st_params->period_bytes = le32_to_cpu(params->period_bytes); in virtio_snd_set_pcm_params()
273 st_params->features = le32_to_cpu(params->features); in virtio_snd_set_pcm_params()
275 st_params->channels = params->channels; in virtio_snd_set_pcm_params()
276 st_params->format = params->format; in virtio_snd_set_pcm_params()
277 st_params->rate = params->rate; in virtio_snd_set_pcm_params()
293 size_t msg_sz = iov_to_buf(cmd->elem->out_sg, in virtio_snd_handle_pcm_set_params()
294 cmd->elem->out_num, in virtio_snd_handle_pcm_set_params()
304 "%s: virtio-snd command size incorrect %zu vs \ in virtio_snd_handle_pcm_set_params()
306 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); in virtio_snd_handle_pcm_set_params()
311 cmd->resp.code = virtio_snd_set_pcm_params(s, stream_id, &req); in virtio_snd_handle_pcm_set_params()
378 as->nchannels = MIN(AUDIO_MAX_CHANNELS, params->channels); in virtio_snd_get_qemu_audsettings()
379 as->fmt = virtio_snd_get_qemu_format(params->format); in virtio_snd_get_qemu_audsettings()
380 as->freq = virtio_snd_get_qemu_freq(params->rate); in virtio_snd_get_qemu_audsettings()
381 as->endianness = 0; /* Conforming to VIRTIO 1.0: always little endian. */ in virtio_snd_get_qemu_audsettings()
393 if (stream->info.direction == VIRTIO_SND_D_OUTPUT) { in virtio_snd_pcm_close()
394 AUD_close_out(&stream->pcm->snd->card, stream->voice.out); in virtio_snd_pcm_close()
395 stream->voice.out = NULL; in virtio_snd_pcm_close()
396 } else if (stream->info.direction == VIRTIO_SND_D_INPUT) { in virtio_snd_pcm_close()
397 AUD_close_in(&stream->pcm->snd->card, stream->voice.in); in virtio_snd_pcm_close()
398 stream->voice.in = NULL; in virtio_snd_pcm_close()
416 if (s->pcm->streams == NULL || in virtio_snd_pcm_prepare()
417 s->pcm->pcm_params == NULL || in virtio_snd_pcm_prepare()
418 stream_id >= s->snd_conf.streams) { in virtio_snd_pcm_prepare()
430 stream->active = false; in virtio_snd_pcm_prepare()
431 stream->id = stream_id; in virtio_snd_pcm_prepare()
432 stream->pcm = s->pcm; in virtio_snd_pcm_prepare()
433 stream->s = s; in virtio_snd_pcm_prepare()
434 qemu_mutex_init(&stream->queue_mutex); in virtio_snd_pcm_prepare()
435 QSIMPLEQ_INIT(&stream->queue); in virtio_snd_pcm_prepare()
438 * stream_id >= s->snd_conf.streams was checked before so this is in virtio_snd_pcm_prepare()
439 * in-bounds in virtio_snd_pcm_prepare()
441 s->pcm->streams[stream_id] = stream; in virtio_snd_pcm_prepare()
445 stream->info.direction = stream_id < s->snd_conf.streams / 2 + in virtio_snd_pcm_prepare()
446 (s->snd_conf.streams & 1) ? VIRTIO_SND_D_OUTPUT : VIRTIO_SND_D_INPUT; in virtio_snd_pcm_prepare()
447 stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID; in virtio_snd_pcm_prepare()
448 stream->info.features = 0; in virtio_snd_pcm_prepare()
449 stream->info.channels_min = 1; in virtio_snd_pcm_prepare()
450 stream->info.channels_max = as.nchannels; in virtio_snd_pcm_prepare()
451 stream->info.formats = supported_formats; in virtio_snd_pcm_prepare()
452 stream->info.rates = supported_rates; in virtio_snd_pcm_prepare()
453 stream->params = *params; in virtio_snd_pcm_prepare()
455 stream->positions[0] = VIRTIO_SND_CHMAP_FL; in virtio_snd_pcm_prepare()
456 stream->positions[1] = VIRTIO_SND_CHMAP_FR; in virtio_snd_pcm_prepare()
457 stream->as = as; in virtio_snd_pcm_prepare()
459 if (stream->info.direction == VIRTIO_SND_D_OUTPUT) { in virtio_snd_pcm_prepare()
460 stream->voice.out = AUD_open_out(&s->card, in virtio_snd_pcm_prepare()
461 stream->voice.out, in virtio_snd_pcm_prepare()
462 "virtio-sound.out", in virtio_snd_pcm_prepare()
466 AUD_set_volume_out(stream->voice.out, 0, 255, 255); in virtio_snd_pcm_prepare()
468 stream->voice.in = AUD_open_in(&s->card, in virtio_snd_pcm_prepare()
469 stream->voice.in, in virtio_snd_pcm_prepare()
470 "virtio-sound.in", in virtio_snd_pcm_prepare()
474 AUD_set_volume_in(stream->voice.in, 0, 255, 255); in virtio_snd_pcm_prepare()
513 size_t msg_sz = iov_to_buf(cmd->elem->out_sg, in virtio_snd_handle_pcm_prepare()
514 cmd->elem->out_num, in virtio_snd_handle_pcm_prepare()
520 cmd->resp.code = msg_sz == sizeof(stream_id) in virtio_snd_handle_pcm_prepare()
539 size_t msg_sz = iov_to_buf(cmd->elem->out_sg, in virtio_snd_handle_pcm_start_stop()
540 cmd->elem->out_num, in virtio_snd_handle_pcm_start_stop()
547 "%s: virtio-snd command size incorrect %zu vs \ in virtio_snd_handle_pcm_start_stop()
549 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); in virtio_snd_handle_pcm_start_stop()
554 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK); in virtio_snd_handle_pcm_start_stop()
560 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { in virtio_snd_handle_pcm_start_stop()
561 stream->active = start; in virtio_snd_handle_pcm_start_stop()
563 if (stream->info.direction == VIRTIO_SND_D_OUTPUT) { in virtio_snd_handle_pcm_start_stop()
564 AUD_set_active_out(stream->voice.out, start); in virtio_snd_handle_pcm_start_stop()
566 AUD_set_active_in(stream->voice.in, start); in virtio_snd_handle_pcm_start_stop()
570 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); in virtio_snd_handle_pcm_start_stop()
573 stream->active = start; in virtio_snd_handle_pcm_start_stop()
586 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { in virtio_snd_pcm_get_io_msgs_count()
587 QSIMPLEQ_FOREACH_SAFE(buffer, &stream->queue, entry, next) { in virtio_snd_pcm_get_io_msgs_count()
605 size_t msg_sz = iov_to_buf(cmd->elem->out_sg, in virtio_snd_handle_pcm_release()
606 cmd->elem->out_num, in virtio_snd_handle_pcm_release()
616 "%s: virtio-snd command size incorrect %zu vs \ in virtio_snd_handle_pcm_release()
618 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); in virtio_snd_handle_pcm_release()
633 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); in virtio_snd_handle_pcm_release()
639 * virtio-v1.2-csd01, 5.14.6.6.5.1, in virtio_snd_handle_pcm_release()
642 * - The device MUST complete all pending I/O messages for the in virtio_snd_handle_pcm_release()
644 * - The device MUST NOT complete the control request while there in virtio_snd_handle_pcm_release()
651 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK); in virtio_snd_handle_pcm_release()
664 size_t msg_sz = iov_to_buf(cmd->elem->out_sg, in process_cmd()
665 cmd->elem->out_num, in process_cmd()
667 &cmd->ctrl, in process_cmd()
675 "%s: virtio-snd command size incorrect %zu vs \ in process_cmd()
680 code = le32_to_cpu(cmd->ctrl.code); in process_cmd()
689 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); in process_cmd()
713 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); in process_cmd()
718 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); in process_cmd()
721 iov_from_buf(cmd->elem->in_sg, in process_cmd()
722 cmd->elem->in_num, in process_cmd()
724 &cmd->resp, in process_cmd()
726 virtqueue_push(cmd->vq, cmd->elem, in process_cmd()
727 sizeof(virtio_snd_hdr) + cmd->payload_size); in process_cmd()
728 virtio_notify(VIRTIO_DEVICE(s), cmd->vq); in process_cmd()
740 if (unlikely(qatomic_read(&s->processing_cmdq))) { in virtio_snd_process_cmdq()
744 WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) { in virtio_snd_process_cmdq()
745 qatomic_set(&s->processing_cmdq, true); in virtio_snd_process_cmdq()
746 while (!QTAILQ_EMPTY(&s->cmdq)) { in virtio_snd_process_cmdq()
747 cmd = QTAILQ_FIRST(&s->cmdq); in virtio_snd_process_cmdq()
752 QTAILQ_REMOVE(&s->cmdq, cmd, next); in virtio_snd_process_cmdq()
756 qatomic_set(&s->processing_cmdq, false); in virtio_snd_process_cmdq()
783 cmd->elem = elem; in virtio_snd_handle_ctrl()
784 cmd->vq = vq; in virtio_snd_handle_ctrl()
785 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK); in virtio_snd_handle_ctrl()
786 /* implicit cmd->payload_size = 0; */ in virtio_snd_handle_ctrl()
787 QTAILQ_INSERT_TAIL(&s->cmdq, cmd, next); in virtio_snd_handle_ctrl()
808 * Must only be called if vsnd->invalid is not empty.
816 g_assert(!QSIMPLEQ_EMPTY(&vsnd->invalid)); in empty_invalid_queue()
818 while (!QSIMPLEQ_EMPTY(&vsnd->invalid)) { in empty_invalid_queue()
819 buffer = QSIMPLEQ_FIRST(&vsnd->invalid); in empty_invalid_queue()
820 /* If buffer->vq != vq, our logic is fundamentally wrong, so bail out */ in empty_invalid_queue()
821 g_assert(buffer->vq == vq); in empty_invalid_queue()
824 iov_from_buf(buffer->elem->in_sg, in empty_invalid_queue()
825 buffer->elem->in_num, in empty_invalid_queue()
830 buffer->elem, in empty_invalid_queue()
832 QSIMPLEQ_REMOVE_HEAD(&vsnd->invalid, entry); in empty_invalid_queue()
855 * If any of the I/O messages are invalid, put them in vsnd->invalid and in virtio_snd_handle_tx_xfer()
873 msg_sz = iov_to_buf(elem->out_sg, in virtio_snd_handle_tx_xfer()
874 elem->out_num, in virtio_snd_handle_tx_xfer()
883 if (stream_id >= vsnd->snd_conf.streams in virtio_snd_handle_tx_xfer()
884 || vsnd->pcm->streams[stream_id] == NULL) { in virtio_snd_handle_tx_xfer()
888 stream = vsnd->pcm->streams[stream_id]; in virtio_snd_handle_tx_xfer()
889 if (stream->info.direction != VIRTIO_SND_D_OUTPUT) { in virtio_snd_handle_tx_xfer()
893 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { in virtio_snd_handle_tx_xfer()
894 size = iov_size(elem->out_sg, elem->out_num) - msg_sz; in virtio_snd_handle_tx_xfer()
897 buffer->elem = elem; in virtio_snd_handle_tx_xfer()
898 buffer->populated = false; in virtio_snd_handle_tx_xfer()
899 buffer->vq = vq; in virtio_snd_handle_tx_xfer()
900 buffer->size = size; in virtio_snd_handle_tx_xfer()
901 buffer->offset = 0; in virtio_snd_handle_tx_xfer()
903 QSIMPLEQ_INSERT_TAIL(&stream->queue, buffer, entry); in virtio_snd_handle_tx_xfer()
910 buffer->elem = elem; in virtio_snd_handle_tx_xfer()
911 buffer->vq = vq; in virtio_snd_handle_tx_xfer()
912 QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry); in virtio_snd_handle_tx_xfer()
936 * if any of the I/O messages are invalid, put them in vsnd->invalid and in virtio_snd_handle_rx_xfer()
954 msg_sz = iov_to_buf(elem->out_sg, in virtio_snd_handle_rx_xfer()
955 elem->out_num, in virtio_snd_handle_rx_xfer()
964 if (stream_id >= vsnd->snd_conf.streams in virtio_snd_handle_rx_xfer()
965 || !vsnd->pcm->streams[stream_id]) { in virtio_snd_handle_rx_xfer()
969 stream = vsnd->pcm->streams[stream_id]; in virtio_snd_handle_rx_xfer()
970 if (stream == NULL || stream->info.direction != VIRTIO_SND_D_INPUT) { in virtio_snd_handle_rx_xfer()
973 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { in virtio_snd_handle_rx_xfer()
974 size = iov_size(elem->in_sg, elem->in_num) - in virtio_snd_handle_rx_xfer()
977 buffer->elem = elem; in virtio_snd_handle_rx_xfer()
978 buffer->vq = vq; in virtio_snd_handle_rx_xfer()
979 buffer->size = 0; in virtio_snd_handle_rx_xfer()
980 buffer->offset = 0; in virtio_snd_handle_rx_xfer()
981 QSIMPLEQ_INSERT_TAIL(&stream->queue, buffer, entry); in virtio_snd_handle_rx_xfer()
988 buffer->elem = elem; in virtio_snd_handle_rx_xfer()
989 buffer->vq = vq; in virtio_snd_handle_rx_xfer()
990 QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry); in virtio_snd_handle_rx_xfer()
1002 * virtio-v1.2-csd01, 5.14.3, in get_features()
1007 features |= s->features; in get_features()
1036 if (vsnd->snd_conf.jacks > 8) { in virtio_snd_realize()
1039 vsnd->snd_conf.jacks); in virtio_snd_realize()
1042 if (vsnd->snd_conf.streams < 1 || vsnd->snd_conf.streams > 10) { in virtio_snd_realize()
1045 vsnd->snd_conf.streams); in virtio_snd_realize()
1049 if (vsnd->snd_conf.chmaps > VIRTIO_SND_CHMAP_MAX_SIZE) { in virtio_snd_realize()
1052 vsnd->snd_conf.chmaps); in virtio_snd_realize()
1056 if (!AUD_register_card("virtio-sound", &vsnd->card, errp)) { in virtio_snd_realize()
1060 vsnd->vmstate = in virtio_snd_realize()
1063 vsnd->pcm = g_new0(VirtIOSoundPCM, 1); in virtio_snd_realize()
1064 vsnd->pcm->snd = vsnd; in virtio_snd_realize()
1065 vsnd->pcm->streams = in virtio_snd_realize()
1066 g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams); in virtio_snd_realize()
1067 vsnd->pcm->pcm_params = in virtio_snd_realize()
1068 g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams); in virtio_snd_realize()
1071 virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1); in virtio_snd_realize()
1080 vsnd->queues[VIRTIO_SND_VQ_CONTROL] = in virtio_snd_realize()
1082 vsnd->queues[VIRTIO_SND_VQ_EVENT] = in virtio_snd_realize()
1084 vsnd->queues[VIRTIO_SND_VQ_TX] = in virtio_snd_realize()
1086 vsnd->queues[VIRTIO_SND_VQ_RX] = in virtio_snd_realize()
1088 qemu_mutex_init(&vsnd->cmdq_mutex); in virtio_snd_realize()
1089 QTAILQ_INIT(&vsnd->cmdq); in virtio_snd_realize()
1090 QSIMPLEQ_INIT(&vsnd->invalid); in virtio_snd_realize()
1092 for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) { in virtio_snd_realize()
1120 resp.latency_bytes = cpu_to_le32((uint32_t)buffer->size); in return_tx_buffer()
1121 iov_from_buf(buffer->elem->in_sg, in return_tx_buffer()
1122 buffer->elem->in_num, in return_tx_buffer()
1126 virtqueue_push(buffer->vq, in return_tx_buffer()
1127 buffer->elem, in return_tx_buffer()
1129 virtio_notify(VIRTIO_DEVICE(stream->s), buffer->vq); in return_tx_buffer()
1130 QSIMPLEQ_REMOVE(&stream->queue, in return_tx_buffer()
1149 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { in virtio_snd_pcm_out_cb()
1150 while (!QSIMPLEQ_EMPTY(&stream->queue)) { in virtio_snd_pcm_out_cb()
1151 buffer = QSIMPLEQ_FIRST(&stream->queue); in virtio_snd_pcm_out_cb()
1152 if (!virtio_queue_ready(buffer->vq)) { in virtio_snd_pcm_out_cb()
1155 if (!stream->active) { in virtio_snd_pcm_out_cb()
1160 if (!buffer->populated) { in virtio_snd_pcm_out_cb()
1161 iov_to_buf(buffer->elem->out_sg, in virtio_snd_pcm_out_cb()
1162 buffer->elem->out_num, in virtio_snd_pcm_out_cb()
1164 buffer->data, in virtio_snd_pcm_out_cb()
1165 buffer->size); in virtio_snd_pcm_out_cb()
1166 buffer->populated = true; in virtio_snd_pcm_out_cb()
1169 size = AUD_write(stream->voice.out, in virtio_snd_pcm_out_cb()
1170 buffer->data + buffer->offset, in virtio_snd_pcm_out_cb()
1171 MIN(buffer->size, available)); in virtio_snd_pcm_out_cb()
1172 assert(size <= MIN(buffer->size, available)); in virtio_snd_pcm_out_cb()
1178 buffer->size -= size; in virtio_snd_pcm_out_cb()
1179 buffer->offset += size; in virtio_snd_pcm_out_cb()
1180 available -= size; in virtio_snd_pcm_out_cb()
1181 if (buffer->size < 1) { in virtio_snd_pcm_out_cb()
1208 /* Copy data -if any- to guest */ in return_rx_buffer()
1209 iov_from_buf(buffer->elem->in_sg, in return_rx_buffer()
1210 buffer->elem->in_num, in return_rx_buffer()
1212 buffer->data, in return_rx_buffer()
1213 buffer->size); in return_rx_buffer()
1214 iov_from_buf(buffer->elem->in_sg, in return_rx_buffer()
1215 buffer->elem->in_num, in return_rx_buffer()
1216 buffer->size, in return_rx_buffer()
1219 virtqueue_push(buffer->vq, in return_rx_buffer()
1220 buffer->elem, in return_rx_buffer()
1221 sizeof(virtio_snd_pcm_status) + buffer->size); in return_rx_buffer()
1222 virtio_notify(VIRTIO_DEVICE(stream->s), buffer->vq); in return_rx_buffer()
1223 QSIMPLEQ_REMOVE(&stream->queue, in return_rx_buffer()
1243 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { in virtio_snd_pcm_in_cb()
1244 while (!QSIMPLEQ_EMPTY(&stream->queue)) { in virtio_snd_pcm_in_cb()
1245 buffer = QSIMPLEQ_FIRST(&stream->queue); in virtio_snd_pcm_in_cb()
1246 if (!virtio_queue_ready(buffer->vq)) { in virtio_snd_pcm_in_cb()
1249 if (!stream->active) { in virtio_snd_pcm_in_cb()
1255 max_size = iov_size(buffer->elem->in_sg, buffer->elem->in_num); in virtio_snd_pcm_in_cb()
1257 if (buffer->size >= max_size) { in virtio_snd_pcm_in_cb()
1261 size = AUD_read(stream->voice.in, in virtio_snd_pcm_in_cb()
1262 buffer->data + buffer->size, in virtio_snd_pcm_in_cb()
1263 MIN(available, (stream->params.period_bytes - in virtio_snd_pcm_in_cb()
1264 buffer->size))); in virtio_snd_pcm_in_cb()
1269 buffer->size += size; in virtio_snd_pcm_in_cb()
1270 available -= size; in virtio_snd_pcm_in_cb()
1271 if (buffer->size >= stream->params.period_bytes) { in virtio_snd_pcm_in_cb()
1296 (stream->info.direction == VIRTIO_SND_D_OUTPUT) ? return_tx_buffer : in virtio_snd_pcm_flush()
1299 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { in virtio_snd_pcm_flush()
1300 while (!QSIMPLEQ_EMPTY(&stream->queue)) { in virtio_snd_pcm_flush()
1301 buffer = QSIMPLEQ_FIRST(&stream->queue); in virtio_snd_pcm_flush()
1313 qemu_del_vm_change_state_handler(vsnd->vmstate); in virtio_snd_unrealize()
1316 if (vsnd->pcm) { in virtio_snd_unrealize()
1317 if (vsnd->pcm->streams) { in virtio_snd_unrealize()
1318 for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) { in virtio_snd_unrealize()
1319 stream = vsnd->pcm->streams[i]; in virtio_snd_unrealize()
1321 virtio_snd_process_cmdq(stream->s); in virtio_snd_unrealize()
1323 qemu_mutex_destroy(&stream->queue_mutex); in virtio_snd_unrealize()
1327 g_free(vsnd->pcm->streams); in virtio_snd_unrealize()
1329 g_free(vsnd->pcm->pcm_params); in virtio_snd_unrealize()
1330 g_free(vsnd->pcm); in virtio_snd_unrealize()
1331 vsnd->pcm = NULL; in virtio_snd_unrealize()
1333 AUD_remove_card(&vsnd->card); in virtio_snd_unrealize()
1334 qemu_mutex_destroy(&vsnd->cmdq_mutex); in virtio_snd_unrealize()
1335 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_CONTROL]); in virtio_snd_unrealize()
1336 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_EVENT]); in virtio_snd_unrealize()
1337 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_TX]); in virtio_snd_unrealize()
1338 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_RX]); in virtio_snd_unrealize()
1353 g_assert(QSIMPLEQ_EMPTY(&vsnd->invalid)); in virtio_snd_reset()
1355 WITH_QEMU_LOCK_GUARD(&vsnd->cmdq_mutex) { in virtio_snd_reset()
1356 while (!QTAILQ_EMPTY(&vsnd->cmdq)) { in virtio_snd_reset()
1357 cmd = QTAILQ_FIRST(&vsnd->cmdq); in virtio_snd_reset()
1358 QTAILQ_REMOVE(&vsnd->cmdq, cmd, next); in virtio_snd_reset()
1370 set_bit(DEVICE_CATEGORY_SOUND, dc->categories); in virtio_snd_class_init()
1373 dc->vmsd = &vmstate_virtio_snd; in virtio_snd_class_init()
1374 vdc->vmsd = &vmstate_virtio_snd_device; in virtio_snd_class_init()
1375 vdc->realize = virtio_snd_realize; in virtio_snd_class_init()
1376 vdc->unrealize = virtio_snd_unrealize; in virtio_snd_class_init()
1377 vdc->get_config = virtio_snd_get_config; in virtio_snd_class_init()
1378 vdc->get_features = get_features; in virtio_snd_class_init()
1379 vdc->reset = virtio_snd_reset; in virtio_snd_class_init()
1380 vdc->legacy_features = 0; in virtio_snd_class_init()