Revision d8f699cb hw/tsc210x.c

b/hw/tsc210x.c
32 32
struct tsc210x_state_s {
33 33
    qemu_irq pint;
34 34
    QEMUTimer *timer;
35
    QEMUSoundCard card;
35 36
    struct uwire_slave_s chip;
37
    struct i2s_codec_s codec;
38
    uint8_t in_fifo[16384];
39
    uint8_t out_fifo[16384];
36 40

  
37 41
    int x, y;
38 42
    int pressure;
......
63 67
    uint16_t dac_power;
64 68
    int64_t powerdown;
65 69
    uint16_t filter_data[0x14];
70

  
71
    const char *name;
72
    SWVoiceIn *adc_voice[1];
73
    SWVoiceOut *dac_voice[1];
74
    int i2s_rx_rate;
75
    int i2s_tx_rate;
76
    AudioState *audio;
66 77
};
67 78

  
68 79
static const int resolution[4] = { 12, 8, 10, 12 };
......
171 182
    s->filter_data[0x12] = 0x7d83;
172 183
    s->filter_data[0x13] = 0x84ee;
173 184

  
185
    s->i2s_tx_rate = 0;
186
    s->i2s_rx_rate = 0;
187

  
174 188
    qemu_set_irq(s->pint, !s->irq);
175 189
}
176 190

  
191
struct tsc210x_rate_info_s {
192
    int rate;
193
    int dsor;
194
    int fsref;
195
};
196

  
197
/*  { rate,  dsor,  fsref } */
198
static const struct tsc210x_rate_info_s tsc2101_rates[] = {
199
    /* Fsref / 6.0 */
200
    { 7350,	7,	1 },
201
    { 8000,	7,	0 },
202
    /* Fsref / 5.5 */
203
    { 8018,	6,	1 },
204
    { 8727,	6,	0 },
205
    /* Fsref / 5.0 */
206
    { 8820,	5,	1 },
207
    { 9600,	5,	0 },
208
    /* Fsref / 4.0 */
209
    { 11025,	4,	1 },
210
    { 12000,	4,	0 },
211
    /* Fsref / 3.0 */
212
    { 14700,	3,	1 },
213
    { 16000,	3,	0 },
214
    /* Fsref / 2.0 */
215
    { 22050,	2,	1 },
216
    { 24000,	2,	0 },
217
    /* Fsref / 1.5 */
218
    { 29400,	1,	1 },
219
    { 32000,	1,	0 },
220
    /* Fsref */
221
    { 44100,	0,	1 },
222
    { 48000,	0,	0 },
223

  
224
    { 0,	0, 	0 },
225
};
226

  
227
/*  { rate,   dsor, fsref }	*/
228
static const struct tsc210x_rate_info_s tsc2102_rates[] = {
229
    /* Fsref / 6.0 */
230
    { 7350,	63,	1 },
231
    { 8000,	63,	0 },
232
    /* Fsref / 6.0 */
233
    { 7350,	54,	1 },
234
    { 8000,	54,	0 },
235
    /* Fsref / 5.0 */
236
    { 8820,	45,	1 },
237
    { 9600,	45,	0 },
238
    /* Fsref / 4.0 */
239
    { 11025,	36,	1 },
240
    { 12000,	36,	0 },
241
    /* Fsref / 3.0 */
242
    { 14700,	27,	1 },
243
    { 16000,	27,	0 },
244
    /* Fsref / 2.0 */
245
    { 22050,	18,	1 },
246
    { 24000,	18,	0 },
247
    /* Fsref / 1.5 */
248
    { 29400,	9,	1 },
249
    { 32000,	9,	0 },
250
    /* Fsref */
251
    { 44100,	0,	1 },
252
    { 48000,	0,	0 },
253

  
254
    { 0,	0, 	0 },
255
};
256

  
257
static inline void tsc210x_out_flush(struct tsc210x_state_s *s, int len)
258
{
259
    uint8_t *data = s->codec.out.fifo + s->codec.out.start;
260
    uint8_t *end = data + len;
261

  
262
    while (data < end)
263
        data += AUD_write(s->dac_voice[0], data, end - data) ?: (end - data);
264

  
265
    s->codec.out.len -= len;
266
    if (s->codec.out.len)
267
        memmove(s->codec.out.fifo, end, s->codec.out.len);
268
    s->codec.out.start = 0;
269
}
270

  
271
static void tsc210x_audio_out_cb(struct tsc210x_state_s *s, int free_b)
272
{
273
    if (s->codec.out.len >= free_b) {
274
        tsc210x_out_flush(s, free_b);
275
        return;
276
    }
277

  
278
    s->codec.out.size = MIN(free_b, 16384);
279
    qemu_irq_raise(s->codec.tx_start);
280
}
281

  
282
static void tsc2102_audio_set_format(struct tsc210x_state_s *s)
283
{
284
    int enable;
285
    const struct tsc210x_rate_info_s *rate;
286
    audsettings_t fmt;
287

  
288
    if (s->dac_voice[0]) {
289
        tsc210x_out_flush(s, s->codec.out.len);
290
        s->codec.out.size = 0;
291
        AUD_set_active_out(s->dac_voice[0], 0);
292
        AUD_close_out(&s->card, s->dac_voice[0]);
293
        s->dac_voice[0] = 0;
294
    }
295

  
296
    enable =
297
            (~s->dac_power & (1 << 15)) &&			/* PWDNC */
298
            (~s->dac_power & (1 << 10));			/* DAPWDN */
299
    if (!enable)
300
        return;
301

  
302
    for (rate = tsc2102_rates; rate->rate; rate ++)
303
        if (rate->dsor == (s->audio_ctrl1 & 0x3f) &&		/* DACFS */
304
                        rate->fsref == ((s->audio_ctrl3 >> 13) & 1))/* REFFS */
305
            break;
306
    if (!rate->rate) {
307
        printf("%s: unknown sampling rate configured\n", __FUNCTION__);
308
        return;
309
    }
310

  
311
    /* Force our own sampling rate even in slave DAC mode */
312
    fmt.endianness = 0;
313
    fmt.nchannels = 2;
314
    fmt.freq = rate->rate;
315
    fmt.fmt = AUD_FMT_S16;
316

  
317
    s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0],
318
                    "tsc2102.sink", s, (void *) tsc210x_audio_out_cb, &fmt);
319
    if (s->dac_voice[0])
320
        AUD_set_active_out(s->dac_voice[0], 1);
321
}
322

  
177 323
static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
178 324
{
179 325
    switch (reg) {
......
437 583
            fprintf(stderr, "tsc2102_audio_register_write: "
438 584
                            "wrong value written into Audio 1\n");
439 585
#endif
586
        if (s->audio)
587
            tsc2102_audio_set_format(s);
440 588
        return;
441 589

  
442 590
    case 0x01:
......
479 627
            fprintf(stderr, "tsc2102_audio_register_write: "
480 628
                            "wrong value written into Power\n");
481 629
#endif
630
        if (s->audio)
631
            tsc2102_audio_set_format(s);
482 632
        return;
483 633

  
484 634
    case 0x06:	/* Audio Control 3 */
......
489 639
            fprintf(stderr, "tsc2102_audio_register_write: "
490 640
                            "wrong value written into Audio 3\n");
491 641
#endif
642
        if (s->audio)
643
            tsc2102_audio_set_format(s);
492 644
        return;
493 645

  
494 646
    case 0x07:	/* LCH_BASS_BOOST_N0 */
......
718 870
        tsc210x_pin_update(s);
719 871
}
720 872

  
873
static void tsc210x_i2s_swallow(struct tsc210x_state_s *s)
874
{
875
    if (s->dac_voice[0])
876
        tsc210x_out_flush(s, s->codec.out.len);
877
    else
878
        s->codec.out.len = 0;
879
}
880

  
881
static void tsc210x_i2s_set_rate(struct tsc210x_state_s *s, int in, int out)
882
{
883
    s->i2s_tx_rate = out;
884
    s->i2s_rx_rate = in;
885
}
886

  
721 887
static void tsc210x_save(QEMUFile *f, void *opaque)
722 888
{
723 889
    struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
......
817 983

  
818 984
static int tsc2102_iid = 0;
819 985

  
820
struct uwire_slave_s *tsc2102_init(qemu_irq pint)
986
struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio)
821 987
{
822 988
    struct tsc210x_state_s *s;
823 989

  
......
830 996
    s->precision = s->nextprecision = 0;
831 997
    s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
832 998
    s->pint = pint;
999
    s->name = "tsc2102";
1000
    s->audio = audio;
833 1001

  
834 1002
    s->chip.opaque = s;
835 1003
    s->chip.send = (void *) tsc210x_write;
836 1004
    s->chip.receive = (void *) tsc210x_read;
837 1005

  
1006
    s->codec.opaque = s;
1007
    s->codec.tx_swallow = (void *) tsc210x_i2s_swallow;
1008
    s->codec.set_rate = (void *) tsc210x_i2s_set_rate;
1009
    s->codec.in.fifo = s->in_fifo;
1010
    s->codec.out.fifo = s->out_fifo;
1011

  
838 1012
    tsc210x_reset(s);
839 1013

  
840 1014
    qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
841 1015
                    "QEMU TSC2102-driven Touchscreen");
842 1016

  
1017
    if (s->audio)
1018
        AUD_register_card(s->audio, s->name, &s->card);
1019

  
843 1020
    qemu_register_reset((void *) tsc210x_reset, s);
844
    register_savevm("tsc2102", tsc2102_iid ++, 0,
1021
    register_savevm(s->name, tsc2102_iid ++, 0,
845 1022
                    tsc210x_save, tsc210x_load, s);
846 1023

  
847 1024
    return &s->chip;
848 1025
}
1026

  
1027
struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip)
1028
{
1029
    struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
1030

  
1031
    return &s->codec;
1032
}

Also available in: Unified diff