Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/aoa/core/core.c
10817 views
1
/*
2
* Apple Onboard Audio driver core
3
*
4
* Copyright 2006 Johannes Berg <[email protected]>
5
*
6
* GPL v2, can be found in COPYING.
7
*/
8
9
#include <linux/init.h>
10
#include <linux/module.h>
11
#include <linux/list.h>
12
#include "../aoa.h"
13
#include "alsa.h"
14
15
MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver");
16
MODULE_AUTHOR("Johannes Berg <[email protected]>");
17
MODULE_LICENSE("GPL");
18
19
/* We allow only one fabric. This simplifies things,
20
* and more don't really make that much sense */
21
static struct aoa_fabric *fabric;
22
static LIST_HEAD(codec_list);
23
24
static int attach_codec_to_fabric(struct aoa_codec *c)
25
{
26
int err;
27
28
if (!try_module_get(c->owner))
29
return -EBUSY;
30
/* found_codec has to be assigned */
31
err = -ENOENT;
32
if (fabric->found_codec)
33
err = fabric->found_codec(c);
34
if (err) {
35
module_put(c->owner);
36
printk(KERN_ERR "snd-aoa: fabric didn't like codec %s\n",
37
c->name);
38
return err;
39
}
40
c->fabric = fabric;
41
42
err = 0;
43
if (c->init)
44
err = c->init(c);
45
if (err) {
46
printk(KERN_ERR "snd-aoa: codec %s didn't init\n", c->name);
47
c->fabric = NULL;
48
if (fabric->remove_codec)
49
fabric->remove_codec(c);
50
module_put(c->owner);
51
return err;
52
}
53
if (fabric->attached_codec)
54
fabric->attached_codec(c);
55
return 0;
56
}
57
58
int aoa_codec_register(struct aoa_codec *codec)
59
{
60
int err = 0;
61
62
/* if there's a fabric already, we can tell if we
63
* will want to have this codec, so propagate error
64
* through. Otherwise, this will happen later... */
65
if (fabric)
66
err = attach_codec_to_fabric(codec);
67
if (!err)
68
list_add(&codec->list, &codec_list);
69
return err;
70
}
71
EXPORT_SYMBOL_GPL(aoa_codec_register);
72
73
void aoa_codec_unregister(struct aoa_codec *codec)
74
{
75
list_del(&codec->list);
76
if (codec->fabric && codec->exit)
77
codec->exit(codec);
78
if (fabric && fabric->remove_codec)
79
fabric->remove_codec(codec);
80
codec->fabric = NULL;
81
module_put(codec->owner);
82
}
83
EXPORT_SYMBOL_GPL(aoa_codec_unregister);
84
85
int aoa_fabric_register(struct aoa_fabric *new_fabric, struct device *dev)
86
{
87
struct aoa_codec *c;
88
int err;
89
90
/* allow querying for presence of fabric
91
* (i.e. do this test first!) */
92
if (new_fabric == fabric) {
93
err = -EALREADY;
94
goto attach;
95
}
96
if (fabric)
97
return -EEXIST;
98
if (!new_fabric)
99
return -EINVAL;
100
101
err = aoa_alsa_init(new_fabric->name, new_fabric->owner, dev);
102
if (err)
103
return err;
104
105
fabric = new_fabric;
106
107
attach:
108
list_for_each_entry(c, &codec_list, list) {
109
if (c->fabric != fabric)
110
attach_codec_to_fabric(c);
111
}
112
return err;
113
}
114
EXPORT_SYMBOL_GPL(aoa_fabric_register);
115
116
void aoa_fabric_unregister(struct aoa_fabric *old_fabric)
117
{
118
struct aoa_codec *c;
119
120
if (fabric != old_fabric)
121
return;
122
123
list_for_each_entry(c, &codec_list, list) {
124
if (c->fabric)
125
aoa_fabric_unlink_codec(c);
126
}
127
128
aoa_alsa_cleanup();
129
130
fabric = NULL;
131
}
132
EXPORT_SYMBOL_GPL(aoa_fabric_unregister);
133
134
void aoa_fabric_unlink_codec(struct aoa_codec *codec)
135
{
136
if (!codec->fabric) {
137
printk(KERN_ERR "snd-aoa: fabric unassigned "
138
"in aoa_fabric_unlink_codec\n");
139
dump_stack();
140
return;
141
}
142
if (codec->exit)
143
codec->exit(codec);
144
if (codec->fabric->remove_codec)
145
codec->fabric->remove_codec(codec);
146
codec->fabric = NULL;
147
module_put(codec->owner);
148
}
149
EXPORT_SYMBOL_GPL(aoa_fabric_unlink_codec);
150
151
static int __init aoa_init(void)
152
{
153
return 0;
154
}
155
156
static void __exit aoa_exit(void)
157
{
158
aoa_alsa_cleanup();
159
}
160
161
module_init(aoa_init);
162
module_exit(aoa_exit);
163
164