Statistics
| Branch: | Revision:

root / hw / wm8750.c @ ca87d03b

History | View | Annotate | Download (17.8 kB)

1 adb86c37 balrog
/*
2 adb86c37 balrog
 * WM8750 audio CODEC.
3 adb86c37 balrog
 *
4 adb86c37 balrog
 * Copyright (c) 2006 Openedhand Ltd.
5 adb86c37 balrog
 * Written by Andrzej Zaborowski <balrog@zabor.org>
6 adb86c37 balrog
 *
7 adb86c37 balrog
 * This file is licensed under GNU GPL.
8 adb86c37 balrog
 */
9 adb86c37 balrog
10 87ecb68b pbrook
#include "hw.h"
11 87ecb68b pbrook
#include "i2c.h"
12 87ecb68b pbrook
#include "audio/audio.h"
13 adb86c37 balrog
14 adb86c37 balrog
#define IN_PORT_N        3
15 adb86c37 balrog
#define OUT_PORT_N        3
16 adb86c37 balrog
17 adb86c37 balrog
#define CODEC                "wm8750"
18 adb86c37 balrog
19 adb86c37 balrog
struct wm_rate_s;
20 adb86c37 balrog
struct wm8750_s {
21 adb86c37 balrog
    i2c_slave i2c;
22 adb86c37 balrog
    uint8_t i2c_data[2];
23 adb86c37 balrog
    int i2c_len;
24 adb86c37 balrog
    QEMUSoundCard card;
25 adb86c37 balrog
    SWVoiceIn *adc_voice[IN_PORT_N];
26 adb86c37 balrog
    SWVoiceOut *dac_voice[OUT_PORT_N];
27 adb86c37 balrog
    int enable;
28 adb86c37 balrog
    void (*data_req)(void *, int, int);
29 adb86c37 balrog
    void *opaque;
30 adb86c37 balrog
    uint8_t data_in[4096];
31 adb86c37 balrog
    uint8_t data_out[4096];
32 adb86c37 balrog
    int idx_in, req_in;
33 adb86c37 balrog
    int idx_out, req_out;
34 adb86c37 balrog
35 adb86c37 balrog
    SWVoiceOut **out[2];
36 adb86c37 balrog
    uint8_t outvol[7], outmute[2];
37 adb86c37 balrog
    SWVoiceIn **in[2];
38 adb86c37 balrog
    uint8_t invol[4], inmute[2];
39 adb86c37 balrog
40 adb86c37 balrog
    uint8_t diff[2], pol, ds, monomix[2], alc, mute;
41 adb86c37 balrog
    uint8_t path[4], mpath[2], power, format;
42 adb86c37 balrog
    uint32_t inmask, outmask;
43 adb86c37 balrog
    const struct wm_rate_s *rate;
44 adb86c37 balrog
};
45 adb86c37 balrog
46 adb86c37 balrog
static inline void wm8750_in_load(struct wm8750_s *s)
47 adb86c37 balrog
{
48 adb86c37 balrog
    int acquired;
49 adb86c37 balrog
    if (s->idx_in + s->req_in <= sizeof(s->data_in))
50 adb86c37 balrog
        return;
51 adb86c37 balrog
    s->idx_in = audio_MAX(0, (int) sizeof(s->data_in) - s->req_in);
52 adb86c37 balrog
    acquired = AUD_read(*s->in[0], s->data_in + s->idx_in,
53 adb86c37 balrog
                    sizeof(s->data_in) - s->idx_in);
54 adb86c37 balrog
}
55 adb86c37 balrog
56 adb86c37 balrog
static inline void wm8750_out_flush(struct wm8750_s *s)
57 adb86c37 balrog
{
58 adb86c37 balrog
    int sent;
59 adb86c37 balrog
    if (!s->idx_out)
60 adb86c37 balrog
        return;
61 adb86c37 balrog
    sent = AUD_write(*s->out[0], s->data_out, s->idx_out);
62 adb86c37 balrog
    s->idx_out = 0;
63 adb86c37 balrog
}
64 adb86c37 balrog
65 adb86c37 balrog
static void wm8750_audio_in_cb(void *opaque, int avail_b)
66 adb86c37 balrog
{
67 adb86c37 balrog
    struct wm8750_s *s = (struct wm8750_s *) opaque;
68 adb86c37 balrog
    s->req_in = avail_b;
69 adb86c37 balrog
    s->data_req(s->opaque, s->req_out >> 2, avail_b >> 2);
70 adb86c37 balrog
71 adb86c37 balrog
#if 0
72 adb86c37 balrog
    wm8750_in_load(s);
73 adb86c37 balrog
#endif
74 adb86c37 balrog
}
75 adb86c37 balrog
76 adb86c37 balrog
static void wm8750_audio_out_cb(void *opaque, int free_b)
77 adb86c37 balrog
{
78 adb86c37 balrog
    struct wm8750_s *s = (struct wm8750_s *) opaque;
79 adb86c37 balrog
    wm8750_out_flush(s);
80 adb86c37 balrog
81 adb86c37 balrog
    s->req_out = free_b;
82 adb86c37 balrog
    s->data_req(s->opaque, free_b >> 2, s->req_in >> 2);
83 adb86c37 balrog
}
84 adb86c37 balrog
85 adb86c37 balrog
struct wm_rate_s {
86 adb86c37 balrog
    int adc;
87 adb86c37 balrog
    int adc_hz;
88 adb86c37 balrog
    int dac;
89 adb86c37 balrog
    int dac_hz;
90 adb86c37 balrog
};
91 adb86c37 balrog
92 adb86c37 balrog
static const struct wm_rate_s wm_rate_table[] = {
93 adb86c37 balrog
    {  256, 48000,  256, 48000 },        /* SR: 00000 */
94 adb86c37 balrog
    {  384, 48000,  384, 48000 },        /* SR: 00001 */
95 adb86c37 balrog
    {  256, 48000, 1536,  8000 },        /* SR: 00010 */
96 adb86c37 balrog
    {  384, 48000, 2304,  8000 },        /* SR: 00011 */
97 adb86c37 balrog
    { 1536,  8000,  256, 48000 },        /* SR: 00100 */
98 adb86c37 balrog
    { 2304,  8000,  384, 48000 },        /* SR: 00101 */
99 adb86c37 balrog
    { 1536,  8000, 1536,  8000 },        /* SR: 00110 */
100 adb86c37 balrog
    { 2304,  8000, 2304,  8000 },        /* SR: 00111 */
101 adb86c37 balrog
    { 1024, 12000, 1024, 12000 },        /* SR: 01000 */
102 adb86c37 balrog
    { 1526, 12000, 1536, 12000 },        /* SR: 01001 */
103 adb86c37 balrog
    {  768, 16000,  768, 16000 },        /* SR: 01010 */
104 adb86c37 balrog
    { 1152, 16000, 1152, 16000 },        /* SR: 01011 */
105 adb86c37 balrog
    {  384, 32000,  384, 32000 },        /* SR: 01100 */
106 adb86c37 balrog
    {  576, 32000,  576, 32000 },        /* SR: 01101 */
107 adb86c37 balrog
    {  128, 96000,  128, 96000 },        /* SR: 01110 */
108 adb86c37 balrog
    {  192, 96000,  192, 96000 },        /* SR: 01111 */
109 adb86c37 balrog
    {  256, 44100,  256, 44100 },        /* SR: 10000 */
110 adb86c37 balrog
    {  384, 44100,  384, 44100 },        /* SR: 10001 */
111 adb86c37 balrog
    {  256, 44100, 1408,  8018 },        /* SR: 10010 */
112 adb86c37 balrog
    {  384, 44100, 2112,  8018 },        /* SR: 10011 */
113 adb86c37 balrog
    { 1408,  8018,  256, 44100 },        /* SR: 10100 */
114 adb86c37 balrog
    { 2112,  8018,  384, 44100 },        /* SR: 10101 */
115 adb86c37 balrog
    { 1408,  8018, 1408,  8018 },        /* SR: 10110 */
116 adb86c37 balrog
    { 2112,  8018, 2112,  8018 },        /* SR: 10111 */
117 adb86c37 balrog
    { 1024, 11025, 1024, 11025 },        /* SR: 11000 */
118 adb86c37 balrog
    { 1536, 11025, 1536, 11025 },        /* SR: 11001 */
119 adb86c37 balrog
    {  512, 22050,  512, 22050 },        /* SR: 11010 */
120 adb86c37 balrog
    {  768, 22050,  768, 22050 },        /* SR: 11011 */
121 adb86c37 balrog
    {  512, 24000,  512, 24000 },        /* SR: 11100 */
122 adb86c37 balrog
    {  768, 24000,  768, 24000 },        /* SR: 11101 */
123 adb86c37 balrog
    {  128, 88200,  128, 88200 },        /* SR: 11110 */
124 adb86c37 balrog
    {  192, 88200,  128, 88200 },        /* SR: 11111 */
125 adb86c37 balrog
};
126 adb86c37 balrog
127 9596ebb7 pbrook
static void wm8750_set_format(struct wm8750_s *s)
128 adb86c37 balrog
{
129 adb86c37 balrog
    int i;
130 adb86c37 balrog
    audsettings_t in_fmt;
131 adb86c37 balrog
    audsettings_t out_fmt;
132 adb86c37 balrog
    audsettings_t monoout_fmt;
133 adb86c37 balrog
134 adb86c37 balrog
    wm8750_out_flush(s);
135 adb86c37 balrog
136 adb86c37 balrog
    if (s->in[0] && *s->in[0])
137 adb86c37 balrog
        AUD_set_active_in(*s->in[0], 0);
138 adb86c37 balrog
    if (s->out[0] && *s->out[0])
139 adb86c37 balrog
        AUD_set_active_out(*s->out[0], 0);
140 adb86c37 balrog
141 adb86c37 balrog
    for (i = 0; i < IN_PORT_N; i ++)
142 adb86c37 balrog
        if (s->adc_voice[i]) {
143 adb86c37 balrog
            AUD_close_in(&s->card, s->adc_voice[i]);
144 adb86c37 balrog
            s->adc_voice[i] = 0;
145 adb86c37 balrog
        }
146 adb86c37 balrog
    for (i = 0; i < OUT_PORT_N; i ++)
147 adb86c37 balrog
        if (s->dac_voice[i]) {
148 adb86c37 balrog
            AUD_close_out(&s->card, s->dac_voice[i]);
149 adb86c37 balrog
            s->dac_voice[i] = 0;
150 adb86c37 balrog
        }
151 adb86c37 balrog
152 adb86c37 balrog
    if (!s->enable)
153 adb86c37 balrog
        return;
154 adb86c37 balrog
155 adb86c37 balrog
    /* Setup input */
156 adb86c37 balrog
    in_fmt.endianness = 0;
157 adb86c37 balrog
    in_fmt.nchannels = 2;
158 adb86c37 balrog
    in_fmt.freq = s->rate->adc_hz;
159 adb86c37 balrog
    in_fmt.fmt = AUD_FMT_S16;
160 adb86c37 balrog
161 adb86c37 balrog
    s->adc_voice[0] = AUD_open_in(&s->card, s->adc_voice[0],
162 adb86c37 balrog
                    CODEC ".input1", s, wm8750_audio_in_cb, &in_fmt);
163 adb86c37 balrog
    s->adc_voice[1] = AUD_open_in(&s->card, s->adc_voice[1],
164 adb86c37 balrog
                    CODEC ".input2", s, wm8750_audio_in_cb, &in_fmt);
165 adb86c37 balrog
    s->adc_voice[2] = AUD_open_in(&s->card, s->adc_voice[2],
166 adb86c37 balrog
                    CODEC ".input3", s, wm8750_audio_in_cb, &in_fmt);
167 adb86c37 balrog
168 adb86c37 balrog
    /* Setup output */
169 adb86c37 balrog
    out_fmt.endianness = 0;
170 adb86c37 balrog
    out_fmt.nchannels = 2;
171 adb86c37 balrog
    out_fmt.freq = s->rate->dac_hz;
172 adb86c37 balrog
    out_fmt.fmt = AUD_FMT_S16;
173 adb86c37 balrog
    monoout_fmt.endianness = 0;
174 adb86c37 balrog
    monoout_fmt.nchannels = 1;
175 adb86c37 balrog
    monoout_fmt.freq = s->rate->dac_hz;
176 adb86c37 balrog
    monoout_fmt.fmt = AUD_FMT_S16;
177 adb86c37 balrog
178 adb86c37 balrog
    s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0],
179 adb86c37 balrog
                    CODEC ".speaker", s, wm8750_audio_out_cb, &out_fmt);
180 adb86c37 balrog
    s->dac_voice[1] = AUD_open_out(&s->card, s->dac_voice[1],
181 adb86c37 balrog
                    CODEC ".headphone", s, wm8750_audio_out_cb, &out_fmt);
182 adb86c37 balrog
    /* MONOMIX is also in stereo for simplicity */
183 adb86c37 balrog
    s->dac_voice[2] = AUD_open_out(&s->card, s->dac_voice[2],
184 adb86c37 balrog
                    CODEC ".monomix", s, wm8750_audio_out_cb, &out_fmt);
185 adb86c37 balrog
    /* no sense emulating OUT3 which is a mix of other outputs */
186 adb86c37 balrog
187 adb86c37 balrog
    /* We should connect the left and right channels to their
188 adb86c37 balrog
     * respective inputs/outputs but we have completely no need
189 adb86c37 balrog
     * for mixing or combining paths to different ports, so we
190 adb86c37 balrog
     * connect both channels to where the left channel is routed.  */
191 adb86c37 balrog
    if (s->in[0] && *s->in[0])
192 adb86c37 balrog
        AUD_set_active_in(*s->in[0], 1);
193 adb86c37 balrog
    if (s->out[0] && *s->out[0])
194 adb86c37 balrog
        AUD_set_active_out(*s->out[0], 1);
195 adb86c37 balrog
}
196 adb86c37 balrog
197 9596ebb7 pbrook
static void inline wm8750_mask_update(struct wm8750_s *s)
198 adb86c37 balrog
{
199 adb86c37 balrog
#define R_ONLY        0x0000ffff
200 adb86c37 balrog
#define L_ONLY        0xffff0000
201 adb86c37 balrog
#define BOTH        (R_ONLY | L_ONLY)
202 adb86c37 balrog
#define NONE        (R_ONLY & L_ONLY)
203 adb86c37 balrog
    s->inmask =
204 adb86c37 balrog
            (s->inmute[0] ? R_ONLY : BOTH) &
205 adb86c37 balrog
            (s->inmute[1] ? L_ONLY : BOTH) &
206 adb86c37 balrog
            (s->mute ? NONE : BOTH);
207 adb86c37 balrog
    s->outmask =
208 adb86c37 balrog
            (s->outmute[0] ? R_ONLY : BOTH) &
209 adb86c37 balrog
            (s->outmute[1] ? L_ONLY : BOTH) &
210 adb86c37 balrog
            (s->mute ? NONE : BOTH);
211 adb86c37 balrog
}
212 adb86c37 balrog
213 adb86c37 balrog
void wm8750_reset(i2c_slave *i2c)
214 adb86c37 balrog
{
215 adb86c37 balrog
    struct wm8750_s *s = (struct wm8750_s *) i2c;
216 adb86c37 balrog
    s->enable = 0;
217 adb86c37 balrog
    wm8750_set_format(s);
218 adb86c37 balrog
    s->diff[0] = 0;
219 adb86c37 balrog
    s->diff[1] = 0;
220 adb86c37 balrog
    s->ds = 0;
221 adb86c37 balrog
    s->alc = 0;
222 adb86c37 balrog
    s->in[0] = &s->adc_voice[0];
223 adb86c37 balrog
    s->invol[0] = 0x17;
224 adb86c37 balrog
    s->invol[1] = 0x17;
225 adb86c37 balrog
    s->invol[2] = 0xc3;
226 adb86c37 balrog
    s->invol[3] = 0xc3;
227 adb86c37 balrog
    s->out[0] = &s->dac_voice[0];
228 adb86c37 balrog
    s->outvol[0] = 0xff;
229 adb86c37 balrog
    s->outvol[1] = 0xff;
230 adb86c37 balrog
    s->outvol[2] = 0x79;
231 adb86c37 balrog
    s->outvol[3] = 0x79;
232 adb86c37 balrog
    s->outvol[4] = 0x79;
233 adb86c37 balrog
    s->outvol[5] = 0x79;
234 adb86c37 balrog
    s->inmute[0] = 0;
235 adb86c37 balrog
    s->inmute[1] = 0;
236 adb86c37 balrog
    s->outmute[0] = 0;
237 adb86c37 balrog
    s->outmute[1] = 0;
238 adb86c37 balrog
    s->mute = 1;
239 adb86c37 balrog
    s->path[0] = 0;
240 adb86c37 balrog
    s->path[1] = 0;
241 adb86c37 balrog
    s->path[2] = 0;
242 adb86c37 balrog
    s->path[3] = 0;
243 adb86c37 balrog
    s->mpath[0] = 0;
244 adb86c37 balrog
    s->mpath[1] = 0;
245 adb86c37 balrog
    s->format = 0x0a;
246 adb86c37 balrog
    s->idx_in = sizeof(s->data_in);
247 adb86c37 balrog
    s->req_in = 0;
248 adb86c37 balrog
    s->idx_out = 0;
249 adb86c37 balrog
    s->req_out = 0;
250 adb86c37 balrog
    wm8750_mask_update(s);
251 adb86c37 balrog
    s->i2c_len = 0;
252 adb86c37 balrog
}
253 adb86c37 balrog
254 adb86c37 balrog
static void wm8750_event(i2c_slave *i2c, enum i2c_event event)
255 adb86c37 balrog
{
256 adb86c37 balrog
    struct wm8750_s *s = (struct wm8750_s *) i2c;
257 adb86c37 balrog
258 adb86c37 balrog
    switch (event) {
259 adb86c37 balrog
    case I2C_START_SEND:
260 adb86c37 balrog
        s->i2c_len = 0;
261 adb86c37 balrog
        break;
262 adb86c37 balrog
    case I2C_FINISH:
263 adb86c37 balrog
#ifdef VERBOSE
264 adb86c37 balrog
        if (s->i2c_len < 2)
265 adb86c37 balrog
            printf("%s: message too short (%i bytes)\n",
266 adb86c37 balrog
                            __FUNCTION__, s->i2c_len);
267 adb86c37 balrog
#endif
268 adb86c37 balrog
        break;
269 adb86c37 balrog
    default:
270 adb86c37 balrog
        break;
271 adb86c37 balrog
    }
272 adb86c37 balrog
}
273 adb86c37 balrog
274 adb86c37 balrog
#define WM8750_LINVOL        0x00
275 adb86c37 balrog
#define WM8750_RINVOL        0x01
276 adb86c37 balrog
#define WM8750_LOUT1V        0x02
277 adb86c37 balrog
#define WM8750_ROUT1V        0x03
278 adb86c37 balrog
#define WM8750_ADCDAC        0x05
279 adb86c37 balrog
#define WM8750_IFACE        0x07
280 adb86c37 balrog
#define WM8750_SRATE        0x08
281 adb86c37 balrog
#define WM8750_LDAC        0x0a
282 adb86c37 balrog
#define WM8750_RDAC        0x0b
283 adb86c37 balrog
#define WM8750_BASS        0x0c
284 adb86c37 balrog
#define WM8750_TREBLE        0x0d
285 adb86c37 balrog
#define WM8750_RESET        0x0f
286 adb86c37 balrog
#define WM8750_3D        0x10
287 adb86c37 balrog
#define WM8750_ALC1        0x11
288 adb86c37 balrog
#define WM8750_ALC2        0x12
289 adb86c37 balrog
#define WM8750_ALC3        0x13
290 adb86c37 balrog
#define WM8750_NGATE        0x14
291 adb86c37 balrog
#define WM8750_LADC        0x15
292 adb86c37 balrog
#define WM8750_RADC        0x16
293 adb86c37 balrog
#define WM8750_ADCTL1        0x17
294 adb86c37 balrog
#define WM8750_ADCTL2        0x18
295 adb86c37 balrog
#define WM8750_PWR1        0x19
296 adb86c37 balrog
#define WM8750_PWR2        0x1a
297 adb86c37 balrog
#define WM8750_ADCTL3        0x1b
298 adb86c37 balrog
#define WM8750_ADCIN        0x1f
299 adb86c37 balrog
#define WM8750_LADCIN        0x20
300 adb86c37 balrog
#define WM8750_RADCIN        0x21
301 adb86c37 balrog
#define WM8750_LOUTM1        0x22
302 adb86c37 balrog
#define WM8750_LOUTM2        0x23
303 adb86c37 balrog
#define WM8750_ROUTM1        0x24
304 adb86c37 balrog
#define WM8750_ROUTM2        0x25
305 adb86c37 balrog
#define WM8750_MOUTM1        0x26
306 adb86c37 balrog
#define WM8750_MOUTM2        0x27
307 adb86c37 balrog
#define WM8750_LOUT2V        0x28
308 adb86c37 balrog
#define WM8750_ROUT2V        0x29
309 adb86c37 balrog
#define WM8750_MOUTV        0x2a
310 adb86c37 balrog
311 adb86c37 balrog
static int wm8750_tx(i2c_slave *i2c, uint8_t data)
312 adb86c37 balrog
{
313 adb86c37 balrog
    struct wm8750_s *s = (struct wm8750_s *) i2c;
314 adb86c37 balrog
    uint8_t cmd;
315 adb86c37 balrog
    uint16_t value;
316 adb86c37 balrog
317 adb86c37 balrog
    if (s->i2c_len >= 2) {
318 adb86c37 balrog
        printf("%s: long message (%i bytes)\n", __FUNCTION__, s->i2c_len);
319 adb86c37 balrog
#ifdef VERBOSE
320 adb86c37 balrog
        return 1;
321 adb86c37 balrog
#endif
322 adb86c37 balrog
    }
323 adb86c37 balrog
    s->i2c_data[s->i2c_len ++] = data;
324 adb86c37 balrog
    if (s->i2c_len != 2)
325 adb86c37 balrog
        return 0;
326 adb86c37 balrog
327 adb86c37 balrog
    cmd = s->i2c_data[0] >> 1;
328 adb86c37 balrog
    value = ((s->i2c_data[0] << 8) | s->i2c_data[1]) & 0x1ff;
329 adb86c37 balrog
330 adb86c37 balrog
    switch (cmd) {
331 adb86c37 balrog
    case WM8750_LADCIN:        /* ADC Signal Path Control (Left) */
332 adb86c37 balrog
        s->diff[0] = (((value >> 6) & 3) == 3);        /* LINSEL */
333 adb86c37 balrog
        if (s->diff[0])
334 adb86c37 balrog
            s->in[0] = &s->adc_voice[0 + s->ds * 1];
335 adb86c37 balrog
        else
336 adb86c37 balrog
            s->in[0] = &s->adc_voice[((value >> 6) & 3) * 1 + 0];
337 adb86c37 balrog
        break;
338 adb86c37 balrog
339 adb86c37 balrog
    case WM8750_RADCIN:        /* ADC Signal Path Control (Right) */
340 adb86c37 balrog
        s->diff[1] = (((value >> 6) & 3) == 3);        /* RINSEL */
341 adb86c37 balrog
        if (s->diff[1])
342 adb86c37 balrog
            s->in[1] = &s->adc_voice[0 + s->ds * 1];
343 adb86c37 balrog
        else
344 adb86c37 balrog
            s->in[1] = &s->adc_voice[((value >> 6) & 3) * 1 + 0];
345 adb86c37 balrog
        break;
346 adb86c37 balrog
347 adb86c37 balrog
    case WM8750_ADCIN:        /* ADC Input Mode */
348 adb86c37 balrog
        s->ds = (value >> 8) & 1;        /* DS */
349 adb86c37 balrog
        if (s->diff[0])
350 adb86c37 balrog
            s->in[0] = &s->adc_voice[0 + s->ds * 1];
351 adb86c37 balrog
        if (s->diff[1])
352 adb86c37 balrog
            s->in[1] = &s->adc_voice[0 + s->ds * 1];
353 adb86c37 balrog
        s->monomix[0] = (value >> 6) & 3;        /* MONOMIX */
354 adb86c37 balrog
        break;
355 adb86c37 balrog
356 adb86c37 balrog
    case WM8750_ADCTL1:        /* Additional Control (1) */
357 adb86c37 balrog
        s->monomix[1] = (value >> 1) & 1;        /* DMONOMIX */
358 adb86c37 balrog
        break;
359 adb86c37 balrog
360 adb86c37 balrog
    case WM8750_PWR1:        /* Power Management (1) */
361 adb86c37 balrog
        s->enable = ((value >> 6) & 7) == 3;        /* VMIDSEL, VREF */
362 adb86c37 balrog
        wm8750_set_format(s);
363 adb86c37 balrog
        break;
364 adb86c37 balrog
365 adb86c37 balrog
    case WM8750_LINVOL:        /* Left Channel PGA */
366 adb86c37 balrog
        s->invol[0] = value & 0x3f;                /* LINVOL */
367 adb86c37 balrog
        s->inmute[0] = (value >> 7) & 1;        /* LINMUTE */
368 adb86c37 balrog
        wm8750_mask_update(s);
369 adb86c37 balrog
        break;
370 adb86c37 balrog
371 adb86c37 balrog
    case WM8750_RINVOL:        /* Right Channel PGA */
372 adb86c37 balrog
        s->invol[1] = value & 0x3f;                /* RINVOL */
373 adb86c37 balrog
        s->inmute[1] = (value >> 7) & 1;        /* RINMUTE */
374 adb86c37 balrog
        wm8750_mask_update(s);
375 adb86c37 balrog
        break;
376 adb86c37 balrog
377 adb86c37 balrog
    case WM8750_ADCDAC:        /* ADC and DAC Control */
378 adb86c37 balrog
        s->pol = (value >> 5) & 3;                /* ADCPOL */
379 adb86c37 balrog
        s->mute = (value >> 3) & 1;                /* DACMU */
380 adb86c37 balrog
        wm8750_mask_update(s);
381 adb86c37 balrog
        break;
382 adb86c37 balrog
383 adb86c37 balrog
    case WM8750_ADCTL3:        /* Additional Control (3) */
384 adb86c37 balrog
        break;
385 adb86c37 balrog
386 adb86c37 balrog
    case WM8750_LADC:        /* Left ADC Digital Volume */
387 adb86c37 balrog
        s->invol[2] = value & 0xff;                /* LADCVOL */
388 adb86c37 balrog
        break;
389 adb86c37 balrog
390 adb86c37 balrog
    case WM8750_RADC:        /* Right ADC Digital Volume */
391 adb86c37 balrog
        s->invol[3] = value & 0xff;                /* RADCVOL */
392 adb86c37 balrog
        break;
393 adb86c37 balrog
394 adb86c37 balrog
    case WM8750_ALC1:        /* ALC Control (1) */
395 adb86c37 balrog
        s->alc = (value >> 7) & 3;                /* ALCSEL */
396 adb86c37 balrog
        break;
397 adb86c37 balrog
398 adb86c37 balrog
    case WM8750_NGATE:        /* Noise Gate Control */
399 adb86c37 balrog
    case WM8750_3D:        /* 3D enhance */
400 adb86c37 balrog
        break;
401 adb86c37 balrog
402 adb86c37 balrog
    case WM8750_LDAC:        /* Left Channel Digital Volume */
403 adb86c37 balrog
        s->outvol[0] = value & 0xff;                /* LDACVOL */
404 adb86c37 balrog
        break;
405 adb86c37 balrog
406 adb86c37 balrog
    case WM8750_RDAC:        /* Right Channel Digital Volume */
407 adb86c37 balrog
        s->outvol[1] = value & 0xff;                /* RDACVOL */
408 adb86c37 balrog
        break;
409 adb86c37 balrog
410 adb86c37 balrog
    case WM8750_BASS:        /* Bass Control */
411 adb86c37 balrog
        break;
412 adb86c37 balrog
413 adb86c37 balrog
    case WM8750_LOUTM1:        /* Left Mixer Control (1) */
414 adb86c37 balrog
        s->path[0] = (value >> 8) & 1;                /* LD2LO */
415 adb86c37 balrog
        break;
416 adb86c37 balrog
417 adb86c37 balrog
    case WM8750_LOUTM2:        /* Left Mixer Control (2) */
418 adb86c37 balrog
        s->path[1] = (value >> 8) & 1;                /* RD2LO */
419 adb86c37 balrog
        break;
420 adb86c37 balrog
421 adb86c37 balrog
    case WM8750_ROUTM1:        /* Right Mixer Control (1) */
422 adb86c37 balrog
        s->path[2] = (value >> 8) & 1;                /* LD2RO */
423 adb86c37 balrog
        break;
424 adb86c37 balrog
425 adb86c37 balrog
    case WM8750_ROUTM2:        /* Right Mixer Control (2) */
426 adb86c37 balrog
        s->path[3] = (value >> 8) & 1;                /* RD2RO */
427 adb86c37 balrog
        break;
428 adb86c37 balrog
429 adb86c37 balrog
    case WM8750_MOUTM1:        /* Mono Mixer Control (1) */
430 adb86c37 balrog
        s->mpath[0] = (value >> 8) & 1;                /* LD2MO */
431 adb86c37 balrog
        break;
432 adb86c37 balrog
433 adb86c37 balrog
    case WM8750_MOUTM2:        /* Mono Mixer Control (2) */
434 adb86c37 balrog
        s->mpath[1] = (value >> 8) & 1;                /* RD2MO */
435 adb86c37 balrog
        break;
436 adb86c37 balrog
437 adb86c37 balrog
    case WM8750_LOUT1V:        /* LOUT1 Volume */
438 adb86c37 balrog
        s->outvol[2] = value & 0x7f;                /* LOUT2VOL */
439 adb86c37 balrog
        break;
440 adb86c37 balrog
441 adb86c37 balrog
    case WM8750_LOUT2V:        /* LOUT2 Volume */
442 adb86c37 balrog
        s->outvol[4] = value & 0x7f;                /* LOUT2VOL */
443 adb86c37 balrog
        break;
444 adb86c37 balrog
445 adb86c37 balrog
    case WM8750_ROUT1V:        /* ROUT1 Volume */
446 adb86c37 balrog
        s->outvol[3] = value & 0x7f;                /* ROUT2VOL */
447 adb86c37 balrog
        break;
448 adb86c37 balrog
449 adb86c37 balrog
    case WM8750_ROUT2V:        /* ROUT2 Volume */
450 adb86c37 balrog
        s->outvol[5] = value & 0x7f;                /* ROUT2VOL */
451 adb86c37 balrog
        break;
452 adb86c37 balrog
453 adb86c37 balrog
    case WM8750_MOUTV:        /* MONOOUT Volume */
454 adb86c37 balrog
        s->outvol[6] = value & 0x7f;                /* MONOOUTVOL */
455 adb86c37 balrog
        break;
456 adb86c37 balrog
457 adb86c37 balrog
    case WM8750_ADCTL2:        /* Additional Control (2) */
458 adb86c37 balrog
        break;
459 adb86c37 balrog
460 adb86c37 balrog
    case WM8750_PWR2:        /* Power Management (2) */
461 adb86c37 balrog
        s->power = value & 0x7e;
462 adb86c37 balrog
        break;
463 adb86c37 balrog
464 adb86c37 balrog
    case WM8750_IFACE:        /* Digital Audio Interface Format */
465 adb86c37 balrog
#ifdef VERBOSE
466 adb86c37 balrog
        if (value & 0x40)                        /* MS */
467 adb86c37 balrog
            printf("%s: attempt to enable Master Mode\n", __FUNCTION__);
468 adb86c37 balrog
#endif
469 adb86c37 balrog
        s->format = value;
470 adb86c37 balrog
        wm8750_set_format(s);
471 adb86c37 balrog
        break;
472 adb86c37 balrog
473 adb86c37 balrog
    case WM8750_SRATE:        /* Clocking and Sample Rate Control */
474 adb86c37 balrog
        s->rate = &wm_rate_table[(value >> 1) & 0x1f];
475 adb86c37 balrog
        wm8750_set_format(s);
476 adb86c37 balrog
        break;
477 adb86c37 balrog
478 adb86c37 balrog
    case WM8750_RESET:        /* Reset */
479 adb86c37 balrog
        wm8750_reset(&s->i2c);
480 adb86c37 balrog
        break;
481 adb86c37 balrog
482 adb86c37 balrog
#ifdef VERBOSE
483 adb86c37 balrog
    default:
484 adb86c37 balrog
        printf("%s: unknown register %02x\n", __FUNCTION__, cmd);
485 adb86c37 balrog
#endif
486 adb86c37 balrog
    }
487 adb86c37 balrog
488 adb86c37 balrog
    return 0;
489 adb86c37 balrog
}
490 adb86c37 balrog
491 adb86c37 balrog
static int wm8750_rx(i2c_slave *i2c)
492 adb86c37 balrog
{
493 adb86c37 balrog
    return 0x00;
494 adb86c37 balrog
}
495 adb86c37 balrog
496 aa941b94 balrog
static void wm8750_save(QEMUFile *f, void *opaque)
497 aa941b94 balrog
{
498 aa941b94 balrog
    struct wm8750_s *s = (struct wm8750_s *) opaque;
499 aa941b94 balrog
    int i;
500 aa941b94 balrog
    qemu_put_8s(f, &s->i2c_data[0]);
501 aa941b94 balrog
    qemu_put_8s(f, &s->i2c_data[1]);
502 aa941b94 balrog
    qemu_put_be32(f, s->i2c_len);
503 aa941b94 balrog
    qemu_put_be32(f, s->enable);
504 aa941b94 balrog
    qemu_put_be32(f, s->idx_in);
505 aa941b94 balrog
    qemu_put_be32(f, s->req_in);
506 aa941b94 balrog
    qemu_put_be32(f, s->idx_out);
507 aa941b94 balrog
    qemu_put_be32(f, s->req_out);
508 aa941b94 balrog
509 aa941b94 balrog
    for (i = 0; i < 7; i ++)
510 aa941b94 balrog
        qemu_put_8s(f, &s->outvol[i]);
511 aa941b94 balrog
    for (i = 0; i < 2; i ++)
512 aa941b94 balrog
        qemu_put_8s(f, &s->outmute[i]);
513 aa941b94 balrog
    for (i = 0; i < 4; i ++)
514 aa941b94 balrog
        qemu_put_8s(f, &s->invol[i]);
515 aa941b94 balrog
    for (i = 0; i < 2; i ++)
516 aa941b94 balrog
        qemu_put_8s(f, &s->inmute[i]);
517 aa941b94 balrog
518 aa941b94 balrog
    for (i = 0; i < 2; i ++)
519 aa941b94 balrog
        qemu_put_8s(f, &s->diff[i]);
520 aa941b94 balrog
    qemu_put_8s(f, &s->pol);
521 aa941b94 balrog
    qemu_put_8s(f, &s->ds);
522 aa941b94 balrog
    for (i = 0; i < 2; i ++)
523 aa941b94 balrog
        qemu_put_8s(f, &s->monomix[i]);
524 aa941b94 balrog
    qemu_put_8s(f, &s->alc);
525 aa941b94 balrog
    qemu_put_8s(f, &s->mute);
526 aa941b94 balrog
    for (i = 0; i < 4; i ++)
527 aa941b94 balrog
        qemu_put_8s(f, &s->path[i]);
528 aa941b94 balrog
    for (i = 0; i < 2; i ++)
529 aa941b94 balrog
        qemu_put_8s(f, &s->mpath[i]);
530 aa941b94 balrog
    qemu_put_8s(f, &s->format);
531 aa941b94 balrog
    qemu_put_8s(f, &s->power);
532 aa941b94 balrog
    qemu_put_be32s(f, &s->inmask);
533 aa941b94 balrog
    qemu_put_be32s(f, &s->outmask);
534 aa941b94 balrog
    qemu_put_byte(f, (s->rate - wm_rate_table) / sizeof(*s->rate));
535 aa941b94 balrog
    i2c_slave_save(f, &s->i2c);
536 aa941b94 balrog
}
537 aa941b94 balrog
538 aa941b94 balrog
static int wm8750_load(QEMUFile *f, void *opaque, int version_id)
539 aa941b94 balrog
{
540 aa941b94 balrog
    struct wm8750_s *s = (struct wm8750_s *) opaque;
541 aa941b94 balrog
    int i;
542 aa941b94 balrog
    qemu_get_8s(f, &s->i2c_data[0]);
543 aa941b94 balrog
    qemu_get_8s(f, &s->i2c_data[1]);
544 aa941b94 balrog
    s->i2c_len = qemu_get_be32(f);
545 aa941b94 balrog
    s->enable = qemu_get_be32(f);
546 aa941b94 balrog
    s->idx_in = qemu_get_be32(f);
547 aa941b94 balrog
    s->req_in = qemu_get_be32(f);
548 aa941b94 balrog
    s->idx_out = qemu_get_be32(f);
549 aa941b94 balrog
    s->req_out = qemu_get_be32(f);
550 aa941b94 balrog
551 aa941b94 balrog
    for (i = 0; i < 7; i ++)
552 aa941b94 balrog
        qemu_get_8s(f, &s->outvol[i]);
553 aa941b94 balrog
    for (i = 0; i < 2; i ++)
554 aa941b94 balrog
        qemu_get_8s(f, &s->outmute[i]);
555 aa941b94 balrog
    for (i = 0; i < 4; i ++)
556 aa941b94 balrog
        qemu_get_8s(f, &s->invol[i]);
557 aa941b94 balrog
    for (i = 0; i < 2; i ++)
558 aa941b94 balrog
        qemu_get_8s(f, &s->inmute[i]);
559 aa941b94 balrog
560 aa941b94 balrog
    for (i = 0; i < 2; i ++)
561 aa941b94 balrog
        qemu_get_8s(f, &s->diff[i]);
562 aa941b94 balrog
    qemu_get_8s(f, &s->pol);
563 aa941b94 balrog
    qemu_get_8s(f, &s->ds);
564 aa941b94 balrog
    for (i = 0; i < 2; i ++)
565 aa941b94 balrog
        qemu_get_8s(f, &s->monomix[i]);
566 aa941b94 balrog
    qemu_get_8s(f, &s->alc);
567 aa941b94 balrog
    qemu_get_8s(f, &s->mute);
568 aa941b94 balrog
    for (i = 0; i < 4; i ++)
569 aa941b94 balrog
        qemu_get_8s(f, &s->path[i]);
570 aa941b94 balrog
    for (i = 0; i < 2; i ++)
571 aa941b94 balrog
        qemu_get_8s(f, &s->mpath[i]);
572 aa941b94 balrog
    qemu_get_8s(f, &s->format);
573 aa941b94 balrog
    qemu_get_8s(f, &s->power);
574 aa941b94 balrog
    qemu_get_be32s(f, &s->inmask);
575 aa941b94 balrog
    qemu_get_be32s(f, &s->outmask);
576 aa941b94 balrog
    s->rate = &wm_rate_table[(uint8_t) qemu_get_byte(f) & 0x1f];
577 aa941b94 balrog
    i2c_slave_load(f, &s->i2c);
578 aa941b94 balrog
    return 0;
579 aa941b94 balrog
}
580 aa941b94 balrog
581 aa941b94 balrog
static int wm8750_iid = 0;
582 aa941b94 balrog
583 adb86c37 balrog
i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio)
584 adb86c37 balrog
{
585 adb86c37 balrog
    struct wm8750_s *s = (struct wm8750_s *)
586 adb86c37 balrog
            i2c_slave_init(bus, 0, sizeof(struct wm8750_s));
587 adb86c37 balrog
    s->i2c.event = wm8750_event;
588 adb86c37 balrog
    s->i2c.recv = wm8750_rx;
589 adb86c37 balrog
    s->i2c.send = wm8750_tx;
590 adb86c37 balrog
591 adb86c37 balrog
    AUD_register_card(audio, CODEC, &s->card);
592 adb86c37 balrog
    wm8750_reset(&s->i2c);
593 adb86c37 balrog
594 aa941b94 balrog
    register_savevm(CODEC, wm8750_iid ++, 0, wm8750_save, wm8750_load, s);
595 aa941b94 balrog
596 adb86c37 balrog
    return &s->i2c;
597 adb86c37 balrog
}
598 adb86c37 balrog
599 9596ebb7 pbrook
static void wm8750_fini(i2c_slave *i2c)
600 adb86c37 balrog
{
601 adb86c37 balrog
    struct wm8750_s *s = (struct wm8750_s *) i2c;
602 adb86c37 balrog
    wm8750_reset(&s->i2c);
603 adb86c37 balrog
    AUD_remove_card(&s->card);
604 adb86c37 balrog
    qemu_free(s);
605 adb86c37 balrog
}
606 adb86c37 balrog
607 adb86c37 balrog
void wm8750_data_req_set(i2c_slave *i2c,
608 adb86c37 balrog
                void (*data_req)(void *, int, int), void *opaque)
609 adb86c37 balrog
{
610 adb86c37 balrog
    struct wm8750_s *s = (struct wm8750_s *) i2c;
611 adb86c37 balrog
    s->data_req = data_req;
612 adb86c37 balrog
    s->opaque = opaque;
613 adb86c37 balrog
}
614 adb86c37 balrog
615 adb86c37 balrog
void wm8750_dac_dat(void *opaque, uint32_t sample)
616 adb86c37 balrog
{
617 adb86c37 balrog
    struct wm8750_s *s = (struct wm8750_s *) opaque;
618 adb86c37 balrog
    uint32_t *data = (uint32_t *) &s->data_out[s->idx_out];
619 adb86c37 balrog
    *data = sample & s->outmask;
620 adb86c37 balrog
    s->req_out -= 4;
621 adb86c37 balrog
    s->idx_out += 4;
622 adb86c37 balrog
    if (s->idx_out >= sizeof(s->data_out) || s->req_out <= 0)
623 adb86c37 balrog
        wm8750_out_flush(s);
624 adb86c37 balrog
}
625 adb86c37 balrog
626 adb86c37 balrog
uint32_t wm8750_adc_dat(void *opaque)
627 adb86c37 balrog
{
628 adb86c37 balrog
    struct wm8750_s *s = (struct wm8750_s *) opaque;
629 adb86c37 balrog
    uint32_t *data;
630 adb86c37 balrog
    if (s->idx_in >= sizeof(s->data_in))
631 adb86c37 balrog
        wm8750_in_load(s);
632 adb86c37 balrog
    data = (uint32_t *) &s->data_in[s->idx_in];
633 adb86c37 balrog
    s->req_in -= 4;
634 adb86c37 balrog
    s->idx_in += 4;
635 adb86c37 balrog
    return *data & s->inmask;
636 adb86c37 balrog
}