Commit af83e09e9e7589c28bcf66518fd20908378880c6

Authored by balrog
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
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 +}
... ...