xref: /openbmc/linux/sound/ac97/bus.c (revision d28dc3d8)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
274426fbfSRobert Jarzmik /*
374426fbfSRobert Jarzmik  * Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
474426fbfSRobert Jarzmik  */
574426fbfSRobert Jarzmik 
674426fbfSRobert Jarzmik #include <linux/module.h>
774426fbfSRobert Jarzmik #include <linux/bitops.h>
874426fbfSRobert Jarzmik #include <linux/clk.h>
974426fbfSRobert Jarzmik #include <linux/device.h>
1074426fbfSRobert Jarzmik #include <linux/idr.h>
1174426fbfSRobert Jarzmik #include <linux/list.h>
1274426fbfSRobert Jarzmik #include <linux/mutex.h>
132225a3e6SRobert Jarzmik #include <linux/of.h>
1474426fbfSRobert Jarzmik #include <linux/pm.h>
1574426fbfSRobert Jarzmik #include <linux/pm_runtime.h>
1674426fbfSRobert Jarzmik #include <linux/slab.h>
1774426fbfSRobert Jarzmik #include <linux/sysfs.h>
1874426fbfSRobert Jarzmik #include <sound/ac97/codec.h>
1974426fbfSRobert Jarzmik #include <sound/ac97/controller.h>
2074426fbfSRobert Jarzmik #include <sound/ac97/regs.h>
2174426fbfSRobert Jarzmik 
2274426fbfSRobert Jarzmik #include "ac97_core.h"
2374426fbfSRobert Jarzmik 
2474426fbfSRobert Jarzmik /*
2574426fbfSRobert Jarzmik  * Protects ac97_controllers and each ac97_controller structure.
2674426fbfSRobert Jarzmik  */
2774426fbfSRobert Jarzmik static DEFINE_MUTEX(ac97_controllers_mutex);
2874426fbfSRobert Jarzmik static DEFINE_IDR(ac97_adapter_idr);
2974426fbfSRobert Jarzmik static LIST_HEAD(ac97_controllers);
3074426fbfSRobert Jarzmik 
3174426fbfSRobert Jarzmik static struct bus_type ac97_bus_type;
3274426fbfSRobert Jarzmik 
3374426fbfSRobert Jarzmik static inline struct ac97_controller*
to_ac97_controller(struct device * ac97_adapter)3474426fbfSRobert Jarzmik to_ac97_controller(struct device *ac97_adapter)
3574426fbfSRobert Jarzmik {
3674426fbfSRobert Jarzmik 	return container_of(ac97_adapter, struct ac97_controller, adap);
3774426fbfSRobert Jarzmik }
3874426fbfSRobert Jarzmik 
ac97_unbound_ctrl_write(struct ac97_controller * adrv,int slot,unsigned short reg,unsigned short val)3974426fbfSRobert Jarzmik static int ac97_unbound_ctrl_write(struct ac97_controller *adrv, int slot,
4074426fbfSRobert Jarzmik 		     unsigned short reg, unsigned short val)
4174426fbfSRobert Jarzmik {
4274426fbfSRobert Jarzmik 	return -ENODEV;
4374426fbfSRobert Jarzmik }
4474426fbfSRobert Jarzmik 
ac97_unbound_ctrl_read(struct ac97_controller * adrv,int slot,unsigned short reg)4574426fbfSRobert Jarzmik static int ac97_unbound_ctrl_read(struct ac97_controller *adrv, int slot,
4674426fbfSRobert Jarzmik 				  unsigned short reg)
4774426fbfSRobert Jarzmik {
4874426fbfSRobert Jarzmik 	return -ENODEV;
4974426fbfSRobert Jarzmik }
5074426fbfSRobert Jarzmik 
5174426fbfSRobert Jarzmik static const struct ac97_controller_ops ac97_unbound_ctrl_ops = {
5274426fbfSRobert Jarzmik 	.write = ac97_unbound_ctrl_write,
5374426fbfSRobert Jarzmik 	.read = ac97_unbound_ctrl_read,
5474426fbfSRobert Jarzmik };
5574426fbfSRobert Jarzmik 
5674426fbfSRobert Jarzmik static struct ac97_controller ac97_unbound_ctrl = {
5774426fbfSRobert Jarzmik 	.ops = &ac97_unbound_ctrl_ops,
5874426fbfSRobert Jarzmik };
5974426fbfSRobert Jarzmik 
6074426fbfSRobert Jarzmik static struct ac97_codec_device *
ac97_codec_find(struct ac97_controller * ac97_ctrl,unsigned int codec_num)6174426fbfSRobert Jarzmik ac97_codec_find(struct ac97_controller *ac97_ctrl, unsigned int codec_num)
6274426fbfSRobert Jarzmik {
6374426fbfSRobert Jarzmik 	if (codec_num >= AC97_BUS_MAX_CODECS)
6474426fbfSRobert Jarzmik 		return ERR_PTR(-EINVAL);
6574426fbfSRobert Jarzmik 
6674426fbfSRobert Jarzmik 	return ac97_ctrl->codecs[codec_num];
6774426fbfSRobert Jarzmik }
6874426fbfSRobert Jarzmik 
692225a3e6SRobert Jarzmik static struct device_node *
ac97_of_get_child_device(struct ac97_controller * ac97_ctrl,int idx,unsigned int vendor_id)702225a3e6SRobert Jarzmik ac97_of_get_child_device(struct ac97_controller *ac97_ctrl, int idx,
712225a3e6SRobert Jarzmik 			 unsigned int vendor_id)
722225a3e6SRobert Jarzmik {
732225a3e6SRobert Jarzmik 	struct device_node *node;
742225a3e6SRobert Jarzmik 	u32 reg;
752225a3e6SRobert Jarzmik 	char compat[] = "ac97,0000,0000";
762225a3e6SRobert Jarzmik 
772225a3e6SRobert Jarzmik 	snprintf(compat, sizeof(compat), "ac97,%04x,%04x",
782225a3e6SRobert Jarzmik 		 vendor_id >> 16, vendor_id & 0xffff);
792225a3e6SRobert Jarzmik 
802225a3e6SRobert Jarzmik 	for_each_child_of_node(ac97_ctrl->parent->of_node, node) {
812225a3e6SRobert Jarzmik 		if ((idx != of_property_read_u32(node, "reg", &reg)) ||
822225a3e6SRobert Jarzmik 		    !of_device_is_compatible(node, compat))
832225a3e6SRobert Jarzmik 			continue;
8431d2350dSTakashi Iwai 		return node;
852225a3e6SRobert Jarzmik 	}
862225a3e6SRobert Jarzmik 
872225a3e6SRobert Jarzmik 	return NULL;
882225a3e6SRobert Jarzmik }
892225a3e6SRobert Jarzmik 
ac97_codec_release(struct device * dev)9074426fbfSRobert Jarzmik static void ac97_codec_release(struct device *dev)
9174426fbfSRobert Jarzmik {
9274426fbfSRobert Jarzmik 	struct ac97_codec_device *adev;
9374426fbfSRobert Jarzmik 	struct ac97_controller *ac97_ctrl;
9474426fbfSRobert Jarzmik 
9574426fbfSRobert Jarzmik 	adev = to_ac97_device(dev);
9674426fbfSRobert Jarzmik 	ac97_ctrl = adev->ac97_ctrl;
9774426fbfSRobert Jarzmik 	ac97_ctrl->codecs[adev->num] = NULL;
982225a3e6SRobert Jarzmik 	of_node_put(dev->of_node);
9974426fbfSRobert Jarzmik 	kfree(adev);
10074426fbfSRobert Jarzmik }
10174426fbfSRobert Jarzmik 
ac97_codec_add(struct ac97_controller * ac97_ctrl,int idx,unsigned int vendor_id)10274426fbfSRobert Jarzmik static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx,
10374426fbfSRobert Jarzmik 		   unsigned int vendor_id)
10474426fbfSRobert Jarzmik {
10574426fbfSRobert Jarzmik 	struct ac97_codec_device *codec;
10674426fbfSRobert Jarzmik 	int ret;
10774426fbfSRobert Jarzmik 
10874426fbfSRobert Jarzmik 	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
10974426fbfSRobert Jarzmik 	if (!codec)
11074426fbfSRobert Jarzmik 		return -ENOMEM;
11174426fbfSRobert Jarzmik 	ac97_ctrl->codecs[idx] = codec;
11274426fbfSRobert Jarzmik 	codec->vendor_id = vendor_id;
11374426fbfSRobert Jarzmik 	codec->dev.release = ac97_codec_release;
11474426fbfSRobert Jarzmik 	codec->dev.bus = &ac97_bus_type;
11574426fbfSRobert Jarzmik 	codec->dev.parent = &ac97_ctrl->adap;
11674426fbfSRobert Jarzmik 	codec->num = idx;
11774426fbfSRobert Jarzmik 	codec->ac97_ctrl = ac97_ctrl;
11874426fbfSRobert Jarzmik 
11974426fbfSRobert Jarzmik 	device_initialize(&codec->dev);
12074426fbfSRobert Jarzmik 	dev_set_name(&codec->dev, "%s:%u", dev_name(ac97_ctrl->parent), idx);
1212225a3e6SRobert Jarzmik 	codec->dev.of_node = ac97_of_get_child_device(ac97_ctrl, idx,
1222225a3e6SRobert Jarzmik 						      vendor_id);
12374426fbfSRobert Jarzmik 
12474426fbfSRobert Jarzmik 	ret = device_add(&codec->dev);
125607975b3SDing Xiang 	if (ret) {
126607975b3SDing Xiang 		put_device(&codec->dev);
127607975b3SDing Xiang 		return ret;
128607975b3SDing Xiang 	}
12974426fbfSRobert Jarzmik 
13074426fbfSRobert Jarzmik 	return 0;
13174426fbfSRobert Jarzmik }
13274426fbfSRobert Jarzmik 
snd_ac97_bus_scan_one(struct ac97_controller * adrv,unsigned int codec_num)13374426fbfSRobert Jarzmik unsigned int snd_ac97_bus_scan_one(struct ac97_controller *adrv,
13474426fbfSRobert Jarzmik 				   unsigned int codec_num)
13574426fbfSRobert Jarzmik {
13674426fbfSRobert Jarzmik 	unsigned short vid1, vid2;
13774426fbfSRobert Jarzmik 	int ret;
13874426fbfSRobert Jarzmik 
13974426fbfSRobert Jarzmik 	ret = adrv->ops->read(adrv, codec_num, AC97_VENDOR_ID1);
14074426fbfSRobert Jarzmik 	vid1 = (ret & 0xffff);
14174426fbfSRobert Jarzmik 	if (ret < 0)
14274426fbfSRobert Jarzmik 		return 0;
14374426fbfSRobert Jarzmik 
14474426fbfSRobert Jarzmik 	ret = adrv->ops->read(adrv, codec_num, AC97_VENDOR_ID2);
14574426fbfSRobert Jarzmik 	vid2 = (ret & 0xffff);
14674426fbfSRobert Jarzmik 	if (ret < 0)
14774426fbfSRobert Jarzmik 		return 0;
14874426fbfSRobert Jarzmik 
14974426fbfSRobert Jarzmik 	dev_dbg(&adrv->adap, "%s(codec_num=%u): vendor_id=0x%08x\n",
15074426fbfSRobert Jarzmik 		__func__, codec_num, AC97_ID(vid1, vid2));
15174426fbfSRobert Jarzmik 	return AC97_ID(vid1, vid2);
15274426fbfSRobert Jarzmik }
15374426fbfSRobert Jarzmik 
ac97_bus_scan(struct ac97_controller * ac97_ctrl)15474426fbfSRobert Jarzmik static int ac97_bus_scan(struct ac97_controller *ac97_ctrl)
15574426fbfSRobert Jarzmik {
15674426fbfSRobert Jarzmik 	int ret, i;
15774426fbfSRobert Jarzmik 	unsigned int vendor_id;
15874426fbfSRobert Jarzmik 
15974426fbfSRobert Jarzmik 	for (i = 0; i < AC97_BUS_MAX_CODECS; i++) {
16074426fbfSRobert Jarzmik 		if (ac97_codec_find(ac97_ctrl, i))
16174426fbfSRobert Jarzmik 			continue;
16274426fbfSRobert Jarzmik 		if (!(ac97_ctrl->slots_available & BIT(i)))
16374426fbfSRobert Jarzmik 			continue;
16474426fbfSRobert Jarzmik 		vendor_id = snd_ac97_bus_scan_one(ac97_ctrl, i);
16574426fbfSRobert Jarzmik 		if (!vendor_id)
16674426fbfSRobert Jarzmik 			continue;
16774426fbfSRobert Jarzmik 
16874426fbfSRobert Jarzmik 		ret = ac97_codec_add(ac97_ctrl, i, vendor_id);
16974426fbfSRobert Jarzmik 		if (ret < 0)
17074426fbfSRobert Jarzmik 			return ret;
17174426fbfSRobert Jarzmik 	}
17274426fbfSRobert Jarzmik 	return 0;
17374426fbfSRobert Jarzmik }
17474426fbfSRobert Jarzmik 
ac97_bus_reset(struct ac97_controller * ac97_ctrl)17574426fbfSRobert Jarzmik static int ac97_bus_reset(struct ac97_controller *ac97_ctrl)
17674426fbfSRobert Jarzmik {
17774426fbfSRobert Jarzmik 	ac97_ctrl->ops->reset(ac97_ctrl);
17874426fbfSRobert Jarzmik 
17974426fbfSRobert Jarzmik 	return 0;
18074426fbfSRobert Jarzmik }
18174426fbfSRobert Jarzmik 
18274426fbfSRobert Jarzmik /**
18374426fbfSRobert Jarzmik  * snd_ac97_codec_driver_register - register an AC97 codec driver
18474426fbfSRobert Jarzmik  * @dev: AC97 driver codec to register
18574426fbfSRobert Jarzmik  *
18674426fbfSRobert Jarzmik  * Register an AC97 codec driver to the ac97 bus driver, aka. the AC97 digital
18774426fbfSRobert Jarzmik  * controller.
18874426fbfSRobert Jarzmik  *
18974426fbfSRobert Jarzmik  * Returns 0 on success or error code
19074426fbfSRobert Jarzmik  */
snd_ac97_codec_driver_register(struct ac97_codec_driver * drv)19174426fbfSRobert Jarzmik int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv)
19274426fbfSRobert Jarzmik {
19374426fbfSRobert Jarzmik 	drv->driver.bus = &ac97_bus_type;
19474426fbfSRobert Jarzmik 	return driver_register(&drv->driver);
19574426fbfSRobert Jarzmik }
19674426fbfSRobert Jarzmik EXPORT_SYMBOL_GPL(snd_ac97_codec_driver_register);
19774426fbfSRobert Jarzmik 
19874426fbfSRobert Jarzmik /**
19974426fbfSRobert Jarzmik  * snd_ac97_codec_driver_unregister - unregister an AC97 codec driver
20074426fbfSRobert Jarzmik  * @dev: AC97 codec driver to unregister
20174426fbfSRobert Jarzmik  *
20274426fbfSRobert Jarzmik  * Unregister a previously registered ac97 codec driver.
20374426fbfSRobert Jarzmik  */
snd_ac97_codec_driver_unregister(struct ac97_codec_driver * drv)20474426fbfSRobert Jarzmik void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv)
20574426fbfSRobert Jarzmik {
20674426fbfSRobert Jarzmik 	driver_unregister(&drv->driver);
20774426fbfSRobert Jarzmik }
20874426fbfSRobert Jarzmik EXPORT_SYMBOL_GPL(snd_ac97_codec_driver_unregister);
20974426fbfSRobert Jarzmik 
21074426fbfSRobert Jarzmik /**
21174426fbfSRobert Jarzmik  * snd_ac97_codec_get_platdata - get platform_data
21274426fbfSRobert Jarzmik  * @adev: the ac97 codec device
21374426fbfSRobert Jarzmik  *
21474426fbfSRobert Jarzmik  * For legacy platforms, in order to have platform_data in codec drivers
21574426fbfSRobert Jarzmik  * available, while ac97 device are auto-created upon probe, this retrieves the
21674426fbfSRobert Jarzmik  * platdata which was setup on ac97 controller registration.
21774426fbfSRobert Jarzmik  *
21874426fbfSRobert Jarzmik  * Returns the platform data pointer
21974426fbfSRobert Jarzmik  */
snd_ac97_codec_get_platdata(const struct ac97_codec_device * adev)22074426fbfSRobert Jarzmik void *snd_ac97_codec_get_platdata(const struct ac97_codec_device *adev)
22174426fbfSRobert Jarzmik {
22274426fbfSRobert Jarzmik 	struct ac97_controller *ac97_ctrl = adev->ac97_ctrl;
22374426fbfSRobert Jarzmik 
22474426fbfSRobert Jarzmik 	return ac97_ctrl->codecs_pdata[adev->num];
22574426fbfSRobert Jarzmik }
22674426fbfSRobert Jarzmik EXPORT_SYMBOL_GPL(snd_ac97_codec_get_platdata);
22774426fbfSRobert Jarzmik 
ac97_ctrl_codecs_unregister(struct ac97_controller * ac97_ctrl)22874426fbfSRobert Jarzmik static void ac97_ctrl_codecs_unregister(struct ac97_controller *ac97_ctrl)
22974426fbfSRobert Jarzmik {
23074426fbfSRobert Jarzmik 	int i;
23174426fbfSRobert Jarzmik 
23274426fbfSRobert Jarzmik 	for (i = 0; i < AC97_BUS_MAX_CODECS; i++)
23374426fbfSRobert Jarzmik 		if (ac97_ctrl->codecs[i]) {
23474426fbfSRobert Jarzmik 			ac97_ctrl->codecs[i]->ac97_ctrl = &ac97_unbound_ctrl;
23574426fbfSRobert Jarzmik 			device_unregister(&ac97_ctrl->codecs[i]->dev);
23674426fbfSRobert Jarzmik 		}
23774426fbfSRobert Jarzmik }
23874426fbfSRobert Jarzmik 
cold_reset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)23974426fbfSRobert Jarzmik static ssize_t cold_reset_store(struct device *dev,
24074426fbfSRobert Jarzmik 				struct device_attribute *attr, const char *buf,
24174426fbfSRobert Jarzmik 				size_t len)
24274426fbfSRobert Jarzmik {
24374426fbfSRobert Jarzmik 	struct ac97_controller *ac97_ctrl;
24474426fbfSRobert Jarzmik 
24574426fbfSRobert Jarzmik 	mutex_lock(&ac97_controllers_mutex);
24674426fbfSRobert Jarzmik 	ac97_ctrl = to_ac97_controller(dev);
24774426fbfSRobert Jarzmik 	ac97_ctrl->ops->reset(ac97_ctrl);
24874426fbfSRobert Jarzmik 	mutex_unlock(&ac97_controllers_mutex);
24974426fbfSRobert Jarzmik 	return len;
25074426fbfSRobert Jarzmik }
25174426fbfSRobert Jarzmik static DEVICE_ATTR_WO(cold_reset);
25274426fbfSRobert Jarzmik 
warm_reset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)25374426fbfSRobert Jarzmik static ssize_t warm_reset_store(struct device *dev,
25474426fbfSRobert Jarzmik 				struct device_attribute *attr, const char *buf,
25574426fbfSRobert Jarzmik 				size_t len)
25674426fbfSRobert Jarzmik {
25774426fbfSRobert Jarzmik 	struct ac97_controller *ac97_ctrl;
25874426fbfSRobert Jarzmik 
25974426fbfSRobert Jarzmik 	if (!dev)
26074426fbfSRobert Jarzmik 		return -ENODEV;
26174426fbfSRobert Jarzmik 
26274426fbfSRobert Jarzmik 	mutex_lock(&ac97_controllers_mutex);
26374426fbfSRobert Jarzmik 	ac97_ctrl = to_ac97_controller(dev);
26474426fbfSRobert Jarzmik 	ac97_ctrl->ops->warm_reset(ac97_ctrl);
26574426fbfSRobert Jarzmik 	mutex_unlock(&ac97_controllers_mutex);
26674426fbfSRobert Jarzmik 	return len;
26774426fbfSRobert Jarzmik }
26874426fbfSRobert Jarzmik static DEVICE_ATTR_WO(warm_reset);
26974426fbfSRobert Jarzmik 
27074426fbfSRobert Jarzmik static struct attribute *ac97_controller_device_attrs[] = {
27174426fbfSRobert Jarzmik 	&dev_attr_cold_reset.attr,
27274426fbfSRobert Jarzmik 	&dev_attr_warm_reset.attr,
27374426fbfSRobert Jarzmik 	NULL
27474426fbfSRobert Jarzmik };
27574426fbfSRobert Jarzmik 
276fa2e5a64SRikard Falkeborn static const struct attribute_group ac97_adapter_attr_group = {
27774426fbfSRobert Jarzmik 	.name	= "ac97_operations",
27874426fbfSRobert Jarzmik 	.attrs	= ac97_controller_device_attrs,
27974426fbfSRobert Jarzmik };
28074426fbfSRobert Jarzmik 
28174426fbfSRobert Jarzmik static const struct attribute_group *ac97_adapter_groups[] = {
28274426fbfSRobert Jarzmik 	&ac97_adapter_attr_group,
28374426fbfSRobert Jarzmik 	NULL,
28474426fbfSRobert Jarzmik };
28574426fbfSRobert Jarzmik 
ac97_del_adapter(struct ac97_controller * ac97_ctrl)28674426fbfSRobert Jarzmik static void ac97_del_adapter(struct ac97_controller *ac97_ctrl)
28774426fbfSRobert Jarzmik {
28874426fbfSRobert Jarzmik 	mutex_lock(&ac97_controllers_mutex);
28974426fbfSRobert Jarzmik 	ac97_ctrl_codecs_unregister(ac97_ctrl);
29074426fbfSRobert Jarzmik 	list_del(&ac97_ctrl->controllers);
29174426fbfSRobert Jarzmik 	mutex_unlock(&ac97_controllers_mutex);
29274426fbfSRobert Jarzmik 
29374426fbfSRobert Jarzmik 	device_unregister(&ac97_ctrl->adap);
29474426fbfSRobert Jarzmik }
29574426fbfSRobert Jarzmik 
ac97_adapter_release(struct device * dev)29674426fbfSRobert Jarzmik static void ac97_adapter_release(struct device *dev)
29774426fbfSRobert Jarzmik {
29874426fbfSRobert Jarzmik 	struct ac97_controller *ac97_ctrl;
29974426fbfSRobert Jarzmik 
30074426fbfSRobert Jarzmik 	ac97_ctrl = to_ac97_controller(dev);
30174426fbfSRobert Jarzmik 	idr_remove(&ac97_adapter_idr, ac97_ctrl->nr);
30274426fbfSRobert Jarzmik 	dev_dbg(&ac97_ctrl->adap, "adapter unregistered by %s\n",
30374426fbfSRobert Jarzmik 		dev_name(ac97_ctrl->parent));
30474426fbfSRobert Jarzmik }
30574426fbfSRobert Jarzmik 
30674426fbfSRobert Jarzmik static const struct device_type ac97_adapter_type = {
30774426fbfSRobert Jarzmik 	.groups		= ac97_adapter_groups,
30874426fbfSRobert Jarzmik 	.release	= ac97_adapter_release,
30974426fbfSRobert Jarzmik };
31074426fbfSRobert Jarzmik 
ac97_add_adapter(struct ac97_controller * ac97_ctrl)31174426fbfSRobert Jarzmik static int ac97_add_adapter(struct ac97_controller *ac97_ctrl)
31274426fbfSRobert Jarzmik {
31374426fbfSRobert Jarzmik 	int ret;
31474426fbfSRobert Jarzmik 
31574426fbfSRobert Jarzmik 	mutex_lock(&ac97_controllers_mutex);
31674426fbfSRobert Jarzmik 	ret = idr_alloc(&ac97_adapter_idr, ac97_ctrl, 0, 0, GFP_KERNEL);
31774426fbfSRobert Jarzmik 	ac97_ctrl->nr = ret;
31874426fbfSRobert Jarzmik 	if (ret >= 0) {
31974426fbfSRobert Jarzmik 		dev_set_name(&ac97_ctrl->adap, "ac97-%d", ret);
32074426fbfSRobert Jarzmik 		ac97_ctrl->adap.type = &ac97_adapter_type;
32174426fbfSRobert Jarzmik 		ac97_ctrl->adap.parent = ac97_ctrl->parent;
32274426fbfSRobert Jarzmik 		ret = device_register(&ac97_ctrl->adap);
32374426fbfSRobert Jarzmik 		if (ret)
32474426fbfSRobert Jarzmik 			put_device(&ac97_ctrl->adap);
32574426fbfSRobert Jarzmik 	}
32674426fbfSRobert Jarzmik 	if (!ret)
32774426fbfSRobert Jarzmik 		list_add(&ac97_ctrl->controllers, &ac97_controllers);
32874426fbfSRobert Jarzmik 	mutex_unlock(&ac97_controllers_mutex);
32974426fbfSRobert Jarzmik 
33074426fbfSRobert Jarzmik 	if (!ret)
33174426fbfSRobert Jarzmik 		dev_dbg(&ac97_ctrl->adap, "adapter registered by %s\n",
33274426fbfSRobert Jarzmik 			dev_name(ac97_ctrl->parent));
33374426fbfSRobert Jarzmik 	return ret;
33474426fbfSRobert Jarzmik }
33574426fbfSRobert Jarzmik 
33674426fbfSRobert Jarzmik /**
33774426fbfSRobert Jarzmik  * snd_ac97_controller_register - register an ac97 controller
33874426fbfSRobert Jarzmik  * @ops: the ac97 bus operations
33974426fbfSRobert Jarzmik  * @dev: the device providing the ac97 DC function
34074426fbfSRobert Jarzmik  * @slots_available: mask of the ac97 codecs that can be scanned and probed
34174426fbfSRobert Jarzmik  *                   bit0 => codec 0, bit1 => codec 1 ... bit 3 => codec 3
34274426fbfSRobert Jarzmik  *
34374426fbfSRobert Jarzmik  * Register a digital controller which can control up to 4 ac97 codecs. This is
34474426fbfSRobert Jarzmik  * the controller side of the AC97 AC-link, while the slave side are the codecs.
34574426fbfSRobert Jarzmik  *
34674426fbfSRobert Jarzmik  * Returns a valid controller upon success, negative pointer value upon error
34774426fbfSRobert Jarzmik  */
snd_ac97_controller_register(const struct ac97_controller_ops * ops,struct device * dev,unsigned short slots_available,void ** codecs_pdata)34874426fbfSRobert Jarzmik struct ac97_controller *snd_ac97_controller_register(
34974426fbfSRobert Jarzmik 	const struct ac97_controller_ops *ops, struct device *dev,
35074426fbfSRobert Jarzmik 	unsigned short slots_available, void **codecs_pdata)
35174426fbfSRobert Jarzmik {
35274426fbfSRobert Jarzmik 	struct ac97_controller *ac97_ctrl;
35374426fbfSRobert Jarzmik 	int ret, i;
35474426fbfSRobert Jarzmik 
35574426fbfSRobert Jarzmik 	ac97_ctrl = kzalloc(sizeof(*ac97_ctrl), GFP_KERNEL);
35674426fbfSRobert Jarzmik 	if (!ac97_ctrl)
35774426fbfSRobert Jarzmik 		return ERR_PTR(-ENOMEM);
35874426fbfSRobert Jarzmik 
35974426fbfSRobert Jarzmik 	for (i = 0; i < AC97_BUS_MAX_CODECS && codecs_pdata; i++)
36074426fbfSRobert Jarzmik 		ac97_ctrl->codecs_pdata[i] = codecs_pdata[i];
36174426fbfSRobert Jarzmik 
36274426fbfSRobert Jarzmik 	ac97_ctrl->ops = ops;
36374426fbfSRobert Jarzmik 	ac97_ctrl->slots_available = slots_available;
36474426fbfSRobert Jarzmik 	ac97_ctrl->parent = dev;
36574426fbfSRobert Jarzmik 	ret = ac97_add_adapter(ac97_ctrl);
36674426fbfSRobert Jarzmik 
36774426fbfSRobert Jarzmik 	if (ret)
36874426fbfSRobert Jarzmik 		goto err;
36974426fbfSRobert Jarzmik 	ac97_bus_reset(ac97_ctrl);
37074426fbfSRobert Jarzmik 	ac97_bus_scan(ac97_ctrl);
37174426fbfSRobert Jarzmik 
37274426fbfSRobert Jarzmik 	return ac97_ctrl;
37374426fbfSRobert Jarzmik err:
37474426fbfSRobert Jarzmik 	kfree(ac97_ctrl);
37574426fbfSRobert Jarzmik 	return ERR_PTR(ret);
37674426fbfSRobert Jarzmik }
37774426fbfSRobert Jarzmik EXPORT_SYMBOL_GPL(snd_ac97_controller_register);
37874426fbfSRobert Jarzmik 
37974426fbfSRobert Jarzmik /**
38074426fbfSRobert Jarzmik  * snd_ac97_controller_unregister - unregister an ac97 controller
38174426fbfSRobert Jarzmik  * @ac97_ctrl: the device previously provided to ac97_controller_register()
38274426fbfSRobert Jarzmik  *
38374426fbfSRobert Jarzmik  */
snd_ac97_controller_unregister(struct ac97_controller * ac97_ctrl)38474426fbfSRobert Jarzmik void snd_ac97_controller_unregister(struct ac97_controller *ac97_ctrl)
38574426fbfSRobert Jarzmik {
38674426fbfSRobert Jarzmik 	ac97_del_adapter(ac97_ctrl);
38774426fbfSRobert Jarzmik }
38874426fbfSRobert Jarzmik EXPORT_SYMBOL_GPL(snd_ac97_controller_unregister);
38974426fbfSRobert Jarzmik 
39074426fbfSRobert Jarzmik #ifdef CONFIG_PM
ac97_pm_runtime_suspend(struct device * dev)39174426fbfSRobert Jarzmik static int ac97_pm_runtime_suspend(struct device *dev)
39274426fbfSRobert Jarzmik {
39374426fbfSRobert Jarzmik 	struct ac97_codec_device *codec = to_ac97_device(dev);
39474426fbfSRobert Jarzmik 	int ret = pm_generic_runtime_suspend(dev);
39574426fbfSRobert Jarzmik 
39674426fbfSRobert Jarzmik 	if (ret == 0 && dev->driver) {
39774426fbfSRobert Jarzmik 		if (pm_runtime_is_irq_safe(dev))
39874426fbfSRobert Jarzmik 			clk_disable(codec->clk);
39974426fbfSRobert Jarzmik 		else
40074426fbfSRobert Jarzmik 			clk_disable_unprepare(codec->clk);
40174426fbfSRobert Jarzmik 	}
40274426fbfSRobert Jarzmik 
40374426fbfSRobert Jarzmik 	return ret;
40474426fbfSRobert Jarzmik }
40574426fbfSRobert Jarzmik 
ac97_pm_runtime_resume(struct device * dev)40674426fbfSRobert Jarzmik static int ac97_pm_runtime_resume(struct device *dev)
40774426fbfSRobert Jarzmik {
40874426fbfSRobert Jarzmik 	struct ac97_codec_device *codec = to_ac97_device(dev);
40974426fbfSRobert Jarzmik 	int ret;
41074426fbfSRobert Jarzmik 
41174426fbfSRobert Jarzmik 	if (dev->driver) {
41274426fbfSRobert Jarzmik 		if (pm_runtime_is_irq_safe(dev))
41374426fbfSRobert Jarzmik 			ret = clk_enable(codec->clk);
41474426fbfSRobert Jarzmik 		else
41574426fbfSRobert Jarzmik 			ret = clk_prepare_enable(codec->clk);
41674426fbfSRobert Jarzmik 		if (ret)
41774426fbfSRobert Jarzmik 			return ret;
41874426fbfSRobert Jarzmik 	}
41974426fbfSRobert Jarzmik 
42074426fbfSRobert Jarzmik 	return pm_generic_runtime_resume(dev);
42174426fbfSRobert Jarzmik }
42274426fbfSRobert Jarzmik #endif /* CONFIG_PM */
42374426fbfSRobert Jarzmik 
42474426fbfSRobert Jarzmik static const struct dev_pm_ops ac97_pm = {
42574426fbfSRobert Jarzmik 	.suspend	= pm_generic_suspend,
42674426fbfSRobert Jarzmik 	.resume		= pm_generic_resume,
42774426fbfSRobert Jarzmik 	.freeze		= pm_generic_freeze,
42874426fbfSRobert Jarzmik 	.thaw		= pm_generic_thaw,
42974426fbfSRobert Jarzmik 	.poweroff	= pm_generic_poweroff,
43074426fbfSRobert Jarzmik 	.restore	= pm_generic_restore,
43174426fbfSRobert Jarzmik 	SET_RUNTIME_PM_OPS(
43274426fbfSRobert Jarzmik 		ac97_pm_runtime_suspend,
43374426fbfSRobert Jarzmik 		ac97_pm_runtime_resume,
43474426fbfSRobert Jarzmik 		NULL)
43574426fbfSRobert Jarzmik };
43674426fbfSRobert Jarzmik 
ac97_get_enable_clk(struct ac97_codec_device * adev)43774426fbfSRobert Jarzmik static int ac97_get_enable_clk(struct ac97_codec_device *adev)
43874426fbfSRobert Jarzmik {
43974426fbfSRobert Jarzmik 	int ret;
44074426fbfSRobert Jarzmik 
44174426fbfSRobert Jarzmik 	adev->clk = clk_get(&adev->dev, "ac97_clk");
44274426fbfSRobert Jarzmik 	if (IS_ERR(adev->clk))
44374426fbfSRobert Jarzmik 		return PTR_ERR(adev->clk);
44474426fbfSRobert Jarzmik 
44574426fbfSRobert Jarzmik 	ret = clk_prepare_enable(adev->clk);
44674426fbfSRobert Jarzmik 	if (ret)
44774426fbfSRobert Jarzmik 		clk_put(adev->clk);
44874426fbfSRobert Jarzmik 
44974426fbfSRobert Jarzmik 	return ret;
45074426fbfSRobert Jarzmik }
45174426fbfSRobert Jarzmik 
ac97_put_disable_clk(struct ac97_codec_device * adev)45274426fbfSRobert Jarzmik static void ac97_put_disable_clk(struct ac97_codec_device *adev)
45374426fbfSRobert Jarzmik {
45474426fbfSRobert Jarzmik 	clk_disable_unprepare(adev->clk);
45574426fbfSRobert Jarzmik 	clk_put(adev->clk);
45674426fbfSRobert Jarzmik }
45774426fbfSRobert Jarzmik 
vendor_id_show(struct device * dev,struct device_attribute * attr,char * buf)45874426fbfSRobert Jarzmik static ssize_t vendor_id_show(struct device *dev,
45974426fbfSRobert Jarzmik 			      struct device_attribute *attr, char *buf)
46074426fbfSRobert Jarzmik {
46174426fbfSRobert Jarzmik 	struct ac97_codec_device *codec = to_ac97_device(dev);
46274426fbfSRobert Jarzmik 
4637450320eSTakashi Iwai 	return sysfs_emit(buf, "%08x", codec->vendor_id);
46474426fbfSRobert Jarzmik }
465*d28dc3d8SYu Liao static DEVICE_ATTR_RO(vendor_id);
46674426fbfSRobert Jarzmik 
46774426fbfSRobert Jarzmik static struct attribute *ac97_dev_attrs[] = {
46874426fbfSRobert Jarzmik 	&dev_attr_vendor_id.attr,
46974426fbfSRobert Jarzmik 	NULL,
47074426fbfSRobert Jarzmik };
47174426fbfSRobert Jarzmik ATTRIBUTE_GROUPS(ac97_dev);
47274426fbfSRobert Jarzmik 
ac97_bus_match(struct device * dev,struct device_driver * drv)47374426fbfSRobert Jarzmik static int ac97_bus_match(struct device *dev, struct device_driver *drv)
47474426fbfSRobert Jarzmik {
47574426fbfSRobert Jarzmik 	struct ac97_codec_device *adev = to_ac97_device(dev);
47674426fbfSRobert Jarzmik 	struct ac97_codec_driver *adrv = to_ac97_driver(drv);
47774426fbfSRobert Jarzmik 	const struct ac97_id *id = adrv->id_table;
47874426fbfSRobert Jarzmik 	int i = 0;
47974426fbfSRobert Jarzmik 
48074426fbfSRobert Jarzmik 	if (adev->vendor_id == 0x0 || adev->vendor_id == 0xffffffff)
48174426fbfSRobert Jarzmik 		return false;
48274426fbfSRobert Jarzmik 
48374426fbfSRobert Jarzmik 	do {
48474426fbfSRobert Jarzmik 		if (ac97_ids_match(id[i].id, adev->vendor_id, id[i].mask))
48574426fbfSRobert Jarzmik 			return true;
48674426fbfSRobert Jarzmik 	} while (id[i++].id);
48774426fbfSRobert Jarzmik 
48874426fbfSRobert Jarzmik 	return false;
48974426fbfSRobert Jarzmik }
49074426fbfSRobert Jarzmik 
ac97_bus_probe(struct device * dev)49174426fbfSRobert Jarzmik static int ac97_bus_probe(struct device *dev)
49274426fbfSRobert Jarzmik {
49374426fbfSRobert Jarzmik 	struct ac97_codec_device *adev = to_ac97_device(dev);
49474426fbfSRobert Jarzmik 	struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
49574426fbfSRobert Jarzmik 	int ret;
49674426fbfSRobert Jarzmik 
49774426fbfSRobert Jarzmik 	ret = ac97_get_enable_clk(adev);
49874426fbfSRobert Jarzmik 	if (ret)
49974426fbfSRobert Jarzmik 		return ret;
50074426fbfSRobert Jarzmik 
50174426fbfSRobert Jarzmik 	pm_runtime_get_noresume(dev);
50274426fbfSRobert Jarzmik 	pm_runtime_set_active(dev);
50374426fbfSRobert Jarzmik 	pm_runtime_enable(dev);
50474426fbfSRobert Jarzmik 
50574426fbfSRobert Jarzmik 	ret = adrv->probe(adev);
50674426fbfSRobert Jarzmik 	if (ret == 0)
50774426fbfSRobert Jarzmik 		return 0;
50874426fbfSRobert Jarzmik 
50974426fbfSRobert Jarzmik 	pm_runtime_disable(dev);
51074426fbfSRobert Jarzmik 	pm_runtime_set_suspended(dev);
51174426fbfSRobert Jarzmik 	pm_runtime_put_noidle(dev);
51274426fbfSRobert Jarzmik 	ac97_put_disable_clk(adev);
51374426fbfSRobert Jarzmik 
51474426fbfSRobert Jarzmik 	return ret;
51574426fbfSRobert Jarzmik }
51674426fbfSRobert Jarzmik 
ac97_bus_remove(struct device * dev)517fc7a6209SUwe Kleine-König static void ac97_bus_remove(struct device *dev)
51874426fbfSRobert Jarzmik {
51974426fbfSRobert Jarzmik 	struct ac97_codec_device *adev = to_ac97_device(dev);
52074426fbfSRobert Jarzmik 	struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
52174426fbfSRobert Jarzmik 	int ret;
52274426fbfSRobert Jarzmik 
523a38e9330SYufen Yu 	ret = pm_runtime_resume_and_get(dev);
524d15ec0b4SLihua Yao 	if (ret < 0)
525fc7a6209SUwe Kleine-König 		return;
52674426fbfSRobert Jarzmik 
5277351324cSDawei Li 	adrv->remove(adev);
52874426fbfSRobert Jarzmik 	pm_runtime_put_noidle(dev);
52974426fbfSRobert Jarzmik 	ac97_put_disable_clk(adev);
53074426fbfSRobert Jarzmik 
531250ea7c5SLihua Yao 	pm_runtime_disable(dev);
53274426fbfSRobert Jarzmik }
53374426fbfSRobert Jarzmik 
53474426fbfSRobert Jarzmik static struct bus_type ac97_bus_type = {
53574426fbfSRobert Jarzmik 	.name		= "ac97bus",
53674426fbfSRobert Jarzmik 	.dev_groups	= ac97_dev_groups,
53774426fbfSRobert Jarzmik 	.match		= ac97_bus_match,
53874426fbfSRobert Jarzmik 	.pm		= &ac97_pm,
53974426fbfSRobert Jarzmik 	.probe		= ac97_bus_probe,
54074426fbfSRobert Jarzmik 	.remove		= ac97_bus_remove,
54174426fbfSRobert Jarzmik };
54274426fbfSRobert Jarzmik 
ac97_bus_init(void)54374426fbfSRobert Jarzmik static int __init ac97_bus_init(void)
54474426fbfSRobert Jarzmik {
54574426fbfSRobert Jarzmik 	return bus_register(&ac97_bus_type);
54674426fbfSRobert Jarzmik }
54774426fbfSRobert Jarzmik subsys_initcall(ac97_bus_init);
54874426fbfSRobert Jarzmik 
ac97_bus_exit(void)54974426fbfSRobert Jarzmik static void __exit ac97_bus_exit(void)
55074426fbfSRobert Jarzmik {
55174426fbfSRobert Jarzmik 	bus_unregister(&ac97_bus_type);
55274426fbfSRobert Jarzmik }
55374426fbfSRobert Jarzmik module_exit(ac97_bus_exit);
55474426fbfSRobert Jarzmik 
55574426fbfSRobert Jarzmik MODULE_LICENSE("GPL");
55674426fbfSRobert Jarzmik MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
557