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