qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH v2] Implement the Screamer sound chip for the mac99 machine type
@ 2020-01-05  1:58 Programmingkid
  2020-01-05 14:39 ` Programmingkid
  2020-01-11  0:32 ` Zoltán Kővágó
  0 siblings, 2 replies; 16+ messages in thread
From: Programmingkid @ 2020-01-05  1:58 UTC (permalink / raw)
  To: qemu Developers, Howard Spoelstra, Zoltán, mark Cave-Ayland
  Cc: Gerd Hoffmann

I found the patch that breaks Screamer sound support for qemu-system-ppc. It is this:

commit 2ceb8240fa4e4e30fb853565eb2bed3032d74f62
Author: Kővágó, Zoltán <dirty.ice.hu@gmail.com>
Date:   Thu Sep 19 23:24:11 2019 +0200

    coreaudio: port to the new audio backend api
    
    Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com>
    Message-id: 586a1e66de5cbc6c5234f9ae556d24befb6afada.1568927990.git.DirtY.iCE.hu@gmail.com
    Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>


Reversing this patch should make the Screamer patch work with the current git version of QEMU.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] Implement the Screamer sound chip for the mac99 machine type
  2020-01-05  1:58 [PATCH v2] Implement the Screamer sound chip for the mac99 machine type Programmingkid
@ 2020-01-05 14:39 ` Programmingkid
  2020-01-11  0:32 ` Zoltán Kővágó
  1 sibling, 0 replies; 16+ messages in thread
From: Programmingkid @ 2020-01-05 14:39 UTC (permalink / raw)
  To: qemu Developers, Howard Spoelstra, Zoltán, Mark Cave-Ayland,
	Peter Maydell, Gerd Hoffmann


> On Jan 4, 2020, at 8:58 PM, Programmingkid <programmingkidx@gmail.com> wrote:
> 
> I found the patch that breaks Screamer sound support for qemu-system-ppc. It is this:
> 
> commit 2ceb8240fa4e4e30fb853565eb2bed3032d74f62
> Author: Kővágó, Zoltán <dirty.ice.hu@gmail.com>
> Date:   Thu Sep 19 23:24:11 2019 +0200
> 
>    coreaudio: port to the new audio backend api
> 
>    Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com>
>    Message-id: 586a1e66de5cbc6c5234f9ae556d24befb6afada.1568927990.git.DirtY.iCE.hu@gmail.com
>    Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> 
> 
> Reversing this patch should make the Screamer patch work with the current git version of QEMU.

@Peter Maydell

Does QEMU play audio correctly on your version of Mac OS X? I am using Mac OS 10.12 and the audio sound demonically loud and scary. I am currently at this git revision:

f0dcfddecee8b860e015bb07d67cfcbdfbfd51d

Merge: 40f09ee833 725fe5d10d
Author: Peter Maydell <peter.maydell@linaro.org>
Date:   Fri Jan 3 17:18:08 2020 +0000

    Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging

I have ran several tests with qemu-system-i386 using Windows guest with the ac97 and sb16 sound cards. It sounds just as bad for me on qemu-system-ppc. 

Thank you.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] Implement the Screamer sound chip for the mac99 machine type
  2020-01-05  1:58 [PATCH v2] Implement the Screamer sound chip for the mac99 machine type Programmingkid
  2020-01-05 14:39 ` Programmingkid
@ 2020-01-11  0:32 ` Zoltán Kővágó
  2020-01-11  0:59   ` Programmingkid
  2020-01-28  8:30   ` Volker Rümelin
  1 sibling, 2 replies; 16+ messages in thread
From: Zoltán Kővágó @ 2020-01-11  0:32 UTC (permalink / raw)
  To: Programmingkid, qemu Developers, Howard Spoelstra, mark Cave-Ayland
  Cc: Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 1098 bytes --]

On 2020-01-05 02:58, Programmingkid wrote:
> I found the patch that breaks Screamer sound support for qemu-system-ppc. It is this:
> 
> commit 2ceb8240fa4e4e30fb853565eb2bed3032d74f62
> Author: Kővágó, Zoltán <dirty.ice.hu@gmail.com>
> Date:   Thu Sep 19 23:24:11 2019 +0200
> 
>      coreaudio: port to the new audio backend api
>      
>      Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com>
>      Message-id: 586a1e66de5cbc6c5234f9ae556d24befb6afada.1568927990.git.DirtY.iCE.hu@gmail.com
>      Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> 
> 
> Reversing this patch should make the Screamer patch work with the current git version of QEMU.
> 

Hi,

Unfortunately it's not that simple to simply revert the patch since the 
old backend api no longer exists.  Also I don't have a Mac so it's 
almost impossible for me to test the results.  I looked at the specified 
commit and I think I found a problem, could you please apply the 
attached patch on the current git master and check whether it solves the 
problem?  If yes I'll turn it into a proper patch.

Regards,
Zoltan


[-- Attachment #2: coreaudio_test.diff --]
[-- Type: text/x-patch, Size: 3838 bytes --]

diff --git a/audio/audio_template.h b/audio/audio_template.h
index 3287d7075e..a7b46b8363 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -153,6 +153,13 @@ static int glue (audio_pcm_sw_init_, TYPE) (
     sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
 #endif
 
+#ifdef FLOAT_MIXENG
+#ifdef DAC
+    sw->conv = mixeng_conv_float;
+#else
+    sw->clip = mixeng_clip_float;
+#endif
+#else
 #ifdef DAC
     sw->conv = mixeng_conv
 #else
@@ -162,6 +169,7 @@ static int glue (audio_pcm_sw_init_, TYPE) (
         [sw->info.sign]
         [sw->info.swap_endianness]
         [audio_bits_to_index (sw->info.bits)];
+#endif
 
     sw->name = g_strdup (name);
     err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
diff --git a/audio/mixeng.h b/audio/mixeng.h
index 18e62c7c49..343f5fb810 100644
--- a/audio/mixeng.h
+++ b/audio/mixeng.h
@@ -41,6 +41,11 @@ typedef void (f_sample) (void *dst, const struct st_sample *src, int samples);
 extern t_sample *mixeng_conv[2][2][2][3];
 extern f_sample *mixeng_clip[2][2][2][3];
 
+#ifdef FLOAT_MIXENG
+void mixeng_conv_float(struct st_sample *dst, const void *src, int samples);
+void mixeng_clip_float(void *dst, const struct st_sample *src, int samples);
+#endif
+
 void *st_rate_start (int inrate, int outrate);
 void st_rate_flow(void *opaque, st_sample *ibuf, st_sample *obuf,
                   size_t *isamp, size_t *osamp);
diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index 66f0f459cf..4e7e509ad0 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -471,20 +471,6 @@ static OSStatus audioDeviceIOProc(
     return 0;
 }
 
-static UInt32 coreaudio_get_flags(struct audio_pcm_info *info,
-                                  struct audsettings *as)
-{
-    UInt32 flags = info->sign ? kAudioFormatFlagIsSignedInteger : 0;
-    if (as->endianness) { /* 0 = little, 1 = big */
-        flags |= kAudioFormatFlagIsBigEndian;
-    }
-
-    if (flags == 0) { /* must not be 0 */
-        flags = kAudioFormatFlagsAreAllClear;
-    }
-    return flags;
-}
-
 static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
                               void *drv_opaque)
 {
@@ -572,15 +558,6 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
 
     /* set Samplerate */
     core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
-    core->outputStreamBasicDescription.mFormatID = kAudioFormatLinearPCM;
-    core->outputStreamBasicDescription.mFormatFlags =
-        coreaudio_get_flags(&hw->info, as);
-    core->outputStreamBasicDescription.mBytesPerPacket =
-        core->outputStreamBasicDescription.mBytesPerFrame =
-        hw->info.nchannels * hw->info.bits / 8;
-    core->outputStreamBasicDescription.mFramesPerPacket = 1;
-    core->outputStreamBasicDescription.mChannelsPerFrame = hw->info.nchannels;
-    core->outputStreamBasicDescription.mBitsPerChannel = hw->info.bits;
 
     status = coreaudio_set_streamformat(core->outputDeviceID,
                                         &core->outputStreamBasicDescription);
diff --git a/audio/mixeng.c b/audio/mixeng.c
index 2f5ba71381..424ffe30d7 100644
--- a/audio/mixeng.c
+++ b/audio/mixeng.c
@@ -267,6 +267,27 @@ f_sample *mixeng_clip[2][2][2][3] = {
     }
 };
 
+#ifdef FLOAT_MIXENG
+void mixeng_conv_float(struct st_sample *dst, const void *src, int samples)
+{
+    float *in = (float *) src;
+    while (samples--) {
+        dst->l = *in++;
+        dst->r = *in++;
+        dst++;
+    }
+}
+
+void mixeng_clip_float(void *dst, const struct st_sample *src, int samples)
+{
+    float *out = (float *) dst;
+    while (samples--) {
+        *out++ = src->l;
+        *out++ = src->r;
+        src++;
+    }
+}
+#endif
 
 void audio_sample_to_uint64(void *samples, int pos,
                             uint64_t *left, uint64_t *right)

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] Implement the Screamer sound chip for the mac99 machine type
  2020-01-11  0:32 ` Zoltán Kővágó
@ 2020-01-11  0:59   ` Programmingkid
  2020-01-28  8:30   ` Volker Rümelin
  1 sibling, 0 replies; 16+ messages in thread
From: Programmingkid @ 2020-01-11  0:59 UTC (permalink / raw)
  To: Zoltán Kővágó
  Cc: Gerd Hoffmann, Mark Cave-Ayland, qemu Developers, Howard Spoelstra


> On Jan 10, 2020, at 7:32 PM, Zoltán Kővágó <dirty.ice.hu@gmail.com> wrote:
> 
> On 2020-01-05 02:58, Programmingkid wrote:
>> I found the patch that breaks Screamer sound support for qemu-system-ppc. It is this:
>> commit 2ceb8240fa4e4e30fb853565eb2bed3032d74f62
>> Author: Kővágó, Zoltán <dirty.ice.hu@gmail.com>
>> Date:   Thu Sep 19 23:24:11 2019 +0200
>>     coreaudio: port to the new audio backend api
>>          Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com>
>>     Message-id: 586a1e66de5cbc6c5234f9ae556d24befb6afada.1568927990.git.DirtY.iCE.hu@gmail.com
>>     Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
>> Reversing this patch should make the Screamer patch work with the current git version of QEMU.
> 
> Hi,
> 
> Unfortunately it's not that simple to simply revert the patch since the old backend api no longer exists.  Also I don't have a Mac so it's almost impossible for me to test the results.  I looked at the specified commit and I think I found a problem, could you please apply the attached patch on the current git master and check whether it solves the problem?  If yes I'll turn it into a proper patch.
> 
> Regards,
> Zoltan
> 
> <coreaudio_test.diff>

Sorry it did not fix the problem. I only hear pops occasionally. Most of the time only silence can be heard.

Thank you for the patch. 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] Implement the Screamer sound chip for the mac99 machine type
  2020-01-11  0:32 ` Zoltán Kővágó
  2020-01-11  0:59   ` Programmingkid
@ 2020-01-28  8:30   ` Volker Rümelin
  2020-01-28  9:38     ` Howard Spoelstra
  2020-02-02 19:47     ` [PATCH v2] Implement the Screamer sound chip for the mac99 machine type Zoltán Kővágó
  1 sibling, 2 replies; 16+ messages in thread
From: Volker Rümelin @ 2020-01-28  8:30 UTC (permalink / raw)
  To: Zoltán Kővágó,
	Programmingkid, qemu Developers, Howard Spoelstra,
	Mark Cave-Ayland
  Cc: Gerd Hoffmann

> Hi,
>
> Unfortunately it's not that simple to simply revert the patch since the old backend api no longer exists.  Also I don't have a Mac so it's almost impossible for me to test the results.  I looked at the specified commit and I think I found a problem, could you please apply the attached patch on the current git master and check whether it solves the problem?  If yes I'll turn it into a proper patch.
>
> Regards,
> Zoltan
>

Hi Zoltán,

I also don't have a Mac so I tested your patch with a slightly modified sdlaudio version. I found two bugs in your patch. With the bugs fixed I have working SDL2 audio playback with float type samples. Now I wonder if the fixed patch also fixes coreaudio playback. Depending on how busy you are I can just write a review for your patch and let you handle the rest, or may I send a modified version of your patch to the mailing list for testing?

With best regards
Volker


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] Implement the Screamer sound chip for the mac99 machine type
  2020-01-28  8:30   ` Volker Rümelin
@ 2020-01-28  9:38     ` Howard Spoelstra
  2020-01-29  7:09       ` Volker Rümelin
  2020-02-02 19:47     ` [PATCH v2] Implement the Screamer sound chip for the mac99 machine type Zoltán Kővágó
  1 sibling, 1 reply; 16+ messages in thread
From: Howard Spoelstra @ 2020-01-28  9:38 UTC (permalink / raw)
  To: Volker Rümelin
  Cc: Programmingkid, Gerd Hoffmann, Mark Cave-Ayland, qemu Developers,
	Zoltán Kővágó

[-- Attachment #1: Type: text/plain, Size: 3201 bytes --]

On Tue, Jan 28, 2020 at 9:30 AM Volker Rümelin <vr_qemu@t-online.de> wrote:

> > Hi,
> >
> > Unfortunately it's not that simple to simply revert the patch since the
> old backend api no longer exists.  Also I don't have a Mac so it's almost
> impossible for me to test the results.  I looked at the specified commit
> and I think I found a problem, could you please apply the attached patch on
> the current git master and check whether it solves the problem?  If yes
> I'll turn it into a proper patch.
> >
> > Regards,
> > Zoltan
> >
>
> Hi Zoltán,
>
> I also don't have a Mac so I tested your patch with a slightly modified
> sdlaudio version. I found two bugs in your patch. With the bugs fixed I
> have working SDL2 audio playback with float type samples. Now I wonder if
> the fixed patch also fixes coreaudio playback. Depending on how busy you
> are I can just write a review for your patch and let you handle the rest,
> or may I send a modified version of your patch to the mailing list for
> testing?
>
> With best regards
> Volker
>

Hi Volker,

I can test for coreaudio. Can you let us know exactly what you fixed in the
patch?
While cross compiling for windows, I saw these errors (besides some casting
issues):
line 56: buffer2  (should be *buffer2?)
line 455: ret  (should be ret2?)

audio/dsoundaudio.c:56:20: error: variable or field 'buffer2' declared void
   56 |     void *buffer1, buffer2;
      |                    ^~~~~~~
audio/dsoundaudio.c: In function 'dsound_get_buffer_out':
audio/dsoundaudio.c:428:18: error: returning 'int' from a function with
return type 'void *' makes pointer from integer without a cast
[-Werror=int-conversion]
  428 |         return ds->buffer2;
      |                ~~^~~~~~~~~
audio/dsoundaudio.c:451:17: error: assignment to 'int' from 'void *' makes
integer from pointer without a cast [-Werror=int-conversion]
  451 |     ds->buffer2 = ret2;
      |                 ^
audio/dsoundaudio.c:455:12: error: 'ret' undeclared (first use in this
function); did you mean 'ret2'?
  455 |     return ret;
      |            ^~~
      |            ret2
audio/dsoundaudio.c:455:12: note: each undeclared identifier is reported
only once for each function it appears in
audio/dsoundaudio.c: In function 'dsound_put_buffer_out':
audio/dsoundaudio.c:471:49: error: passing argument 3 of
'dsound_unlock_out' makes pointer from integer without a cast
[-Werror=int-conversion]
  471 |     err = dsound_unlock_out(dsb, ds->buffer1, ds->buffer2,
ds->size1, ds->size2);
      |                                               ~~^~~~~~~~~
      |                                                 |
      |                                                 int
In file included from audio/dsoundaudio.c:267:
audio/dsound_template.h:49:12: note: expected 'LPVOID' {aka 'void *'} but
argument is of type 'int'
   49 |     LPVOID p2,
      |     ~~~~~~~^~
audio/dsoundaudio.c: In function 'dsound_get_buffer_out':
audio/dsoundaudio.c:456:1: error: control reaches end of non-void function
[-Werror=return-type]
  456 | }
      | ^
cc1: all warnings being treated as errors

Best,
Howard

[-- Attachment #2: Type: text/html, Size: 4060 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] Implement the Screamer sound chip for the mac99 machine type
  2020-01-28  9:38     ` Howard Spoelstra
@ 2020-01-29  7:09       ` Volker Rümelin
  2020-01-29  7:13         ` [RFC] coreaudio: fix coreaudio_test.diff Volker Rümelin
  0 siblings, 1 reply; 16+ messages in thread
From: Volker Rümelin @ 2020-01-29  7:09 UTC (permalink / raw)
  To: Howard Spoelstra
  Cc: Programmingkid, Gerd Hoffmann, Mark Cave-Ayland, qemu Developers,
	Zoltán Kővágó


>
> Hi Volker,
>
> I can test for coreaudio. Can you let us know exactly what you fixed in the patch?

Hi Howard,

I wrote a patch that tries to fix the problems in Zoltán's patch. The changes in coreaudio.c are untested. I'll send it as a reply to this mail. Please apply Zoltan's patch and then my patch to qemu master.

> While cross compiling for windows, I saw these errors (besides some casting issues):
> line 56: buffer2  (should be *buffer2?)
> line 455: ret  (should be ret2?)
>
> audio/dsoundaudio.c:56:20: error: variable or field 'buffer2' declared void
>    56 |     void *buffer1, buffer2;
>       |                    ^~~~~~~
> audio/dsoundaudio.c: In function 'dsound_get_buffer_out':

I'm sorry, but I can't build and test on Windows.

With best regards,
Volker


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [RFC] coreaudio: fix coreaudio_test.diff
  2020-01-29  7:09       ` Volker Rümelin
@ 2020-01-29  7:13         ` Volker Rümelin
  2020-01-30 15:03           ` Howard Spoelstra
  2020-01-31 15:55           ` Programmingkid
  0 siblings, 2 replies; 16+ messages in thread
From: Volker Rümelin @ 2020-01-29  7:13 UTC (permalink / raw)
  To: Howard Spoelstra
  Cc: Programmingkid, Gerd Hoffmann, Mark Cave-Ayland, qemu Developers,
	Zoltán Kővágó

This is an untested patch that tries to fix the problems in the
patch found at
https://lists.nongnu.org/archive/html/qemu-devel/2020-01/msg02142.html. 

Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
---
 audio/audio_template.h | 16 ++++++++--------
 audio/coreaudio.c      |  5 +++++
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/audio/audio_template.h b/audio/audio_template.h
index a7b46b8363..e6724c5d68 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -153,13 +153,6 @@ static int glue (audio_pcm_sw_init_, TYPE) (
     sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
 #endif
 
-#ifdef FLOAT_MIXENG
-#ifdef DAC
-    sw->conv = mixeng_conv_float;
-#else
-    sw->clip = mixeng_clip_float;
-#endif
-#else
 #ifdef DAC
     sw->conv = mixeng_conv
 #else
@@ -169,7 +162,6 @@ static int glue (audio_pcm_sw_init_, TYPE) (
         [sw->info.sign]
         [sw->info.swap_endianness]
         [audio_bits_to_index (sw->info.bits)];
-#endif
 
     sw->name = g_strdup (name);
     err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
@@ -284,6 +276,13 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
         goto err1;
     }
 
+#ifdef FLOAT_MIXENG
+#ifdef DAC
+    hw->clip = mixeng_clip_float;
+#else
+    hw->conv = mixeng_conv_float;
+#endif
+#else
 #ifdef DAC
     hw->clip = mixeng_clip
 #else
@@ -293,6 +292,7 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
         [hw->info.sign]
         [hw->info.swap_endianness]
         [audio_bits_to_index (hw->info.bits)];
+#endif
 
     glue(audio_pcm_hw_alloc_resources_, TYPE)(hw);
 
diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index 4e7e509ad0..ff0d23fd7d 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -482,6 +482,7 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
     Audiodev *dev = drv_opaque;
     AudiodevCoreaudioPerDirectionOptions *cpdo = dev->u.coreaudio.out;
     int frames;
+    struct audsettings fake_as;
 
     /* create mutex */
     err = pthread_mutex_init(&core->mutex, NULL);
@@ -490,6 +491,10 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
         return -1;
     }
 
+    memcpy(&fake_as, as, sizeof(struct audsettings));
+    as = &fake_as;
+    /* size of float is 32bits */
+    as->fmt = AUDIO_FORMAT_S32;
     audio_pcm_init_info (&hw->info, as);
 
     status = coreaudio_get_voice(&core->outputDeviceID);
-- 
2.16.4



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [RFC] coreaudio: fix coreaudio_test.diff
  2020-01-29  7:13         ` [RFC] coreaudio: fix coreaudio_test.diff Volker Rümelin
@ 2020-01-30 15:03           ` Howard Spoelstra
  2020-01-31  7:37             ` Volker Rümelin
  2020-01-31 15:55           ` Programmingkid
  1 sibling, 1 reply; 16+ messages in thread
From: Howard Spoelstra @ 2020-01-30 15:03 UTC (permalink / raw)
  To: Volker Rümelin
  Cc: Programmingkid, Gerd Hoffmann, Mark Cave-Ayland, qemu Developers,
	Zoltán Kővágó

[-- Attachment #1: Type: text/plain, Size: 3012 bytes --]

On Wed, Jan 29, 2020 at 8:13 AM Volker Rümelin <vr_qemu@t-online.de> wrote:

> This is an untested patch that tries to fix the problems in the
> patch found at
> https://lists.nongnu.org/archive/html/qemu-devel/2020-01/msg02142.html.
>
> Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
> ---
>  audio/audio_template.h | 16 ++++++++--------
>  audio/coreaudio.c      |  5 +++++
>  2 files changed, 13 insertions(+), 8 deletions(-)
>
> diff --git a/audio/audio_template.h b/audio/audio_template.h
> index a7b46b8363..e6724c5d68 100644
> --- a/audio/audio_template.h
> +++ b/audio/audio_template.h
> @@ -153,13 +153,6 @@ static int glue (audio_pcm_sw_init_, TYPE) (
>      sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
>  #endif
>
> -#ifdef FLOAT_MIXENG
> -#ifdef DAC
> -    sw->conv = mixeng_conv_float;
> -#else
> -    sw->clip = mixeng_clip_float;
> -#endif
> -#else
>  #ifdef DAC
>      sw->conv = mixeng_conv
>  #else
> @@ -169,7 +162,6 @@ static int glue (audio_pcm_sw_init_, TYPE) (
>          [sw->info.sign]
>          [sw->info.swap_endianness]
>          [audio_bits_to_index (sw->info.bits)];
> -#endif
>
>      sw->name = g_strdup (name);
>      err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
> @@ -284,6 +276,13 @@ static HW *glue(audio_pcm_hw_add_new_,
> TYPE)(AudioState *s,
>          goto err1;
>      }
>
> +#ifdef FLOAT_MIXENG
> +#ifdef DAC
> +    hw->clip = mixeng_clip_float;
> +#else
> +    hw->conv = mixeng_conv_float;
> +#endif
> +#else
>  #ifdef DAC
>      hw->clip = mixeng_clip
>  #else
> @@ -293,6 +292,7 @@ static HW *glue(audio_pcm_hw_add_new_,
> TYPE)(AudioState *s,
>          [hw->info.sign]
>          [hw->info.swap_endianness]
>          [audio_bits_to_index (hw->info.bits)];
> +#endif
>
>      glue(audio_pcm_hw_alloc_resources_, TYPE)(hw);
>
> diff --git a/audio/coreaudio.c b/audio/coreaudio.c
> index 4e7e509ad0..ff0d23fd7d 100644
> --- a/audio/coreaudio.c
> +++ b/audio/coreaudio.c
> @@ -482,6 +482,7 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct
> audsettings *as,
>      Audiodev *dev = drv_opaque;
>      AudiodevCoreaudioPerDirectionOptions *cpdo = dev->u.coreaudio.out;
>      int frames;
> +    struct audsettings fake_as;
>
>      /* create mutex */
>      err = pthread_mutex_init(&core->mutex, NULL);
> @@ -490,6 +491,10 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct
> audsettings *as,
>          return -1;
>      }
>
> +    memcpy(&fake_as, as, sizeof(struct audsettings));
> +    as = &fake_as;
> +    /* size of float is 32bits */
> +    as->fmt = AUDIO_FORMAT_S32;
>      audio_pcm_init_info (&hw->info, as);
>
>      status = coreaudio_get_voice(&core->outputDeviceID);
> --
> 2.16.4
>
> Hi all,

Thanks to the generous help from Mark, I can now report that it is good to
hear coreaudio has been restored into a working state with this patch! I
tested qemu-system-ppc running MacOS and OSX.

Best,
Howard

[-- Attachment #2: Type: text/html, Size: 3937 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] coreaudio: fix coreaudio_test.diff
  2020-01-30 15:03           ` Howard Spoelstra
@ 2020-01-31  7:37             ` Volker Rümelin
  2020-01-31  8:03               ` Gerd Hoffmann
  0 siblings, 1 reply; 16+ messages in thread
From: Volker Rümelin @ 2020-01-31  7:37 UTC (permalink / raw)
  To: Howard Spoelstra
  Cc: Programmingkid, Gerd Hoffmann, Mark Cave-Ayland, qemu Developers,
	Zoltán Kővágó

>
> Hi all,
>
> Thanks to the generous help from Mark, I can now report that it is good to hear coreaudio has been restored into a working state with this patch! I tested qemu-system-ppc running MacOS and OSX.
>
> Best,
> Howard

Thank you for testing the two patches. I will wait a few days to see if Zoltán wants to write a cleaned up patch. Otherwise I'll try to write a patch that's acceptable for submission.

With best regards
Volker


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] coreaudio: fix coreaudio_test.diff
  2020-01-31  7:37             ` Volker Rümelin
@ 2020-01-31  8:03               ` Gerd Hoffmann
  2020-01-31  8:35                 ` Mark Cave-Ayland
  0 siblings, 1 reply; 16+ messages in thread
From: Gerd Hoffmann @ 2020-01-31  8:03 UTC (permalink / raw)
  To: Volker Rümelin
  Cc: Programmingkid, Zoltán Kővágó,
	Mark Cave-Ayland, qemu Developers, Howard Spoelstra

On Fri, Jan 31, 2020 at 08:37:50AM +0100, Volker Rümelin wrote:
> >
> > Hi all,
> >
> > Thanks to the generous help from Mark, I can now report that it is good to hear coreaudio has been restored into a working state with this patch! I tested qemu-system-ppc running MacOS and OSX.
> >
> > Best,
> > Howard
> 
> Thank you for testing the two patches. I will wait a few days to see if Zoltán wants to write a cleaned up patch. Otherwise I'll try to write a patch that's acceptable for submission.

I'm busy collecting pending audio fixes for the next pull req,
planned to send out early next week.  Would be cool if I can
include a coreaudio fix ;)

The RFC patch looks sane to me but it clearly needs a better
commit message.

Current patch queue state:
  https://git.kraxel.org/cgit/qemu/log/?h=queue/audio

If I missed something please resend.

cheers,
  Gerd



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] coreaudio: fix coreaudio_test.diff
  2020-01-31  8:03               ` Gerd Hoffmann
@ 2020-01-31  8:35                 ` Mark Cave-Ayland
  2020-01-31  9:12                   ` Howard Spoelstra
  0 siblings, 1 reply; 16+ messages in thread
From: Mark Cave-Ayland @ 2020-01-31  8:35 UTC (permalink / raw)
  To: Gerd Hoffmann, Volker Rümelin
  Cc: Programmingkid, Howard Spoelstra, qemu Developers,
	Zoltán Kővágó

On 31/01/2020 08:03, Gerd Hoffmann wrote:

>> Thank you for testing the two patches. I will wait a few days to see if Zoltán wants to write a cleaned up patch. Otherwise I'll try to write a patch that's acceptable for submission.
> 
> I'm busy collecting pending audio fixes for the next pull req,
> planned to send out early next week.  Would be cool if I can
> include a coreaudio fix ;)
> 
> The RFC patch looks sane to me but it clearly needs a better
> commit message.
> 
> Current patch queue state:
>   https://git.kraxel.org/cgit/qemu/log/?h=queue/audio
> 
> If I missed something please resend.

That would be great! One thing to note is that Volker's RFC patch applies on top of
Zoltan's original diff from
https://lists.nongnu.org/archive/html/qemu-devel/2020-01/msg02142.html rather than
being standalone.

If you take a look at my branch at https://github.com/mcayland/qemu/commits/for-cat7
then it's just a case of squashing the top 2 commits and coming up with a suitable
commit message.


ATB,

Mark.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] coreaudio: fix coreaudio_test.diff
  2020-01-31  8:35                 ` Mark Cave-Ayland
@ 2020-01-31  9:12                   ` Howard Spoelstra
  0 siblings, 0 replies; 16+ messages in thread
From: Howard Spoelstra @ 2020-01-31  9:12 UTC (permalink / raw)
  To: Mark Cave-Ayland
  Cc: qemu Developers, Programmingkid, Volker Rümelin,
	Gerd Hoffmann, Zoltán Kővágó

[-- Attachment #1: Type: text/plain, Size: 1535 bytes --]

On Fri, Jan 31, 2020 at 9:35 AM Mark Cave-Ayland <
mark.cave-ayland@ilande.co.uk> wrote:

> On 31/01/2020 08:03, Gerd Hoffmann wrote:
>
> >> Thank you for testing the two patches. I will wait a few days to see if
> Zoltán wants to write a cleaned up patch. Otherwise I'll try to write a
> patch that's acceptable for submission.
> >
> > I'm busy collecting pending audio fixes for the next pull req,
> > planned to send out early next week.  Would be cool if I can
> > include a coreaudio fix ;)
> >
> > The RFC patch looks sane to me but it clearly needs a better
> > commit message.
> >
> > Current patch queue state:
> >   https://git.kraxel.org/cgit/qemu/log/?h=queue/audio
> >
> > If I missed something please resend.
>
> That would be great! One thing to note is that Volker's RFC patch applies
> on top of
> Zoltan's original diff from
> https://lists.nongnu.org/archive/html/qemu-devel/2020-01/msg02142.html
> rather than
> being standalone.
>
> If you take a look at my branch at
> https://github.com/mcayland/qemu/commits/for-cat7
> then it's just a case of squashing the top 2 commits and coming up with a
> suitable
> commit message.
>
>
> ATB,
>
> Mark.
>

Yes, lovely!

I just applied the dsound patch from KJ Liew on top of the for-cat7 branch.

https://lists.nongnu.org/archive/html/qemu-devel/2020-01/msg03805.html

While it will not apply directly (not finding the file to patch in the
source tree), it nevertheless gets rid of the dsound errors too.

Best,
Howard

[-- Attachment #2: Type: text/html, Size: 2560 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] coreaudio: fix coreaudio_test.diff
  2020-01-29  7:13         ` [RFC] coreaudio: fix coreaudio_test.diff Volker Rümelin
  2020-01-30 15:03           ` Howard Spoelstra
@ 2020-01-31 15:55           ` Programmingkid
  1 sibling, 0 replies; 16+ messages in thread
From: Programmingkid @ 2020-01-31 15:55 UTC (permalink / raw)
  To: Volker Rümelin
  Cc: Gerd Hoffmann, Zoltán Kővágó,
	Mark Cave-Ayland, qemu Developers, Howard Spoelstra


> On Jan 29, 2020, at 2:13 AM, Volker Rümelin <vr_qemu@t-online.de> wrote:
> 
> This is an untested patch that tries to fix the problems in the
> patch found at
> https://lists.nongnu.org/archive/html/qemu-devel/2020-01/msg02142.html. 
> 
> Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
> ---
> audio/audio_template.h | 16 ++++++++--------
> audio/coreaudio.c      |  5 +++++
> 2 files changed, 13 insertions(+), 8 deletions(-)
> 
> diff --git a/audio/audio_template.h b/audio/audio_template.h
> index a7b46b8363..e6724c5d68 100644
> --- a/audio/audio_template.h
> +++ b/audio/audio_template.h
> @@ -153,13 +153,6 @@ static int glue (audio_pcm_sw_init_, TYPE) (
>     sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
> #endif
> 
> -#ifdef FLOAT_MIXENG
> -#ifdef DAC
> -    sw->conv = mixeng_conv_float;
> -#else
> -    sw->clip = mixeng_clip_float;
> -#endif
> -#else
> #ifdef DAC
>     sw->conv = mixeng_conv
> #else
> @@ -169,7 +162,6 @@ static int glue (audio_pcm_sw_init_, TYPE) (
>         [sw->info.sign]
>         [sw->info.swap_endianness]
>         [audio_bits_to_index (sw->info.bits)];
> -#endif
> 
>     sw->name = g_strdup (name);
>     err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
> @@ -284,6 +276,13 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
>         goto err1;
>     }
> 
> +#ifdef FLOAT_MIXENG
> +#ifdef DAC
> +    hw->clip = mixeng_clip_float;
> +#else
> +    hw->conv = mixeng_conv_float;
> +#endif
> +#else
> #ifdef DAC
>     hw->clip = mixeng_clip
> #else
> @@ -293,6 +292,7 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
>         [hw->info.sign]
>         [hw->info.swap_endianness]
>         [audio_bits_to_index (hw->info.bits)];
> +#endif
> 
>     glue(audio_pcm_hw_alloc_resources_, TYPE)(hw);
> 
> diff --git a/audio/coreaudio.c b/audio/coreaudio.c
> index 4e7e509ad0..ff0d23fd7d 100644
> --- a/audio/coreaudio.c
> +++ b/audio/coreaudio.c
> @@ -482,6 +482,7 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
>     Audiodev *dev = drv_opaque;
>     AudiodevCoreaudioPerDirectionOptions *cpdo = dev->u.coreaudio.out;
>     int frames;
> +    struct audsettings fake_as;
> 
>     /* create mutex */
>     err = pthread_mutex_init(&core->mutex, NULL);
> @@ -490,6 +491,10 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
>         return -1;
>     }
> 
> +    memcpy(&fake_as, as, sizeof(struct audsettings));
> +    as = &fake_as;
> +    /* size of float is 32bits */
> +    as->fmt = AUDIO_FORMAT_S32;
>     audio_pcm_init_info (&hw->info, as);
> 
>     status = coreaudio_get_voice(&core->outputDeviceID);
> -- 
> 2.16.4
> 

I could not apply this patch using 'patch -p1 < <patch file>'. I kept seeing the error malformed patch. 

When I applied the patch by hand QEMU was able to play sound normally again. Thank you :)

I used qemu-system-i386 at git commit adcd6e93b9519f7fe421d543e3aa646895b32e1a to test this patch. 

Both the AC97 and SB16 sound cards with Windows XP and Windows NT 4.0 respectively. Only the ES1370 sound card used with Windows 2000 failed to play anything. This is probably a problem with it and not your patch.

Reviewed-by: John Arbuckle <programmingkidx@gmail.com>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] Implement the Screamer sound chip for the mac99 machine type
  2020-01-28  8:30   ` Volker Rümelin
  2020-01-28  9:38     ` Howard Spoelstra
@ 2020-02-02 19:47     ` Zoltán Kővágó
  1 sibling, 0 replies; 16+ messages in thread
From: Zoltán Kővágó @ 2020-02-02 19:47 UTC (permalink / raw)
  To: Volker Rümelin, Programmingkid, qemu Developers,
	Howard Spoelstra, Mark Cave-Ayland
  Cc: Gerd Hoffmann

On 2020-01-28 09:30, Volker Rümelin wrote:
>> Hi,
>>
>> Unfortunately it's not that simple to simply revert the patch since the old backend api no longer exists.  Also I don't have a Mac so it's almost impossible for me to test the results.  I looked at the specified commit and I think I found a problem, could you please apply the attached patch on the current git master and check whether it solves the problem?  If yes I'll turn it into a proper patch.
>>
>> Regards,
>> Zoltan
>>
> 
> Hi Zoltán,
> 
> I also don't have a Mac so I tested your patch with a slightly modified sdlaudio version. I found two bugs in your patch. With the bugs fixed I have working SDL2 audio playback with float type samples. Now I wonder if the fixed patch also fixes coreaudio playback. Depending on how busy you are I can just write a review for your patch and let you handle the rest, or may I send a modified version of your patch to the mailing list for testing?
> 
> With best regards
> Volker
Hi,

Maybe I'm a bit late since you already did it, but go ahead, I don't 
have too much time to work on qemu recently.

Regards,
Zoltan


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2] Implement the Screamer sound chip for the mac99 machine type
@ 2019-12-29  2:45 John Arbuckle
  0 siblings, 0 replies; 16+ messages in thread
From: John Arbuckle @ 2019-12-29  2:45 UTC (permalink / raw)
  To: mark.cave-ayland, qemu-ppc, qemu-devel; +Cc: John Arbuckle

This patch enables the playback of audio on a Mac OS 9 or Mac OS X guest.

Signed-off-by: John Arbuckle <programmingkidx@gmail.com>
---
v2 changes:
- Fixed a bug that prevented the sampling rate from being changed.

 hw/audio/Kconfig              |   3 +
 hw/audio/Makefile.objs        |   2 +
 hw/audio/screamer.c           | 993 ++++++++++++++++++++++++++++++++++++++++++
 hw/misc/macio/macio.c         |  35 +-
 hw/ppc/Kconfig                |   1 +
 hw/ppc/mac.h                  |   5 +
 include/hw/audio/screamer.h   |  42 ++
 include/hw/misc/macio/macio.h |   2 +
 8 files changed, 1082 insertions(+), 1 deletion(-)
 create mode 100644 hw/audio/screamer.c
 create mode 100644 include/hw/audio/screamer.h

diff --git a/hw/audio/Kconfig b/hw/audio/Kconfig
index e9c6fed826..196da6c3fe 100644
--- a/hw/audio/Kconfig
+++ b/hw/audio/Kconfig
@@ -50,3 +50,6 @@ config CS4231
 
 config MARVELL_88W8618
     bool
+
+config SCREAMER
+    bool
diff --git a/hw/audio/Makefile.objs b/hw/audio/Makefile.objs
index 63db383709..55906886bc 100644
--- a/hw/audio/Makefile.objs
+++ b/hw/audio/Makefile.objs
@@ -15,4 +15,6 @@ common-obj-$(CONFIG_CS4231) += cs4231.o
 common-obj-$(CONFIG_MARVELL_88W8618) += marvell_88w8618.o
 common-obj-$(CONFIG_MILKYMIST) += milkymist-ac97.o
 
+common-obj-$(CONFIG_SCREAMER) += screamer.o
+
 common-obj-y += soundhw.o
diff --git a/hw/audio/screamer.c b/hw/audio/screamer.c
new file mode 100644
index 0000000000..d3a86d2e67
--- /dev/null
+++ b/hw/audio/screamer.c
@@ -0,0 +1,993 @@
+/*
+ * File: Screamer.c
+ * Description: Implement the Screamer sound chip used in Apple Macintoshes.
+ * It works by filling a buffer, then playing the buffer.
+ */
+
+#include "qemu/osdep.h"
+#include "audio/audio.h"
+#include "hw/hw.h"
+#include "hw/irq.h"
+#include <inttypes.h>
+#include "hw/ppc/mac.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "include/hw/audio/screamer.h"
+
+#define DEBUG_SCREAMER 0
+#define DPRINTF(fmt, ...) \
+do { if (DEBUG_SCREAMER) { printf(fmt , ## __VA_ARGS__); } } while (0)
+
+#define SOUND_CONTROL_REG  0
+#define CODEC_CONTROL_REG  1
+#define CODEC_STATUS_REG   2
+#define CLIP_COUNT_REG     3
+#define BYTE_SWAP_REG      4
+#define FRAME_COUNT_REG    5
+
+#define AWACS_BUSY         0x01000000
+
+/* Used with AWACS register 1 */
+#define RECALIBRATE         0x004
+#define LOOPTHRU            0x040
+#define SPEAKER_MUTE        0x080
+#define HEADPHONE_MUTE      0x200
+#define OUTPUT_ZERO         0x400
+#define OUTPUT_ONE          0x800
+#define PARALLEL_OUTPUT     0xc00
+
+/* Function prototypes */
+static uint32_t set_busy_bit(uint32_t value, int bit);
+static uint32_t set_part_ready_bit(uint32_t value, int bit_value);
+static uint32_t set_revision(uint32_t input_value);
+static uint32_t set_manufacturer(uint32_t input_value);
+static int get_sampling_rate(ScreamerState *s);
+static uint32_t get_frame_count_reg(ScreamerState *s);
+static void add_to_speaker_buffer(DBDMA_io *io);
+static void dma_request(DBDMA_io *io);
+
+
+/**************************** Getters *************************/
+
+/* Returns the codec control register's encoded AWACS address */
+static uint8_t get_codec_control_address(uint32_t value)
+{
+    uint8_t return_value;
+    return_value = (value >> 12) & 0x00000fff;
+    return return_value;
+}
+
+
+static uint32_t get_sound_control_reg(ScreamerState *s)
+{
+    DPRINTF("%s() called - returned 0x%x\n", __func__, s->sound_control);
+    return s->sound_control;
+}
+
+/* The AWACS registers are accessed thru this register */
+static uint32_t get_codec_control_reg(ScreamerState *s)
+{
+    int awacs_register = get_codec_control_address(s->codec_control);
+    uint32_t return_value = s->awacs[awacs_register];
+    return_value = set_busy_bit(return_value, 0); /* Tell CPU we are ready */
+    DPRINTF("%s() called - returned 0x%x\tAWACS register: %d\n", __func__,
+            return_value, awacs_register);
+    return return_value;
+}
+
+/*
+ * Determines if the readback bit is set.
+ * It is used by the Codec Control register.
+ */
+static bool readback_enabled(ScreamerState *s)
+{
+/* Note: bit zero is the readback enabled bit */
+    if (s->awacs[7] & 1) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+static uint32_t get_codec_status_reg(ScreamerState *s)
+{
+    uint32_t return_value;
+
+    /* if in readback mode - return AWACS register value */
+    if (readback_enabled(s)) {
+        int awacs_register = (s->awacs[7] & 0xe) >> 1;
+        s->awacs[7] = s->awacs[7] & 0xfffffffe; /* turn off readback mode */
+        return_value = s->awacs[awacs_register] << 4;
+        DPRINTF("readback enable bit is set, returning AWACS register %d\t"
+                "value:0x%x\n", awacs_register, return_value);
+
+        return return_value;
+    }
+
+    /* Tell CPU we are ready */
+    return_value = set_part_ready_bit(s->codec_status, 1);
+
+    /* Set Revision to Screamer */
+    return_value = set_revision(return_value);
+
+    /* Set the Manufacturer to Crystal */
+    return_value = set_manufacturer(return_value);
+    DPRINTF("%s() called - returned 0x%x\n", __func__, return_value);
+
+    return return_value;
+}
+
+static uint32_t get_clip_count_reg(ScreamerState *s)
+{
+    DPRINTF("%s() called - returned 0x%x\n", __func__, s->clip_count);
+    uint32_t return_value;
+    return_value = s->clip_count;
+    /* This is reset everytime it is read */
+    s->clip_count = 0;
+    return return_value;
+}
+
+static uint32_t get_byte_swap_reg(ScreamerState *s)
+{
+    DPRINTF("%s() called - returned 0x%x\n", __func__, s->byte_swap);
+    /*
+     * If all you hear is noise, it could be this register reporting the
+     * wrong value.
+     */
+    return s->byte_swap ? 0 : 1;
+}
+
+/*
+ * Returns the frame (sample) count
+ */
+static uint32_t get_frame_count_reg(ScreamerState *s)
+{
+    DPRINTF("%s() called - returned 0x%x\n", __func__, s->frame_count);
+    return s->frame_count;
+}
+
+static uint8_t get_left_vol(uint32_t value)
+{
+    return value & 0xf;
+}
+
+static uint8_t get_right_vol(uint32_t value)
+{
+    return value & 0x3c0 >> 6;
+}
+
+/*
+ * Returns the sampling rate.
+ * If the audio is playing back too fast or too slow, this function may be the
+ * cause.
+ */
+static int get_sampling_rate(ScreamerState *s)
+{
+    uint32_t screamer_rate = s->sound_control & 0x700;
+    int return_value;
+
+    /* All return values are in Hertz */
+    switch (screamer_rate) {
+    case 0x0:
+        return_value = 44100;
+        break;
+    case 0x100:
+        return_value = 29400;
+        break;
+    case 0x200:
+        return_value = 22050;
+        break;
+    case 0x300:
+        return_value = 17640;
+        break;
+    case 0x400:
+        return_value = 14700;
+        break;
+    case 0x500:
+        return_value = 11025;
+        break;
+    case 0x600:
+        return_value = 8820;
+        break;
+    case 0x700:
+        return_value = 7350;
+        break;
+    default:
+        DPRINTF("get_sampling_rate() unknown value: 0x%x\nDefaulting to"
+                " 44100 Hz.\n", screamer_rate);
+        return 44100;
+}
+    DPRINTF("%s() called - returning %dHz\n", __func__, return_value);
+    return return_value;
+}
+
+/**************************** End of getters *************************/
+
+/***************************** Speaker call back *************************/
+
+/* resets the play and buffer position markers */
+static void reset_markers(ScreamerState *s)
+{
+    s->spk_play_position = 0;
+    s->spk_buffer_position = 0;
+}
+
+
+/* Sends the samples to the host for playing */
+static void send_samples_to_host(ScreamerState *s, int max_samples)
+{
+    int write_length, requested_length;
+    requested_length = MIN(max_samples, (s->spk_buffer_position -
+                                         s->spk_play_position));
+    write_length = AUD_write(s->speaker_voice,
+                             &s->spk_buffer[s->spk_play_position],
+                             requested_length);
+    DPRINTF("requested length: %d\twrite length: %d\t",
+            requested_length, write_length);
+    s->spk_play_position += write_length;
+    DPRINTF("AUD_write %d/%d\n", s->spk_play_position, s->spk_buffer_position);
+    s->frame_count += write_length;
+}
+
+
+/*
+ * Called by QEMU's audio system to tell the output backend to send samples
+ * from the buffer to the host sound system.
+ * opaque: a pointer to the ScreamerState instance.
+ * max_samples: the number of samples that can be sent to the hardware buffer.
+ */
+static void speaker_callback(void *opaque, int max_samples)
+{
+    ScreamerState *s = (ScreamerState *) opaque;
+
+    /* if we have more samples to play */
+    if (s->spk_buffer_position > 0) {
+        if (s->spk_buffer_position > s->spk_play_position) {
+            DPRINTF("%s() called - max_samples: %d\n", __func__, max_samples);
+            send_samples_to_host(s, max_samples);
+        }
+        if (s->spk_play_position >= s->spk_buffer_position) {
+            DPRINTF("done playing buffer\n");
+            DPRINTF("pp: %d\tbp: %d\n", s->spk_play_position,
+                    s->spk_buffer_position);
+            if (s->spk_play_position > s->spk_buffer_position) {
+                DPRINTF("Error detected! - pp > bp\n\a");
+            }
+            reset_markers(s);
+            /* play postponed samples */
+            if (s->dma_io.len > 0) {
+                DPRINTF("playing postponed samples\n");
+                add_to_speaker_buffer(&s->dma_io);
+                return;
+            }
+        }
+    }
+}
+
+/************************* End of speaker call back *************************/
+
+
+/* Opens the speaker's voice */
+static void open_speaker_voice(ScreamerState *s)
+{
+    DPRINTF("%s() called\n", __func__);
+
+    /* if voice is already open return from function */
+    if (s->speaker_voice != NULL) {
+        DPRINTF("closing speaker voice\n");
+        AUD_close_out(&s->card, s->speaker_voice);
+        s->speaker_voice = NULL;
+    }
+    struct audsettings audio_settings;
+    audio_settings.freq = get_sampling_rate(s);  /* in hertz */
+    audio_settings.nchannels = 2;                /* stereo output */
+    audio_settings.fmt = AUDIO_FORMAT_S16;       /* signed 16 bit */
+    audio_settings.endianness = get_byte_swap_reg(s); /* endianness */
+    s->speaker_voice = AUD_open_out(&s->card, s->speaker_voice, SOUND_CHIP_NAME
+                                    " speaker", s, speaker_callback,
+                                    &audio_settings);
+    if (!s->speaker_voice) {
+        AUD_log(SOUND_CHIP_NAME, "Out voice could not be opened\n");
+    } else {
+        AUD_set_active_out(s->speaker_voice, true);
+    }
+}
+
+
+/******************************* Setters *************************************/
+
+
+/* Updates QEMU's audio backend settings */
+static void set_QEMU_audio_settings(ScreamerState *s)
+{
+    DPRINTF("%s() called\n", __func__);
+    open_speaker_voice(s);
+}
+
+
+/* Return value: 1 = muted  0 = not muted */
+static int is_muted(ScreamerState *s)
+{
+    int mute_state = s->awacs[1] & SPEAKER_MUTE ? 1 : 0;
+    if (s->awacs[1] & SPEAKER_MUTE) {
+        DPRINTF("speaker is muted\n");
+    } else {
+        DPRINTF("speaker is unmuted\n");
+    }
+
+    if (s->awacs[1] & HEADPHONE_MUTE) {
+        DPRINTF("headphone is muted\n");
+    } else {
+        DPRINTF("headphone is unmuted\n");
+    }
+    return mute_state;
+}
+
+
+/* Converts Screamer's volume system to QEMU's system */
+static int screamer_to_qemu_volume(int x)
+{
+    return -16 * x + 240;
+}
+
+
+/* Sets QEMU's volume. */
+static void set_volume(ScreamerState *s)
+{
+    int should_mute = is_muted(s);
+
+    /* Get Screamer volume values */
+    uint8_t left_vol = get_left_vol(s->awacs[4]);
+    uint8_t right_vol = get_right_vol(s->awacs[4]);
+    DPRINTF("set_volume() called - M:%d\tL:%d\tR:%d\n", should_mute, left_vol,
+            right_vol);
+
+    /* Convert Screamer to QEMU volume values */
+    left_vol = screamer_to_qemu_volume(left_vol);
+    right_vol = screamer_to_qemu_volume(right_vol);
+    DPRINTF("QEMU volume: L:%d\tR:%d\n", left_vol, right_vol);
+    AUD_set_volume_out(s->speaker_voice, should_mute, left_vol, right_vol);
+}
+
+
+/* Sets the sound control register */
+static void set_sound_control_reg(ScreamerState *s, uint32_t value)
+{
+    DPRINTF("set_sound_control_reg() called - value: 0x%x\n", value);
+    s->sound_control = value;
+    set_QEMU_audio_settings(s);
+}
+
+
+/* Used for input gain only - can be ignored for now. */
+static void set_awacs_0_reg(ScreamerState *s, uint32_t new_value)
+{
+    DPRINTF("Settings AWACS register 0 to 0x%x\n", s->awacs[0]);
+    s->awacs[0] = new_value;
+}
+
+
+static void set_awacs_1_reg(ScreamerState *s, uint32_t new_value)
+{
+    DPRINTF("Settings AWACS register 1 to 0x%x\n", new_value);
+
+    s->awacs[1] = new_value;
+
+    /* If recalibration requested */
+    if (new_value & RECALIBRATE) {
+        DPRINTF("Recalibration requested - unimplemented\n");
+        new_value = new_value ^ RECALIBRATE; /* Turn off recalibrate bit */
+    }
+
+    /* If loop thru set - what does this mean? */
+    if (new_value & LOOPTHRU) {
+        DPRINTF("Loopthru enabled - doing nothing\n");
+    }
+
+    /* Set headphone jack mute state */
+    if (new_value & HEADPHONE_MUTE) {
+        DPRINTF("Headphone muted\n");
+    }
+
+    else {
+        DPRINTF("Headphone unmuted\n");
+    }
+
+    if (new_value & SPEAKER_MUTE) {
+        DPRINTF("Speaker muted\n");
+    }
+
+    else {
+        DPRINTF("Speaker unmuted\n");
+    }
+
+    if (new_value & OUTPUT_ZERO) {
+        DPRINTF("output zero set - not sure what this means\n");
+    }
+
+    if (new_value & OUTPUT_ONE) {
+        DPRINTF("output one set - not sure what this means\n");
+    }
+
+    if (new_value & PARALLEL_OUTPUT) {
+        DPRINTF("parallel port enabled - but no parallel port here\n");
+    }
+
+    set_volume(s);
+}
+
+
+/* This is used for headphone volume - not needed */
+static void set_awacs_2_reg(ScreamerState *s, uint32_t new_value)
+{
+    DPRINTF("Settings AWACS register 2 to 0x%x\n"
+            "Ignoring change in headphone volume.\n", s->awacs[2]);
+    s->awacs[2] = new_value;
+}
+
+
+/* Unknown register purpose */
+static void set_awacs_3_reg(ScreamerState *s, uint32_t new_value)
+{
+    DPRINTF("Settings AWACS register 3 to 0x%x\n"
+            "This register has an unknown purpose and does not do anything\n",
+            s->awacs[3]);
+    s->awacs[3] = new_value;
+}
+
+
+/* Mostly deals with speaker volume */
+static void set_awacs_4_reg(ScreamerState *s, uint32_t new_value)
+{
+    DPRINTF("AWACS register 4 write: 0x%x\n", new_value);
+    s->awacs[4] = new_value;
+    set_volume(s);
+}
+
+
+/* This register is about loop thru stuff I don't understand */
+static void set_awacs_5_reg(ScreamerState *s, uint32_t new_value)
+{
+    DPRINTF("Settings AWACS register 5 to 0x%x\n"
+            "Loop thru update ignored.\n", s->awacs[5]);
+    s->awacs[5] = new_value;
+}
+
+
+/* Prints the states of the AWACS power register */
+static void print_power_reg_values(uint32_t value)
+{
+    if ((value & 0x3) == 0) {
+        printf("Screamer run state set\n");
+    }
+    if ((value & 0x3) == 1) {
+        printf("Screamer doze state set\n");
+    }
+    if ((value & 0x3) == 2) {
+        printf("Screamer idle state set\n");
+    }
+}
+
+
+/* Power Magement register */
+static void set_awacs_6_reg(ScreamerState *s, uint32_t new_value)
+{
+    DPRINTF("Settings AWACS register 6 to 0x%x\n"
+            "Power management update ignored.\n", s->awacs[6]);
+    if (DEBUG_SCREAMER) {
+        print_power_reg_values(new_value);
+    }
+    s->awacs[6] = new_value;
+}
+
+
+/* Read Back - repeating something that was sent to this chip? */
+static void set_awacs_7_reg(ScreamerState *s, uint32_t new_value)
+{
+    DPRINTF("Settings AWACS register 7 to 0x%x\n", new_value);
+    s->awacs[7] = new_value;
+}
+
+
+/* Sets the AWACs registers - a.k.a. shadow registers */
+static void set_awacs_register(ScreamerState *s, uint32_t value)
+{
+    int the_register = get_codec_control_address(value);
+
+    switch (the_register) {
+    case 0:
+        set_awacs_0_reg(s, value);
+        break;
+    case 1:
+        set_awacs_1_reg(s, value);
+        break;
+    case 2:
+        set_awacs_2_reg(s, value);
+        break;
+    case 3:
+        set_awacs_3_reg(s, value);
+        break;
+    case 4:
+        set_awacs_4_reg(s, value);
+        break;
+    case 5:
+        set_awacs_5_reg(s, value);
+        break;
+    case 6:
+        set_awacs_6_reg(s, value);
+        break;
+    case 7:
+        set_awacs_7_reg(s, value);
+        break;
+    default:
+        DPRINTF("Unhandled awacs registers %d\n", the_register);
+    }
+}
+
+
+/* Used to set the AWACS registers */
+static void set_codec_control_reg(ScreamerState *s, uint32_t value)
+{
+    DPRINTF("set_codec_control_reg() called - value: 0x%x\n", value);
+    s->codec_control = value;
+    set_awacs_register(s, value);
+}
+
+static void set_codec_status_reg(ScreamerState *s, uint32_t value)
+{
+    DPRINTF("set_codec_status_reg() called - value: 0x%x\n", value);
+    s->codec_status = value;
+}
+
+static void set_clip_count_reg(ScreamerState *s, uint32_t new_value)
+{
+    DPRINTF("set_clip_count_reg() called - value: 0x%x\n", new_value);
+    s->clip_count = new_value;
+}
+
+static void set_byte_swap_reg(ScreamerState *s, uint32_t value)
+{
+    DPRINTF("set_byte_swap_reg() called - value: 0x%x\n", value);
+    s->byte_swap = value;
+}
+
+static void set_frame_count_reg(ScreamerState *s, uint32_t new_value)
+{
+    DPRINTF("%s() called - value: 0x%x\n", __func__, new_value);
+    s->frame_count = new_value;
+}
+
+/*
+ * Sets the busy bit of codec control register.
+ * It is used to tell the CPU to wait.
+ * value: the codec control register's value
+ * bit_value: used to set or disable the busy bit
+ */
+static uint32_t set_busy_bit(uint32_t value, int bit_value)
+{
+    const int busy_bit = 0x01000000;
+    uint32_t return_value;
+    if (bit_value == 1)  /* Set this bit */
+        return_value = (value | busy_bit);
+    else /* bit_value == 0  Disable this bit */
+        return_value = (value & ~busy_bit);
+    return return_value;
+}
+
+
+/*
+ * Sets the part ready bit of the codec status register
+ * value: the codec status register's value
+ * bit_value: used to set or disable the part ready bit
+ */
+static uint32_t set_part_ready_bit(uint32_t value, int bit_value)
+{
+    const int part_ready_bit = 0x00400000;
+    uint32_t return_value;
+    if (bit_value == 1)  /* Set this bit */
+        return_value = (value | part_ready_bit);
+    else /* bit_value == 0  Disable this bit */
+        return_value = (value & ~part_ready_bit);
+    return return_value;
+}
+
+/* Sets bits 12 and 13 to 1 to indicate the Screamer revision */
+static uint32_t set_revision(uint32_t input_value)
+{
+    uint32_t return_value;
+    return_value = input_value | 0x3000;
+    return return_value;
+}
+
+/* Sets bit 8 to indicate Crystal as the manufacturer */
+static uint32_t set_manufacturer(uint32_t input_value)
+{
+    uint32_t return_value;
+    return_value = input_value | 0x100;
+    return return_value;
+}
+
+
+/************************** End of Setters *********************************/
+
+
+/*************************** DMA functions *********************************/
+
+/*
+ * Sends audio samples from a microphone or line-in to memory.
+ * Used for sound input.
+ * Currently only prevents a deadlock condition with Mac OS 9.
+ */
+static void screamer_to_dma(DBDMA_io *io)
+{
+    DPRINTF("%s() called\n", __func__);
+    ScreamerState *s = (ScreamerState *)io->opaque;
+    DBDMAState *dbs = s->dbdma;
+    DBDMA_channel *ch = &dbs->channels[0x12];
+    ch->regs[DBDMA_STATUS] |= DEAD;
+    ch->regs[DBDMA_STATUS] &= ~ACTIVE;
+    io->dma_end(io);
+    return;
+}
+
+
+static void print_dma_info(DBDMA_io *io)
+{
+    #define RUN        0x8000
+    #define PAUSE      0x4000
+    #define FLUSH      0x2000
+    #define WAKE       0x1000
+    #define DEAD       0x0800
+    #define ACTIVE     0x0400
+    #define BT         0x0100
+    #define DEVSTAT    0x00ff
+
+    /*
+     * RUN and PAUSE are bits under software control only.
+     * FLUSH and WAKE are set by SW and cleared by hardware.
+     * DEAD, ACTIVE and BT are only under hardware control.
+     */
+
+    DBDMA_channel *ch = io->channel;
+    printf("DMA FLAGS: ");
+
+    if (ch->regs[DBDMA_STATUS] & RUN) {
+        printf("RUN ");
+    }
+
+    if (ch->regs[DBDMA_STATUS] & ACTIVE) {
+        printf("ACTIVE ");
+    }
+
+    if (ch->regs[DBDMA_STATUS] & PAUSE) {
+        printf("PAUSE ");
+    }
+
+    if (ch->regs[DBDMA_STATUS] & DEAD) {
+        printf("DEAD ");
+    }
+
+    if (ch->regs[DBDMA_STATUS] & WAKE) {
+        printf("WAKE ");
+    }
+
+    if (ch->regs[DBDMA_STATUS] & BT) {
+        printf("BT ");
+    }
+
+    if (ch->regs[DBDMA_STATUS] & DEVSTAT) {
+        printf("DEVSTAT ");
+    }
+
+    if (ch->regs[DBDMA_STATUS] & FLUSH) {
+        printf("FLUSH ");
+    }
+
+    if (ch->io.processing == true) {
+        printf("processing  ");
+    }
+
+    printf("\n");
+}
+
+/* Tell the DMA controller we request more samples */
+static void dma_request(DBDMA_io *io)
+{
+    DPRINTF("%s() called\n", __func__);
+    if (DEBUG_SCREAMER) {
+        print_dma_info(io);
+    }
+    io->len = 0;
+    io->dma_end(io);
+}
+
+
+/* Adds sample data to the buffer */
+static void add_to_speaker_buffer(DBDMA_io *io)
+{
+    ScreamerState *s = (ScreamerState *) io->opaque;
+
+    if (s->spk_buffer_position + io->len > MAX_BUFFER_SIZE) {
+        /* postpone calling these samples until the buffer has been emptied */
+        memcpy(&s->dma_io, io, sizeof(DBDMA_io));
+        return;
+    }
+    dma_memory_read(&address_space_memory, io->addr,
+                    &s->spk_buffer[s->spk_buffer_position], io->len);
+    s->spk_buffer_position += io->len;
+    DPRINTF("%s() called - len: %d pos: %d/%d\n", __func__, io->len,
+            s->spk_buffer_position, MAX_BUFFER_SIZE);
+
+    dma_request(io);
+}
+
+/*
+ * Called by the DMA chip to transfer samples from memory to the
+ * Screamer chip.
+ * Used for sound output.
+ */
+static void dma_to_screamer(DBDMA_io *io)
+{
+    add_to_speaker_buffer(io);
+}
+
+
+/*
+ * This will flush the audio buffer of previous audio - eliminating previous
+ * audio playback.
+ */
+static void send_silence_to_speaker(ScreamerState *s)
+{
+    DPRINTF("Silencing audio buffer...\n");
+    int length = MAX_BUFFER_SIZE;
+    s->spk_buffer_position = length;
+    s->spk_play_position = 0;
+    memset(s->spk_buffer, 0, length);
+    s->dma_io.len = 0; /* stop any postponed samples from playing */
+}
+
+
+/* This is called after audio stops playing */
+static void dma_send_flush(DBDMA_io *io)
+{
+    DPRINTF("dma_send_flush() called\n");
+    if (DEBUG_SCREAMER) {
+        print_dma_info(io);
+    }
+    ScreamerState *s = (ScreamerState *)io->opaque;
+    reset_markers(s);
+    send_silence_to_speaker(s);
+    if (io->len > 0) {
+        dma_request(io);
+    }
+}
+
+
+static void dma_receive_flush(DBDMA_io *io)
+{
+    DPRINTF("dma_receive_flush() called\n");
+}
+
+
+/* Set the functions the DMA system will call */
+void screamer_register_dma_functions(ScreamerState *s, void *dbdma,
+                                   int send_channel, int receive_channel)
+{
+    DPRINTF("%s() called\n", __func__);
+    DPRINTF("send channel: %d\treceive channel: %d\n", send_channel,
+           receive_channel);
+    s->dbdma = dbdma;
+
+    /* Setup the DMA send system */
+    DBDMA_register_channel(s->dbdma, send_channel, s->dma_send_irq,
+                           dma_to_screamer, dma_send_flush, s);
+
+    /* Setup the DMA receive system */
+    DBDMA_register_channel(s->dbdma, receive_channel, s->dma_receive_irq,
+                           screamer_to_dma, dma_receive_flush, s);
+}
+
+/************************* End of DMA functions **************************/
+
+/* Resets this sound chip */
+static void screamer_reset(DeviceState *d)
+{
+    DPRINTF("screamer_reset() called\n");
+    ScreamerState *s = SCREAMER(d);
+    set_sound_control_reg(s, 0);
+    set_codec_control_reg(s, 0);
+    set_codec_status_reg(s, 0);
+    set_clip_count_reg(s, 0);
+    set_byte_swap_reg(s, 0);
+    set_frame_count_reg(s, 0);
+    int i, num_awacs_regs = 8;
+    for (i = 0; i < num_awacs_regs; i++) {
+        s->awacs[i] = 0;
+    }
+    set_QEMU_audio_settings(s);
+    reset_markers(s);
+    s->dma_io.len = 0;
+}
+
+/* Called when the CPU reads the memory addresses assigned to Screamer */
+static uint64_t screamer_mmio_read(void *opaque, hwaddr addr, unsigned size)
+{
+    ScreamerState *state = opaque;
+    uint32_t return_value;
+
+    addr = addr >> 4;
+    switch (addr) {
+    case SOUND_CONTROL_REG:
+        return_value = get_sound_control_reg(state);
+        break;
+    case CODEC_CONTROL_REG:
+        return_value = get_codec_control_reg(state);
+        break;
+    case CODEC_STATUS_REG:
+        return_value = get_codec_status_reg(state);
+        break;
+    case CLIP_COUNT_REG:
+        return_value = get_clip_count_reg(state);
+        break;
+    case BYTE_SWAP_REG:
+        return_value = get_byte_swap_reg(state);
+        break;
+    case FRAME_COUNT_REG:
+        return_value = get_frame_count_reg(state);
+        break;
+    default:
+        DPRINTF("Unknown register read - addr:%llu\tsize:%d\n", addr, size);
+        return_value = 12021981; /* Value used for debugging purposes */
+    }
+    DPRINTF("screamer_mmio_read() called addr: %llu  size: %d", addr >> 4,
+            size);
+    DPRINTF("  returning 0x%x\n", return_value);
+    return return_value;
+}
+
+
+/* Called when the CPU writes to the memory addresses assigned to Screamer */
+static void screamer_mmio_write(void *opaque, hwaddr addr, uint64_t raw_value,
+                                unsigned size)
+{
+    DPRINTF("screamer_mmio_write() called - size: %d\n", size);
+    ScreamerState *state = opaque;
+    uint32_t value = raw_value & 0xffffffff;
+    addr = addr >> 4;
+
+    switch (addr) {
+    case SOUND_CONTROL_REG:
+        set_sound_control_reg(state, value);
+        break;
+    case CODEC_CONTROL_REG:
+        set_codec_control_reg(state, value);
+        break;
+    case CODEC_STATUS_REG:
+        set_codec_status_reg(state, value);
+        break;
+    case CLIP_COUNT_REG:
+        set_clip_count_reg(state, value);
+        break;
+    case BYTE_SWAP_REG:
+        set_byte_swap_reg(state, value);
+        break;
+    case FRAME_COUNT_REG:
+        set_frame_count_reg(state, value);
+        break;
+    default:
+        DPRINTF("Unknown register write - addr:%llu\tvalue:%d\n", addr, value);
+    }
+}
+
+/* Used for memory_region_init_io() for memory mapped I/O */
+static const MemoryRegionOps screamer_ops = {
+    .read = screamer_mmio_read,
+    .write = screamer_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
+};
+
+/* Called when the device has become active */
+static void screamer_realize(DeviceState *dev, Error **errp)
+{
+    DPRINTF("screamer_realize() called\n");
+    screamer_reset(dev);
+}
+
+
+/*
+ * Called when an instance of the Screamer device is created.
+ * Also called when this HMP command is called: device_add screamer
+ */
+static void screamer_init(Object *obj)
+{
+    DPRINTF("screamer_init() called\n");
+
+    ScreamerState *s = (ScreamerState *)obj;
+    SysBusDevice *d = SYS_BUS_DEVICE(obj);
+    const int region_size = 5 * 32;
+
+    /* Makes the read and write ops work */
+    memory_region_init_io(&s->io_memory_region, OBJECT(s),
+                          &screamer_ops, s, SOUND_CHIP_NAME, region_size);
+
+    /* Sets the SysBusDevice's memory property */
+    sysbus_init_mmio(d, &s->io_memory_region);
+
+    /* Setup all the interrupt requests */
+    sysbus_init_irq(d, &s->irq);
+    sysbus_init_irq(d, &s->dma_send_irq);
+    sysbus_init_irq(d, &s->dma_receive_irq);
+
+    /* Registers Screamer with QEMU's audio system */
+    AUD_register_card(SOUND_CHIP_NAME, &s->card);
+}
+
+
+/*
+ * These properties are displayed when using this command in the HMP.
+ * Command-line Example: --device screamer,help
+ * HMP Example:          device-list-properties
+ */
+static Property screamer_properties[] = {
+    DEFINE_PROP_END_OF_LIST()
+};
+
+/*
+ * When saving and restoring the state of the VM, this is used to save and
+ * restore the registers.
+ */
+static const VMStateDescription vmstate_screamer = {
+    .name = "Screamer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT16_ARRAY(awacs, ScreamerState, 8), /* 8 AWACS registers */
+        VMSTATE_UINT32(sound_control, ScreamerState),
+        VMSTATE_UINT32(codec_control, ScreamerState),
+        VMSTATE_UINT32(codec_status, ScreamerState),
+        VMSTATE_UINT32(clip_count, ScreamerState),
+        VMSTATE_UINT32(byte_swap, ScreamerState),
+        VMSTATE_UINT32(frame_count, ScreamerState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+
+/*
+ * Sets the class data. It is like polymorphism and inheritance in object
+ * oriented languages.
+ */
+static void screamer_class_init(ObjectClass *class, void *data)
+{
+    DPRINTF("screamer_class_init() called\n");
+    DeviceClass *dc = DEVICE_CLASS(class);
+    dc->realize = screamer_realize;
+    dc->reset = screamer_reset;
+    dc->desc = "Apple Screamer";
+    dc->props = screamer_properties;
+    dc->vmsd = &vmstate_screamer;
+    dc->hotpluggable = false;
+}
+
+/* Used for QOM function registration */
+static const TypeInfo screamer_info = {
+    .name          = "screamer",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(ScreamerState),
+    .instance_init = screamer_init,
+    .class_init    = screamer_class_init,
+};
+
+/* QOM registration of above functions for calling */
+static void screamer_register_types(void)
+{
+    DPRINTF("screamer_register_types() called\n");
+    type_register_static(&screamer_info);
+}
+
+/* QEMU Object Model (QOM) stuff */
+type_init(screamer_register_types)
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index 50f20d8206..3d5f816ee8 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -37,6 +37,7 @@
 #include "hw/intc/heathrow_pic.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
+#include "include/hw/audio/screamer.h"
 
 /* Note: this code is strongly inspirated from the corresponding code
  * in PearPC */
@@ -109,7 +110,10 @@ static void macio_common_realize(PCIDevice *d, Error **errp)
     SysBusDevice *sysbus_dev;
     Error *err = NULL;
 
-    object_property_set_bool(OBJECT(&s->dbdma), true, "realized", &err);
+    const char *realized_property = "realized";
+    bool new_value = true;
+    object_property_set_bool(OBJECT(&s->dbdma), new_value, realized_property,
+                             &err);
     if (err) {
         error_propagate(errp, err);
         return;
@@ -117,6 +121,19 @@ static void macio_common_realize(PCIDevice *d, Error **errp)
     sysbus_dev = SYS_BUS_DEVICE(&s->dbdma);
     memory_region_add_subregion(&s->bar, 0x08000,
                                 sysbus_mmio_get_region(sysbus_dev, 0));
+    object_property_set_bool(OBJECT(&s->screamer), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    /* Add the screamer sound chip */
+    sysbus_dev = SYS_BUS_DEVICE(&s->screamer);
+    const int offset = 0x14000; /* Offset from base address register (bar) */
+    const int region_number = 0; /* which memory region to use */
+    memory_region_add_subregion(&s->bar, offset,
+                                sysbus_mmio_get_region(sysbus_dev,
+                                                       region_number));
 
     qdev_prop_set_uint32(DEVICE(&s->escc), "disabled", 0);
     qdev_prop_set_uint32(DEVICE(&s->escc), "frequency", ESCC_CLOCK);
@@ -386,6 +403,19 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp)
         memory_region_add_subregion(&s->bar, 0x16000,
                                     sysbus_mmio_get_region(sysbus_dev, 0));
     }
+
+    /* Screamer Sound Chip */
+    const int gpio_0 = 0;
+    const int gpio_1 = 1;
+    const int transmit_channel = 0x10;
+    const int receive_channel = 0x12;
+    sysbus_dev = SYS_BUS_DEVICE(&s->screamer);
+    sysbus_connect_irq(sysbus_dev, gpio_0, qdev_get_gpio_in(pic_dev,
+                                           NEWWORLD_SCREAMER_IRQ));
+    sysbus_connect_irq(sysbus_dev, gpio_1, qdev_get_gpio_in(pic_dev,
+                                           NEWWORLD_SCREAMER_DMA_IRQ));
+    screamer_register_dma_functions(SCREAMER(sysbus_dev), &s->dbdma,
+                                    transmit_channel, receive_channel);
 }
 
 static void macio_newworld_init(Object *obj)
@@ -420,6 +450,9 @@ static void macio_instance_init(Object *obj)
                          TYPE_MAC_DBDMA);
 
     macio_init_child_obj(s, "escc", &s->escc, sizeof(s->escc), TYPE_ESCC);
+
+    macio_init_child_obj(s, SOUND_CHIP_NAME, &s->screamer, sizeof(s->screamer),
+                         TYPE_SCREAMER);
 }
 
 static const VMStateDescription vmstate_macio_oldworld = {
diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
index f927ec9c74..987e2dc0c9 100644
--- a/hw/ppc/Kconfig
+++ b/hw/ppc/Kconfig
@@ -95,6 +95,7 @@ config MAC_NEWWORLD
     select MACIO_GPIO
     select MAC_PMU
     select UNIN_PCI
+    select SCREAMER
 
 config E500
     bool
diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 6af87d1fa0..c65f2fd15f 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -34,6 +34,8 @@
 #include "hw/misc/mos6522.h"
 #include "hw/pci/pci_host.h"
 #include "hw/pci-host/uninorth.h"
+#include "hw/ppc/mac_dbdma.h"
+#include "audio/audio.h"
 
 /* SMP is not enabled, for now */
 #define MAX_CPUS 1
@@ -68,6 +70,9 @@
 #define NEWWORLD_IDE1_DMA_IRQ  0x3
 #define NEWWORLD_EXTING_GPIO1  0x2f
 #define NEWWORLD_EXTING_GPIO9  0x37
+#define NEWWORLD_SCREAMER_IRQ  0x18
+#define NEWWORLD_SCREAMER_DMA_IRQ 0x9
+#define NEWWORLD_SCREAMER_RX_IRQ 0xa
 
 /* Core99 machine */
 #define TYPE_CORE99_MACHINE MACHINE_TYPE_NAME("mac99")
diff --git a/include/hw/audio/screamer.h b/include/hw/audio/screamer.h
new file mode 100644
index 0000000000..7155541688
--- /dev/null
+++ b/include/hw/audio/screamer.h
@@ -0,0 +1,42 @@
+/*
+ * File: screamer.h
+ * Description: header file to the hw/audio/screamer.c file
+ */
+
+#ifndef screamer_h
+#define screamer_h
+
+#include <inttypes.h>
+#include "audio/audio.h"
+#include "hw/ppc/mac_dbdma.h"
+
+#define TYPE_SCREAMER "screamer"
+#define SCREAMER(obj) OBJECT_CHECK(ScreamerState, (obj), TYPE_SCREAMER)
+#define SOUND_CHIP_NAME "Screamer Sound Chip"
+#define MAX_BUFFER_SIZE (128 * 64)
+
+typedef struct ScreamerState {
+    SysBusDevice parent_obj;
+    uint16_t awacs[8]; /* Shadow/awacs registers */
+    uint32_t sound_control;
+    uint32_t codec_control;
+    uint32_t codec_status;
+    uint32_t clip_count;
+    uint32_t byte_swap;
+    uint32_t frame_count;
+    SWVoiceOut *speaker_voice;
+    DBDMAState *dbdma;
+    qemu_irq dma_send_irq;
+    qemu_irq dma_receive_irq;
+    qemu_irq irq;
+    QEMUSoundCard card;
+    MemoryRegion io_memory_region;
+    uint8_t spk_buffer[MAX_BUFFER_SIZE];
+    uint16_t spk_buffer_position, spk_play_position;
+    DBDMA_io dma_io;
+} ScreamerState;
+
+void screamer_register_dma_functions(ScreamerState *s, void *dbdma,
+                                     int send_channel, int receive_channel);
+
+#endif /* screamer_h */
diff --git a/include/hw/misc/macio/macio.h b/include/hw/misc/macio/macio.h
index 070a694eb5..81ad552d61 100644
--- a/include/hw/misc/macio/macio.h
+++ b/include/hw/misc/macio/macio.h
@@ -35,6 +35,7 @@
 #include "hw/ppc/mac.h"
 #include "hw/ppc/mac_dbdma.h"
 #include "hw/ppc/openpic.h"
+#include "hw/audio/screamer.h"
 
 /* MacIO virtual bus */
 #define TYPE_MACIO_BUS "macio-bus"
@@ -86,6 +87,7 @@ typedef struct MacIOState {
     PMUState pmu;
     DBDMAState dbdma;
     ESCCState escc;
+    ScreamerState screamer;
     uint64_t frequency;
 } MacIOState;
 
-- 
2.14.3 (Apple Git-98)



^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2020-02-02 19:47 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-05  1:58 [PATCH v2] Implement the Screamer sound chip for the mac99 machine type Programmingkid
2020-01-05 14:39 ` Programmingkid
2020-01-11  0:32 ` Zoltán Kővágó
2020-01-11  0:59   ` Programmingkid
2020-01-28  8:30   ` Volker Rümelin
2020-01-28  9:38     ` Howard Spoelstra
2020-01-29  7:09       ` Volker Rümelin
2020-01-29  7:13         ` [RFC] coreaudio: fix coreaudio_test.diff Volker Rümelin
2020-01-30 15:03           ` Howard Spoelstra
2020-01-31  7:37             ` Volker Rümelin
2020-01-31  8:03               ` Gerd Hoffmann
2020-01-31  8:35                 ` Mark Cave-Ayland
2020-01-31  9:12                   ` Howard Spoelstra
2020-01-31 15:55           ` Programmingkid
2020-02-02 19:47     ` [PATCH v2] Implement the Screamer sound chip for the mac99 machine type Zoltán Kővágó
  -- strict thread matches above, loose matches on Subject: below --
2019-12-29  2:45 John Arbuckle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).