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* 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 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 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 * 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 * 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", ®)) || 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 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 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 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 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 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 */ 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 */ 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 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 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 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 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 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 46374426fbfSRobert Jarzmik return sprintf(buf, "%08x", codec->vendor_id); 46474426fbfSRobert Jarzmik } 46574426fbfSRobert Jarzmik 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 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 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 517*fc7a6209SUwe 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) 525*fc7a6209SUwe Kleine-König return; 52674426fbfSRobert Jarzmik 52774426fbfSRobert Jarzmik ret = adrv->remove(adev); 52874426fbfSRobert Jarzmik pm_runtime_put_noidle(dev); 52974426fbfSRobert Jarzmik if (ret == 0) 53074426fbfSRobert Jarzmik ac97_put_disable_clk(adev); 53174426fbfSRobert Jarzmik 532250ea7c5SLihua Yao pm_runtime_disable(dev); 53374426fbfSRobert Jarzmik } 53474426fbfSRobert Jarzmik 53574426fbfSRobert Jarzmik static struct bus_type ac97_bus_type = { 53674426fbfSRobert Jarzmik .name = "ac97bus", 53774426fbfSRobert Jarzmik .dev_groups = ac97_dev_groups, 53874426fbfSRobert Jarzmik .match = ac97_bus_match, 53974426fbfSRobert Jarzmik .pm = &ac97_pm, 54074426fbfSRobert Jarzmik .probe = ac97_bus_probe, 54174426fbfSRobert Jarzmik .remove = ac97_bus_remove, 54274426fbfSRobert Jarzmik }; 54374426fbfSRobert Jarzmik 54474426fbfSRobert Jarzmik static int __init ac97_bus_init(void) 54574426fbfSRobert Jarzmik { 54674426fbfSRobert Jarzmik return bus_register(&ac97_bus_type); 54774426fbfSRobert Jarzmik } 54874426fbfSRobert Jarzmik subsys_initcall(ac97_bus_init); 54974426fbfSRobert Jarzmik 55074426fbfSRobert Jarzmik static void __exit ac97_bus_exit(void) 55174426fbfSRobert Jarzmik { 55274426fbfSRobert Jarzmik bus_unregister(&ac97_bus_type); 55374426fbfSRobert Jarzmik } 55474426fbfSRobert Jarzmik module_exit(ac97_bus_exit); 55574426fbfSRobert Jarzmik 55674426fbfSRobert Jarzmik MODULE_LICENSE("GPL"); 55774426fbfSRobert Jarzmik MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>"); 558