mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
Merge branch 'master' of git://git.qemu.org/qemu into x86-next
This commit is contained in:
commit
0b6e9aa89e
16 changed files with 288 additions and 66 deletions
|
@ -21,10 +21,6 @@ void tb_flush(CPUState *cpu)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void tb_unlock(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
|
void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,9 +335,8 @@ static int audio_get_conf_int (const char *key, int defval, int *defaultp)
|
||||||
char *strval;
|
char *strval;
|
||||||
|
|
||||||
strval = getenv (key);
|
strval = getenv (key);
|
||||||
if (strval) {
|
if (strval && !qemu_strtoi(strval, NULL, 10, &val)) {
|
||||||
*defaultp = 0;
|
*defaultp = 0;
|
||||||
val = atoi (strval);
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
4
cpus.c
4
cpus.c
|
@ -1355,6 +1355,7 @@ static int tcg_cpu_exec(CPUState *cpu)
|
||||||
int64_t ti;
|
int64_t ti;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
assert(tcg_enabled());
|
||||||
#ifdef CONFIG_PROFILER
|
#ifdef CONFIG_PROFILER
|
||||||
ti = profile_getclock();
|
ti = profile_getclock();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1397,6 +1398,7 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
|
||||||
{
|
{
|
||||||
CPUState *cpu = arg;
|
CPUState *cpu = arg;
|
||||||
|
|
||||||
|
assert(tcg_enabled());
|
||||||
rcu_register_thread();
|
rcu_register_thread();
|
||||||
tcg_register_thread();
|
tcg_register_thread();
|
||||||
|
|
||||||
|
@ -1631,6 +1633,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
|
||||||
{
|
{
|
||||||
CPUState *cpu = arg;
|
CPUState *cpu = arg;
|
||||||
|
|
||||||
|
assert(tcg_enabled());
|
||||||
g_assert(!use_icount);
|
g_assert(!use_icount);
|
||||||
|
|
||||||
rcu_register_thread();
|
rcu_register_thread();
|
||||||
|
@ -1854,6 +1857,7 @@ static void qemu_tcg_init_vcpu(CPUState *cpu)
|
||||||
static QemuThread *single_tcg_cpu_thread;
|
static QemuThread *single_tcg_cpu_thread;
|
||||||
static int tcg_region_inited;
|
static int tcg_region_inited;
|
||||||
|
|
||||||
|
assert(tcg_enabled());
|
||||||
/*
|
/*
|
||||||
* Initialize TCG regions--once. Now is a good time, because:
|
* Initialize TCG regions--once. Now is a good time, because:
|
||||||
* (1) TCG's init context, prologue and target globals have been set up.
|
* (1) TCG's init context, prologue and target globals have been set up.
|
||||||
|
|
3
exec.c
3
exec.c
|
@ -1323,6 +1323,7 @@ static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t length)
|
||||||
RAMBlock *block;
|
RAMBlock *block;
|
||||||
ram_addr_t end;
|
ram_addr_t end;
|
||||||
|
|
||||||
|
assert(tcg_enabled());
|
||||||
end = TARGET_PAGE_ALIGN(start + length);
|
end = TARGET_PAGE_ALIGN(start + length);
|
||||||
start &= TARGET_PAGE_MASK;
|
start &= TARGET_PAGE_MASK;
|
||||||
|
|
||||||
|
@ -2655,6 +2656,7 @@ void memory_notdirty_write_prepare(NotDirtyInfo *ndi,
|
||||||
void memory_notdirty_write_complete(NotDirtyInfo *ndi)
|
void memory_notdirty_write_complete(NotDirtyInfo *ndi)
|
||||||
{
|
{
|
||||||
if (ndi->pages) {
|
if (ndi->pages) {
|
||||||
|
assert(tcg_enabled());
|
||||||
page_collection_unlock(ndi->pages);
|
page_collection_unlock(ndi->pages);
|
||||||
ndi->pages = NULL;
|
ndi->pages = NULL;
|
||||||
}
|
}
|
||||||
|
@ -3046,6 +3048,7 @@ static void tcg_commit(MemoryListener *listener)
|
||||||
CPUAddressSpace *cpuas;
|
CPUAddressSpace *cpuas;
|
||||||
AddressSpaceDispatch *d;
|
AddressSpaceDispatch *d;
|
||||||
|
|
||||||
|
assert(tcg_enabled());
|
||||||
/* since each CPU stores ram addresses in its TLB cache, we must
|
/* since each CPU stores ram addresses in its TLB cache, we must
|
||||||
reset the modified entries */
|
reset the modified entries */
|
||||||
cpuas = container_of(listener, CPUAddressSpace, tcg_as_listener);
|
cpuas = container_of(listener, CPUAddressSpace, tcg_as_listener);
|
||||||
|
|
|
@ -18,11 +18,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/atomic.h"
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
#include "intel-hda.h"
|
#include "intel-hda.h"
|
||||||
#include "intel-hda-defs.h"
|
#include "intel-hda-defs.h"
|
||||||
#include "audio/audio.h"
|
#include "audio/audio.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
@ -126,6 +128,10 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
|
||||||
#define PARAM nomixemu
|
#define PARAM nomixemu
|
||||||
#include "hda-codec-common.h"
|
#include "hda-codec-common.h"
|
||||||
|
|
||||||
|
#define HDA_TIMER_TICKS (SCALE_MS)
|
||||||
|
#define B_SIZE sizeof(st->buf)
|
||||||
|
#define B_MASK (sizeof(st->buf) - 1)
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static const char *fmt2name[] = {
|
static const char *fmt2name[] = {
|
||||||
|
@ -154,8 +160,13 @@ struct HDAAudioStream {
|
||||||
SWVoiceIn *in;
|
SWVoiceIn *in;
|
||||||
SWVoiceOut *out;
|
SWVoiceOut *out;
|
||||||
} voice;
|
} voice;
|
||||||
uint8_t buf[HDA_BUFFER_SIZE];
|
uint8_t compat_buf[HDA_BUFFER_SIZE];
|
||||||
uint32_t bpos;
|
uint32_t compat_bpos;
|
||||||
|
uint8_t buf[8192]; /* size must be power of two */
|
||||||
|
int64_t rpos;
|
||||||
|
int64_t wpos;
|
||||||
|
QEMUTimer *buft;
|
||||||
|
int64_t buft_start;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TYPE_HDA_AUDIO "hda-audio"
|
#define TYPE_HDA_AUDIO "hda-audio"
|
||||||
|
@ -174,55 +185,217 @@ struct HDAAudioState {
|
||||||
/* properties */
|
/* properties */
|
||||||
uint32_t debug;
|
uint32_t debug;
|
||||||
bool mixer;
|
bool mixer;
|
||||||
|
bool use_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline int64_t hda_bytes_per_second(HDAAudioStream *st)
|
||||||
|
{
|
||||||
|
return 2 * st->as.nchannels * st->as.freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void hda_timer_sync_adjust(HDAAudioStream *st, int64_t target_pos)
|
||||||
|
{
|
||||||
|
int64_t limit = B_SIZE / 8;
|
||||||
|
int64_t corr = 0;
|
||||||
|
|
||||||
|
if (target_pos > limit) {
|
||||||
|
corr = HDA_TIMER_TICKS;
|
||||||
|
}
|
||||||
|
if (target_pos < -limit) {
|
||||||
|
corr = -HDA_TIMER_TICKS;
|
||||||
|
}
|
||||||
|
if (corr == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_hda_audio_adjust(st->node->name, target_pos);
|
||||||
|
atomic_fetch_add(&st->buft_start, corr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hda_audio_input_timer(void *opaque)
|
||||||
|
{
|
||||||
|
HDAAudioStream *st = opaque;
|
||||||
|
|
||||||
|
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
|
|
||||||
|
int64_t buft_start = atomic_fetch_add(&st->buft_start, 0);
|
||||||
|
int64_t wpos = atomic_fetch_add(&st->wpos, 0);
|
||||||
|
int64_t rpos = atomic_fetch_add(&st->rpos, 0);
|
||||||
|
|
||||||
|
int64_t wanted_rpos = hda_bytes_per_second(st) * (now - buft_start)
|
||||||
|
/ NANOSECONDS_PER_SECOND;
|
||||||
|
wanted_rpos &= -4; /* IMPORTANT! clip to frames */
|
||||||
|
|
||||||
|
if (wanted_rpos <= rpos) {
|
||||||
|
/* we already transmitted the data */
|
||||||
|
goto out_timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t to_transfer = audio_MIN(wpos - rpos, wanted_rpos - rpos);
|
||||||
|
while (to_transfer) {
|
||||||
|
uint32_t start = (rpos & B_MASK);
|
||||||
|
uint32_t chunk = audio_MIN(B_SIZE - start, to_transfer);
|
||||||
|
int rc = hda_codec_xfer(
|
||||||
|
&st->state->hda, st->stream, false, st->buf + start, chunk);
|
||||||
|
if (!rc) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rpos += chunk;
|
||||||
|
to_transfer -= chunk;
|
||||||
|
atomic_fetch_add(&st->rpos, chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_timer:
|
||||||
|
|
||||||
|
if (st->running) {
|
||||||
|
timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void hda_audio_input_cb(void *opaque, int avail)
|
static void hda_audio_input_cb(void *opaque, int avail)
|
||||||
{
|
{
|
||||||
HDAAudioStream *st = opaque;
|
HDAAudioStream *st = opaque;
|
||||||
int recv = 0;
|
|
||||||
int len;
|
|
||||||
bool rc;
|
|
||||||
|
|
||||||
while (avail - recv >= sizeof(st->buf)) {
|
int64_t wpos = atomic_fetch_add(&st->wpos, 0);
|
||||||
if (st->bpos != sizeof(st->buf)) {
|
int64_t rpos = atomic_fetch_add(&st->rpos, 0);
|
||||||
len = AUD_read(st->voice.in, st->buf + st->bpos,
|
|
||||||
sizeof(st->buf) - st->bpos);
|
int64_t to_transfer = audio_MIN(B_SIZE - (wpos - rpos), avail);
|
||||||
st->bpos += len;
|
|
||||||
recv += len;
|
hda_timer_sync_adjust(st, -((wpos - rpos) + to_transfer - (B_SIZE >> 1)));
|
||||||
if (st->bpos != sizeof(st->buf)) {
|
|
||||||
|
while (to_transfer) {
|
||||||
|
uint32_t start = (uint32_t) (wpos & B_MASK);
|
||||||
|
uint32_t chunk = (uint32_t) audio_MIN(B_SIZE - start, to_transfer);
|
||||||
|
uint32_t read = AUD_read(st->voice.in, st->buf + start, chunk);
|
||||||
|
wpos += read;
|
||||||
|
to_transfer -= read;
|
||||||
|
atomic_fetch_add(&st->wpos, read);
|
||||||
|
if (chunk != read) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc = hda_codec_xfer(&st->state->hda, st->stream, false,
|
}
|
||||||
st->buf, sizeof(st->buf));
|
|
||||||
|
static void hda_audio_output_timer(void *opaque)
|
||||||
|
{
|
||||||
|
HDAAudioStream *st = opaque;
|
||||||
|
|
||||||
|
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
|
|
||||||
|
int64_t buft_start = atomic_fetch_add(&st->buft_start, 0);
|
||||||
|
int64_t wpos = atomic_fetch_add(&st->wpos, 0);
|
||||||
|
int64_t rpos = atomic_fetch_add(&st->rpos, 0);
|
||||||
|
|
||||||
|
int64_t wanted_wpos = hda_bytes_per_second(st) * (now - buft_start)
|
||||||
|
/ NANOSECONDS_PER_SECOND;
|
||||||
|
wanted_wpos &= -4; /* IMPORTANT! clip to frames */
|
||||||
|
|
||||||
|
if (wanted_wpos <= wpos) {
|
||||||
|
/* we already received the data */
|
||||||
|
goto out_timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t to_transfer = audio_MIN(B_SIZE - (wpos - rpos), wanted_wpos - wpos);
|
||||||
|
while (to_transfer) {
|
||||||
|
uint32_t start = (wpos & B_MASK);
|
||||||
|
uint32_t chunk = audio_MIN(B_SIZE - start, to_transfer);
|
||||||
|
int rc = hda_codec_xfer(
|
||||||
|
&st->state->hda, st->stream, true, st->buf + start, chunk);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
st->bpos = 0;
|
wpos += chunk;
|
||||||
|
to_transfer -= chunk;
|
||||||
|
atomic_fetch_add(&st->wpos, chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_timer:
|
||||||
|
|
||||||
|
if (st->running) {
|
||||||
|
timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hda_audio_output_cb(void *opaque, int avail)
|
static void hda_audio_output_cb(void *opaque, int avail)
|
||||||
|
{
|
||||||
|
HDAAudioStream *st = opaque;
|
||||||
|
|
||||||
|
int64_t wpos = atomic_fetch_add(&st->wpos, 0);
|
||||||
|
int64_t rpos = atomic_fetch_add(&st->rpos, 0);
|
||||||
|
|
||||||
|
int64_t to_transfer = audio_MIN(wpos - rpos, avail);
|
||||||
|
|
||||||
|
if (wpos - rpos == B_SIZE) {
|
||||||
|
/* drop buffer, reset timer adjust */
|
||||||
|
st->rpos = 0;
|
||||||
|
st->wpos = 0;
|
||||||
|
st->buft_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
|
trace_hda_audio_overrun(st->node->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hda_timer_sync_adjust(st, (wpos - rpos) - to_transfer - (B_SIZE >> 1));
|
||||||
|
|
||||||
|
while (to_transfer) {
|
||||||
|
uint32_t start = (uint32_t) (rpos & B_MASK);
|
||||||
|
uint32_t chunk = (uint32_t) audio_MIN(B_SIZE - start, to_transfer);
|
||||||
|
uint32_t written = AUD_write(st->voice.out, st->buf + start, chunk);
|
||||||
|
rpos += written;
|
||||||
|
to_transfer -= written;
|
||||||
|
atomic_fetch_add(&st->rpos, written);
|
||||||
|
if (chunk != written) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hda_audio_compat_input_cb(void *opaque, int avail)
|
||||||
|
{
|
||||||
|
HDAAudioStream *st = opaque;
|
||||||
|
int recv = 0;
|
||||||
|
int len;
|
||||||
|
bool rc;
|
||||||
|
|
||||||
|
while (avail - recv >= sizeof(st->compat_buf)) {
|
||||||
|
if (st->compat_bpos != sizeof(st->compat_buf)) {
|
||||||
|
len = AUD_read(st->voice.in, st->compat_buf + st->compat_bpos,
|
||||||
|
sizeof(st->compat_buf) - st->compat_bpos);
|
||||||
|
st->compat_bpos += len;
|
||||||
|
recv += len;
|
||||||
|
if (st->compat_bpos != sizeof(st->compat_buf)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = hda_codec_xfer(&st->state->hda, st->stream, false,
|
||||||
|
st->compat_buf, sizeof(st->compat_buf));
|
||||||
|
if (!rc) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
st->compat_bpos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hda_audio_compat_output_cb(void *opaque, int avail)
|
||||||
{
|
{
|
||||||
HDAAudioStream *st = opaque;
|
HDAAudioStream *st = opaque;
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
int len;
|
int len;
|
||||||
bool rc;
|
bool rc;
|
||||||
|
|
||||||
while (avail - sent >= sizeof(st->buf)) {
|
while (avail - sent >= sizeof(st->compat_buf)) {
|
||||||
if (st->bpos == sizeof(st->buf)) {
|
if (st->compat_bpos == sizeof(st->compat_buf)) {
|
||||||
rc = hda_codec_xfer(&st->state->hda, st->stream, true,
|
rc = hda_codec_xfer(&st->state->hda, st->stream, true,
|
||||||
st->buf, sizeof(st->buf));
|
st->compat_buf, sizeof(st->compat_buf));
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
st->bpos = 0;
|
st->compat_bpos = 0;
|
||||||
}
|
}
|
||||||
len = AUD_write(st->voice.out, st->buf + st->bpos,
|
len = AUD_write(st->voice.out, st->compat_buf + st->compat_bpos,
|
||||||
sizeof(st->buf) - st->bpos);
|
sizeof(st->compat_buf) - st->compat_bpos);
|
||||||
st->bpos += len;
|
st->compat_bpos += len;
|
||||||
sent += len;
|
sent += len;
|
||||||
if (st->bpos != sizeof(st->buf)) {
|
if (st->compat_bpos != sizeof(st->compat_buf)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,8 +410,18 @@ static void hda_audio_set_running(HDAAudioStream *st, bool running)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
st->running = running;
|
st->running = running;
|
||||||
dprint(st->state, 1, "%s: %s (stream %d)\n", st->node->name,
|
trace_hda_audio_running(st->node->name, st->stream, st->running);
|
||||||
st->running ? "on" : "off", st->stream);
|
if (st->state->use_timer) {
|
||||||
|
if (running) {
|
||||||
|
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
|
st->rpos = 0;
|
||||||
|
st->wpos = 0;
|
||||||
|
st->buft_start = now;
|
||||||
|
timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS);
|
||||||
|
} else {
|
||||||
|
timer_del(st->buft);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (st->output) {
|
if (st->output) {
|
||||||
AUD_set_active_out(st->voice.out, st->running);
|
AUD_set_active_out(st->voice.out, st->running);
|
||||||
} else {
|
} else {
|
||||||
|
@ -274,22 +457,36 @@ static void hda_audio_set_amp(HDAAudioStream *st)
|
||||||
|
|
||||||
static void hda_audio_setup(HDAAudioStream *st)
|
static void hda_audio_setup(HDAAudioStream *st)
|
||||||
{
|
{
|
||||||
|
bool use_timer = st->state->use_timer;
|
||||||
|
audio_callback_fn cb;
|
||||||
|
|
||||||
if (st->node == NULL) {
|
if (st->node == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprint(st->state, 1, "%s: format: %d x %s @ %d Hz\n",
|
trace_hda_audio_format(st->node->name, st->as.nchannels,
|
||||||
st->node->name, st->as.nchannels,
|
|
||||||
fmt2name[st->as.fmt], st->as.freq);
|
fmt2name[st->as.fmt], st->as.freq);
|
||||||
|
|
||||||
if (st->output) {
|
if (st->output) {
|
||||||
st->voice.out = AUD_open_out(&st->state->card, st->voice.out,
|
if (use_timer) {
|
||||||
st->node->name, st,
|
cb = hda_audio_output_cb;
|
||||||
hda_audio_output_cb, &st->as);
|
st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||||
|
hda_audio_output_timer, st);
|
||||||
} else {
|
} else {
|
||||||
|
cb = hda_audio_compat_output_cb;
|
||||||
|
}
|
||||||
|
st->voice.out = AUD_open_out(&st->state->card, st->voice.out,
|
||||||
|
st->node->name, st, cb, &st->as);
|
||||||
|
} else {
|
||||||
|
if (use_timer) {
|
||||||
|
cb = hda_audio_input_cb;
|
||||||
|
st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||||
|
hda_audio_input_timer, st);
|
||||||
|
} else {
|
||||||
|
cb = hda_audio_compat_input_cb;
|
||||||
|
}
|
||||||
st->voice.in = AUD_open_in(&st->state->card, st->voice.in,
|
st->voice.in = AUD_open_in(&st->state->card, st->voice.in,
|
||||||
st->node->name, st,
|
st->node->name, st, cb, &st->as);
|
||||||
hda_audio_input_cb, &st->as);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,7 +702,7 @@ static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
|
||||||
/* unmute output by default */
|
/* unmute output by default */
|
||||||
st->gain_left = QEMU_HDA_AMP_STEPS;
|
st->gain_left = QEMU_HDA_AMP_STEPS;
|
||||||
st->gain_right = QEMU_HDA_AMP_STEPS;
|
st->gain_right = QEMU_HDA_AMP_STEPS;
|
||||||
st->bpos = sizeof(st->buf);
|
st->compat_bpos = sizeof(st->compat_buf);
|
||||||
st->output = true;
|
st->output = true;
|
||||||
} else {
|
} else {
|
||||||
st->output = false;
|
st->output = false;
|
||||||
|
@ -532,6 +729,9 @@ static void hda_audio_exit(HDACodecDevice *hda)
|
||||||
if (st->node == NULL) {
|
if (st->node == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (a->use_timer) {
|
||||||
|
timer_del(st->buft);
|
||||||
|
}
|
||||||
if (st->output) {
|
if (st->output) {
|
||||||
AUD_close_out(&a->card, st->voice.out);
|
AUD_close_out(&a->card, st->voice.out);
|
||||||
} else {
|
} else {
|
||||||
|
@ -581,6 +781,26 @@ static void hda_audio_reset(DeviceState *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool vmstate_hda_audio_stream_buf_needed(void *opaque)
|
||||||
|
{
|
||||||
|
HDAAudioStream *st = opaque;
|
||||||
|
return st->state->use_timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_hda_audio_stream_buf = {
|
||||||
|
.name = "hda-audio-stream/buffer",
|
||||||
|
.version_id = 1,
|
||||||
|
.needed = vmstate_hda_audio_stream_buf_needed,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_BUFFER(buf, HDAAudioStream),
|
||||||
|
VMSTATE_INT64(rpos, HDAAudioStream),
|
||||||
|
VMSTATE_INT64(wpos, HDAAudioStream),
|
||||||
|
VMSTATE_TIMER_PTR(buft, HDAAudioStream),
|
||||||
|
VMSTATE_INT64(buft_start, HDAAudioStream),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_hda_audio_stream = {
|
static const VMStateDescription vmstate_hda_audio_stream = {
|
||||||
.name = "hda-audio-stream",
|
.name = "hda-audio-stream",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
|
@ -592,9 +812,13 @@ static const VMStateDescription vmstate_hda_audio_stream = {
|
||||||
VMSTATE_UINT32(gain_right, HDAAudioStream),
|
VMSTATE_UINT32(gain_right, HDAAudioStream),
|
||||||
VMSTATE_BOOL(mute_left, HDAAudioStream),
|
VMSTATE_BOOL(mute_left, HDAAudioStream),
|
||||||
VMSTATE_BOOL(mute_right, HDAAudioStream),
|
VMSTATE_BOOL(mute_right, HDAAudioStream),
|
||||||
VMSTATE_UINT32(bpos, HDAAudioStream),
|
VMSTATE_UINT32(compat_bpos, HDAAudioStream),
|
||||||
VMSTATE_BUFFER(buf, HDAAudioStream),
|
VMSTATE_BUFFER(compat_buf, HDAAudioStream),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
|
},
|
||||||
|
.subsections = (const VMStateDescription * []) {
|
||||||
|
&vmstate_hda_audio_stream_buf,
|
||||||
|
NULL
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -615,6 +839,7 @@ static const VMStateDescription vmstate_hda_audio = {
|
||||||
static Property hda_audio_properties[] = {
|
static Property hda_audio_properties[] = {
|
||||||
DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0),
|
DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0),
|
||||||
DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer, true),
|
DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer, true),
|
||||||
|
DEFINE_PROP_BOOL("use-timer", HDAAudioState, use_timer, true),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -407,13 +407,6 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
|
||||||
if (st->bpl == NULL) {
|
if (st->bpl == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (st->ctl & (1 << 26)) {
|
|
||||||
/*
|
|
||||||
* Wait with the next DMA xfer until the guest
|
|
||||||
* has acked the buffer completion interrupt
|
|
||||||
*/
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
left = len;
|
left = len;
|
||||||
s = st->bentries;
|
s = st->bentries;
|
||||||
|
|
|
@ -17,3 +17,9 @@ milkymist_ac97_in_cb(int avail, uint32_t remaining) "avail %d remaining %u"
|
||||||
milkymist_ac97_in_cb_transferred(int transferred) "transferred %d"
|
milkymist_ac97_in_cb_transferred(int transferred) "transferred %d"
|
||||||
milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u"
|
milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u"
|
||||||
milkymist_ac97_out_cb_transferred(int transferred) "transferred %d"
|
milkymist_ac97_out_cb_transferred(int transferred) "transferred %d"
|
||||||
|
|
||||||
|
# hw/audio/hda-codec.c
|
||||||
|
hda_audio_running(const char *stream, int nr, bool running) "st %s, nr %d, run %d"
|
||||||
|
hda_audio_format(const char *stream, int chan, const char *fmt, int freq) "st %s, %d x %s @ %d Hz"
|
||||||
|
hda_audio_adjust(const char *stream, int pos) "st %s, pos %d"
|
||||||
|
hda_audio_overrun(const char *stream) "st %s"
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
.driver = "migration",\
|
.driver = "migration",\
|
||||||
.property = "decompress-error-check",\
|
.property = "decompress-error-check",\
|
||||||
.value = "off",\
|
.value = "off",\
|
||||||
|
},{\
|
||||||
|
.driver = "hda-audio",\
|
||||||
|
.property = "use-timer",\
|
||||||
|
.value = "false",\
|
||||||
},
|
},
|
||||||
|
|
||||||
#define HW_COMPAT_2_11 \
|
#define HW_COMPAT_2_11 \
|
||||||
|
|
|
@ -37,11 +37,10 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import absolute_import
|
|
||||||
import base64
|
import base64
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from . import qmp
|
import qmp
|
||||||
|
|
||||||
|
|
||||||
class QemuGuestAgent(qmp.QEMUMonitorProtocol):
|
class QemuGuestAgent(qmp.QEMUMonitorProtocol):
|
||||||
|
|
|
@ -11,9 +11,8 @@
|
||||||
# See the COPYING file in the top-level directory.
|
# See the COPYING file in the top-level directory.
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import absolute_import
|
|
||||||
import sys, os
|
import sys, os
|
||||||
from .qmp import QEMUMonitorProtocol
|
from qmp import QEMUMonitorProtocol
|
||||||
|
|
||||||
def print_response(rsp, prefix=[]):
|
def print_response(rsp, prefix=[]):
|
||||||
if type(rsp) == list:
|
if type(rsp) == list:
|
||||||
|
|
|
@ -66,8 +66,7 @@
|
||||||
# sent to QEMU, which is useful for debugging and documentation generation.
|
# sent to QEMU, which is useful for debugging and documentation generation.
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import absolute_import
|
import qmp
|
||||||
from . import qmp
|
|
||||||
import json
|
import json
|
||||||
import ast
|
import ast
|
||||||
import readline
|
import readline
|
||||||
|
|
|
@ -11,12 +11,11 @@
|
||||||
# the COPYING file in the top-level directory.
|
# the COPYING file in the top-level directory.
|
||||||
##
|
##
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
import fuse, stat
|
import fuse, stat
|
||||||
from fuse import Fuse
|
from fuse import Fuse
|
||||||
import os, posix
|
import os, posix
|
||||||
from errno import *
|
from errno import *
|
||||||
from .qmp import QEMUMonitorProtocol
|
from qmp import QEMUMonitorProtocol
|
||||||
|
|
||||||
fuse.fuse_python_api = (0, 2)
|
fuse.fuse_python_api = (0, 2)
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,9 @@
|
||||||
##
|
##
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import absolute_import
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from .qmp import QEMUMonitorProtocol
|
from qmp import QEMUMonitorProtocol
|
||||||
|
|
||||||
cmd, args = sys.argv[0], sys.argv[1:]
|
cmd, args = sys.argv[0], sys.argv[1:]
|
||||||
socket_path = None
|
socket_path = None
|
||||||
|
|
|
@ -12,10 +12,9 @@
|
||||||
##
|
##
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import absolute_import
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from .qmp import QEMUMonitorProtocol
|
from qmp import QEMUMonitorProtocol
|
||||||
|
|
||||||
cmd, args = sys.argv[0], sys.argv[1:]
|
cmd, args = sys.argv[0], sys.argv[1:]
|
||||||
socket_path = None
|
socket_path = None
|
||||||
|
|
|
@ -12,10 +12,9 @@
|
||||||
##
|
##
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import absolute_import
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from .qmp import QEMUMonitorProtocol
|
from qmp import QEMUMonitorProtocol
|
||||||
|
|
||||||
cmd, args = sys.argv[0], sys.argv[1:]
|
cmd, args = sys.argv[0], sys.argv[1:]
|
||||||
socket_path = None
|
socket_path = None
|
||||||
|
|
|
@ -14,10 +14,9 @@
|
||||||
##
|
##
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import absolute_import
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from .qmp import QEMUMonitorProtocol
|
from qmp import QEMUMonitorProtocol
|
||||||
|
|
||||||
cmd, args = sys.argv[0], sys.argv[1:]
|
cmd, args = sys.argv[0], sys.argv[1:]
|
||||||
socket_path = None
|
socket_path = None
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue