xref: /OK3568_Linux_fs/kernel/sound/ac97/bus.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <linux/module.h>
7*4882a593Smuzhiyun #include <linux/bitops.h>
8*4882a593Smuzhiyun #include <linux/clk.h>
9*4882a593Smuzhiyun #include <linux/device.h>
10*4882a593Smuzhiyun #include <linux/idr.h>
11*4882a593Smuzhiyun #include <linux/list.h>
12*4882a593Smuzhiyun #include <linux/mutex.h>
13*4882a593Smuzhiyun #include <linux/of.h>
14*4882a593Smuzhiyun #include <linux/pm.h>
15*4882a593Smuzhiyun #include <linux/pm_runtime.h>
16*4882a593Smuzhiyun #include <linux/slab.h>
17*4882a593Smuzhiyun #include <linux/sysfs.h>
18*4882a593Smuzhiyun #include <sound/ac97/codec.h>
19*4882a593Smuzhiyun #include <sound/ac97/controller.h>
20*4882a593Smuzhiyun #include <sound/ac97/regs.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include "ac97_core.h"
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun /*
25*4882a593Smuzhiyun  * Protects ac97_controllers and each ac97_controller structure.
26*4882a593Smuzhiyun  */
27*4882a593Smuzhiyun static DEFINE_MUTEX(ac97_controllers_mutex);
28*4882a593Smuzhiyun static DEFINE_IDR(ac97_adapter_idr);
29*4882a593Smuzhiyun static LIST_HEAD(ac97_controllers);
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun static struct bus_type ac97_bus_type;
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun static inline struct ac97_controller*
to_ac97_controller(struct device * ac97_adapter)34*4882a593Smuzhiyun to_ac97_controller(struct device *ac97_adapter)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	return container_of(ac97_adapter, struct ac97_controller, adap);
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
ac97_unbound_ctrl_write(struct ac97_controller * adrv,int slot,unsigned short reg,unsigned short val)39*4882a593Smuzhiyun static int ac97_unbound_ctrl_write(struct ac97_controller *adrv, int slot,
40*4882a593Smuzhiyun 		     unsigned short reg, unsigned short val)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	return -ENODEV;
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun 
ac97_unbound_ctrl_read(struct ac97_controller * adrv,int slot,unsigned short reg)45*4882a593Smuzhiyun static int ac97_unbound_ctrl_read(struct ac97_controller *adrv, int slot,
46*4882a593Smuzhiyun 				  unsigned short reg)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	return -ENODEV;
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun static const struct ac97_controller_ops ac97_unbound_ctrl_ops = {
52*4882a593Smuzhiyun 	.write = ac97_unbound_ctrl_write,
53*4882a593Smuzhiyun 	.read = ac97_unbound_ctrl_read,
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun static struct ac97_controller ac97_unbound_ctrl = {
57*4882a593Smuzhiyun 	.ops = &ac97_unbound_ctrl_ops,
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun static struct ac97_codec_device *
ac97_codec_find(struct ac97_controller * ac97_ctrl,unsigned int codec_num)61*4882a593Smuzhiyun ac97_codec_find(struct ac97_controller *ac97_ctrl, unsigned int codec_num)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	if (codec_num >= AC97_BUS_MAX_CODECS)
64*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	return ac97_ctrl->codecs[codec_num];
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun static struct device_node *
ac97_of_get_child_device(struct ac97_controller * ac97_ctrl,int idx,unsigned int vendor_id)70*4882a593Smuzhiyun ac97_of_get_child_device(struct ac97_controller *ac97_ctrl, int idx,
71*4882a593Smuzhiyun 			 unsigned int vendor_id)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	struct device_node *node;
74*4882a593Smuzhiyun 	u32 reg;
75*4882a593Smuzhiyun 	char compat[] = "ac97,0000,0000";
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	snprintf(compat, sizeof(compat), "ac97,%04x,%04x",
78*4882a593Smuzhiyun 		 vendor_id >> 16, vendor_id & 0xffff);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	for_each_child_of_node(ac97_ctrl->parent->of_node, node) {
81*4882a593Smuzhiyun 		if ((idx != of_property_read_u32(node, "reg", &reg)) ||
82*4882a593Smuzhiyun 		    !of_device_is_compatible(node, compat))
83*4882a593Smuzhiyun 			continue;
84*4882a593Smuzhiyun 		return node;
85*4882a593Smuzhiyun 	}
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return NULL;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
ac97_codec_release(struct device * dev)90*4882a593Smuzhiyun static void ac97_codec_release(struct device *dev)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	struct ac97_codec_device *adev;
93*4882a593Smuzhiyun 	struct ac97_controller *ac97_ctrl;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	adev = to_ac97_device(dev);
96*4882a593Smuzhiyun 	ac97_ctrl = adev->ac97_ctrl;
97*4882a593Smuzhiyun 	ac97_ctrl->codecs[adev->num] = NULL;
98*4882a593Smuzhiyun 	of_node_put(dev->of_node);
99*4882a593Smuzhiyun 	kfree(adev);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
ac97_codec_add(struct ac97_controller * ac97_ctrl,int idx,unsigned int vendor_id)102*4882a593Smuzhiyun static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx,
103*4882a593Smuzhiyun 		   unsigned int vendor_id)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	struct ac97_codec_device *codec;
106*4882a593Smuzhiyun 	int ret;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
109*4882a593Smuzhiyun 	if (!codec)
110*4882a593Smuzhiyun 		return -ENOMEM;
111*4882a593Smuzhiyun 	ac97_ctrl->codecs[idx] = codec;
112*4882a593Smuzhiyun 	codec->vendor_id = vendor_id;
113*4882a593Smuzhiyun 	codec->dev.release = ac97_codec_release;
114*4882a593Smuzhiyun 	codec->dev.bus = &ac97_bus_type;
115*4882a593Smuzhiyun 	codec->dev.parent = &ac97_ctrl->adap;
116*4882a593Smuzhiyun 	codec->num = idx;
117*4882a593Smuzhiyun 	codec->ac97_ctrl = ac97_ctrl;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	device_initialize(&codec->dev);
120*4882a593Smuzhiyun 	dev_set_name(&codec->dev, "%s:%u", dev_name(ac97_ctrl->parent), idx);
121*4882a593Smuzhiyun 	codec->dev.of_node = ac97_of_get_child_device(ac97_ctrl, idx,
122*4882a593Smuzhiyun 						      vendor_id);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	ret = device_add(&codec->dev);
125*4882a593Smuzhiyun 	if (ret) {
126*4882a593Smuzhiyun 		put_device(&codec->dev);
127*4882a593Smuzhiyun 		return ret;
128*4882a593Smuzhiyun 	}
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	return 0;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
snd_ac97_bus_scan_one(struct ac97_controller * adrv,unsigned int codec_num)133*4882a593Smuzhiyun unsigned int snd_ac97_bus_scan_one(struct ac97_controller *adrv,
134*4882a593Smuzhiyun 				   unsigned int codec_num)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun 	unsigned short vid1, vid2;
137*4882a593Smuzhiyun 	int ret;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	ret = adrv->ops->read(adrv, codec_num, AC97_VENDOR_ID1);
140*4882a593Smuzhiyun 	vid1 = (ret & 0xffff);
141*4882a593Smuzhiyun 	if (ret < 0)
142*4882a593Smuzhiyun 		return 0;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	ret = adrv->ops->read(adrv, codec_num, AC97_VENDOR_ID2);
145*4882a593Smuzhiyun 	vid2 = (ret & 0xffff);
146*4882a593Smuzhiyun 	if (ret < 0)
147*4882a593Smuzhiyun 		return 0;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	dev_dbg(&adrv->adap, "%s(codec_num=%u): vendor_id=0x%08x\n",
150*4882a593Smuzhiyun 		__func__, codec_num, AC97_ID(vid1, vid2));
151*4882a593Smuzhiyun 	return AC97_ID(vid1, vid2);
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
ac97_bus_scan(struct ac97_controller * ac97_ctrl)154*4882a593Smuzhiyun static int ac97_bus_scan(struct ac97_controller *ac97_ctrl)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun 	int ret, i;
157*4882a593Smuzhiyun 	unsigned int vendor_id;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	for (i = 0; i < AC97_BUS_MAX_CODECS; i++) {
160*4882a593Smuzhiyun 		if (ac97_codec_find(ac97_ctrl, i))
161*4882a593Smuzhiyun 			continue;
162*4882a593Smuzhiyun 		if (!(ac97_ctrl->slots_available & BIT(i)))
163*4882a593Smuzhiyun 			continue;
164*4882a593Smuzhiyun 		vendor_id = snd_ac97_bus_scan_one(ac97_ctrl, i);
165*4882a593Smuzhiyun 		if (!vendor_id)
166*4882a593Smuzhiyun 			continue;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 		ret = ac97_codec_add(ac97_ctrl, i, vendor_id);
169*4882a593Smuzhiyun 		if (ret < 0)
170*4882a593Smuzhiyun 			return ret;
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 	return 0;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
ac97_bus_reset(struct ac97_controller * ac97_ctrl)175*4882a593Smuzhiyun static int ac97_bus_reset(struct ac97_controller *ac97_ctrl)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 	ac97_ctrl->ops->reset(ac97_ctrl);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	return 0;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun /**
183*4882a593Smuzhiyun  * snd_ac97_codec_driver_register - register an AC97 codec driver
184*4882a593Smuzhiyun  * @dev: AC97 driver codec to register
185*4882a593Smuzhiyun  *
186*4882a593Smuzhiyun  * Register an AC97 codec driver to the ac97 bus driver, aka. the AC97 digital
187*4882a593Smuzhiyun  * controller.
188*4882a593Smuzhiyun  *
189*4882a593Smuzhiyun  * Returns 0 on success or error code
190*4882a593Smuzhiyun  */
snd_ac97_codec_driver_register(struct ac97_codec_driver * drv)191*4882a593Smuzhiyun int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	drv->driver.bus = &ac97_bus_type;
194*4882a593Smuzhiyun 	return driver_register(&drv->driver);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_ac97_codec_driver_register);
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun /**
199*4882a593Smuzhiyun  * snd_ac97_codec_driver_unregister - unregister an AC97 codec driver
200*4882a593Smuzhiyun  * @dev: AC97 codec driver to unregister
201*4882a593Smuzhiyun  *
202*4882a593Smuzhiyun  * Unregister a previously registered ac97 codec driver.
203*4882a593Smuzhiyun  */
snd_ac97_codec_driver_unregister(struct ac97_codec_driver * drv)204*4882a593Smuzhiyun void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	driver_unregister(&drv->driver);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_ac97_codec_driver_unregister);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun /**
211*4882a593Smuzhiyun  * snd_ac97_codec_get_platdata - get platform_data
212*4882a593Smuzhiyun  * @adev: the ac97 codec device
213*4882a593Smuzhiyun  *
214*4882a593Smuzhiyun  * For legacy platforms, in order to have platform_data in codec drivers
215*4882a593Smuzhiyun  * available, while ac97 device are auto-created upon probe, this retrieves the
216*4882a593Smuzhiyun  * platdata which was setup on ac97 controller registration.
217*4882a593Smuzhiyun  *
218*4882a593Smuzhiyun  * Returns the platform data pointer
219*4882a593Smuzhiyun  */
snd_ac97_codec_get_platdata(const struct ac97_codec_device * adev)220*4882a593Smuzhiyun void *snd_ac97_codec_get_platdata(const struct ac97_codec_device *adev)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	struct ac97_controller *ac97_ctrl = adev->ac97_ctrl;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	return ac97_ctrl->codecs_pdata[adev->num];
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_ac97_codec_get_platdata);
227*4882a593Smuzhiyun 
ac97_ctrl_codecs_unregister(struct ac97_controller * ac97_ctrl)228*4882a593Smuzhiyun static void ac97_ctrl_codecs_unregister(struct ac97_controller *ac97_ctrl)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun 	int i;
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	for (i = 0; i < AC97_BUS_MAX_CODECS; i++)
233*4882a593Smuzhiyun 		if (ac97_ctrl->codecs[i]) {
234*4882a593Smuzhiyun 			ac97_ctrl->codecs[i]->ac97_ctrl = &ac97_unbound_ctrl;
235*4882a593Smuzhiyun 			device_unregister(&ac97_ctrl->codecs[i]->dev);
236*4882a593Smuzhiyun 		}
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
cold_reset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)239*4882a593Smuzhiyun static ssize_t cold_reset_store(struct device *dev,
240*4882a593Smuzhiyun 				struct device_attribute *attr, const char *buf,
241*4882a593Smuzhiyun 				size_t len)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	struct ac97_controller *ac97_ctrl;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	mutex_lock(&ac97_controllers_mutex);
246*4882a593Smuzhiyun 	ac97_ctrl = to_ac97_controller(dev);
247*4882a593Smuzhiyun 	ac97_ctrl->ops->reset(ac97_ctrl);
248*4882a593Smuzhiyun 	mutex_unlock(&ac97_controllers_mutex);
249*4882a593Smuzhiyun 	return len;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun static DEVICE_ATTR_WO(cold_reset);
252*4882a593Smuzhiyun 
warm_reset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)253*4882a593Smuzhiyun static ssize_t warm_reset_store(struct device *dev,
254*4882a593Smuzhiyun 				struct device_attribute *attr, const char *buf,
255*4882a593Smuzhiyun 				size_t len)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	struct ac97_controller *ac97_ctrl;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	if (!dev)
260*4882a593Smuzhiyun 		return -ENODEV;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	mutex_lock(&ac97_controllers_mutex);
263*4882a593Smuzhiyun 	ac97_ctrl = to_ac97_controller(dev);
264*4882a593Smuzhiyun 	ac97_ctrl->ops->warm_reset(ac97_ctrl);
265*4882a593Smuzhiyun 	mutex_unlock(&ac97_controllers_mutex);
266*4882a593Smuzhiyun 	return len;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun static DEVICE_ATTR_WO(warm_reset);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun static struct attribute *ac97_controller_device_attrs[] = {
271*4882a593Smuzhiyun 	&dev_attr_cold_reset.attr,
272*4882a593Smuzhiyun 	&dev_attr_warm_reset.attr,
273*4882a593Smuzhiyun 	NULL
274*4882a593Smuzhiyun };
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun static struct attribute_group ac97_adapter_attr_group = {
277*4882a593Smuzhiyun 	.name	= "ac97_operations",
278*4882a593Smuzhiyun 	.attrs	= ac97_controller_device_attrs,
279*4882a593Smuzhiyun };
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun static const struct attribute_group *ac97_adapter_groups[] = {
282*4882a593Smuzhiyun 	&ac97_adapter_attr_group,
283*4882a593Smuzhiyun 	NULL,
284*4882a593Smuzhiyun };
285*4882a593Smuzhiyun 
ac97_del_adapter(struct ac97_controller * ac97_ctrl)286*4882a593Smuzhiyun static void ac97_del_adapter(struct ac97_controller *ac97_ctrl)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun 	mutex_lock(&ac97_controllers_mutex);
289*4882a593Smuzhiyun 	ac97_ctrl_codecs_unregister(ac97_ctrl);
290*4882a593Smuzhiyun 	list_del(&ac97_ctrl->controllers);
291*4882a593Smuzhiyun 	mutex_unlock(&ac97_controllers_mutex);
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	device_unregister(&ac97_ctrl->adap);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun 
ac97_adapter_release(struct device * dev)296*4882a593Smuzhiyun static void ac97_adapter_release(struct device *dev)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun 	struct ac97_controller *ac97_ctrl;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	ac97_ctrl = to_ac97_controller(dev);
301*4882a593Smuzhiyun 	idr_remove(&ac97_adapter_idr, ac97_ctrl->nr);
302*4882a593Smuzhiyun 	dev_dbg(&ac97_ctrl->adap, "adapter unregistered by %s\n",
303*4882a593Smuzhiyun 		dev_name(ac97_ctrl->parent));
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun static const struct device_type ac97_adapter_type = {
307*4882a593Smuzhiyun 	.groups		= ac97_adapter_groups,
308*4882a593Smuzhiyun 	.release	= ac97_adapter_release,
309*4882a593Smuzhiyun };
310*4882a593Smuzhiyun 
ac97_add_adapter(struct ac97_controller * ac97_ctrl)311*4882a593Smuzhiyun static int ac97_add_adapter(struct ac97_controller *ac97_ctrl)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun 	int ret;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	mutex_lock(&ac97_controllers_mutex);
316*4882a593Smuzhiyun 	ret = idr_alloc(&ac97_adapter_idr, ac97_ctrl, 0, 0, GFP_KERNEL);
317*4882a593Smuzhiyun 	ac97_ctrl->nr = ret;
318*4882a593Smuzhiyun 	if (ret >= 0) {
319*4882a593Smuzhiyun 		dev_set_name(&ac97_ctrl->adap, "ac97-%d", ret);
320*4882a593Smuzhiyun 		ac97_ctrl->adap.type = &ac97_adapter_type;
321*4882a593Smuzhiyun 		ac97_ctrl->adap.parent = ac97_ctrl->parent;
322*4882a593Smuzhiyun 		ret = device_register(&ac97_ctrl->adap);
323*4882a593Smuzhiyun 		if (ret)
324*4882a593Smuzhiyun 			put_device(&ac97_ctrl->adap);
325*4882a593Smuzhiyun 	}
326*4882a593Smuzhiyun 	if (!ret)
327*4882a593Smuzhiyun 		list_add(&ac97_ctrl->controllers, &ac97_controllers);
328*4882a593Smuzhiyun 	mutex_unlock(&ac97_controllers_mutex);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	if (!ret)
331*4882a593Smuzhiyun 		dev_dbg(&ac97_ctrl->adap, "adapter registered by %s\n",
332*4882a593Smuzhiyun 			dev_name(ac97_ctrl->parent));
333*4882a593Smuzhiyun 	return ret;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun /**
337*4882a593Smuzhiyun  * snd_ac97_controller_register - register an ac97 controller
338*4882a593Smuzhiyun  * @ops: the ac97 bus operations
339*4882a593Smuzhiyun  * @dev: the device providing the ac97 DC function
340*4882a593Smuzhiyun  * @slots_available: mask of the ac97 codecs that can be scanned and probed
341*4882a593Smuzhiyun  *                   bit0 => codec 0, bit1 => codec 1 ... bit 3 => codec 3
342*4882a593Smuzhiyun  *
343*4882a593Smuzhiyun  * Register a digital controller which can control up to 4 ac97 codecs. This is
344*4882a593Smuzhiyun  * the controller side of the AC97 AC-link, while the slave side are the codecs.
345*4882a593Smuzhiyun  *
346*4882a593Smuzhiyun  * Returns a valid controller upon success, negative pointer value upon error
347*4882a593Smuzhiyun  */
snd_ac97_controller_register(const struct ac97_controller_ops * ops,struct device * dev,unsigned short slots_available,void ** codecs_pdata)348*4882a593Smuzhiyun struct ac97_controller *snd_ac97_controller_register(
349*4882a593Smuzhiyun 	const struct ac97_controller_ops *ops, struct device *dev,
350*4882a593Smuzhiyun 	unsigned short slots_available, void **codecs_pdata)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun 	struct ac97_controller *ac97_ctrl;
353*4882a593Smuzhiyun 	int ret, i;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	ac97_ctrl = kzalloc(sizeof(*ac97_ctrl), GFP_KERNEL);
356*4882a593Smuzhiyun 	if (!ac97_ctrl)
357*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	for (i = 0; i < AC97_BUS_MAX_CODECS && codecs_pdata; i++)
360*4882a593Smuzhiyun 		ac97_ctrl->codecs_pdata[i] = codecs_pdata[i];
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	ac97_ctrl->ops = ops;
363*4882a593Smuzhiyun 	ac97_ctrl->slots_available = slots_available;
364*4882a593Smuzhiyun 	ac97_ctrl->parent = dev;
365*4882a593Smuzhiyun 	ret = ac97_add_adapter(ac97_ctrl);
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	if (ret)
368*4882a593Smuzhiyun 		goto err;
369*4882a593Smuzhiyun 	ac97_bus_reset(ac97_ctrl);
370*4882a593Smuzhiyun 	ac97_bus_scan(ac97_ctrl);
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	return ac97_ctrl;
373*4882a593Smuzhiyun err:
374*4882a593Smuzhiyun 	kfree(ac97_ctrl);
375*4882a593Smuzhiyun 	return ERR_PTR(ret);
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_ac97_controller_register);
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun /**
380*4882a593Smuzhiyun  * snd_ac97_controller_unregister - unregister an ac97 controller
381*4882a593Smuzhiyun  * @ac97_ctrl: the device previously provided to ac97_controller_register()
382*4882a593Smuzhiyun  *
383*4882a593Smuzhiyun  */
snd_ac97_controller_unregister(struct ac97_controller * ac97_ctrl)384*4882a593Smuzhiyun void snd_ac97_controller_unregister(struct ac97_controller *ac97_ctrl)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun 	ac97_del_adapter(ac97_ctrl);
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_ac97_controller_unregister);
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun #ifdef CONFIG_PM
ac97_pm_runtime_suspend(struct device * dev)391*4882a593Smuzhiyun static int ac97_pm_runtime_suspend(struct device *dev)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun 	struct ac97_codec_device *codec = to_ac97_device(dev);
394*4882a593Smuzhiyun 	int ret = pm_generic_runtime_suspend(dev);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	if (ret == 0 && dev->driver) {
397*4882a593Smuzhiyun 		if (pm_runtime_is_irq_safe(dev))
398*4882a593Smuzhiyun 			clk_disable(codec->clk);
399*4882a593Smuzhiyun 		else
400*4882a593Smuzhiyun 			clk_disable_unprepare(codec->clk);
401*4882a593Smuzhiyun 	}
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	return ret;
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun 
ac97_pm_runtime_resume(struct device * dev)406*4882a593Smuzhiyun static int ac97_pm_runtime_resume(struct device *dev)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	struct ac97_codec_device *codec = to_ac97_device(dev);
409*4882a593Smuzhiyun 	int ret;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	if (dev->driver) {
412*4882a593Smuzhiyun 		if (pm_runtime_is_irq_safe(dev))
413*4882a593Smuzhiyun 			ret = clk_enable(codec->clk);
414*4882a593Smuzhiyun 		else
415*4882a593Smuzhiyun 			ret = clk_prepare_enable(codec->clk);
416*4882a593Smuzhiyun 		if (ret)
417*4882a593Smuzhiyun 			return ret;
418*4882a593Smuzhiyun 	}
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	return pm_generic_runtime_resume(dev);
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun #endif /* CONFIG_PM */
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun static const struct dev_pm_ops ac97_pm = {
425*4882a593Smuzhiyun 	.suspend	= pm_generic_suspend,
426*4882a593Smuzhiyun 	.resume		= pm_generic_resume,
427*4882a593Smuzhiyun 	.freeze		= pm_generic_freeze,
428*4882a593Smuzhiyun 	.thaw		= pm_generic_thaw,
429*4882a593Smuzhiyun 	.poweroff	= pm_generic_poweroff,
430*4882a593Smuzhiyun 	.restore	= pm_generic_restore,
431*4882a593Smuzhiyun 	SET_RUNTIME_PM_OPS(
432*4882a593Smuzhiyun 		ac97_pm_runtime_suspend,
433*4882a593Smuzhiyun 		ac97_pm_runtime_resume,
434*4882a593Smuzhiyun 		NULL)
435*4882a593Smuzhiyun };
436*4882a593Smuzhiyun 
ac97_get_enable_clk(struct ac97_codec_device * adev)437*4882a593Smuzhiyun static int ac97_get_enable_clk(struct ac97_codec_device *adev)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun 	int ret;
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	adev->clk = clk_get(&adev->dev, "ac97_clk");
442*4882a593Smuzhiyun 	if (IS_ERR(adev->clk))
443*4882a593Smuzhiyun 		return PTR_ERR(adev->clk);
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	ret = clk_prepare_enable(adev->clk);
446*4882a593Smuzhiyun 	if (ret)
447*4882a593Smuzhiyun 		clk_put(adev->clk);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	return ret;
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun 
ac97_put_disable_clk(struct ac97_codec_device * adev)452*4882a593Smuzhiyun static void ac97_put_disable_clk(struct ac97_codec_device *adev)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun 	clk_disable_unprepare(adev->clk);
455*4882a593Smuzhiyun 	clk_put(adev->clk);
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun 
vendor_id_show(struct device * dev,struct device_attribute * attr,char * buf)458*4882a593Smuzhiyun static ssize_t vendor_id_show(struct device *dev,
459*4882a593Smuzhiyun 			      struct device_attribute *attr, char *buf)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun 	struct ac97_codec_device *codec = to_ac97_device(dev);
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	return sprintf(buf, "%08x", codec->vendor_id);
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun DEVICE_ATTR_RO(vendor_id);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun static struct attribute *ac97_dev_attrs[] = {
468*4882a593Smuzhiyun 	&dev_attr_vendor_id.attr,
469*4882a593Smuzhiyun 	NULL,
470*4882a593Smuzhiyun };
471*4882a593Smuzhiyun ATTRIBUTE_GROUPS(ac97_dev);
472*4882a593Smuzhiyun 
ac97_bus_match(struct device * dev,struct device_driver * drv)473*4882a593Smuzhiyun static int ac97_bus_match(struct device *dev, struct device_driver *drv)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun 	struct ac97_codec_device *adev = to_ac97_device(dev);
476*4882a593Smuzhiyun 	struct ac97_codec_driver *adrv = to_ac97_driver(drv);
477*4882a593Smuzhiyun 	const struct ac97_id *id = adrv->id_table;
478*4882a593Smuzhiyun 	int i = 0;
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 	if (adev->vendor_id == 0x0 || adev->vendor_id == 0xffffffff)
481*4882a593Smuzhiyun 		return false;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	do {
484*4882a593Smuzhiyun 		if (ac97_ids_match(id[i].id, adev->vendor_id, id[i].mask))
485*4882a593Smuzhiyun 			return true;
486*4882a593Smuzhiyun 	} while (id[i++].id);
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	return false;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun 
ac97_bus_probe(struct device * dev)491*4882a593Smuzhiyun static int ac97_bus_probe(struct device *dev)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun 	struct ac97_codec_device *adev = to_ac97_device(dev);
494*4882a593Smuzhiyun 	struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
495*4882a593Smuzhiyun 	int ret;
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	ret = ac97_get_enable_clk(adev);
498*4882a593Smuzhiyun 	if (ret)
499*4882a593Smuzhiyun 		return ret;
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	pm_runtime_get_noresume(dev);
502*4882a593Smuzhiyun 	pm_runtime_set_active(dev);
503*4882a593Smuzhiyun 	pm_runtime_enable(dev);
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	ret = adrv->probe(adev);
506*4882a593Smuzhiyun 	if (ret == 0)
507*4882a593Smuzhiyun 		return 0;
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	pm_runtime_disable(dev);
510*4882a593Smuzhiyun 	pm_runtime_set_suspended(dev);
511*4882a593Smuzhiyun 	pm_runtime_put_noidle(dev);
512*4882a593Smuzhiyun 	ac97_put_disable_clk(adev);
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	return ret;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun 
ac97_bus_remove(struct device * dev)517*4882a593Smuzhiyun static int ac97_bus_remove(struct device *dev)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun 	struct ac97_codec_device *adev = to_ac97_device(dev);
520*4882a593Smuzhiyun 	struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
521*4882a593Smuzhiyun 	int ret;
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	ret = pm_runtime_resume_and_get(dev);
524*4882a593Smuzhiyun 	if (ret < 0)
525*4882a593Smuzhiyun 		return ret;
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	ret = adrv->remove(adev);
528*4882a593Smuzhiyun 	pm_runtime_put_noidle(dev);
529*4882a593Smuzhiyun 	if (ret == 0)
530*4882a593Smuzhiyun 		ac97_put_disable_clk(adev);
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	pm_runtime_disable(dev);
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	return ret;
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun static struct bus_type ac97_bus_type = {
538*4882a593Smuzhiyun 	.name		= "ac97bus",
539*4882a593Smuzhiyun 	.dev_groups	= ac97_dev_groups,
540*4882a593Smuzhiyun 	.match		= ac97_bus_match,
541*4882a593Smuzhiyun 	.pm		= &ac97_pm,
542*4882a593Smuzhiyun 	.probe		= ac97_bus_probe,
543*4882a593Smuzhiyun 	.remove		= ac97_bus_remove,
544*4882a593Smuzhiyun };
545*4882a593Smuzhiyun 
ac97_bus_init(void)546*4882a593Smuzhiyun static int __init ac97_bus_init(void)
547*4882a593Smuzhiyun {
548*4882a593Smuzhiyun 	return bus_register(&ac97_bus_type);
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun subsys_initcall(ac97_bus_init);
551*4882a593Smuzhiyun 
ac97_bus_exit(void)552*4882a593Smuzhiyun static void __exit ac97_bus_exit(void)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun 	bus_unregister(&ac97_bus_type);
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun module_exit(ac97_bus_exit);
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun MODULE_LICENSE("GPL");
559*4882a593Smuzhiyun MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
560