brintos

brintos / linux-shallow public Read only

0
0
Text · 3.3 KiB · 99b032a Raw
162 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Apple Onboard Audio driver core4 *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 we62	 * will want to have this codec, so propagate error63	 * 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 fabric90	 * (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);162