Commit af83e09e9e7589c28bcf66518fd20908378880c6
1 parent
762abf67
Use external clock in wm8750 slave mode.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4325 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
57 additions
and
9 deletions
hw/i2c.h
... | ... | @@ -69,6 +69,7 @@ void wm8750_dac_dat(void *opaque, uint32_t sample); |
69 | 69 | uint32_t wm8750_adc_dat(void *opaque); |
70 | 70 | void *wm8750_dac_buffer(void *opaque, int samples); |
71 | 71 | void wm8750_dac_commit(void *opaque); |
72 | +void wm8750_set_bclk_in(void *opaque, int hz); | |
72 | 73 | |
73 | 74 | /* ssd0303.c */ |
74 | 75 | void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address); | ... | ... |
hw/musicpal.c
... | ... | @@ -298,6 +298,20 @@ static void audio_callback(void *opaque, int free_out, int free_in) |
298 | 298 | qemu_irq_raise(s->irq); |
299 | 299 | } |
300 | 300 | |
301 | +static void musicpal_audio_clock_update(musicpal_audio_state *s) | |
302 | +{ | |
303 | + int rate; | |
304 | + | |
305 | + if (s->playback_mode & MP_AUDIO_CLOCK_24MHZ) | |
306 | + rate = 24576000 / 64; /* 24.576MHz */ | |
307 | + else | |
308 | + rate = 11289600 / 64; /* 11.2896MHz */ | |
309 | + | |
310 | + rate /= ((s->clock_div >> 8) & 0xff) + 1; | |
311 | + | |
312 | + wm8750_set_bclk_in(s->wm, rate / 2); | |
313 | +} | |
314 | + | |
301 | 315 | static uint32_t musicpal_audio_read(void *opaque, target_phys_addr_t offset) |
302 | 316 | { |
303 | 317 | musicpal_audio_state *s = opaque; |
... | ... | @@ -339,12 +353,14 @@ static void musicpal_audio_write(void *opaque, target_phys_addr_t offset, |
339 | 353 | s->play_pos = 0; |
340 | 354 | } |
341 | 355 | s->playback_mode = value; |
356 | + musicpal_audio_clock_update(s); | |
342 | 357 | break; |
343 | 358 | |
344 | 359 | case MP_AUDIO_CLOCK_DIV: |
345 | 360 | s->clock_div = value; |
346 | 361 | s->last_free = 0; |
347 | 362 | s->play_pos = 0; |
363 | + musicpal_audio_clock_update(s); | |
348 | 364 | break; |
349 | 365 | |
350 | 366 | case MP_AUDIO_IRQ_STATUS: | ... | ... |
hw/wm8750.c
... | ... | @@ -40,6 +40,7 @@ struct wm8750_s { |
40 | 40 | uint8_t diff[2], pol, ds, monomix[2], alc, mute; |
41 | 41 | uint8_t path[4], mpath[2], power, format; |
42 | 42 | const struct wm_rate_s *rate; |
43 | + int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master; | |
43 | 44 | }; |
44 | 45 | |
45 | 46 | /* pow(10.0, -i / 20.0) * 255, i = 0..42 */ |
... | ... | @@ -197,7 +198,7 @@ static void wm8750_set_format(struct wm8750_s *s) |
197 | 198 | /* Setup input */ |
198 | 199 | in_fmt.endianness = 0; |
199 | 200 | in_fmt.nchannels = 2; |
200 | - in_fmt.freq = s->rate->adc_hz; | |
201 | + in_fmt.freq = s->adc_hz; | |
201 | 202 | in_fmt.fmt = AUD_FMT_S16; |
202 | 203 | |
203 | 204 | s->adc_voice[0] = AUD_open_in(&s->card, s->adc_voice[0], |
... | ... | @@ -210,7 +211,7 @@ static void wm8750_set_format(struct wm8750_s *s) |
210 | 211 | /* Setup output */ |
211 | 212 | out_fmt.endianness = 0; |
212 | 213 | out_fmt.nchannels = 2; |
213 | - out_fmt.freq = s->rate->dac_hz; | |
214 | + out_fmt.freq = s->dac_hz; | |
214 | 215 | out_fmt.fmt = AUD_FMT_S16; |
215 | 216 | monoout_fmt.endianness = 0; |
216 | 217 | monoout_fmt.nchannels = 1; |
... | ... | @@ -238,12 +239,33 @@ static void wm8750_set_format(struct wm8750_s *s) |
238 | 239 | AUD_set_active_out(*s->out[0], 1); |
239 | 240 | } |
240 | 241 | |
242 | +static void wm8750_clk_update(struct wm8750_s *s, int ext) | |
243 | +{ | |
244 | + if (s->master || !s->ext_dac_hz) | |
245 | + s->dac_hz = s->rate->dac_hz; | |
246 | + else | |
247 | + s->dac_hz = s->ext_dac_hz; | |
248 | + | |
249 | + if (s->master || !s->ext_adc_hz) | |
250 | + s->adc_hz = s->rate->adc_hz; | |
251 | + else | |
252 | + s->adc_hz = s->ext_adc_hz; | |
253 | + | |
254 | + if (s->master || (!s->ext_dac_hz && !s->ext_adc_hz)) { | |
255 | + if (!ext) | |
256 | + wm8750_set_format(s); | |
257 | + } else { | |
258 | + if (ext) | |
259 | + wm8750_set_format(s); | |
260 | + } | |
261 | +} | |
262 | + | |
241 | 263 | void wm8750_reset(i2c_slave *i2c) |
242 | 264 | { |
243 | 265 | struct wm8750_s *s = (struct wm8750_s *) i2c; |
244 | 266 | s->rate = &wm_rate_table[0]; |
245 | 267 | s->enable = 0; |
246 | - wm8750_set_format(s); | |
268 | + wm8750_clk_update(s, 1); | |
247 | 269 | s->diff[0] = 0; |
248 | 270 | s->diff[1] = 0; |
249 | 271 | s->ds = 0; |
... | ... | @@ -515,17 +537,14 @@ static int wm8750_tx(i2c_slave *i2c, uint8_t data) |
515 | 537 | break; |
516 | 538 | |
517 | 539 | case WM8750_IFACE: /* Digital Audio Interface Format */ |
518 | -#ifdef VERBOSE | |
519 | - if (value & 0x40) /* MS */ | |
520 | - printf("%s: attempt to enable Master Mode\n", __FUNCTION__); | |
521 | -#endif | |
522 | 540 | s->format = value; |
523 | - wm8750_set_format(s); | |
541 | + s->master = (value >> 6) & 1; /* MS */ | |
542 | + wm8750_clk_update(s, s->master); | |
524 | 543 | break; |
525 | 544 | |
526 | 545 | case WM8750_SRATE: /* Clocking and Sample Rate Control */ |
527 | 546 | s->rate = &wm_rate_table[(value >> 1) & 0x1f]; |
528 | - wm8750_set_format(s); | |
547 | + wm8750_clk_update(s, 0); | |
529 | 548 | break; |
530 | 549 | |
531 | 550 | case WM8750_RESET: /* Reset */ |
... | ... | @@ -666,6 +685,7 @@ void wm8750_data_req_set(i2c_slave *i2c, |
666 | 685 | void wm8750_dac_dat(void *opaque, uint32_t sample) |
667 | 686 | { |
668 | 687 | struct wm8750_s *s = (struct wm8750_s *) opaque; |
688 | + | |
669 | 689 | *(uint32_t *) &s->data_out[s->idx_out] = sample; |
670 | 690 | s->req_out -= 4; |
671 | 691 | s->idx_out += 4; |
... | ... | @@ -695,10 +715,21 @@ uint32_t wm8750_adc_dat(void *opaque) |
695 | 715 | { |
696 | 716 | struct wm8750_s *s = (struct wm8750_s *) opaque; |
697 | 717 | uint32_t *data; |
718 | + | |
698 | 719 | if (s->idx_in >= sizeof(s->data_in)) |
699 | 720 | wm8750_in_load(s); |
721 | + | |
700 | 722 | data = (uint32_t *) &s->data_in[s->idx_in]; |
701 | 723 | s->req_in -= 4; |
702 | 724 | s->idx_in += 4; |
703 | 725 | return *data; |
704 | 726 | } |
727 | + | |
728 | +void wm8750_set_bclk_in(void *opaque, int hz) | |
729 | +{ | |
730 | + struct wm8750_s *s = (struct wm8750_s *) opaque; | |
731 | + | |
732 | + s->ext_adc_hz = hz; | |
733 | + s->ext_dac_hz = hz; | |
734 | + wm8750_clk_update(s, 1); | |
735 | +} | ... | ... |