~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/wm8750.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2009-03-07 06:20:34 UTC
  • mfrom: (1.1.9 upstream)
  • mto: This revision was merged to the branch mainline in revision 7.
  • Revision ID: james.westby@ubuntu.com-20090307062034-i3pead4mw653v2el
Tags: 0.10.0-1
[ Aurelien Jarno ]
* New upstream release:
  - Fix fr-be keyboard mapping (closes: bug#514462).
  - Fix stat64 structure on ppc-linux-user (closes: bug#470231).
  - Add a chroot option (closes: bug#415996).
  - Add evdev support (closes: bug#513210).
  - Fix loop on symlinks in user mode (closes: bug#297572).
  - Bump depends on openbios-sparc.
  - Depends on openbios-ppc.
  - Update 12_signal_powerpc_support.patch.
  - Update 21_net_soopts.patch.
  - Drop 44_socklen_t_check.patch (merged upstream).
  - Drop 49_null_check.patch (merged upstream).
  - Update 64_ppc_asm_constraints.patch.
  - Drop security/CVE-2008-0928-fedora.patch (merged upstream).
  - Drop security/CVE-2007-5730.patch (merged upstream).
* patches/80_stable-branch.patch: add patches from stable branch:
  - Fix race condition between signal handler/execution loop (closes:
    bug#474386, bug#501731).
* debian/copyright: update.
* Compile and install .dtb files:
  - debian/control: build-depends on device-tree-compiler.
  - debian/patches/81_compile_dtb.patch: new patch from upstream.
  - debian/rules: compile and install bamboo.dtb and mpc8544.dtb.

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
 
40
40
    uint8_t diff[2], pol, ds, monomix[2], alc, mute;
41
41
    uint8_t path[4], mpath[2], power, format;
42
 
    uint32_t inmask, outmask;
43
42
    const struct wm_rate_s *rate;
44
 
};
 
43
    int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master;
 
44
};
 
45
 
 
46
/* pow(10.0, -i / 20.0) * 255, i = 0..42 */
 
47
static const uint8_t wm8750_vol_db_table[] = {
 
48
    255, 227, 203, 181, 161, 143, 128, 114, 102, 90, 81, 72, 64, 57, 51, 45,
 
49
    40, 36, 32, 29, 26, 23, 20, 18, 16, 14, 13, 11, 10, 9, 8, 7, 6, 6, 5, 5,
 
50
    4, 4, 3, 3, 3, 2, 2
 
51
};
 
52
 
 
53
#define WM8750_OUTVOL_TRANSFORM(x)      wm8750_vol_db_table[(0x7f - x) / 3]
 
54
#define WM8750_INVOL_TRANSFORM(x)       (x << 2)
45
55
 
46
56
static inline void wm8750_in_load(struct wm8750_s *s)
47
57
{
55
65
 
56
66
static inline void wm8750_out_flush(struct wm8750_s *s)
57
67
{
58
 
    int sent;
59
 
    if (!s->idx_out)
60
 
        return;
61
 
    sent = AUD_write(*s->out[0], s->data_out, s->idx_out);
 
68
    int sent = 0;
 
69
    while (sent < s->idx_out)
 
70
        sent += AUD_write(*s->out[0], s->data_out + sent, s->idx_out - sent)
 
71
                ?: s->idx_out;
62
72
    s->idx_out = 0;
63
73
}
64
74
 
67
77
    struct wm8750_s *s = (struct wm8750_s *) opaque;
68
78
    s->req_in = avail_b;
69
79
    s->data_req(s->opaque, s->req_out >> 2, avail_b >> 2);
70
 
 
71
 
#if 0
72
 
    wm8750_in_load(s);
73
 
#endif
74
80
}
75
81
 
76
82
static void wm8750_audio_out_cb(void *opaque, int free_b)
77
83
{
78
84
    struct wm8750_s *s = (struct wm8750_s *) opaque;
79
 
    wm8750_out_flush(s);
80
85
 
81
 
    s->req_out = free_b;
82
 
    s->data_req(s->opaque, free_b >> 2, s->req_in >> 2);
 
86
    if (s->idx_out >= free_b) {
 
87
        s->idx_out = free_b;
 
88
        s->req_out = 0;
 
89
        wm8750_out_flush(s);
 
90
    } else
 
91
        s->req_out = free_b - s->idx_out;
 
92
 
 
93
    s->data_req(s->opaque, s->req_out >> 2, s->req_in >> 2);
83
94
}
84
95
 
85
96
struct wm_rate_s {
121
132
    {  512, 24000,  512, 24000 },       /* SR: 11100 */
122
133
    {  768, 24000,  768, 24000 },       /* SR: 11101 */
123
134
    {  128, 88200,  128, 88200 },       /* SR: 11110 */
124
 
    {  192, 88200,  128, 88200 },       /* SR: 11111 */
 
135
    {  192, 88200,  192, 88200 },       /* SR: 11111 */
125
136
};
126
137
 
 
138
static void wm8750_vol_update(struct wm8750_s *s)
 
139
{
 
140
    /* FIXME: multiply all volumes by s->invol[2], s->invol[3] */
 
141
 
 
142
    AUD_set_volume_in(s->adc_voice[0], s->mute,
 
143
                    s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
 
144
                    s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
 
145
    AUD_set_volume_in(s->adc_voice[1], s->mute,
 
146
                    s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
 
147
                    s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
 
148
    AUD_set_volume_in(s->adc_voice[2], s->mute,
 
149
                    s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
 
150
                    s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
 
151
 
 
152
    /* FIXME: multiply all volumes by s->outvol[0], s->outvol[1] */
 
153
 
 
154
    /* Speaker: LOUT2VOL ROUT2VOL */
 
155
    AUD_set_volume_out(s->dac_voice[0], s->mute,
 
156
                    s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[4]),
 
157
                    s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[5]));
 
158
 
 
159
    /* Headphone: LOUT1VOL ROUT1VOL */
 
160
    AUD_set_volume_out(s->dac_voice[1], s->mute,
 
161
                    s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[2]),
 
162
                    s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[3]));
 
163
 
 
164
    /* MONOOUT: MONOVOL MONOVOL */
 
165
    AUD_set_volume_out(s->dac_voice[2], s->mute,
 
166
                    s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6]),
 
167
                    s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6]));
 
168
}
 
169
 
127
170
static void wm8750_set_format(struct wm8750_s *s)
128
171
{
129
172
    int i;
130
 
    audsettings_t in_fmt;
131
 
    audsettings_t out_fmt;
132
 
    audsettings_t monoout_fmt;
 
173
    struct audsettings in_fmt;
 
174
    struct audsettings out_fmt;
 
175
    struct audsettings monoout_fmt;
133
176
 
134
177
    wm8750_out_flush(s);
135
178
 
155
198
    /* Setup input */
156
199
    in_fmt.endianness = 0;
157
200
    in_fmt.nchannels = 2;
158
 
    in_fmt.freq = s->rate->adc_hz;
 
201
    in_fmt.freq = s->adc_hz;
159
202
    in_fmt.fmt = AUD_FMT_S16;
160
203
 
161
204
    s->adc_voice[0] = AUD_open_in(&s->card, s->adc_voice[0],
168
211
    /* Setup output */
169
212
    out_fmt.endianness = 0;
170
213
    out_fmt.nchannels = 2;
171
 
    out_fmt.freq = s->rate->dac_hz;
 
214
    out_fmt.freq = s->dac_hz;
172
215
    out_fmt.fmt = AUD_FMT_S16;
173
216
    monoout_fmt.endianness = 0;
174
217
    monoout_fmt.nchannels = 1;
184
227
                    CODEC ".monomix", s, wm8750_audio_out_cb, &out_fmt);
185
228
    /* no sense emulating OUT3 which is a mix of other outputs */
186
229
 
 
230
    wm8750_vol_update(s);
 
231
 
187
232
    /* We should connect the left and right channels to their
188
233
     * respective inputs/outputs but we have completely no need
189
234
     * for mixing or combining paths to different ports, so we
194
239
        AUD_set_active_out(*s->out[0], 1);
195
240
}
196
241
 
197
 
static void inline wm8750_mask_update(struct wm8750_s *s)
 
242
static void wm8750_clk_update(struct wm8750_s *s, int ext)
198
243
{
199
 
#define R_ONLY  0x0000ffff
200
 
#define L_ONLY  0xffff0000
201
 
#define BOTH    (R_ONLY | L_ONLY)
202
 
#define NONE    (R_ONLY & L_ONLY)
203
 
    s->inmask =
204
 
            (s->inmute[0] ? R_ONLY : BOTH) &
205
 
            (s->inmute[1] ? L_ONLY : BOTH) &
206
 
            (s->mute ? NONE : BOTH);
207
 
    s->outmask =
208
 
            (s->outmute[0] ? R_ONLY : BOTH) &
209
 
            (s->outmute[1] ? L_ONLY : BOTH) &
210
 
            (s->mute ? NONE : BOTH);
 
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
    }
211
261
}
212
262
 
213
263
void wm8750_reset(i2c_slave *i2c)
214
264
{
215
265
    struct wm8750_s *s = (struct wm8750_s *) i2c;
 
266
    s->rate = &wm_rate_table[0];
216
267
    s->enable = 0;
217
 
    wm8750_set_format(s);
 
268
    wm8750_clk_update(s, 1);
218
269
    s->diff[0] = 0;
219
270
    s->diff[1] = 0;
220
271
    s->ds = 0;
231
282
    s->outvol[3] = 0x79;
232
283
    s->outvol[4] = 0x79;
233
284
    s->outvol[5] = 0x79;
 
285
    s->outvol[6] = 0x79;
234
286
    s->inmute[0] = 0;
235
287
    s->inmute[1] = 0;
236
288
    s->outmute[0] = 0;
247
299
    s->req_in = 0;
248
300
    s->idx_out = 0;
249
301
    s->req_out = 0;
250
 
    wm8750_mask_update(s);
 
302
    wm8750_vol_update(s);
251
303
    s->i2c_len = 0;
252
304
}
253
305
 
365
417
    case WM8750_LINVOL: /* Left Channel PGA */
366
418
        s->invol[0] = value & 0x3f;             /* LINVOL */
367
419
        s->inmute[0] = (value >> 7) & 1;        /* LINMUTE */
368
 
        wm8750_mask_update(s);
 
420
        wm8750_vol_update(s);
369
421
        break;
370
422
 
371
423
    case WM8750_RINVOL: /* Right Channel PGA */
372
424
        s->invol[1] = value & 0x3f;             /* RINVOL */
373
425
        s->inmute[1] = (value >> 7) & 1;        /* RINMUTE */
374
 
        wm8750_mask_update(s);
 
426
        wm8750_vol_update(s);
375
427
        break;
376
428
 
377
429
    case WM8750_ADCDAC: /* ADC and DAC Control */
378
430
        s->pol = (value >> 5) & 3;              /* ADCPOL */
379
431
        s->mute = (value >> 3) & 1;             /* DACMU */
380
 
        wm8750_mask_update(s);
 
432
        wm8750_vol_update(s);
381
433
        break;
382
434
 
383
435
    case WM8750_ADCTL3: /* Additional Control (3) */
385
437
 
386
438
    case WM8750_LADC:   /* Left ADC Digital Volume */
387
439
        s->invol[2] = value & 0xff;             /* LADCVOL */
 
440
        wm8750_vol_update(s);
388
441
        break;
389
442
 
390
443
    case WM8750_RADC:   /* Right ADC Digital Volume */
391
444
        s->invol[3] = value & 0xff;             /* RADCVOL */
 
445
        wm8750_vol_update(s);
392
446
        break;
393
447
 
394
448
    case WM8750_ALC1:   /* ALC Control (1) */
401
455
 
402
456
    case WM8750_LDAC:   /* Left Channel Digital Volume */
403
457
        s->outvol[0] = value & 0xff;            /* LDACVOL */
 
458
        wm8750_vol_update(s);
404
459
        break;
405
460
 
406
461
    case WM8750_RDAC:   /* Right Channel Digital Volume */
407
462
        s->outvol[1] = value & 0xff;            /* RDACVOL */
 
463
        wm8750_vol_update(s);
408
464
        break;
409
465
 
410
466
    case WM8750_BASS:   /* Bass Control */
412
468
 
413
469
    case WM8750_LOUTM1: /* Left Mixer Control (1) */
414
470
        s->path[0] = (value >> 8) & 1;          /* LD2LO */
 
471
        /* TODO: mute/unmute respective paths */
 
472
        wm8750_vol_update(s);
415
473
        break;
416
474
 
417
475
    case WM8750_LOUTM2: /* Left Mixer Control (2) */
418
476
        s->path[1] = (value >> 8) & 1;          /* RD2LO */
 
477
        /* TODO: mute/unmute respective paths */
 
478
        wm8750_vol_update(s);
419
479
        break;
420
480
 
421
481
    case WM8750_ROUTM1: /* Right Mixer Control (1) */
422
482
        s->path[2] = (value >> 8) & 1;          /* LD2RO */
 
483
        /* TODO: mute/unmute respective paths */
 
484
        wm8750_vol_update(s);
423
485
        break;
424
486
 
425
487
    case WM8750_ROUTM2: /* Right Mixer Control (2) */
426
488
        s->path[3] = (value >> 8) & 1;          /* RD2RO */
 
489
        /* TODO: mute/unmute respective paths */
 
490
        wm8750_vol_update(s);
427
491
        break;
428
492
 
429
493
    case WM8750_MOUTM1: /* Mono Mixer Control (1) */
430
494
        s->mpath[0] = (value >> 8) & 1;         /* LD2MO */
 
495
        /* TODO: mute/unmute respective paths */
 
496
        wm8750_vol_update(s);
431
497
        break;
432
498
 
433
499
    case WM8750_MOUTM2: /* Mono Mixer Control (2) */
434
500
        s->mpath[1] = (value >> 8) & 1;         /* RD2MO */
 
501
        /* TODO: mute/unmute respective paths */
 
502
        wm8750_vol_update(s);
435
503
        break;
436
504
 
437
505
    case WM8750_LOUT1V: /* LOUT1 Volume */
438
 
        s->outvol[2] = value & 0x7f;            /* LOUT2VOL */
 
506
        s->outvol[2] = value & 0x7f;            /* LOUT1VOL */
 
507
        wm8750_vol_update(s);
439
508
        break;
440
509
 
441
510
    case WM8750_LOUT2V: /* LOUT2 Volume */
442
511
        s->outvol[4] = value & 0x7f;            /* LOUT2VOL */
 
512
        wm8750_vol_update(s);
443
513
        break;
444
514
 
445
515
    case WM8750_ROUT1V: /* ROUT1 Volume */
446
 
        s->outvol[3] = value & 0x7f;            /* ROUT2VOL */
 
516
        s->outvol[3] = value & 0x7f;            /* ROUT1VOL */
 
517
        wm8750_vol_update(s);
447
518
        break;
448
519
 
449
520
    case WM8750_ROUT2V: /* ROUT2 Volume */
450
521
        s->outvol[5] = value & 0x7f;            /* ROUT2VOL */
 
522
        wm8750_vol_update(s);
451
523
        break;
452
524
 
453
525
    case WM8750_MOUTV:  /* MONOOUT Volume */
454
526
        s->outvol[6] = value & 0x7f;            /* MONOOUTVOL */
 
527
        wm8750_vol_update(s);
455
528
        break;
456
529
 
457
530
    case WM8750_ADCTL2: /* Additional Control (2) */
459
532
 
460
533
    case WM8750_PWR2:   /* Power Management (2) */
461
534
        s->power = value & 0x7e;
 
535
        /* TODO: mute/unmute respective paths */
 
536
        wm8750_vol_update(s);
462
537
        break;
463
538
 
464
539
    case WM8750_IFACE:  /* Digital Audio Interface Format */
465
 
#ifdef VERBOSE
466
 
        if (value & 0x40)                       /* MS */
467
 
            printf("%s: attempt to enable Master Mode\n", __FUNCTION__);
468
 
#endif
469
540
        s->format = value;
470
 
        wm8750_set_format(s);
 
541
        s->master = (value >> 6) & 1;                   /* MS */
 
542
        wm8750_clk_update(s, s->master);
471
543
        break;
472
544
 
473
545
    case WM8750_SRATE:  /* Clocking and Sample Rate Control */
474
546
        s->rate = &wm_rate_table[(value >> 1) & 0x1f];
475
 
        wm8750_set_format(s);
 
547
        wm8750_clk_update(s, 0);
476
548
        break;
477
549
 
478
550
    case WM8750_RESET:  /* Reset */
529
601
        qemu_put_8s(f, &s->mpath[i]);
530
602
    qemu_put_8s(f, &s->format);
531
603
    qemu_put_8s(f, &s->power);
532
 
    qemu_put_be32s(f, &s->inmask);
533
 
    qemu_put_be32s(f, &s->outmask);
534
604
    qemu_put_byte(f, (s->rate - wm_rate_table) / sizeof(*s->rate));
535
605
    i2c_slave_save(f, &s->i2c);
536
606
}
571
641
        qemu_get_8s(f, &s->mpath[i]);
572
642
    qemu_get_8s(f, &s->format);
573
643
    qemu_get_8s(f, &s->power);
574
 
    qemu_get_be32s(f, &s->inmask);
575
 
    qemu_get_be32s(f, &s->outmask);
576
644
    s->rate = &wm_rate_table[(uint8_t) qemu_get_byte(f) & 0x1f];
577
645
    i2c_slave_load(f, &s->i2c);
578
646
    return 0;
579
647
}
580
648
 
581
 
static int wm8750_iid = 0;
582
 
 
583
649
i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio)
584
650
{
585
651
    struct wm8750_s *s = (struct wm8750_s *)
591
657
    AUD_register_card(audio, CODEC, &s->card);
592
658
    wm8750_reset(&s->i2c);
593
659
 
594
 
    register_savevm(CODEC, wm8750_iid ++, 0, wm8750_save, wm8750_load, s);
 
660
    register_savevm(CODEC, -1, 0, wm8750_save, wm8750_load, s);
595
661
 
596
662
    return &s->i2c;
597
663
}
598
664
 
 
665
#if 0
599
666
static void wm8750_fini(i2c_slave *i2c)
600
667
{
601
668
    struct wm8750_s *s = (struct wm8750_s *) i2c;
603
670
    AUD_remove_card(&s->card);
604
671
    qemu_free(s);
605
672
}
 
673
#endif
606
674
 
607
675
void wm8750_data_req_set(i2c_slave *i2c,
608
676
                void (*data_req)(void *, int, int), void *opaque)
615
683
void wm8750_dac_dat(void *opaque, uint32_t sample)
616
684
{
617
685
    struct wm8750_s *s = (struct wm8750_s *) opaque;
618
 
    uint32_t *data = (uint32_t *) &s->data_out[s->idx_out];
619
 
    *data = sample & s->outmask;
 
686
 
 
687
    *(uint32_t *) &s->data_out[s->idx_out] = sample;
620
688
    s->req_out -= 4;
621
689
    s->idx_out += 4;
622
690
    if (s->idx_out >= sizeof(s->data_out) || s->req_out <= 0)
623
691
        wm8750_out_flush(s);
624
692
}
625
693
 
 
694
void *wm8750_dac_buffer(void *opaque, int samples)
 
695
{
 
696
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
697
    /* XXX: Should check if there are <i>samples</i> free samples available */
 
698
    void *ret = s->data_out + s->idx_out;
 
699
 
 
700
    s->idx_out += samples << 2;
 
701
    s->req_out -= samples << 2;
 
702
    return ret;
 
703
}
 
704
 
 
705
void wm8750_dac_commit(void *opaque)
 
706
{
 
707
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
708
 
 
709
    return wm8750_out_flush(s);
 
710
}
 
711
 
626
712
uint32_t wm8750_adc_dat(void *opaque)
627
713
{
628
714
    struct wm8750_s *s = (struct wm8750_s *) opaque;
629
715
    uint32_t *data;
 
716
 
630
717
    if (s->idx_in >= sizeof(s->data_in))
631
718
        wm8750_in_load(s);
 
719
 
632
720
    data = (uint32_t *) &s->data_in[s->idx_in];
633
721
    s->req_in -= 4;
634
722
    s->idx_in += 4;
635
 
    return *data & s->inmask;
 
723
    return *data;
 
724
}
 
725
 
 
726
void wm8750_set_bclk_in(void *opaque, int new_hz)
 
727
{
 
728
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
729
 
 
730
    s->ext_adc_hz = new_hz;
 
731
    s->ext_dac_hz = new_hz;
 
732
    wm8750_clk_update(s, 1);
636
733
}