Commit | Line | Data |
---|---|---|
74426fbf RJ |
1 | /* |
2 | * Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr> | |
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/list.h> | |
10 | #include <linux/slab.h> | |
11 | #include <sound/ac97/codec.h> | |
12 | #include <sound/ac97/compat.h> | |
13 | #include <sound/ac97/controller.h> | |
14 | #include <sound/soc.h> | |
15 | ||
16 | #include "ac97_core.h" | |
17 | ||
c7b81707 LY |
18 | static void compat_ac97_release(struct device *dev) |
19 | { | |
20 | kfree(to_ac97_t(dev)); | |
21 | } | |
22 | ||
74426fbf RJ |
23 | static void compat_ac97_reset(struct snd_ac97 *ac97) |
24 | { | |
25 | struct ac97_codec_device *adev = to_ac97_device(ac97->private_data); | |
26 | struct ac97_controller *actrl = adev->ac97_ctrl; | |
27 | ||
28 | if (actrl->ops->reset) | |
29 | actrl->ops->reset(actrl); | |
30 | } | |
31 | ||
32 | static void compat_ac97_warm_reset(struct snd_ac97 *ac97) | |
33 | { | |
34 | struct ac97_codec_device *adev = to_ac97_device(ac97->private_data); | |
35 | struct ac97_controller *actrl = adev->ac97_ctrl; | |
36 | ||
37 | if (actrl->ops->warm_reset) | |
38 | actrl->ops->warm_reset(actrl); | |
39 | } | |
40 | ||
41 | static void compat_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |
42 | unsigned short val) | |
43 | { | |
44 | struct ac97_codec_device *adev = to_ac97_device(ac97->private_data); | |
45 | struct ac97_controller *actrl = adev->ac97_ctrl; | |
46 | ||
47 | actrl->ops->write(actrl, ac97->num, reg, val); | |
48 | } | |
49 | ||
50 | static unsigned short compat_ac97_read(struct snd_ac97 *ac97, | |
51 | unsigned short reg) | |
52 | { | |
53 | struct ac97_codec_device *adev = to_ac97_device(ac97->private_data); | |
54 | struct ac97_controller *actrl = adev->ac97_ctrl; | |
55 | ||
56 | return actrl->ops->read(actrl, ac97->num, reg); | |
57 | } | |
58 | ||
59 | static struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = { | |
60 | .reset = compat_ac97_reset, | |
61 | .warm_reset = compat_ac97_warm_reset, | |
62 | .write = compat_ac97_write, | |
63 | .read = compat_ac97_read, | |
64 | }; | |
65 | ||
66 | static struct snd_ac97_bus compat_soc_ac97_bus = { | |
67 | .ops = &compat_snd_ac97_bus_ops, | |
68 | }; | |
69 | ||
70 | struct snd_ac97 *snd_ac97_compat_alloc(struct ac97_codec_device *adev) | |
71 | { | |
72 | struct snd_ac97 *ac97; | |
c7b81707 | 73 | int ret; |
74426fbf RJ |
74 | |
75 | ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); | |
76 | if (ac97 == NULL) | |
77 | return ERR_PTR(-ENOMEM); | |
78 | ||
74426fbf RJ |
79 | ac97->private_data = adev; |
80 | ac97->bus = &compat_soc_ac97_bus; | |
c7b81707 LY |
81 | |
82 | ac97->dev.parent = &adev->dev; | |
83 | ac97->dev.release = compat_ac97_release; | |
84 | dev_set_name(&ac97->dev, "%s-compat", dev_name(&adev->dev)); | |
85 | ret = device_register(&ac97->dev); | |
86 | if (ret) { | |
87 | put_device(&ac97->dev); | |
88 | return ERR_PTR(ret); | |
89 | } | |
90 | ||
74426fbf RJ |
91 | return ac97; |
92 | } | |
93 | EXPORT_SYMBOL_GPL(snd_ac97_compat_alloc); | |
94 | ||
95 | void snd_ac97_compat_release(struct snd_ac97 *ac97) | |
96 | { | |
c7b81707 | 97 | device_unregister(&ac97->dev); |
74426fbf RJ |
98 | } |
99 | EXPORT_SYMBOL_GPL(snd_ac97_compat_release); | |
100 | ||
101 | int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id, | |
102 | unsigned int id_mask) | |
103 | { | |
104 | struct ac97_codec_device *adev = to_ac97_device(ac97->private_data); | |
105 | struct ac97_controller *actrl = adev->ac97_ctrl; | |
106 | unsigned int scanned; | |
107 | ||
108 | if (try_warm) { | |
109 | compat_ac97_warm_reset(ac97); | |
110 | scanned = snd_ac97_bus_scan_one(actrl, adev->num); | |
111 | if (ac97_ids_match(scanned, adev->vendor_id, id_mask)) | |
112 | return 1; | |
113 | } | |
114 | ||
115 | compat_ac97_reset(ac97); | |
116 | compat_ac97_warm_reset(ac97); | |
117 | scanned = snd_ac97_bus_scan_one(actrl, adev->num); | |
118 | if (ac97_ids_match(scanned, adev->vendor_id, id_mask)) | |
119 | return 0; | |
120 | ||
121 | return -ENODEV; | |
122 | } | |
123 | EXPORT_SYMBOL_GPL(snd_ac97_reset); |