Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
core.c
Go to the documentation of this file.
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 
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 }
72 
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 }
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:
109  if (c->fabric != fabric)
110  attach_codec_to_fabric(c);
111  }
112  return err;
113 }
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 
124  if (c->fabric)
126  }
127 
129 
130  fabric = NULL;
131 }
133 
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 }
150 
151 static int __init aoa_init(void)
152 {
153  return 0;
154 }
155 
156 static void __exit aoa_exit(void)
157 {
159 }
160 
161 module_init(aoa_init);
162 module_exit(aoa_exit);