~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to hw/wm8750.c

  • Committer: Blue Swirl
  • Date: 2009-08-31 15:14:40 UTC
  • Revision ID: git-v1:528e93a9787ccfc59582a44035f5f342caf5b84f
Fix breakage due to __thread

Thread-local storage is not supported on all hosts.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
#define CODEC           "wm8750"
18
18
 
19
 
struct wm_rate_s;
20
 
struct wm8750_s {
 
19
typedef struct {
 
20
    int adc;
 
21
    int adc_hz;
 
22
    int dac;
 
23
    int dac_hz;
 
24
} WMRate;
 
25
 
 
26
typedef struct {
21
27
    i2c_slave i2c;
22
28
    uint8_t i2c_data[2];
23
29
    int i2c_len;
39
45
 
40
46
    uint8_t diff[2], pol, ds, monomix[2], alc, mute;
41
47
    uint8_t path[4], mpath[2], power, format;
42
 
    const struct wm_rate_s *rate;
 
48
    const WMRate *rate;
43
49
    int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master;
44
 
};
 
50
} WM8750State;
45
51
 
46
52
/* pow(10.0, -i / 20.0) * 255, i = 0..42 */
47
53
static const uint8_t wm8750_vol_db_table[] = {
53
59
#define WM8750_OUTVOL_TRANSFORM(x)      wm8750_vol_db_table[(0x7f - x) / 3]
54
60
#define WM8750_INVOL_TRANSFORM(x)       (x << 2)
55
61
 
56
 
static inline void wm8750_in_load(struct wm8750_s *s)
 
62
static inline void wm8750_in_load(WM8750State *s)
57
63
{
58
64
    int acquired;
59
65
    if (s->idx_in + s->req_in <= sizeof(s->data_in))
63
69
                    sizeof(s->data_in) - s->idx_in);
64
70
}
65
71
 
66
 
static inline void wm8750_out_flush(struct wm8750_s *s)
 
72
static inline void wm8750_out_flush(WM8750State *s)
67
73
{
68
74
    int sent = 0;
69
75
    while (sent < s->idx_out)
74
80
 
75
81
static void wm8750_audio_in_cb(void *opaque, int avail_b)
76
82
{
77
 
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
83
    WM8750State *s = (WM8750State *) opaque;
78
84
    s->req_in = avail_b;
79
85
    s->data_req(s->opaque, s->req_out >> 2, avail_b >> 2);
80
86
}
81
87
 
82
88
static void wm8750_audio_out_cb(void *opaque, int free_b)
83
89
{
84
 
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
90
    WM8750State *s = (WM8750State *) opaque;
85
91
 
86
92
    if (s->idx_out >= free_b) {
87
93
        s->idx_out = free_b;
93
99
    s->data_req(s->opaque, s->req_out >> 2, s->req_in >> 2);
94
100
}
95
101
 
96
 
struct wm_rate_s {
97
 
    int adc;
98
 
    int adc_hz;
99
 
    int dac;
100
 
    int dac_hz;
101
 
};
102
 
 
103
 
static const struct wm_rate_s wm_rate_table[] = {
 
102
static const WMRate wm_rate_table[] = {
104
103
    {  256, 48000,  256, 48000 },       /* SR: 00000 */
105
104
    {  384, 48000,  384, 48000 },       /* SR: 00001 */
106
105
    {  256, 48000, 1536,  8000 },       /* SR: 00010 */
135
134
    {  192, 88200,  192, 88200 },       /* SR: 11111 */
136
135
};
137
136
 
138
 
static void wm8750_vol_update(struct wm8750_s *s)
 
137
static void wm8750_vol_update(WM8750State *s)
139
138
{
140
139
    /* FIXME: multiply all volumes by s->invol[2], s->invol[3] */
141
140
 
167
166
                    s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6]));
168
167
}
169
168
 
170
 
static void wm8750_set_format(struct wm8750_s *s)
 
169
static void wm8750_set_format(WM8750State *s)
171
170
{
172
171
    int i;
173
 
    audsettings_t in_fmt;
174
 
    audsettings_t out_fmt;
175
 
    audsettings_t monoout_fmt;
 
172
    struct audsettings in_fmt;
 
173
    struct audsettings out_fmt;
 
174
    struct audsettings monoout_fmt;
176
175
 
177
176
    wm8750_out_flush(s);
178
177
 
184
183
    for (i = 0; i < IN_PORT_N; i ++)
185
184
        if (s->adc_voice[i]) {
186
185
            AUD_close_in(&s->card, s->adc_voice[i]);
187
 
            s->adc_voice[i] = 0;
 
186
            s->adc_voice[i] = NULL;
188
187
        }
189
188
    for (i = 0; i < OUT_PORT_N; i ++)
190
189
        if (s->dac_voice[i]) {
191
190
            AUD_close_out(&s->card, s->dac_voice[i]);
192
 
            s->dac_voice[i] = 0;
 
191
            s->dac_voice[i] = NULL;
193
192
        }
194
193
 
195
194
    if (!s->enable)
239
238
        AUD_set_active_out(*s->out[0], 1);
240
239
}
241
240
 
242
 
static void wm8750_clk_update(struct wm8750_s *s, int ext)
 
241
static void wm8750_clk_update(WM8750State *s, int ext)
243
242
{
244
243
    if (s->master || !s->ext_dac_hz)
245
244
        s->dac_hz = s->rate->dac_hz;
260
259
    }
261
260
}
262
261
 
263
 
void wm8750_reset(i2c_slave *i2c)
 
262
static void wm8750_reset(i2c_slave *i2c)
264
263
{
265
 
    struct wm8750_s *s = (struct wm8750_s *) i2c;
 
264
    WM8750State *s = (WM8750State *) i2c;
266
265
    s->rate = &wm_rate_table[0];
267
266
    s->enable = 0;
268
267
    wm8750_clk_update(s, 1);
305
304
 
306
305
static void wm8750_event(i2c_slave *i2c, enum i2c_event event)
307
306
{
308
 
    struct wm8750_s *s = (struct wm8750_s *) i2c;
 
307
    WM8750State *s = (WM8750State *) i2c;
309
308
 
310
309
    switch (event) {
311
310
    case I2C_START_SEND:
362
361
 
363
362
static int wm8750_tx(i2c_slave *i2c, uint8_t data)
364
363
{
365
 
    struct wm8750_s *s = (struct wm8750_s *) i2c;
 
364
    WM8750State *s = (WM8750State *) i2c;
366
365
    uint8_t cmd;
367
366
    uint16_t value;
368
367
 
567
566
 
568
567
static void wm8750_save(QEMUFile *f, void *opaque)
569
568
{
570
 
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
569
    WM8750State *s = (WM8750State *) opaque;
571
570
    int i;
572
571
    qemu_put_8s(f, &s->i2c_data[0]);
573
572
    qemu_put_8s(f, &s->i2c_data[1]);
607
606
 
608
607
static int wm8750_load(QEMUFile *f, void *opaque, int version_id)
609
608
{
610
 
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
609
    WM8750State *s = (WM8750State *) opaque;
611
610
    int i;
612
611
    qemu_get_8s(f, &s->i2c_data[0]);
613
612
    qemu_get_8s(f, &s->i2c_data[1]);
646
645
    return 0;
647
646
}
648
647
 
649
 
static int wm8750_iid = 0;
650
 
 
651
 
i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio)
 
648
static int wm8750_init(i2c_slave *i2c)
652
649
{
653
 
    struct wm8750_s *s = (struct wm8750_s *)
654
 
            i2c_slave_init(bus, 0, sizeof(struct wm8750_s));
655
 
    s->i2c.event = wm8750_event;
656
 
    s->i2c.recv = wm8750_rx;
657
 
    s->i2c.send = wm8750_tx;
 
650
    WM8750State *s = FROM_I2C_SLAVE(WM8750State, i2c);
658
651
 
659
 
    AUD_register_card(audio, CODEC, &s->card);
 
652
    AUD_register_card(CODEC, &s->card);
660
653
    wm8750_reset(&s->i2c);
661
654
 
662
 
    register_savevm(CODEC, wm8750_iid ++, 0, wm8750_save, wm8750_load, s);
663
 
 
664
 
    return &s->i2c;
 
655
    register_savevm(CODEC, -1, 0, wm8750_save, wm8750_load, s);
 
656
    return 0;
665
657
}
666
658
 
667
659
#if 0
668
660
static void wm8750_fini(i2c_slave *i2c)
669
661
{
670
 
    struct wm8750_s *s = (struct wm8750_s *) i2c;
 
662
    WM8750State *s = (WM8750State *) i2c;
671
663
    wm8750_reset(&s->i2c);
672
664
    AUD_remove_card(&s->card);
673
665
    qemu_free(s);
674
666
}
675
667
#endif
676
668
 
677
 
void wm8750_data_req_set(i2c_slave *i2c,
 
669
void wm8750_data_req_set(DeviceState *dev,
678
670
                void (*data_req)(void *, int, int), void *opaque)
679
671
{
680
 
    struct wm8750_s *s = (struct wm8750_s *) i2c;
 
672
    WM8750State *s = FROM_I2C_SLAVE(WM8750State, I2C_SLAVE_FROM_QDEV(dev));
681
673
    s->data_req = data_req;
682
674
    s->opaque = opaque;
683
675
}
684
676
 
685
677
void wm8750_dac_dat(void *opaque, uint32_t sample)
686
678
{
687
 
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
679
    WM8750State *s = (WM8750State *) opaque;
688
680
 
689
681
    *(uint32_t *) &s->data_out[s->idx_out] = sample;
690
682
    s->req_out -= 4;
695
687
 
696
688
void *wm8750_dac_buffer(void *opaque, int samples)
697
689
{
698
 
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
690
    WM8750State *s = (WM8750State *) opaque;
699
691
    /* XXX: Should check if there are <i>samples</i> free samples available */
700
692
    void *ret = s->data_out + s->idx_out;
701
693
 
706
698
 
707
699
void wm8750_dac_commit(void *opaque)
708
700
{
709
 
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
701
    WM8750State *s = (WM8750State *) opaque;
710
702
 
711
 
    return wm8750_out_flush(s);
 
703
    wm8750_out_flush(s);
712
704
}
713
705
 
714
706
uint32_t wm8750_adc_dat(void *opaque)
715
707
{
716
 
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
708
    WM8750State *s = (WM8750State *) opaque;
717
709
    uint32_t *data;
718
710
 
719
711
    if (s->idx_in >= sizeof(s->data_in))
725
717
    return *data;
726
718
}
727
719
 
728
 
void wm8750_set_bclk_in(void *opaque, int hz)
 
720
void wm8750_set_bclk_in(void *opaque, int new_hz)
729
721
{
730
 
    struct wm8750_s *s = (struct wm8750_s *) opaque;
 
722
    WM8750State *s = (WM8750State *) opaque;
731
723
 
732
 
    s->ext_adc_hz = hz;
733
 
    s->ext_dac_hz = hz;
 
724
    s->ext_adc_hz = new_hz;
 
725
    s->ext_dac_hz = new_hz;
734
726
    wm8750_clk_update(s, 1);
735
727
}
 
728
 
 
729
static I2CSlaveInfo wm8750_info = {
 
730
    .qdev.name = "wm8750",
 
731
    .qdev.size = sizeof(WM8750State),
 
732
    .init = wm8750_init,
 
733
    .event = wm8750_event,
 
734
    .recv = wm8750_rx,
 
735
    .send = wm8750_tx
 
736
};
 
737
 
 
738
static void wm8750_register_devices(void)
 
739
{
 
740
    i2c_register_slave(&wm8750_info);
 
741
}
 
742
 
 
743
device_init(wm8750_register_devices)