Lines Matching +full:- +full:- +full:-

22 #include "hw/qdev-properties.h"
23 #include "intel-hda.h"
25 #include "qemu/host-utils.h"
27 #include "intel-hda-defs.h"
32 /* -------------------------------------------------------------------------- */
61 for (i = 0; i < node->nparams; i++) { in hda_codec_find_param()
62 if (node->params[i].id == id) { in hda_codec_find_param()
63 return &node->params[i]; in hda_codec_find_param()
73 for (i = 0; i < codec->nnodes; i++) { in hda_codec_find_node()
74 if (codec->nodes[i].nid == nid) { in hda_codec_find_node()
75 return &codec->nodes[i]; in hda_codec_find_node()
87 as->freq = (format & AC_FMT_BASE_44K) ? 44100 : 48000; in hda_codec_parse_fmt()
90 case 1: as->freq *= 2; break; in hda_codec_parse_fmt()
91 case 2: as->freq *= 3; break; in hda_codec_parse_fmt()
92 case 3: as->freq *= 4; break; in hda_codec_parse_fmt()
96 case 1: as->freq /= 2; break; in hda_codec_parse_fmt()
97 case 2: as->freq /= 3; break; in hda_codec_parse_fmt()
98 case 3: as->freq /= 4; break; in hda_codec_parse_fmt()
99 case 4: as->freq /= 5; break; in hda_codec_parse_fmt()
100 case 5: as->freq /= 6; break; in hda_codec_parse_fmt()
101 case 6: as->freq /= 7; break; in hda_codec_parse_fmt()
102 case 7: as->freq /= 8; break; in hda_codec_parse_fmt()
106 case AC_FMT_BITS_8: as->fmt = AUDIO_FORMAT_S8; break; in hda_codec_parse_fmt()
107 case AC_FMT_BITS_16: as->fmt = AUDIO_FORMAT_S16; break; in hda_codec_parse_fmt()
108 case AC_FMT_BITS_32: as->fmt = AUDIO_FORMAT_S32; break; in hda_codec_parse_fmt()
111 as->nchannels = ((format & AC_FMT_CHAN_MASK) >> AC_FMT_CHAN_SHIFT) + 1; in hda_codec_parse_fmt()
114 /* -------------------------------------------------------------------------- */
123 0x1fc /* 16 -> 96 kHz */)
129 #include "hda-codec-common.h"
132 #include "hda-codec-common.h"
135 #define B_SIZE sizeof(st->buf)
136 #define B_MASK (sizeof(st->buf) - 1)
138 /* -------------------------------------------------------------------------- */
141 [ AUDIO_FORMAT_U8 ] = "PCM-U8",
142 [ AUDIO_FORMAT_S8 ] = "PCM-S8",
143 [ AUDIO_FORMAT_U16 ] = "PCM-U16",
144 [ AUDIO_FORMAT_S16 ] = "PCM-S16",
145 [ AUDIO_FORMAT_U32 ] = "PCM-U32",
146 [ AUDIO_FORMAT_S32 ] = "PCM-S32",
149 #define TYPE_HDA_AUDIO "hda-audio"
195 return 2 * (uint32_t)st->as.nchannels * (uint32_t)st->as.freq; in hda_bytes_per_second()
206 if (target_pos < -limit) { in hda_timer_sync_adjust()
207 corr = -HDA_TIMER_TICKS; in hda_timer_sync_adjust()
209 if (target_pos < -(2 * limit)) { in hda_timer_sync_adjust()
210 corr = -(4 * HDA_TIMER_TICKS); in hda_timer_sync_adjust()
216 trace_hda_audio_adjust(st->node->name, target_pos); in hda_timer_sync_adjust()
217 st->buft_start += corr; in hda_timer_sync_adjust()
226 int64_t uptime = now - st->buft_start; in hda_audio_input_timer()
227 int64_t wpos = st->wpos; in hda_audio_input_timer()
228 int64_t rpos = st->rpos; in hda_audio_input_timer()
238 wanted_rpos &= -4; /* IMPORTANT! clip to frames */ in hda_audio_input_timer()
245 int64_t to_transfer = MIN(wpos - rpos, wanted_rpos - rpos); in hda_audio_input_timer()
248 uint32_t chunk = MIN(B_SIZE - start, to_transfer); in hda_audio_input_timer()
250 &st->state->hda, st->stream, false, st->buf + start, chunk); in hda_audio_input_timer()
255 to_transfer -= chunk; in hda_audio_input_timer()
256 st->rpos += chunk; in hda_audio_input_timer()
261 if (st->running) { in hda_audio_input_timer()
262 timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS); in hda_audio_input_timer()
270 int64_t wpos = st->wpos; in hda_audio_input_cb()
271 int64_t rpos = st->rpos; in hda_audio_input_cb()
273 int64_t to_transfer = MIN(B_SIZE - (wpos - rpos), avail); in hda_audio_input_cb()
277 uint32_t chunk = (uint32_t) MIN(B_SIZE - start, to_transfer); in hda_audio_input_cb()
278 uint32_t read = AUD_read(st->voice.in, st->buf + start, chunk); in hda_audio_input_cb()
280 to_transfer -= read; in hda_audio_input_cb()
281 st->wpos += read; in hda_audio_input_cb()
287 hda_timer_sync_adjust(st, -((wpos - rpos) - (B_SIZE >> 1))); in hda_audio_input_cb()
296 int64_t uptime = now - st->buft_start; in hda_audio_output_timer()
297 int64_t wpos = st->wpos; in hda_audio_output_timer()
298 int64_t rpos = st->rpos; in hda_audio_output_timer()
308 wanted_wpos &= -4; /* IMPORTANT! clip to frames */ in hda_audio_output_timer()
315 int64_t to_transfer = MIN(B_SIZE - (wpos - rpos), wanted_wpos - wpos); in hda_audio_output_timer()
318 uint32_t chunk = MIN(B_SIZE - start, to_transfer); in hda_audio_output_timer()
320 &st->state->hda, st->stream, true, st->buf + start, chunk); in hda_audio_output_timer()
325 to_transfer -= chunk; in hda_audio_output_timer()
326 st->wpos += chunk; in hda_audio_output_timer()
331 if (st->running) { in hda_audio_output_timer()
332 timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS); in hda_audio_output_timer()
340 int64_t wpos = st->wpos; in hda_audio_output_cb()
341 int64_t rpos = st->rpos; in hda_audio_output_cb()
343 int64_t to_transfer = MIN(wpos - rpos, avail); in hda_audio_output_cb()
345 if (wpos - rpos == B_SIZE) { in hda_audio_output_cb()
347 st->rpos = 0; in hda_audio_output_cb()
348 st->wpos = 0; in hda_audio_output_cb()
349 st->buft_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); in hda_audio_output_cb()
350 trace_hda_audio_overrun(st->node->name); in hda_audio_output_cb()
356 uint32_t chunk = (uint32_t) MIN(B_SIZE - start, to_transfer); in hda_audio_output_cb()
357 uint32_t written = AUD_write(st->voice.out, st->buf + start, chunk); in hda_audio_output_cb()
359 to_transfer -= written; in hda_audio_output_cb()
360 st->rpos += written; in hda_audio_output_cb()
366 hda_timer_sync_adjust(st, (wpos - rpos) - (B_SIZE >> 1)); in hda_audio_output_cb()
376 while (avail - recv >= sizeof(st->compat_buf)) { in hda_audio_compat_input_cb()
377 if (st->compat_bpos != sizeof(st->compat_buf)) { in hda_audio_compat_input_cb()
378 len = AUD_read(st->voice.in, st->compat_buf + st->compat_bpos, in hda_audio_compat_input_cb()
379 sizeof(st->compat_buf) - st->compat_bpos); in hda_audio_compat_input_cb()
380 st->compat_bpos += len; in hda_audio_compat_input_cb()
382 if (st->compat_bpos != sizeof(st->compat_buf)) { in hda_audio_compat_input_cb()
386 rc = hda_codec_xfer(&st->state->hda, st->stream, false, in hda_audio_compat_input_cb()
387 st->compat_buf, sizeof(st->compat_buf)); in hda_audio_compat_input_cb()
391 st->compat_bpos = 0; in hda_audio_compat_input_cb()
402 while (avail - sent >= sizeof(st->compat_buf)) { in hda_audio_compat_output_cb()
403 if (st->compat_bpos == sizeof(st->compat_buf)) { in hda_audio_compat_output_cb()
404 rc = hda_codec_xfer(&st->state->hda, st->stream, true, in hda_audio_compat_output_cb()
405 st->compat_buf, sizeof(st->compat_buf)); in hda_audio_compat_output_cb()
409 st->compat_bpos = 0; in hda_audio_compat_output_cb()
411 len = AUD_write(st->voice.out, st->compat_buf + st->compat_bpos, in hda_audio_compat_output_cb()
412 sizeof(st->compat_buf) - st->compat_bpos); in hda_audio_compat_output_cb()
413 st->compat_bpos += len; in hda_audio_compat_output_cb()
415 if (st->compat_bpos != sizeof(st->compat_buf)) { in hda_audio_compat_output_cb()
423 if (st->node == NULL) { in hda_audio_set_running()
426 if (st->running == running) { in hda_audio_set_running()
429 st->running = running; in hda_audio_set_running()
430 trace_hda_audio_running(st->node->name, st->stream, st->running); in hda_audio_set_running()
431 if (st->state->use_timer) { in hda_audio_set_running()
434 st->rpos = 0; in hda_audio_set_running()
435 st->wpos = 0; in hda_audio_set_running()
436 st->buft_start = now; in hda_audio_set_running()
437 timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS); in hda_audio_set_running()
439 timer_del(st->buft); in hda_audio_set_running()
442 if (st->output) { in hda_audio_set_running()
443 AUD_set_active_out(st->voice.out, st->running); in hda_audio_set_running()
445 AUD_set_active_in(st->voice.in, st->running); in hda_audio_set_running()
454 if (st->node == NULL) { in hda_audio_set_amp()
458 muted = st->mute_left && st->mute_right; in hda_audio_set_amp()
459 left = st->mute_left ? 0 : st->gain_left; in hda_audio_set_amp()
460 right = st->mute_right ? 0 : st->gain_right; in hda_audio_set_amp()
465 if (!st->state->mixer) { in hda_audio_set_amp()
468 if (st->output) { in hda_audio_set_amp()
469 AUD_set_volume_out(st->voice.out, muted, left, right); in hda_audio_set_amp()
471 AUD_set_volume_in(st->voice.in, muted, left, right); in hda_audio_set_amp()
477 bool use_timer = st->state->use_timer; in hda_audio_setup()
480 if (st->node == NULL) { in hda_audio_setup()
484 trace_hda_audio_format(st->node->name, st->as.nchannels, in hda_audio_setup()
485 fmt2name[st->as.fmt], st->as.freq); in hda_audio_setup()
487 if (st->output) { in hda_audio_setup()
490 timer_del(st->buft); in hda_audio_setup()
494 st->voice.out = AUD_open_out(&st->state->card, st->voice.out, in hda_audio_setup()
495 st->node->name, st, cb, &st->as); in hda_audio_setup()
499 timer_del(st->buft); in hda_audio_setup()
503 st->voice.in = AUD_open_in(&st->state->card, st->voice.in, in hda_audio_setup()
504 st->node->name, st, cb, &st->as); in hda_audio_setup()
526 node = hda_codec_find_node(a->desc, nid); in hda_audio_command()
531 __func__, nid, node->name, verb, payload); in hda_audio_command()
540 hda_codec_response(hda, true, param->val); in hda_audio_command()
543 hda_codec_response(hda, true, a->desc->iid); in hda_audio_command()
549 count = param ? param->val : 0; in hda_audio_command()
553 response |= node->conn[payload] << shift; in hda_audio_command()
562 hda_codec_response(hda, true, node->config); in hda_audio_command()
565 hda_codec_response(hda, true, node->pinctl); in hda_audio_command()
568 if (node->pinctl != payload) { in hda_audio_command()
576 st = a->st + node->stindex; in hda_audio_command()
577 if (st->node == NULL) { in hda_audio_command()
581 st->stream = (payload >> 4) & 0x0f; in hda_audio_command()
582 st->channel = payload & 0x0f; in hda_audio_command()
584 st->node->name, st->stream, st->channel); in hda_audio_command()
585 hda_audio_set_running(st, a->running_real[st->output * 16 + st->stream]); in hda_audio_command()
589 st = a->st + node->stindex; in hda_audio_command()
590 if (st->node == NULL) { in hda_audio_command()
593 response = st->stream << 4 | st->channel; in hda_audio_command()
597 st = a->st + node->stindex; in hda_audio_command()
598 if (st->node == NULL) { in hda_audio_command()
601 st->format = payload; in hda_audio_command()
602 hda_codec_parse_fmt(st->format, &st->as); in hda_audio_command()
607 st = a->st + node->stindex; in hda_audio_command()
608 if (st->node == NULL) { in hda_audio_command()
611 hda_codec_response(hda, true, st->format); in hda_audio_command()
614 st = a->st + node->stindex; in hda_audio_command()
615 if (st->node == NULL) { in hda_audio_command()
619 response = st->gain_left | (st->mute_left ? AC_AMP_MUTE : 0); in hda_audio_command()
621 response = st->gain_right | (st->mute_right ? AC_AMP_MUTE : 0); in hda_audio_command()
626 st = a->st + node->stindex; in hda_audio_command()
627 if (st->node == NULL) { in hda_audio_command()
631 st->node->name, in hda_audio_command()
632 (payload & AC_AMP_SET_OUTPUT) ? "o" : "-", in hda_audio_command()
633 (payload & AC_AMP_SET_INPUT) ? "i" : "-", in hda_audio_command()
634 (payload & AC_AMP_SET_LEFT) ? "l" : "-", in hda_audio_command()
635 (payload & AC_AMP_SET_RIGHT) ? "r" : "-", in hda_audio_command()
640 st->gain_left = payload & AC_AMP_GAIN; in hda_audio_command()
641 st->mute_left = payload & AC_AMP_MUTE; in hda_audio_command()
644 st->gain_right = payload & AC_AMP_GAIN; in hda_audio_command()
645 st->mute_right = payload & AC_AMP_MUTE; in hda_audio_command()
664 __func__, nid, node ? node->name : "?", verb, payload); in hda_audio_command()
673 a->running_compat[stnr] = running; in hda_audio_stream()
674 a->running_real[output * 16 + stnr] = running; in hda_audio_stream()
675 for (s = 0; s < ARRAY_SIZE(a->st); s++) { in hda_audio_stream()
676 if (a->st[s].node == NULL) { in hda_audio_stream()
679 if (a->st[s].output != output) { in hda_audio_stream()
682 if (a->st[s].stream != stnr) { in hda_audio_stream()
685 hda_audio_set_running(&a->st[s], running); in hda_audio_stream()
699 if (!AUD_register_card("hda", &a->card, errp)) { in hda_audio_init()
703 a->desc = desc; in hda_audio_init()
704 a->name = object_get_typename(OBJECT(a)); in hda_audio_init()
705 dprint(a, 1, "%s: cad %d\n", __func__, a->hda.cad); in hda_audio_init()
707 for (i = 0; i < a->desc->nnodes; i++) { in hda_audio_init()
708 node = a->desc->nodes + i; in hda_audio_init()
713 type = (param->val & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; in hda_audio_init()
717 assert(node->stindex < ARRAY_SIZE(a->st)); in hda_audio_init()
718 st = a->st + node->stindex; in hda_audio_init()
719 st->state = a; in hda_audio_init()
720 st->node = node; in hda_audio_init()
723 st->gain_left = QEMU_HDA_AMP_STEPS; in hda_audio_init()
724 st->gain_right = QEMU_HDA_AMP_STEPS; in hda_audio_init()
725 st->compat_bpos = sizeof(st->compat_buf); in hda_audio_init()
726 st->output = true; in hda_audio_init()
727 st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL, in hda_audio_init()
730 st->output = false; in hda_audio_init()
731 st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL, in hda_audio_init()
734 st->format = AC_FMT_TYPE_PCM | AC_FMT_BITS_16 | in hda_audio_init()
736 hda_codec_parse_fmt(st->format, &st->as); in hda_audio_init()
750 for (i = 0; i < ARRAY_SIZE(a->st); i++) { in hda_audio_exit()
751 st = a->st + i; in hda_audio_exit()
752 if (st->node == NULL) { in hda_audio_exit()
755 timer_free(st->buft); in hda_audio_exit()
756 if (st->output) { in hda_audio_exit()
757 AUD_close_out(&a->card, st->voice.out); in hda_audio_exit()
759 AUD_close_in(&a->card, st->voice.in); in hda_audio_exit()
762 AUD_remove_card(&a->card); in hda_audio_exit()
774 for (i = 0; i < ARRAY_SIZE(a->running_compat); i++) in hda_audio_post_load()
775 a->running_real[16 + i] = a->running_compat[i]; in hda_audio_post_load()
778 for (i = 0; i < ARRAY_SIZE(a->st); i++) { in hda_audio_post_load()
779 st = a->st + i; in hda_audio_post_load()
780 if (st->node == NULL) in hda_audio_post_load()
782 hda_codec_parse_fmt(st->format, &st->as); in hda_audio_post_load()
785 hda_audio_set_running(st, a->running_real[st->output * 16 + st->stream]); in hda_audio_post_load()
797 for (i = 0; i < ARRAY_SIZE(a->st); i++) { in hda_audio_reset()
798 st = a->st + i; in hda_audio_reset()
799 if (st->node != NULL) { in hda_audio_reset()
808 return st->state && st->state->use_timer; in vmstate_hda_audio_stream_buf_needed()
812 .name = "hda-audio-stream/buffer",
826 .name = "hda-audio-stream",
847 .name = "hda-audio",
864 DEFINE_PROP_BOOL("use-timer", HDAAudioState, use_timer, true),
872 if (!a->mixer) { in hda_audio_init_output()
884 if (!a->mixer) { in hda_audio_init_duplex()
896 if (!a->mixer) { in hda_audio_init_micro()
908 k->exit = hda_audio_exit; in hda_audio_base_class_init()
909 k->command = hda_audio_command; in hda_audio_base_class_init()
910 k->stream = hda_audio_stream; in hda_audio_base_class_init()
911 set_bit(DEVICE_CATEGORY_SOUND, dc->categories); in hda_audio_base_class_init()
913 dc->vmsd = &vmstate_hda_audio; in hda_audio_base_class_init()
930 k->init = hda_audio_init_output; in hda_audio_output_class_init()
931 dc->desc = "HDA Audio Codec, output-only (line-out)"; in hda_audio_output_class_init()
935 .name = "hda-output",
945 k->init = hda_audio_init_duplex; in hda_audio_duplex_class_init()
946 dc->desc = "HDA Audio Codec, duplex (line-out, line-in)"; in hda_audio_duplex_class_init()
950 .name = "hda-duplex",
960 k->init = hda_audio_init_micro; in hda_audio_micro_class_init()
961 dc->desc = "HDA Audio Codec, duplex (speaker, microphone)"; in hda_audio_micro_class_init()
965 .name = "hda-micro",