File Index
Files and directories
Sign in
FILE

core.c

File preview with syntax highlighting.

linux-6.19.14/sound/aoa/core/core.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Apple Onboard Audio driver core
  4 *
  5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
  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
 14MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver");
 15MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
 16MODULE_LICENSE("GPL");
 17
 18/* We allow only one fabric. This simplifies things,
 19 * and more don't really make that much sense */
 20static struct aoa_fabric *fabric;
 21static LIST_HEAD(codec_list);
 22
 23static 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
 57int 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}
 70EXPORT_SYMBOL_GPL(aoa_codec_register);
 71
 72void 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}
 82EXPORT_SYMBOL_GPL(aoa_codec_unregister);
 83
 84int 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}
113EXPORT_SYMBOL_GPL(aoa_fabric_register);
114
115void 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}
131EXPORT_SYMBOL_GPL(aoa_fabric_unregister);
132
133void 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}
148EXPORT_SYMBOL_GPL(aoa_fabric_unlink_codec);
149
150static int __init aoa_init(void)
151{
152	return 0;
153}
154
155static void __exit aoa_exit(void)
156{
157	aoa_alsa_cleanup();
158}
159
160module_init(aoa_init);
161module_exit(aoa_exit);
~/ Read-only file preview.