7825b74068f4b9a1bfce9bf739518fcd31386f46
[linux-2.6-block.git] / sound / hda / ext / hdac_ext_bus.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  hdac-ext-bus.c - HD-audio extended core bus functions.
4  *
5  *  Copyright (C) 2014-2015 Intel Corp
6  *  Author: Jeeja KP <jeeja.kp@intel.com>
7  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8  *
9  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10  */
11
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/io.h>
15 #include <sound/hdaudio_ext.h>
16
17 MODULE_DESCRIPTION("HDA extended core");
18 MODULE_LICENSE("GPL v2");
19
20 static void hdac_ext_writel(u32 value, u32 __iomem *addr)
21 {
22         writel(value, addr);
23 }
24
25 static u32 hdac_ext_readl(u32 __iomem *addr)
26 {
27         return readl(addr);
28 }
29
30 static void hdac_ext_writew(u16 value, u16 __iomem *addr)
31 {
32         writew(value, addr);
33 }
34
35 static u16 hdac_ext_readw(u16 __iomem *addr)
36 {
37         return readw(addr);
38 }
39
40 static void hdac_ext_writeb(u8 value, u8 __iomem *addr)
41 {
42         writeb(value, addr);
43 }
44
45 static u8 hdac_ext_readb(u8 __iomem *addr)
46 {
47         return readb(addr);
48 }
49
50 static const struct hdac_io_ops hdac_ext_default_io = {
51         .reg_writel = hdac_ext_writel,
52         .reg_readl = hdac_ext_readl,
53         .reg_writew = hdac_ext_writew,
54         .reg_readw = hdac_ext_readw,
55         .reg_writeb = hdac_ext_writeb,
56         .reg_readb = hdac_ext_readb,
57 };
58
59 /**
60  * snd_hdac_ext_bus_init - initialize a HD-audio extended bus
61  * @ebus: the pointer to extended bus object
62  * @dev: device pointer
63  * @ops: bus verb operators
64  * @io_ops: lowlevel I/O operators, can be NULL. If NULL core will use
65  * default ops
66  *
67  * Returns 0 if successful, or a negative error code.
68  */
69 int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
70                         const struct hdac_bus_ops *ops,
71                         const struct hdac_io_ops *io_ops,
72                         const struct hdac_ext_bus_ops *ext_ops)
73 {
74         int ret;
75
76         /* check if io ops are provided, if not load the defaults */
77         if (io_ops == NULL)
78                 io_ops = &hdac_ext_default_io;
79
80         ret = snd_hdac_bus_init(bus, dev, ops, io_ops);
81         if (ret < 0)
82                 return ret;
83
84         bus->ext_ops = ext_ops;
85         /* FIXME:
86          * Currently only one bus is supported, if there is device with more
87          * buses, bus->idx should be greater than 0, but there needs to be a
88          * reliable way to always assign same number.
89          */
90         bus->idx = 0;
91         bus->cmd_dma_state = true;
92
93         return 0;
94 }
95 EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_init);
96
97 /**
98  * snd_hdac_ext_bus_exit - clean up a HD-audio extended bus
99  * @ebus: the pointer to extended bus object
100  */
101 void snd_hdac_ext_bus_exit(struct hdac_bus *bus)
102 {
103         snd_hdac_bus_exit(bus);
104         WARN_ON(!list_empty(&bus->hlink_list));
105 }
106 EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_exit);
107
108 static void default_release(struct device *dev)
109 {
110         snd_hdac_ext_bus_device_exit(container_of(dev, struct hdac_device, dev));
111 }
112
113 /**
114  * snd_hdac_ext_bus_device_init - initialize the HDA extended codec base device
115  * @ebus: hdac extended bus to attach to
116  * @addr: codec address
117  *
118  * Returns zero for success or a negative error code.
119  */
120 int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr,
121                                         struct hdac_device *hdev)
122 {
123         char name[15];
124         int ret;
125
126         hdev->bus = bus;
127
128         snprintf(name, sizeof(name), "ehdaudio%dD%d", bus->idx, addr);
129
130         ret  = snd_hdac_device_init(hdev, bus, name, addr);
131         if (ret < 0) {
132                 dev_err(bus->dev, "device init failed for hdac device\n");
133                 return ret;
134         }
135         hdev->type = HDA_DEV_ASOC;
136         hdev->dev.release = default_release;
137
138         ret = snd_hdac_device_register(hdev);
139         if (ret) {
140                 dev_err(bus->dev, "failed to register hdac device\n");
141                 snd_hdac_ext_bus_device_exit(hdev);
142                 return ret;
143         }
144
145         return 0;
146 }
147 EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init);
148
149 /**
150  * snd_hdac_ext_bus_device_exit - clean up a HD-audio extended codec base device
151  * @hdev: hdac device to clean up
152  */
153 void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev)
154 {
155         snd_hdac_device_exit(hdev);
156 }
157 EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit);
158
159 /**
160  * snd_hdac_ext_bus_device_remove - remove HD-audio extended codec base devices
161  *
162  * @ebus: HD-audio extended bus
163  */
164 void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus)
165 {
166         struct hdac_device *codec, *__codec;
167         /*
168          * we need to remove all the codec devices objects created in the
169          * snd_hdac_ext_bus_device_init
170          */
171         list_for_each_entry_safe(codec, __codec, &bus->codec_list, list) {
172                 snd_hdac_device_unregister(codec);
173                 put_device(&codec->dev);
174         }
175 }
176 EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_remove);
177 #define dev_to_hdac(dev) (container_of((dev), \
178                         struct hdac_device, dev))
179
180 static inline struct hdac_driver *get_hdrv(struct device *dev)
181 {
182         struct hdac_driver *hdrv = drv_to_hdac_driver(dev->driver);
183         return hdrv;
184 }
185
186 static inline struct hdac_device *get_hdev(struct device *dev)
187 {
188         struct hdac_device *hdev = dev_to_hdac_dev(dev);
189         return hdev;
190 }
191
192 static int hda_ext_drv_probe(struct device *dev)
193 {
194         return (get_hdrv(dev))->probe(get_hdev(dev));
195 }
196
197 static int hdac_ext_drv_remove(struct device *dev)
198 {
199         return (get_hdrv(dev))->remove(get_hdev(dev));
200 }
201
202 static void hdac_ext_drv_shutdown(struct device *dev)
203 {
204         return (get_hdrv(dev))->shutdown(get_hdev(dev));
205 }
206
207 /**
208  * snd_hda_ext_driver_register - register a driver for ext hda devices
209  *
210  * @drv: ext hda driver structure
211  */
212 int snd_hda_ext_driver_register(struct hdac_driver *drv)
213 {
214         drv->type = HDA_DEV_ASOC;
215         drv->driver.bus = &snd_hda_bus_type;
216         /* we use default match */
217
218         if (drv->probe)
219                 drv->driver.probe = hda_ext_drv_probe;
220         if (drv->remove)
221                 drv->driver.remove = hdac_ext_drv_remove;
222         if (drv->shutdown)
223                 drv->driver.shutdown = hdac_ext_drv_shutdown;
224
225         return driver_register(&drv->driver);
226 }
227 EXPORT_SYMBOL_GPL(snd_hda_ext_driver_register);
228
229 /**
230  * snd_hda_ext_driver_unregister - unregister a driver for ext hda devices
231  *
232  * @drv: ext hda driver structure
233  */
234 void snd_hda_ext_driver_unregister(struct hdac_driver *drv)
235 {
236         driver_unregister(&drv->driver);
237 }
238 EXPORT_SYMBOL_GPL(snd_hda_ext_driver_unregister);