Commit 4001a81e authored by Andrzej Zaborowski's avatar Andrzej Zaborowski
Browse files

MusicPal mono playback support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4332 c046a42c-6fe2-441c-8c8c-71466251a162
parent 54585ffe
Loading
Loading
Loading
Loading
+29 −14
Original line number Diff line number Diff line
@@ -230,6 +230,7 @@ static i2c_interface *mixer_i2c;
#define MP_AUDIO_16BIT_SAMPLE   (1 << 0)
#define MP_AUDIO_PLAYBACK_EN    (1 << 7)
#define MP_AUDIO_CLOCK_24MHZ    (1 << 9)
#define MP_AUDIO_MONO           (1 << 14)

/* Wolfson 8750 I2C address */
#define MP_WM_ADDR              0x34
@@ -254,32 +255,46 @@ typedef struct musicpal_audio_state {
static void audio_callback(void *opaque, int free_out, int free_in)
{
    musicpal_audio_state *s = opaque;
    int16_t *codec_buffer;
    int16_t *codec_buffer, *mem_buffer;
    int pos, block_size;

    if (!(s->playback_mode & MP_AUDIO_PLAYBACK_EN))
        return;

    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE)
        free_out <<= 2;
    else
        free_out <<= 1;

    if (!(s->playback_mode & MP_AUDIO_MONO))
        free_out <<= 1;

    block_size = s->threshold/2;
    if (free_out - s->last_free < block_size)
        return;

    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE)
    mem_buffer = s->target_buffer + s->play_pos;
    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
        if (s->playback_mode & MP_AUDIO_MONO) {
            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
            for (pos = 0; pos < block_size; pos += 2) {
                *codec_buffer++ = *mem_buffer;
                *codec_buffer++ = *mem_buffer++;
            }
        } else
            memcpy(wm8750_dac_buffer(s->wm, block_size >> 2),
               (uint32_t *)(s->target_buffer + s->play_pos),
               block_size);
    else {
                   (uint32_t *)mem_buffer, block_size);
    } else {
        if (s->playback_mode & MP_AUDIO_MONO) {
            codec_buffer = wm8750_dac_buffer(s->wm, block_size);
            for (pos = 0; pos < block_size; pos++) {
                *codec_buffer++ = cpu_to_le16(256 * *((int8_t *)mem_buffer));
                *codec_buffer++ = cpu_to_le16(256 * *((int8_t *)mem_buffer)++);
            }
        } else {
            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
            for (pos = 0; pos < block_size; pos += 2) {
            *codec_buffer++ = cpu_to_le16(256 *
                    *(int8_t *)(s->target_buffer + s->play_pos + pos));
            *codec_buffer++ = cpu_to_le16(256 *
                    *(int8_t *)(s->target_buffer + s->play_pos + pos + 1));
                *codec_buffer++ = cpu_to_le16(256 * *((int8_t *)mem_buffer)++);
                *codec_buffer++ = cpu_to_le16(256 * *((int8_t *)mem_buffer)++);
            }
        }
    }
    wm8750_dac_commit(s->wm);