OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [sound/] [drivers/] [opl4/] [opl4_seq.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * OPL4 sequencer functions
3
 *
4
 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions, and the following disclaimer,
12
 *    without modification.
13
 * 2. The name of the author may not be used to endorse or promote products
14
 *    derived from this software without specific prior written permission.
15
 *
16
 * Alternatively, this software may be distributed and/or modified under the
17
 * terms of the GNU General Public License as published by the Free Software
18
 * Foundation; either version 2 of the License, or (at your option) any later
19
 * version.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
25
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 */
33
 
34
#include "opl4_local.h"
35
#include <linux/init.h>
36
#include <linux/moduleparam.h>
37
#include <sound/initval.h>
38
 
39
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
40
MODULE_DESCRIPTION("OPL4 wavetable synth driver");
41
MODULE_LICENSE("Dual BSD/GPL");
42
 
43
int volume_boost = 8;
44
 
45
module_param(volume_boost, int, 0644);
46
MODULE_PARM_DESC(volume_boost, "Additional volume for OPL4 wavetable sounds.");
47
 
48
static int snd_opl4_seq_use_inc(struct snd_opl4 *opl4)
49
{
50
        if (!try_module_get(opl4->card->module))
51
                return -EFAULT;
52
        return 0;
53
}
54
 
55
static void snd_opl4_seq_use_dec(struct snd_opl4 *opl4)
56
{
57
        module_put(opl4->card->module);
58
}
59
 
60
static int snd_opl4_seq_use(void *private_data, struct snd_seq_port_subscribe *info)
61
{
62
        struct snd_opl4 *opl4 = private_data;
63
        int err;
64
 
65
        mutex_lock(&opl4->access_mutex);
66
 
67
        if (opl4->used) {
68
                mutex_unlock(&opl4->access_mutex);
69
                return -EBUSY;
70
        }
71
        opl4->used++;
72
 
73
        if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) {
74
                err = snd_opl4_seq_use_inc(opl4);
75
                if (err < 0) {
76
                        mutex_unlock(&opl4->access_mutex);
77
                        return err;
78
                }
79
        }
80
 
81
        mutex_unlock(&opl4->access_mutex);
82
 
83
        snd_opl4_synth_reset(opl4);
84
        return 0;
85
}
86
 
87
static int snd_opl4_seq_unuse(void *private_data, struct snd_seq_port_subscribe *info)
88
{
89
        struct snd_opl4 *opl4 = private_data;
90
 
91
        snd_opl4_synth_shutdown(opl4);
92
 
93
        mutex_lock(&opl4->access_mutex);
94
        opl4->used--;
95
        mutex_unlock(&opl4->access_mutex);
96
 
97
        if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM)
98
                snd_opl4_seq_use_dec(opl4);
99
        return 0;
100
}
101
 
102
static struct snd_midi_op opl4_ops = {
103
        .note_on =              snd_opl4_note_on,
104
        .note_off =             snd_opl4_note_off,
105
        .note_terminate =       snd_opl4_terminate_note,
106
        .control =              snd_opl4_control,
107
        .sysex =                snd_opl4_sysex,
108
};
109
 
110
static int snd_opl4_seq_event_input(struct snd_seq_event *ev, int direct,
111
                                    void *private_data, int atomic, int hop)
112
{
113
        struct snd_opl4 *opl4 = private_data;
114
 
115
        snd_midi_process_event(&opl4_ops, ev, opl4->chset);
116
        return 0;
117
}
118
 
119
static void snd_opl4_seq_free_port(void *private_data)
120
{
121
        struct snd_opl4 *opl4 = private_data;
122
 
123
        snd_midi_channel_free_set(opl4->chset);
124
}
125
 
126
static int snd_opl4_seq_new_device(struct snd_seq_device *dev)
127
{
128
        struct snd_opl4 *opl4;
129
        int client;
130
        struct snd_seq_port_callback pcallbacks;
131
 
132
        opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
133
        if (!opl4)
134
                return -EINVAL;
135
 
136
        if (snd_yrw801_detect(opl4) < 0)
137
                return -ENODEV;
138
 
139
        opl4->chset = snd_midi_channel_alloc_set(16);
140
        if (!opl4->chset)
141
                return -ENOMEM;
142
        opl4->chset->private_data = opl4;
143
 
144
        /* allocate new client */
145
        client = snd_seq_create_kernel_client(opl4->card, opl4->seq_dev_num,
146
                                              "OPL4 Wavetable");
147
        if (client < 0) {
148
                snd_midi_channel_free_set(opl4->chset);
149
                return client;
150
        }
151
        opl4->seq_client = client;
152
        opl4->chset->client = client;
153
 
154
        /* create new port */
155
        memset(&pcallbacks, 0, sizeof(pcallbacks));
156
        pcallbacks.owner = THIS_MODULE;
157
        pcallbacks.use = snd_opl4_seq_use;
158
        pcallbacks.unuse = snd_opl4_seq_unuse;
159
        pcallbacks.event_input = snd_opl4_seq_event_input;
160
        pcallbacks.private_free = snd_opl4_seq_free_port;
161
        pcallbacks.private_data = opl4;
162
 
163
        opl4->chset->port = snd_seq_event_port_attach(client, &pcallbacks,
164
                                                      SNDRV_SEQ_PORT_CAP_WRITE |
165
                                                      SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
166
                                                      SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
167
                                                      SNDRV_SEQ_PORT_TYPE_MIDI_GM |
168
                                                      SNDRV_SEQ_PORT_TYPE_HARDWARE |
169
                                                      SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
170
                                                      16, 24,
171
                                                      "OPL4 Wavetable Port");
172
        if (opl4->chset->port < 0) {
173
                int err = opl4->chset->port;
174
                snd_midi_channel_free_set(opl4->chset);
175
                snd_seq_delete_kernel_client(client);
176
                opl4->seq_client = -1;
177
                return err;
178
        }
179
        return 0;
180
}
181
 
182
static int snd_opl4_seq_delete_device(struct snd_seq_device *dev)
183
{
184
        struct snd_opl4 *opl4;
185
 
186
        opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
187
        if (!opl4)
188
                return -EINVAL;
189
 
190
        if (opl4->seq_client >= 0) {
191
                snd_seq_delete_kernel_client(opl4->seq_client);
192
                opl4->seq_client = -1;
193
        }
194
        return 0;
195
}
196
 
197
static int __init alsa_opl4_synth_init(void)
198
{
199
        static struct snd_seq_dev_ops ops = {
200
                snd_opl4_seq_new_device,
201
                snd_opl4_seq_delete_device
202
        };
203
 
204
        return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL4, &ops,
205
                                              sizeof(struct snd_opl4 *));
206
}
207
 
208
static void __exit alsa_opl4_synth_exit(void)
209
{
210
        snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OPL4);
211
}
212
 
213
module_init(alsa_opl4_synth_init)
214
module_exit(alsa_opl4_synth_exit)

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.