Loading hw/i2c.h +1 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ void wm8750_dac_dat(void *opaque, uint32_t sample); uint32_t wm8750_adc_dat(void *opaque); void *wm8750_dac_buffer(void *opaque, int samples); void wm8750_dac_commit(void *opaque); void wm8750_set_bclk_in(void *opaque, int hz); /* ssd0303.c */ void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address); Loading hw/musicpal.c +16 −0 Original line number Diff line number Diff line Loading @@ -298,6 +298,20 @@ static void audio_callback(void *opaque, int free_out, int free_in) qemu_irq_raise(s->irq); } static void musicpal_audio_clock_update(musicpal_audio_state *s) { int rate; if (s->playback_mode & MP_AUDIO_CLOCK_24MHZ) rate = 24576000 / 64; /* 24.576MHz */ else rate = 11289600 / 64; /* 11.2896MHz */ rate /= ((s->clock_div >> 8) & 0xff) + 1; wm8750_set_bclk_in(s->wm, rate / 2); } static uint32_t musicpal_audio_read(void *opaque, target_phys_addr_t offset) { musicpal_audio_state *s = opaque; Loading Loading @@ -339,12 +353,14 @@ static void musicpal_audio_write(void *opaque, target_phys_addr_t offset, s->play_pos = 0; } s->playback_mode = value; musicpal_audio_clock_update(s); break; case MP_AUDIO_CLOCK_DIV: s->clock_div = value; s->last_free = 0; s->play_pos = 0; musicpal_audio_clock_update(s); break; case MP_AUDIO_IRQ_STATUS: Loading hw/wm8750.c +40 −9 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ struct wm8750_s { uint8_t diff[2], pol, ds, monomix[2], alc, mute; uint8_t path[4], mpath[2], power, format; const struct wm_rate_s *rate; int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master; }; /* pow(10.0, -i / 20.0) * 255, i = 0..42 */ Loading Loading @@ -197,7 +198,7 @@ static void wm8750_set_format(struct wm8750_s *s) /* Setup input */ in_fmt.endianness = 0; in_fmt.nchannels = 2; in_fmt.freq = s->rate->adc_hz; in_fmt.freq = s->adc_hz; in_fmt.fmt = AUD_FMT_S16; s->adc_voice[0] = AUD_open_in(&s->card, s->adc_voice[0], Loading @@ -210,7 +211,7 @@ static void wm8750_set_format(struct wm8750_s *s) /* Setup output */ out_fmt.endianness = 0; out_fmt.nchannels = 2; out_fmt.freq = s->rate->dac_hz; out_fmt.freq = s->dac_hz; out_fmt.fmt = AUD_FMT_S16; monoout_fmt.endianness = 0; monoout_fmt.nchannels = 1; Loading Loading @@ -238,12 +239,33 @@ static void wm8750_set_format(struct wm8750_s *s) AUD_set_active_out(*s->out[0], 1); } static void wm8750_clk_update(struct wm8750_s *s, int ext) { if (s->master || !s->ext_dac_hz) s->dac_hz = s->rate->dac_hz; else s->dac_hz = s->ext_dac_hz; if (s->master || !s->ext_adc_hz) s->adc_hz = s->rate->adc_hz; else s->adc_hz = s->ext_adc_hz; if (s->master || (!s->ext_dac_hz && !s->ext_adc_hz)) { if (!ext) wm8750_set_format(s); } else { if (ext) wm8750_set_format(s); } } void wm8750_reset(i2c_slave *i2c) { struct wm8750_s *s = (struct wm8750_s *) i2c; s->rate = &wm_rate_table[0]; s->enable = 0; wm8750_set_format(s); wm8750_clk_update(s, 1); s->diff[0] = 0; s->diff[1] = 0; s->ds = 0; Loading Loading @@ -515,17 +537,14 @@ static int wm8750_tx(i2c_slave *i2c, uint8_t data) break; case WM8750_IFACE: /* Digital Audio Interface Format */ #ifdef VERBOSE if (value & 0x40) /* MS */ printf("%s: attempt to enable Master Mode\n", __FUNCTION__); #endif s->format = value; wm8750_set_format(s); s->master = (value >> 6) & 1; /* MS */ wm8750_clk_update(s, s->master); break; case WM8750_SRATE: /* Clocking and Sample Rate Control */ s->rate = &wm_rate_table[(value >> 1) & 0x1f]; wm8750_set_format(s); wm8750_clk_update(s, 0); break; case WM8750_RESET: /* Reset */ Loading Loading @@ -666,6 +685,7 @@ void wm8750_data_req_set(i2c_slave *i2c, void wm8750_dac_dat(void *opaque, uint32_t sample) { struct wm8750_s *s = (struct wm8750_s *) opaque; *(uint32_t *) &s->data_out[s->idx_out] = sample; s->req_out -= 4; s->idx_out += 4; Loading Loading @@ -695,10 +715,21 @@ uint32_t wm8750_adc_dat(void *opaque) { struct wm8750_s *s = (struct wm8750_s *) opaque; uint32_t *data; if (s->idx_in >= sizeof(s->data_in)) wm8750_in_load(s); data = (uint32_t *) &s->data_in[s->idx_in]; s->req_in -= 4; s->idx_in += 4; return *data; } void wm8750_set_bclk_in(void *opaque, int hz) { struct wm8750_s *s = (struct wm8750_s *) opaque; s->ext_adc_hz = hz; s->ext_dac_hz = hz; wm8750_clk_update(s, 1); } Loading
hw/i2c.h +1 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ void wm8750_dac_dat(void *opaque, uint32_t sample); uint32_t wm8750_adc_dat(void *opaque); void *wm8750_dac_buffer(void *opaque, int samples); void wm8750_dac_commit(void *opaque); void wm8750_set_bclk_in(void *opaque, int hz); /* ssd0303.c */ void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address); Loading
hw/musicpal.c +16 −0 Original line number Diff line number Diff line Loading @@ -298,6 +298,20 @@ static void audio_callback(void *opaque, int free_out, int free_in) qemu_irq_raise(s->irq); } static void musicpal_audio_clock_update(musicpal_audio_state *s) { int rate; if (s->playback_mode & MP_AUDIO_CLOCK_24MHZ) rate = 24576000 / 64; /* 24.576MHz */ else rate = 11289600 / 64; /* 11.2896MHz */ rate /= ((s->clock_div >> 8) & 0xff) + 1; wm8750_set_bclk_in(s->wm, rate / 2); } static uint32_t musicpal_audio_read(void *opaque, target_phys_addr_t offset) { musicpal_audio_state *s = opaque; Loading Loading @@ -339,12 +353,14 @@ static void musicpal_audio_write(void *opaque, target_phys_addr_t offset, s->play_pos = 0; } s->playback_mode = value; musicpal_audio_clock_update(s); break; case MP_AUDIO_CLOCK_DIV: s->clock_div = value; s->last_free = 0; s->play_pos = 0; musicpal_audio_clock_update(s); break; case MP_AUDIO_IRQ_STATUS: Loading
hw/wm8750.c +40 −9 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ struct wm8750_s { uint8_t diff[2], pol, ds, monomix[2], alc, mute; uint8_t path[4], mpath[2], power, format; const struct wm_rate_s *rate; int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master; }; /* pow(10.0, -i / 20.0) * 255, i = 0..42 */ Loading Loading @@ -197,7 +198,7 @@ static void wm8750_set_format(struct wm8750_s *s) /* Setup input */ in_fmt.endianness = 0; in_fmt.nchannels = 2; in_fmt.freq = s->rate->adc_hz; in_fmt.freq = s->adc_hz; in_fmt.fmt = AUD_FMT_S16; s->adc_voice[0] = AUD_open_in(&s->card, s->adc_voice[0], Loading @@ -210,7 +211,7 @@ static void wm8750_set_format(struct wm8750_s *s) /* Setup output */ out_fmt.endianness = 0; out_fmt.nchannels = 2; out_fmt.freq = s->rate->dac_hz; out_fmt.freq = s->dac_hz; out_fmt.fmt = AUD_FMT_S16; monoout_fmt.endianness = 0; monoout_fmt.nchannels = 1; Loading Loading @@ -238,12 +239,33 @@ static void wm8750_set_format(struct wm8750_s *s) AUD_set_active_out(*s->out[0], 1); } static void wm8750_clk_update(struct wm8750_s *s, int ext) { if (s->master || !s->ext_dac_hz) s->dac_hz = s->rate->dac_hz; else s->dac_hz = s->ext_dac_hz; if (s->master || !s->ext_adc_hz) s->adc_hz = s->rate->adc_hz; else s->adc_hz = s->ext_adc_hz; if (s->master || (!s->ext_dac_hz && !s->ext_adc_hz)) { if (!ext) wm8750_set_format(s); } else { if (ext) wm8750_set_format(s); } } void wm8750_reset(i2c_slave *i2c) { struct wm8750_s *s = (struct wm8750_s *) i2c; s->rate = &wm_rate_table[0]; s->enable = 0; wm8750_set_format(s); wm8750_clk_update(s, 1); s->diff[0] = 0; s->diff[1] = 0; s->ds = 0; Loading Loading @@ -515,17 +537,14 @@ static int wm8750_tx(i2c_slave *i2c, uint8_t data) break; case WM8750_IFACE: /* Digital Audio Interface Format */ #ifdef VERBOSE if (value & 0x40) /* MS */ printf("%s: attempt to enable Master Mode\n", __FUNCTION__); #endif s->format = value; wm8750_set_format(s); s->master = (value >> 6) & 1; /* MS */ wm8750_clk_update(s, s->master); break; case WM8750_SRATE: /* Clocking and Sample Rate Control */ s->rate = &wm_rate_table[(value >> 1) & 0x1f]; wm8750_set_format(s); wm8750_clk_update(s, 0); break; case WM8750_RESET: /* Reset */ Loading Loading @@ -666,6 +685,7 @@ void wm8750_data_req_set(i2c_slave *i2c, void wm8750_dac_dat(void *opaque, uint32_t sample) { struct wm8750_s *s = (struct wm8750_s *) opaque; *(uint32_t *) &s->data_out[s->idx_out] = sample; s->req_out -= 4; s->idx_out += 4; Loading Loading @@ -695,10 +715,21 @@ uint32_t wm8750_adc_dat(void *opaque) { struct wm8750_s *s = (struct wm8750_s *) opaque; uint32_t *data; if (s->idx_in >= sizeof(s->data_in)) wm8750_in_load(s); data = (uint32_t *) &s->data_in[s->idx_in]; s->req_in -= 4; s->idx_in += 4; return *data; } void wm8750_set_bclk_in(void *opaque, int hz) { struct wm8750_s *s = (struct wm8750_s *) opaque; s->ext_adc_hz = hz; s->ext_dac_hz = hz; wm8750_clk_update(s, 1); }