Audio es1370 fix & cleanups

-----BEGIN PGP SIGNATURE-----
 
 iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmUmQIQcHG1hcmNhbmRy
 ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5UiED/0VjK4J6I+MYljyJePj
 ki62XC/dtojuxkE+nwsTrU54u86776TLmthRYyHOffSs8mDpk0ynY6sWD99T4r1b
 9Szmm9FJM658RSpN9i128JAiHKD9Vth7UUpekrLIBgRsW5lGuQFapHouTB1wa3hm
 8ZszUNAGEpAgGM2My9t+pvGy8lrOZan2ZAlQzKfMc+msYTnivK6huzjVw/xUc0kD
 vzfpVMgKntvl391IBf9hFBBrJCWRtDrydtPl1/PxpVj/96FGIxlx+o30X8z9hSzA
 yg96XfwmS/mgqFsw8QqtFyrkSE3iD2yzcrepjtK+erwcv6M0BVG38wn89F571Lcl
 Ga8PcqBd7pP0nMXrgjbX8qB6t58TPipEbFMeS2iabO4pwz0jy9aCVQJ2GZqHNqaF
 VoMN5hEDBhanxFcNEcjSWZEfJOvK7uVLAZ2Xdqcrsm50ESTu55H/BIQWFipTGlqu
 +BlvfpwVYXGziuDsj8h4cUGvyuMY02XWsBU9qvl5aCiyWoyED0ZlR2UJ0jVjn68K
 RUbTrxSMF9hLgI1j8FYkNgXMBuR4+Sopc7vp//AXpp92/yxTNCbe44Y06C9iaib1
 0zrYhd4rfTn0MX+YM9IUKzvoNSVY6VxHoTucyTM9HcT7XtCnmwnMzjY4yGxQ6k3V
 X0WBPpH4mCyXla7TJ0zwbnvH0A==
 =B/KL
 -----END PGP SIGNATURE-----

Merge tag 'audio-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging

Audio es1370 fix & cleanups

# -----BEGIN PGP SIGNATURE-----
#
# iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmUmQIQcHG1hcmNhbmRy
# ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5UiED/0VjK4J6I+MYljyJePj
# ki62XC/dtojuxkE+nwsTrU54u86776TLmthRYyHOffSs8mDpk0ynY6sWD99T4r1b
# 9Szmm9FJM658RSpN9i128JAiHKD9Vth7UUpekrLIBgRsW5lGuQFapHouTB1wa3hm
# 8ZszUNAGEpAgGM2My9t+pvGy8lrOZan2ZAlQzKfMc+msYTnivK6huzjVw/xUc0kD
# vzfpVMgKntvl391IBf9hFBBrJCWRtDrydtPl1/PxpVj/96FGIxlx+o30X8z9hSzA
# yg96XfwmS/mgqFsw8QqtFyrkSE3iD2yzcrepjtK+erwcv6M0BVG38wn89F571Lcl
# Ga8PcqBd7pP0nMXrgjbX8qB6t58TPipEbFMeS2iabO4pwz0jy9aCVQJ2GZqHNqaF
# VoMN5hEDBhanxFcNEcjSWZEfJOvK7uVLAZ2Xdqcrsm50ESTu55H/BIQWFipTGlqu
# +BlvfpwVYXGziuDsj8h4cUGvyuMY02XWsBU9qvl5aCiyWoyED0ZlR2UJ0jVjn68K
# RUbTrxSMF9hLgI1j8FYkNgXMBuR4+Sopc7vp//AXpp92/yxTNCbe44Y06C9iaib1
# 0zrYhd4rfTn0MX+YM9IUKzvoNSVY6VxHoTucyTM9HcT7XtCnmwnMzjY4yGxQ6k3V
# X0WBPpH4mCyXla7TJ0zwbnvH0A==
# =B/KL
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 11 Oct 2023 02:28:20 EDT
# gpg:                using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5
# gpg:                issuer "marcandre.lureau@redhat.com"
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full]
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full]
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* tag 'audio-pull-request' of https://gitlab.com/marcandre.lureau/qemu:
  hw/audio/es1370: trace lost interrupts
  hw/audio/es1370: change variable type and name
  hw/audio/es1370: block structure coding style fixes
  hw/audio/es1370: remove #ifdef ES1370_VERBOSE to avoid bit rot
  hw/audio/es1370: remove #ifdef ES1370_DEBUG to avoid bit rot
  hw/audio/es1370: remove unused dolog macro
  hw/audio/es1370: replace bit-rotted code with tracepoints
  hw/audio/es1370: reset current sample counter

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2023-10-11 09:42:14 -04:00
commit 67d2486c0e
2 changed files with 140 additions and 154 deletions

View File

@ -22,18 +22,19 @@
* THE SOFTWARE.
*/
/* #define DEBUG_ES1370 */
/* #define VERBOSE_ES1370 */
#define SILENT_ES1370
#define DEBUG_ES1370 0
#define VERBOSE_ES1370 0
#include "qemu/osdep.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/pci/pci_device.h"
#include "migration/vmstate.h"
#include "qemu/cutils.h"
#include "qemu/module.h"
#include "sysemu/dma.h"
#include "qom/object.h"
#include "trace.h"
/* Missing stuff:
SCTRL_P[12](END|ST)INC
@ -164,97 +165,85 @@ static void es1370_dac1_callback (void *opaque, int free);
static void es1370_dac2_callback (void *opaque, int free);
static void es1370_adc_callback (void *opaque, int avail);
#ifdef DEBUG_ES1370
#define ldebug(...) AUD_log ("es1370", __VA_ARGS__)
static void print_ctl (uint32_t val)
static void print_ctl(uint32_t val)
{
if (DEBUG_ES1370) {
char buf[1024];
buf[0] = '\0';
#define a(n) if (val & CTRL_##n) strcat (buf, " "#n)
a (ADC_STOP);
a (XCTL1);
a (OPEN);
a (MSFMTSEL);
a (M_SBB);
a (DAC_SYNC);
a (CCB_INTRM);
a (M_CB);
a (XCTL0);
a (BREQ);
a (DAC1_EN);
a (DAC2_EN);
a (ADC_EN);
a (UART_EN);
a (JYSTK_EN);
a (CDC_EN);
a (SERR_DIS);
#define a(n) if (val & CTRL_##n) pstrcat(buf, sizeof(buf), " "#n)
a(ADC_STOP);
a(XCTL1);
a(OPEN);
a(MSFMTSEL);
a(M_SBB);
a(DAC_SYNC);
a(CCB_INTRM);
a(M_CB);
a(XCTL0);
a(BREQ);
a(DAC1_EN);
a(DAC2_EN);
a(ADC_EN);
a(UART_EN);
a(JYSTK_EN);
a(CDC_EN);
a(SERR_DIS);
#undef a
AUD_log ("es1370", "ctl - PCLKDIV %d(DAC2 freq %d), freq %d,%s\n",
AUD_log("es1370", "ctl - PCLKDIV %d(DAC2 freq %d), freq %d,%s\n",
(val & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV,
DAC2_DIVTOSR ((val & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV),
DAC2_DIVTOSR((val & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV),
dac1_samplerate[(val & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL],
buf);
}
}
static void print_sctl (uint32_t val)
static void print_sctl(uint32_t val)
{
if (DEBUG_ES1370) {
static const char *fmt_names[] = {"8M", "8S", "16M", "16S"};
char buf[1024];
buf[0] = '\0';
#define a(n) if (val & SCTRL_##n) strcat (buf, " "#n)
#define b(n) if (!(val & SCTRL_##n)) strcat (buf, " "#n)
b (R1LOOPSEL);
b (P2LOOPSEL);
b (P1LOOPSEL);
a (P2PAUSE);
a (P1PAUSE);
a (R1INTEN);
a (P2INTEN);
a (P1INTEN);
a (P1SCTRLD);
a (P2DACSEN);
#define a(n) if (val & SCTRL_##n) pstrcat(buf, sizeof(buf), " "#n)
#define b(n) if (!(val & SCTRL_##n)) pstrcat(buf, sizeof(buf), " "#n)
b(R1LOOPSEL);
b(P2LOOPSEL);
b(P1LOOPSEL);
a(P2PAUSE);
a(P1PAUSE);
a(R1INTEN);
a(P2INTEN);
a(P1INTEN);
a(P1SCTRLD);
a(P2DACSEN);
if (buf[0]) {
strcat (buf, "\n ");
}
else {
pstrcat(buf, sizeof(buf), "\n ");
} else {
buf[0] = ' ';
buf[1] = '\0';
}
#undef b
#undef a
AUD_log ("es1370",
"%s"
"p2_end_inc %d, p2_st_inc %d, r1_fmt %s, p2_fmt %s, p1_fmt %s\n",
AUD_log("es1370",
"%s p2_end_inc %d, p2_st_inc %d,"
" r1_fmt %s, p2_fmt %s, p1_fmt %s\n",
buf,
(val & SCTRL_P2ENDINC) >> SCTRL_SH_P2ENDINC,
(val & SCTRL_P2STINC) >> SCTRL_SH_P2STINC,
fmt_names [(val >> SCTRL_SH_R1FMT) & 3],
fmt_names [(val >> SCTRL_SH_P2FMT) & 3],
fmt_names [(val >> SCTRL_SH_P1FMT) & 3]
);
fmt_names[(val >> SCTRL_SH_R1FMT) & 3],
fmt_names[(val >> SCTRL_SH_P2FMT) & 3],
fmt_names[(val >> SCTRL_SH_P1FMT) & 3]);
}
}
#else
#define ldebug(...)
#define print_ctl(...)
#define print_sctl(...)
#endif
#ifdef VERBOSE_ES1370
#define dolog(...) AUD_log ("es1370", __VA_ARGS__)
#else
#define dolog(...)
#endif
#ifndef SILENT_ES1370
#define lwarn(...) AUD_log ("es1370: warning", __VA_ARGS__)
#else
#define lwarn(...)
#endif
#define lwarn(...) \
do { \
if (VERBOSE_ES1370) { \
AUD_log("es1370: warning", __VA_ARGS__); \
} \
} while (0)
#define TYPE_ES1370 "ES1370"
OBJECT_DECLARE_SIMPLE_TYPE(ES1370State, ES1370)
@ -320,8 +309,7 @@ static void es1370_update_status (ES1370State *s, uint32_t new_status)
if (level) {
s->status = new_status | STAT_INTR;
}
else {
} else {
s->status = new_status & ~STAT_INTR;
}
pci_set_irq(&s->dev, !!level);
@ -344,8 +332,7 @@ static void es1370_reset (ES1370State *s)
if (i == ADC_CHANNEL) {
AUD_close_in (&s->card, s->adc_voice);
s->adc_voice = NULL;
}
else {
} else {
AUD_close_out (&s->card, s->dac_voice[i]);
s->dac_voice[i] = NULL;
}
@ -411,11 +398,8 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
if ((old_fmt != new_fmt) || (old_freq != new_freq)) {
d->shift = (new_fmt & 1) + (new_fmt >> 1);
ldebug ("channel %zu, freq = %d, nchannels %d, fmt %d, shift %d\n",
i,
new_freq,
1 << (new_fmt & 1),
(new_fmt & 2) ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_U8,
trace_es1370_stream_format(i, new_freq,
new_fmt & 2 ? "s16" : "u8", new_fmt & 1 ? "stereo" : "mono",
d->shift);
if (new_freq) {
struct audsettings as;
@ -435,8 +419,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
es1370_adc_callback,
&as
);
}
else {
} else {
s->dac_voice[i] =
AUD_open_out (
&s->card,
@ -456,8 +439,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
if (i == ADC_CHANNEL) {
AUD_set_active_in (s->adc_voice, on);
}
else {
} else {
AUD_set_active_out (s->dac_voice[i], on);
}
}
@ -470,8 +452,9 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
static inline uint32_t es1370_fixup (ES1370State *s, uint32_t addr)
{
addr &= 0xff;
if (addr >= 0x30 && addr <= 0x3f)
if (addr >= 0x30 && addr <= 0x3f) {
addr |= s->mempage << 8;
}
return addr;
}
@ -502,9 +485,9 @@ static void es1370_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
case ES1370_REG_DAC2_SCOUNT:
case ES1370_REG_ADC_SCOUNT:
d += (addr - ES1370_REG_DAC1_SCOUNT) >> 2;
d->scount = (val & 0xffff) | (d->scount & ~0xffff);
ldebug ("chan %td CURR_SAMP_CT %d, SAMP_CT %d\n",
d - &s->chan[0], val >> 16, (val & 0xffff));
d->scount = (val & 0xffff) << 16 | (val & 0xffff);
trace_es1370_sample_count_wr(d - &s->chan[0],
d->scount >> 16, d->scount & 0xffff);
break;
case ES1370_REG_ADC_FRAMEADR:
@ -515,14 +498,14 @@ static void es1370_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
d += (addr - ES1370_REG_DAC1_FRAMEADR) >> 3;
frameadr:
d->frame_addr = val;
ldebug ("chan %td frame address %#x\n", d - &s->chan[0], val);
trace_es1370_frame_address_wr(d - &s->chan[0], d->frame_addr);
break;
case ES1370_REG_PHANTOM_FRAMECNT:
lwarn ("writing to phantom frame count %#x\n", val);
lwarn("writing to phantom frame count 0x%" PRIx64 "\n", val);
break;
case ES1370_REG_PHANTOM_FRAMEADR:
lwarn ("writing to phantom frame address %#x\n", val);
lwarn("writing to phantom frame address 0x%" PRIx64 "\n", val);
break;
case ES1370_REG_ADC_FRAMECNT:
@ -534,12 +517,12 @@ static void es1370_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
framecnt:
d->frame_cnt = val;
d->leftover = 0;
ldebug ("chan %td frame count %d, buffer size %d\n",
d - &s->chan[0], val >> 16, val & 0xffff);
trace_es1370_frame_count_wr(d - &s->chan[0],
d->frame_cnt >> 16, d->frame_cnt & 0xffff);
break;
default:
lwarn ("writel %#x <- %#x\n", addr, val);
lwarn("writel 0x%" PRIx64 " <- 0x%" PRIx64 "\n", addr, val);
break;
}
}
@ -573,17 +556,9 @@ static uint64_t es1370_read(void *opaque, hwaddr addr, unsigned size)
case ES1370_REG_DAC2_SCOUNT:
case ES1370_REG_ADC_SCOUNT:
d += (addr - ES1370_REG_DAC1_SCOUNT) >> 2;
trace_es1370_sample_count_rd(d - &s->chan[0],
d->scount >> 16, d->scount & 0xffff);
val = d->scount;
#ifdef DEBUG_ES1370
{
uint32_t curr_count = d->scount >> 16;
uint32_t count = d->scount & 0xffff;
curr_count <<= d->shift;
count <<= d->shift;
dolog ("read scount curr %d, total %d\n", curr_count, count);
}
#endif
break;
case ES1370_REG_ADC_FRAMECNT:
@ -593,17 +568,9 @@ static uint64_t es1370_read(void *opaque, hwaddr addr, unsigned size)
case ES1370_REG_DAC2_FRAMECNT:
d += (addr - ES1370_REG_DAC1_FRAMECNT) >> 3;
framecnt:
trace_es1370_frame_count_rd(d - &s->chan[0],
d->frame_cnt >> 16, d->frame_cnt & 0xffff);
val = d->frame_cnt;
#ifdef DEBUG_ES1370
{
uint32_t size = ((d->frame_cnt & 0xffff) + 1) << 2;
uint32_t curr = ((d->frame_cnt >> 16) + 1) << 2;
if (curr > size) {
dolog ("read framecnt curr %d, size %d %d\n", curr, size,
curr > size);
}
}
#endif
break;
case ES1370_REG_ADC_FRAMEADR:
@ -613,30 +580,32 @@ static uint64_t es1370_read(void *opaque, hwaddr addr, unsigned size)
case ES1370_REG_DAC2_FRAMEADR:
d += (addr - ES1370_REG_DAC1_FRAMEADR) >> 3;
frameadr:
trace_es1370_frame_address_rd(d - &s->chan[0], d->frame_addr);
val = d->frame_addr;
break;
case ES1370_REG_PHANTOM_FRAMECNT:
val = ~0U;
lwarn ("reading from phantom frame count\n");
lwarn("reading from phantom frame count\n");
break;
case ES1370_REG_PHANTOM_FRAMEADR:
val = ~0U;
lwarn ("reading from phantom frame address\n");
lwarn("reading from phantom frame address\n");
break;
default:
val = ~0U;
lwarn ("readl %#x -> %#x\n", addr, val);
lwarn("readl 0x%" PRIx64 " -> 0x%x\n", addr, val);
break;
}
return val;
}
static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
int max, int *irq)
int max, bool *irq)
{
uint8_t tmpbuf[4096];
size_t to_transfer;
uint32_t addr = d->frame_addr;
int sc = d->scount & 0xffff;
int csc = d->scount >> 16;
@ -648,53 +617,53 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
}
int left = ((size - cnt + 1) << 2) + d->leftover;
int transferred = 0;
int temp = MIN (max, MIN (left, csc_bytes));
int index = d - &s->chan[0];
to_transfer = MIN(max, MIN(left, csc_bytes));
addr += (cnt << 2) + d->leftover;
if (index == ADC_CHANNEL) {
while (temp > 0) {
while (to_transfer > 0) {
int acquired, to_copy;
to_copy = MIN ((size_t) temp, sizeof (tmpbuf));
to_copy = MIN(to_transfer, sizeof(tmpbuf));
acquired = AUD_read (s->adc_voice, tmpbuf, to_copy);
if (!acquired)
if (!acquired) {
break;
}
pci_dma_write (&s->dev, addr, tmpbuf, acquired);
temp -= acquired;
to_transfer -= acquired;
addr += acquired;
transferred += acquired;
}
}
else {
} else {
SWVoiceOut *voice = s->dac_voice[index];
while (temp > 0) {
while (to_transfer > 0) {
int copied, to_copy;
to_copy = MIN ((size_t) temp, sizeof (tmpbuf));
to_copy = MIN(to_transfer, sizeof(tmpbuf));
pci_dma_read (&s->dev, addr, tmpbuf, to_copy);
copied = AUD_write (voice, tmpbuf, to_copy);
if (!copied)
if (!copied) {
break;
temp -= copied;
}
to_transfer -= copied;
addr += copied;
transferred += copied;
}
}
if (csc_bytes == transferred) {
*irq = 1;
d->scount = sc | (sc << 16);
ldebug ("sc = %d, rate = %f\n",
(sc + 1) << d->shift,
(sc + 1) / (double) 44100);
if (*irq) {
trace_es1370_lost_interrupt(index);
}
else {
*irq = 0;
*irq = true;
d->scount = sc | (sc << 16);
} else {
*irq = false;
d->scount = sc | (((csc_bytes - transferred - 1) >> d->shift) << 16);
}
@ -704,21 +673,26 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
/* Bah, how stupid is that having a 0 represent true value?
i just spent few hours on this shit */
AUD_log ("es1370: warning", "non looping mode\n");
}
else {
} else {
d->frame_cnt = size;
if ((uint32_t) cnt <= d->frame_cnt)
if ((uint32_t) cnt <= d->frame_cnt) {
d->frame_cnt |= cnt << 16;
}
}
d->leftover = (transferred + d->leftover) & 3;
trace_es1370_transfer_audio(index,
d->frame_cnt >> 16, d->frame_cnt & 0xffff,
d->scount >> 16, d->scount & 0xffff,
d->leftover, *irq);
}
static void es1370_run_channel (ES1370State *s, size_t chan, int free_or_avail)
{
uint32_t new_status = s->status;
int max_bytes, irq;
int max_bytes;
bool irq;
struct chan *d = &s->chan[chan];
const struct chan_bits *b = &es1370_chan_bits[chan];
@ -732,6 +706,8 @@ static void es1370_run_channel (ES1370State *s, size_t chan, int free_or_avail)
return;
}
irq = s->sctl & b->sctl_inten && s->status & b->stat_int;
es1370_transfer_audio (s, d, b->sctl_loopsel, max_bytes, &irq);
if (irq) {
@ -806,8 +782,7 @@ static int es1370_post_load (void *opaque, int version_id)
AUD_close_in (&s->card, s->adc_voice);
s->adc_voice = NULL;
}
}
else {
} else {
if (s->dac_voice[i]) {
AUD_close_out (&s->card, s->dac_voice[i]);
s->dac_voice[i] = NULL;

View File

@ -6,6 +6,17 @@ cs4231_mem_readl_reg(uint32_t reg, uint32_t ret) "read reg %d: 0x%08x"
cs4231_mem_writel_reg(uint32_t reg, uint32_t old, uint32_t val) "write reg %d: 0x%08x -> 0x%08x"
cs4231_mem_writel_dreg(uint32_t reg, uint32_t old, uint32_t val) "write dreg %d: 0x%02x -> 0x%02x"
# es1370.c
es1370_frame_address_rd(int ch, uint32_t addr) "ch=%d addr=0x%08x"
es1370_frame_address_wr(int ch, uint32_t addr) "ch=%d addr=0x%08x"
es1370_frame_count_rd(int ch, uint32_t curr, uint32_t size) "ch=%d CURR_CT=%u BUF_SIZE=%u"
es1370_frame_count_wr(int ch, uint32_t curr, uint32_t size) "ch=%d CURR_CT=%u BUF_SIZE=%u"
es1370_lost_interrupt(int ch) "ch=%d lost interrupt"
es1370_sample_count_rd(int ch, uint32_t curr, uint32_t num) "ch=%d CURR_SAMP_CT=%u SAMP_CT=%u"
es1370_sample_count_wr(int ch, uint32_t curr, uint32_t num) "ch=%d CURR_SAMP_CT=%u SAMP_CT=%u"
es1370_stream_format(int ch, uint32_t freq, const char *fmt, const char *mode, uint32_t shift) "ch=%d fmt=%u:%s:%s shift=%u"
es1370_transfer_audio(int ch, uint32_t f_curr, uint32_t f_size, uint32_t s_curr, uint32_t s_num, uint32_t leftover, bool irq) "ch=%d CURR_CT=%u BUF_SIZE=%u CURR_SAMP_CT=%u SAMP_CT=%u leftover=%u irq=%d"
# 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"