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