brintos

brintos / linux-shallow public Read only

0
0
Text · 4.4 KiB · 2a295f6 Raw
193 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * soundbus4 *5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>6 */7 8#include <linux/module.h>9#include <linux/of.h>10#include <linux/of_platform.h>11#include "soundbus.h"12 13MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");14MODULE_LICENSE("GPL");15MODULE_DESCRIPTION("Apple Soundbus");16 17struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev)18{19	struct device *tmp;20 21	if (!dev)22		return NULL;23	tmp = get_device(&dev->ofdev.dev);24	if (tmp)25		return to_soundbus_device(tmp);26	else27		return NULL;28}29EXPORT_SYMBOL_GPL(soundbus_dev_get);30 31void soundbus_dev_put(struct soundbus_dev *dev)32{33	if (dev)34		put_device(&dev->ofdev.dev);35}36EXPORT_SYMBOL_GPL(soundbus_dev_put);37 38static int soundbus_probe(struct device *dev)39{40	int error = -ENODEV;41	struct soundbus_driver *drv;42	struct soundbus_dev *soundbus_dev;43 44	drv = to_soundbus_driver(dev->driver);45	soundbus_dev = to_soundbus_device(dev);46 47	if (!drv->probe)48		return error;49 50	soundbus_dev_get(soundbus_dev);51 52	error = drv->probe(soundbus_dev);53	if (error)54		soundbus_dev_put(soundbus_dev);55 56	return error;57}58 59 60static int soundbus_uevent(const struct device *dev, struct kobj_uevent_env *env)61{62	const struct soundbus_dev * soundbus_dev;63	const struct platform_device * of;64	const char *compat;65	int retval = 0;66	int cplen, seen = 0;67 68	if (!dev)69		return -ENODEV;70 71	soundbus_dev = to_soundbus_device(dev);72	if (!soundbus_dev)73		return -ENODEV;74 75	of = &soundbus_dev->ofdev;76 77	/* stuff we want to pass to /sbin/hotplug */78	retval = add_uevent_var(env, "OF_NAME=%pOFn", of->dev.of_node);79	if (retval)80		return retval;81 82	retval = add_uevent_var(env, "OF_TYPE=%s", of_node_get_device_type(of->dev.of_node));83	if (retval)84		return retval;85 86	/* Since the compatible field can contain pretty much anything87	 * it's not really legal to split it out with commas. We split it88	 * up using a number of environment variables instead. */89 90	compat = of_get_property(of->dev.of_node, "compatible", &cplen);91	while (compat && cplen > 0) {92		int tmp = env->buflen;93		retval = add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);94		if (retval)95			return retval;96		compat += env->buflen - tmp;97		cplen -= env->buflen - tmp;98		seen += 1;99	}100 101	retval = add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);102	if (retval)103		return retval;104	retval = add_uevent_var(env, "MODALIAS=%s", soundbus_dev->modalias);105 106	return retval;107}108 109static void soundbus_device_remove(struct device *dev)110{111	struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);112	struct soundbus_driver * drv = to_soundbus_driver(dev->driver);113 114	if (dev->driver && drv->remove)115		drv->remove(soundbus_dev);116	soundbus_dev_put(soundbus_dev);117}118 119static void soundbus_device_shutdown(struct device *dev)120{121	struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);122	struct soundbus_driver * drv = to_soundbus_driver(dev->driver);123 124	if (dev->driver && drv->shutdown)125		drv->shutdown(soundbus_dev);126}127 128/* soundbus_dev_attrs is declared in sysfs.c */129ATTRIBUTE_GROUPS(soundbus_dev);130static const struct bus_type soundbus_bus_type = {131	.name		= "aoa-soundbus",132	.probe		= soundbus_probe,133	.uevent		= soundbus_uevent,134	.remove		= soundbus_device_remove,135	.shutdown	= soundbus_device_shutdown,136	.dev_groups	= soundbus_dev_groups,137};138 139int soundbus_add_one(struct soundbus_dev *dev)140{141	static int devcount;142 143	/* sanity checks */144	if (!dev->attach_codec ||145	    !dev->ofdev.dev.of_node ||146	    dev->pcmname ||147	    dev->pcmid != -1) {148		printk(KERN_ERR "soundbus: adding device failed sanity check!\n");149		return -EINVAL;150	}151 152	dev_set_name(&dev->ofdev.dev, "soundbus:%x", ++devcount);153	dev->ofdev.dev.bus = &soundbus_bus_type;154	return of_device_register(&dev->ofdev);155}156EXPORT_SYMBOL_GPL(soundbus_add_one);157 158void soundbus_remove_one(struct soundbus_dev *dev)159{160	of_device_unregister(&dev->ofdev);161}162EXPORT_SYMBOL_GPL(soundbus_remove_one);163 164int soundbus_register_driver(struct soundbus_driver *drv)165{166	/* initialize common driver fields */167	drv->driver.name = drv->name;168	drv->driver.bus = &soundbus_bus_type;169 170	/* register with core */171	return driver_register(&drv->driver);172}173EXPORT_SYMBOL_GPL(soundbus_register_driver);174 175void soundbus_unregister_driver(struct soundbus_driver *drv)176{177	driver_unregister(&drv->driver);178}179EXPORT_SYMBOL_GPL(soundbus_unregister_driver);180 181static int __init soundbus_init(void)182{183	return bus_register(&soundbus_bus_type);184}185 186static void __exit soundbus_exit(void)187{188	bus_unregister(&soundbus_bus_type);189}190 191subsys_initcall(soundbus_init);192module_exit(soundbus_exit);193