.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * HD-audio core bus driver |
---|
3 | 4 | */ |
---|
4 | 5 | |
---|
5 | 6 | #include <linux/init.h> |
---|
| 7 | +#include <linux/io.h> |
---|
6 | 8 | #include <linux/device.h> |
---|
7 | 9 | #include <linux/module.h> |
---|
8 | 10 | #include <linux/export.h> |
---|
9 | 11 | #include <sound/hdaudio.h> |
---|
| 12 | +#include "local.h" |
---|
10 | 13 | #include "trace.h" |
---|
11 | 14 | |
---|
12 | | -static void process_unsol_events(struct work_struct *work); |
---|
| 15 | +static void snd_hdac_bus_process_unsol_events(struct work_struct *work); |
---|
13 | 16 | |
---|
14 | 17 | static const struct hdac_bus_ops default_ops = { |
---|
15 | 18 | .command = snd_hdac_bus_send_cmd, |
---|
.. | .. |
---|
19 | 22 | /** |
---|
20 | 23 | * snd_hdac_bus_init - initialize a HD-audio bas bus |
---|
21 | 24 | * @bus: the pointer to bus object |
---|
| 25 | + * @dev: device pointer |
---|
22 | 26 | * @ops: bus verb operators |
---|
23 | | - * @io_ops: lowlevel I/O operators |
---|
24 | 27 | * |
---|
25 | 28 | * Returns 0 if successful, or a negative error code. |
---|
26 | 29 | */ |
---|
27 | 30 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, |
---|
28 | | - const struct hdac_bus_ops *ops, |
---|
29 | | - const struct hdac_io_ops *io_ops) |
---|
| 31 | + const struct hdac_bus_ops *ops) |
---|
30 | 32 | { |
---|
31 | 33 | memset(bus, 0, sizeof(*bus)); |
---|
32 | 34 | bus->dev = dev; |
---|
.. | .. |
---|
34 | 36 | bus->ops = ops; |
---|
35 | 37 | else |
---|
36 | 38 | bus->ops = &default_ops; |
---|
37 | | - bus->io_ops = io_ops; |
---|
| 39 | + bus->dma_type = SNDRV_DMA_TYPE_DEV; |
---|
38 | 40 | INIT_LIST_HEAD(&bus->stream_list); |
---|
39 | 41 | INIT_LIST_HEAD(&bus->codec_list); |
---|
40 | | - INIT_WORK(&bus->unsol_work, process_unsol_events); |
---|
| 42 | + INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); |
---|
41 | 43 | spin_lock_init(&bus->reg_lock); |
---|
42 | 44 | mutex_init(&bus->cmd_mutex); |
---|
| 45 | + mutex_init(&bus->lock); |
---|
| 46 | + INIT_LIST_HEAD(&bus->hlink_list); |
---|
| 47 | + init_waitqueue_head(&bus->rirb_wq); |
---|
43 | 48 | bus->irq = -1; |
---|
| 49 | + |
---|
| 50 | + /* |
---|
| 51 | + * Default value of '8' is as per the HD audio specification (Rev 1.0a). |
---|
| 52 | + * Following relation is used to derive STRIPE control value. |
---|
| 53 | + * For sample rate <= 48K: |
---|
| 54 | + * { ((num_channels * bits_per_sample) / number of SDOs) >= 8 } |
---|
| 55 | + * For sample rate > 48K: |
---|
| 56 | + * { ((num_channels * bits_per_sample * rate/48000) / |
---|
| 57 | + * number of SDOs) >= 8 } |
---|
| 58 | + */ |
---|
| 59 | + bus->sdo_limit = 8; |
---|
| 60 | + |
---|
44 | 61 | return 0; |
---|
45 | 62 | } |
---|
46 | 63 | EXPORT_SYMBOL_GPL(snd_hdac_bus_init); |
---|
.. | .. |
---|
60 | 77 | /** |
---|
61 | 78 | * snd_hdac_bus_exec_verb - execute a HD-audio verb on the given bus |
---|
62 | 79 | * @bus: bus object |
---|
| 80 | + * @addr: the HDAC device address |
---|
63 | 81 | * @cmd: HD-audio encoded verb |
---|
64 | 82 | * @res: pointer to store the response, NULL if performing asynchronously |
---|
65 | 83 | * |
---|
.. | .. |
---|
75 | 93 | mutex_unlock(&bus->cmd_mutex); |
---|
76 | 94 | return err; |
---|
77 | 95 | } |
---|
78 | | -EXPORT_SYMBOL_GPL(snd_hdac_bus_exec_verb); |
---|
79 | 96 | |
---|
80 | 97 | /** |
---|
81 | 98 | * snd_hdac_bus_exec_verb_unlocked - unlocked version |
---|
82 | 99 | * @bus: bus object |
---|
| 100 | + * @addr: the HDAC device address |
---|
83 | 101 | * @cmd: HD-audio encoded verb |
---|
84 | 102 | * @res: pointer to store the response, NULL if performing asynchronously |
---|
85 | 103 | * |
---|
.. | .. |
---|
143 | 161 | |
---|
144 | 162 | schedule_work(&bus->unsol_work); |
---|
145 | 163 | } |
---|
146 | | -EXPORT_SYMBOL_GPL(snd_hdac_bus_queue_event); |
---|
147 | 164 | |
---|
148 | 165 | /* |
---|
149 | 166 | * process queued unsolicited events |
---|
150 | 167 | */ |
---|
151 | | -static void process_unsol_events(struct work_struct *work) |
---|
| 168 | +static void snd_hdac_bus_process_unsol_events(struct work_struct *work) |
---|
152 | 169 | { |
---|
153 | 170 | struct hdac_bus *bus = container_of(work, struct hdac_bus, unsol_work); |
---|
154 | 171 | struct hdac_device *codec; |
---|
.. | .. |
---|
199 | 216 | bus->num_codecs++; |
---|
200 | 217 | return 0; |
---|
201 | 218 | } |
---|
202 | | -EXPORT_SYMBOL_GPL(snd_hdac_bus_add_device); |
---|
203 | 219 | |
---|
204 | 220 | /** |
---|
205 | 221 | * snd_hdac_bus_remove_device - Remove a codec from bus |
---|
.. | .. |
---|
218 | 234 | bus->num_codecs--; |
---|
219 | 235 | flush_work(&bus->unsol_work); |
---|
220 | 236 | } |
---|
221 | | -EXPORT_SYMBOL_GPL(snd_hdac_bus_remove_device); |
---|
| 237 | + |
---|
| 238 | +#ifdef CONFIG_SND_HDA_ALIGNED_MMIO |
---|
| 239 | +/* Helpers for aligned read/write of mmio space, for Tegra */ |
---|
| 240 | +unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask) |
---|
| 241 | +{ |
---|
| 242 | + void __iomem *aligned_addr = |
---|
| 243 | + (void __iomem *)((unsigned long)(addr) & ~0x3); |
---|
| 244 | + unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; |
---|
| 245 | + unsigned int v; |
---|
| 246 | + |
---|
| 247 | + v = readl(aligned_addr); |
---|
| 248 | + return (v >> shift) & mask; |
---|
| 249 | +} |
---|
| 250 | +EXPORT_SYMBOL_GPL(snd_hdac_aligned_read); |
---|
| 251 | + |
---|
| 252 | +void snd_hdac_aligned_write(unsigned int val, void __iomem *addr, |
---|
| 253 | + unsigned int mask) |
---|
| 254 | +{ |
---|
| 255 | + void __iomem *aligned_addr = |
---|
| 256 | + (void __iomem *)((unsigned long)(addr) & ~0x3); |
---|
| 257 | + unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; |
---|
| 258 | + unsigned int v; |
---|
| 259 | + |
---|
| 260 | + v = readl(aligned_addr); |
---|
| 261 | + v &= ~(mask << shift); |
---|
| 262 | + v |= val << shift; |
---|
| 263 | + writel(v, aligned_addr); |
---|
| 264 | +} |
---|
| 265 | +EXPORT_SYMBOL_GPL(snd_hdac_aligned_write); |
---|
| 266 | +#endif /* CONFIG_SND_HDA_ALIGNED_MMIO */ |
---|