~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

Viewing changes to .pc/1.6.1.patch/hw/audio/adlib.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-10-22 22:47:07 UTC
  • mfrom: (1.8.3) (10.1.42 sid)
  • Revision ID: package-import@ubuntu.com-20131022224707-1lya34fw3k3f24tv
Tags: 1.6.0+dfsg-2ubuntu1
* Merge 1.6.0~rc0+dfsg-2exp from debian experimental.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
      - drop openbios-ppc and openhackware Depends to Suggests (for now)
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - New linaro patches from qemu-linaro rebasing branch
  - Dropped patches:
    * xen-simplify-xen_enabled.patch
    * sparc-linux-user-fix-missing-symbols-in-.rel-.rela.plt-sections.patch
    * main_loop-do-not-set-nonblocking-if-xen_enabled.patch
    * xen_machine_pv-do-not-create-a-dummy-CPU-in-machine-.patch
    * virtio-rng-fix-crash
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * linaro arm patches from qemu-linaro rebasing branch
  - New patches:
    * fix-pci-add: change CONFIG variable in ifdef to make sure that
      pci_add is defined.
* Add linaro patches
* Add experimental mach-virt patches for arm virtualization.
* qemu-system-common.install: add debian/tmp/usr/lib to install the
  qemu-bridge-helper

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * QEMU Proxy for OPL2/3 emulation by MAME team
 
3
 *
 
4
 * Copyright (c) 2004-2005 Vassili Karpov (malc)
 
5
 *
 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 
7
 * of this software and associated documentation files (the "Software"), to deal
 
8
 * in the Software without restriction, including without limitation the rights
 
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
10
 * copies of the Software, and to permit persons to whom the Software is
 
11
 * furnished to do so, subject to the following conditions:
 
12
 *
 
13
 * The above copyright notice and this permission notice shall be included in
 
14
 * all copies or substantial portions of the Software.
 
15
 *
 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
22
 * THE SOFTWARE.
 
23
 */
 
24
 
 
25
#include "hw/hw.h"
 
26
#include "hw/audio/audio.h"
 
27
#include "audio/audio.h"
 
28
#include "hw/isa/isa.h"
 
29
 
 
30
//#define DEBUG
 
31
 
 
32
#define ADLIB_KILL_TIMERS 1
 
33
 
 
34
#ifdef HAS_YMF262
 
35
#define ADLIB_DESC "Yamaha YMF262 (OPL3)"
 
36
#else
 
37
#define ADLIB_DESC "Yamaha YM3812 (OPL2)"
 
38
#endif
 
39
 
 
40
#ifdef DEBUG
 
41
#include "qemu/timer.h"
 
42
#endif
 
43
 
 
44
#define dolog(...) AUD_log ("adlib", __VA_ARGS__)
 
45
#ifdef DEBUG
 
46
#define ldebug(...) dolog (__VA_ARGS__)
 
47
#else
 
48
#define ldebug(...)
 
49
#endif
 
50
 
 
51
#ifdef HAS_YMF262
 
52
#include "ymf262.h"
 
53
void YMF262UpdateOneQEMU (int which, INT16 *dst, int length);
 
54
#define SHIFT 2
 
55
#else
 
56
#include "fmopl.h"
 
57
#define SHIFT 1
 
58
#endif
 
59
 
 
60
#define IO_READ_PROTO(name) \
 
61
    uint32_t name (void *opaque, uint32_t nport)
 
62
#define IO_WRITE_PROTO(name) \
 
63
    void name (void *opaque, uint32_t nport, uint32_t val)
 
64
 
 
65
#define TYPE_ADLIB "adlib"
 
66
#define ADLIB(obj) OBJECT_CHECK(AdlibState, (obj), TYPE_ADLIB)
 
67
 
 
68
typedef struct {
 
69
    ISADevice parent_obj;
 
70
 
 
71
    QEMUSoundCard card;
 
72
    uint32_t freq;
 
73
    uint32_t port;
 
74
    int ticking[2];
 
75
    int enabled;
 
76
    int active;
 
77
    int bufpos;
 
78
#ifdef DEBUG
 
79
    int64_t exp[2];
 
80
#endif
 
81
    int16_t *mixbuf;
 
82
    uint64_t dexp[2];
 
83
    SWVoiceOut *voice;
 
84
    int left, pos, samples;
 
85
    QEMUAudioTimeStamp ats;
 
86
#ifndef HAS_YMF262
 
87
    FM_OPL *opl;
 
88
#endif
 
89
} AdlibState;
 
90
 
 
91
static AdlibState *glob_adlib;
 
92
 
 
93
static void adlib_stop_opl_timer (AdlibState *s, size_t n)
 
94
{
 
95
#ifdef HAS_YMF262
 
96
    YMF262TimerOver (0, n);
 
97
#else
 
98
    OPLTimerOver (s->opl, n);
 
99
#endif
 
100
    s->ticking[n] = 0;
 
101
}
 
102
 
 
103
static void adlib_kill_timers (AdlibState *s)
 
104
{
 
105
    size_t i;
 
106
 
 
107
    for (i = 0; i < 2; ++i) {
 
108
        if (s->ticking[i]) {
 
109
            uint64_t delta;
 
110
 
 
111
            delta = AUD_get_elapsed_usec_out (s->voice, &s->ats);
 
112
            ldebug (
 
113
                "delta = %f dexp = %f expired => %d\n",
 
114
                delta / 1000000.0,
 
115
                s->dexp[i] / 1000000.0,
 
116
                delta >= s->dexp[i]
 
117
                );
 
118
            if (ADLIB_KILL_TIMERS || delta >= s->dexp[i]) {
 
119
                adlib_stop_opl_timer (s, i);
 
120
                AUD_init_time_stamp_out (s->voice, &s->ats);
 
121
            }
 
122
        }
 
123
    }
 
124
}
 
125
 
 
126
static IO_WRITE_PROTO (adlib_write)
 
127
{
 
128
    AdlibState *s = opaque;
 
129
    int a = nport & 3;
 
130
 
 
131
    s->active = 1;
 
132
    AUD_set_active_out (s->voice, 1);
 
133
 
 
134
    adlib_kill_timers (s);
 
135
 
 
136
#ifdef HAS_YMF262
 
137
    YMF262Write (0, a, val);
 
138
#else
 
139
    OPLWrite (s->opl, a, val);
 
140
#endif
 
141
}
 
142
 
 
143
static IO_READ_PROTO (adlib_read)
 
144
{
 
145
    AdlibState *s = opaque;
 
146
    uint8_t data;
 
147
    int a = nport & 3;
 
148
 
 
149
    adlib_kill_timers (s);
 
150
 
 
151
#ifdef HAS_YMF262
 
152
    data = YMF262Read (0, a);
 
153
#else
 
154
    data = OPLRead (s->opl, a);
 
155
#endif
 
156
    return data;
 
157
}
 
158
 
 
159
static void timer_handler (int c, double interval_Sec)
 
160
{
 
161
    AdlibState *s = glob_adlib;
 
162
    unsigned n = c & 1;
 
163
#ifdef DEBUG
 
164
    double interval;
 
165
    int64_t exp;
 
166
#endif
 
167
 
 
168
    if (interval_Sec == 0.0) {
 
169
        s->ticking[n] = 0;
 
170
        return;
 
171
    }
 
172
 
 
173
    s->ticking[n] = 1;
 
174
#ifdef DEBUG
 
175
    interval = get_ticks_per_sec () * interval_Sec;
 
176
    exp = qemu_get_clock_ns (vm_clock) + interval;
 
177
    s->exp[n] = exp;
 
178
#endif
 
179
 
 
180
    s->dexp[n] = interval_Sec * 1000000.0;
 
181
    AUD_init_time_stamp_out (s->voice, &s->ats);
 
182
}
 
183
 
 
184
static int write_audio (AdlibState *s, int samples)
 
185
{
 
186
    int net = 0;
 
187
    int pos = s->pos;
 
188
 
 
189
    while (samples) {
 
190
        int nbytes, wbytes, wsampl;
 
191
 
 
192
        nbytes = samples << SHIFT;
 
193
        wbytes = AUD_write (
 
194
            s->voice,
 
195
            s->mixbuf + (pos << (SHIFT - 1)),
 
196
            nbytes
 
197
            );
 
198
 
 
199
        if (wbytes) {
 
200
            wsampl = wbytes >> SHIFT;
 
201
 
 
202
            samples -= wsampl;
 
203
            pos = (pos + wsampl) % s->samples;
 
204
 
 
205
            net += wsampl;
 
206
        }
 
207
        else {
 
208
            break;
 
209
        }
 
210
    }
 
211
 
 
212
    return net;
 
213
}
 
214
 
 
215
static void adlib_callback (void *opaque, int free)
 
216
{
 
217
    AdlibState *s = opaque;
 
218
    int samples, net = 0, to_play, written;
 
219
 
 
220
    samples = free >> SHIFT;
 
221
    if (!(s->active && s->enabled) || !samples) {
 
222
        return;
 
223
    }
 
224
 
 
225
    to_play = audio_MIN (s->left, samples);
 
226
    while (to_play) {
 
227
        written = write_audio (s, to_play);
 
228
 
 
229
        if (written) {
 
230
            s->left -= written;
 
231
            samples -= written;
 
232
            to_play -= written;
 
233
            s->pos = (s->pos + written) % s->samples;
 
234
        }
 
235
        else {
 
236
            return;
 
237
        }
 
238
    }
 
239
 
 
240
    samples = audio_MIN (samples, s->samples - s->pos);
 
241
    if (!samples) {
 
242
        return;
 
243
    }
 
244
 
 
245
#ifdef HAS_YMF262
 
246
    YMF262UpdateOneQEMU (0, s->mixbuf + s->pos * 2, samples);
 
247
#else
 
248
    YM3812UpdateOne (s->opl, s->mixbuf + s->pos, samples);
 
249
#endif
 
250
 
 
251
    while (samples) {
 
252
        written = write_audio (s, samples);
 
253
 
 
254
        if (written) {
 
255
            net += written;
 
256
            samples -= written;
 
257
            s->pos = (s->pos + written) % s->samples;
 
258
        }
 
259
        else {
 
260
            s->left = samples;
 
261
            return;
 
262
        }
 
263
    }
 
264
}
 
265
 
 
266
static void Adlib_fini (AdlibState *s)
 
267
{
 
268
#ifdef HAS_YMF262
 
269
    YMF262Shutdown ();
 
270
#else
 
271
    if (s->opl) {
 
272
        OPLDestroy (s->opl);
 
273
        s->opl = NULL;
 
274
    }
 
275
#endif
 
276
 
 
277
    if (s->mixbuf) {
 
278
        g_free (s->mixbuf);
 
279
    }
 
280
 
 
281
    s->active = 0;
 
282
    s->enabled = 0;
 
283
    AUD_remove_card (&s->card);
 
284
}
 
285
 
 
286
static MemoryRegionPortio adlib_portio_list[] = {
 
287
    { 0x388, 4, 1, .read = adlib_read, .write = adlib_write, },
 
288
    { 0, 4, 1, .read = adlib_read, .write = adlib_write, },
 
289
    { 0, 2, 1, .read = adlib_read, .write = adlib_write, },
 
290
    PORTIO_END_OF_LIST(),
 
291
};
 
292
 
 
293
static void adlib_realizefn (DeviceState *dev, Error **errp)
 
294
{
 
295
    AdlibState *s = ADLIB(dev);
 
296
    PortioList *port_list = g_new(PortioList, 1);
 
297
    struct audsettings as;
 
298
 
 
299
    if (glob_adlib) {
 
300
        error_setg (errp, "Cannot create more than 1 adlib device");
 
301
        return;
 
302
    }
 
303
    glob_adlib = s;
 
304
 
 
305
#ifdef HAS_YMF262
 
306
    if (YMF262Init (1, 14318180, s->freq)) {
 
307
        error_setg (errp, "YMF262Init %d failed", s->freq);
 
308
        return;
 
309
    }
 
310
    else {
 
311
        YMF262SetTimerHandler (0, timer_handler, 0);
 
312
        s->enabled = 1;
 
313
    }
 
314
#else
 
315
    s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, s->freq);
 
316
    if (!s->opl) {
 
317
        error_setg (errp, "OPLCreate %d failed", s->freq);
 
318
        return;
 
319
    }
 
320
    else {
 
321
        OPLSetTimerHandler (s->opl, timer_handler, 0);
 
322
        s->enabled = 1;
 
323
    }
 
324
#endif
 
325
 
 
326
    as.freq = s->freq;
 
327
    as.nchannels = SHIFT;
 
328
    as.fmt = AUD_FMT_S16;
 
329
    as.endianness = AUDIO_HOST_ENDIANNESS;
 
330
 
 
331
    AUD_register_card ("adlib", &s->card);
 
332
 
 
333
    s->voice = AUD_open_out (
 
334
        &s->card,
 
335
        s->voice,
 
336
        "adlib",
 
337
        s,
 
338
        adlib_callback,
 
339
        &as
 
340
        );
 
341
    if (!s->voice) {
 
342
        Adlib_fini (s);
 
343
        error_setg (errp, "Initializing audio voice failed");
 
344
        return;
 
345
    }
 
346
 
 
347
    s->samples = AUD_get_buffer_size_out (s->voice) >> SHIFT;
 
348
    s->mixbuf = g_malloc0 (s->samples << SHIFT);
 
349
 
 
350
    adlib_portio_list[1].offset = s->port;
 
351
    adlib_portio_list[2].offset = s->port + 8;
 
352
    portio_list_init (port_list, OBJECT(s), adlib_portio_list, s, "adlib");
 
353
    portio_list_add (port_list, isa_address_space_io(&s->parent_obj), 0);
 
354
}
 
355
 
 
356
static Property adlib_properties[] = {
 
357
    DEFINE_PROP_HEX32  ("iobase",  AdlibState, port, 0x220),
 
358
    DEFINE_PROP_UINT32 ("freq",    AdlibState, freq,  44100),
 
359
    DEFINE_PROP_END_OF_LIST (),
 
360
};
 
361
 
 
362
static void adlib_class_initfn (ObjectClass *klass, void *data)
 
363
{
 
364
    DeviceClass *dc = DEVICE_CLASS (klass);
 
365
 
 
366
    dc->realize = adlib_realizefn;
 
367
    set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
 
368
    dc->desc = ADLIB_DESC;
 
369
    dc->props = adlib_properties;
 
370
}
 
371
 
 
372
static const TypeInfo adlib_info = {
 
373
    .name          = TYPE_ADLIB,
 
374
    .parent        = TYPE_ISA_DEVICE,
 
375
    .instance_size = sizeof (AdlibState),
 
376
    .class_init    = adlib_class_initfn,
 
377
};
 
378
 
 
379
static int Adlib_init (ISABus *bus)
 
380
{
 
381
    isa_create_simple (bus, TYPE_ADLIB);
 
382
    return 0;
 
383
}
 
384
 
 
385
static void adlib_register_types (void)
 
386
{
 
387
    type_register_static (&adlib_info);
 
388
    isa_register_soundhw("adlib", ADLIB_DESC, Adlib_init);
 
389
}
 
390
 
 
391
type_init (adlib_register_types)