aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/dice
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2014-11-28 10:59:13 -0500
committerTakashi Iwai <tiwai@suse.de>2014-11-29 14:04:15 -0500
commit7c2d4c0cf5bacb42bc3079e61d299dfaa3dbdde5 (patch)
tree6ff440320390f383d2af28128e409a56b4f5feb5 /sound/firewire/dice
parent14ff6a094815988b018ea4d698c2e2cc3ceee27c (diff)
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move some codes into the file with some arrangements. For Dice chipset, well-known FCP or AV/C commands are not used to control devices. It's achieved by read/write transactions into specific addresses. Dice's address area is split into 5 areas. Each area has its own role. The offset for each area can be got by reading head of the address area. By reading these areas, drivers can get to know device status. By writing these areas, drivers can change device status. Dice has a specific mechanism called as 'notification'. When device status is changed, Dice devices tells the event by sending transaction. This notification is sent to an address which drivers register in advance. But this causes an issue to drivers. To handle the notification, drivers need to allocate its own callback function to the address region in host controller. This region is exclusive. For the other applications, drivers must give a mechanism to read the received notification. For this purpose, Dice driver already implements hwdep interface. Dice chipset doesn't allow drivers to register several addresses. In this reason, when this driver is applied to a device, the other drivers should _not_ try to register its own address to the device. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/dice')
-rw-r--r--sound/firewire/dice/Makefile2
-rw-r--r--sound/firewire/dice/dice-transaction.c387
-rw-r--r--sound/firewire/dice/dice.c487
-rw-r--r--sound/firewire/dice/dice.h160
4 files changed, 653 insertions, 383 deletions
diff --git a/sound/firewire/dice/Makefile b/sound/firewire/dice/Makefile
index af05d7e9119a..9f473cb7abf1 100644
--- a/sound/firewire/dice/Makefile
+++ b/sound/firewire/dice/Makefile
@@ -1,2 +1,2 @@
1snd-dice-objs := dice.o 1snd-dice-objs := dice-transaction.o dice.o
2obj-m += snd-dice.o 2obj-m += snd-dice.o
diff --git a/sound/firewire/dice/dice-transaction.c b/sound/firewire/dice/dice-transaction.c
new file mode 100644
index 000000000000..a9b98e087dce
--- /dev/null
+++ b/sound/firewire/dice/dice-transaction.c
@@ -0,0 +1,387 @@
1/*
2 * dice_transaction.c - a part of driver for Dice based devices
3 *
4 * Copyright (c) Clemens Ladisch
5 * Copyright (c) 2014 Takashi Sakamoto
6 *
7 * Licensed under the terms of the GNU General Public License, version 2.
8 */
9
10#include "dice.h"
11
12#define NOTIFICATION_TIMEOUT_MS 100
13
14static u64 get_subaddr(struct snd_dice *dice, enum snd_dice_addr_type type,
15 u64 offset)
16{
17 switch (type) {
18 case SND_DICE_ADDR_TYPE_TX:
19 offset += dice->tx_offset;
20 break;
21 case SND_DICE_ADDR_TYPE_RX:
22 offset += dice->rx_offset;
23 break;
24 case SND_DICE_ADDR_TYPE_SYNC:
25 offset += dice->sync_offset;
26 break;
27 case SND_DICE_ADDR_TYPE_RSRV:
28 offset += dice->rsrv_offset;
29 break;
30 case SND_DICE_ADDR_TYPE_GLOBAL:
31 default:
32 offset += dice->global_offset;
33 break;
34 };
35 offset += DICE_PRIVATE_SPACE;
36 return offset;
37}
38
39int snd_dice_transaction_write(struct snd_dice *dice,
40 enum snd_dice_addr_type type,
41 unsigned int offset, void *buf, unsigned int len)
42{
43 return snd_fw_transaction(dice->unit,
44 (len == 4) ? TCODE_WRITE_QUADLET_REQUEST :
45 TCODE_WRITE_BLOCK_REQUEST,
46 get_subaddr(dice, type, offset), buf, len, 0);
47}
48
49int snd_dice_transaction_read(struct snd_dice *dice,
50 enum snd_dice_addr_type type, unsigned int offset,
51 void *buf, unsigned int len)
52{
53 return snd_fw_transaction(dice->unit,
54 (len == 4) ? TCODE_READ_QUADLET_REQUEST :
55 TCODE_READ_BLOCK_REQUEST,
56 get_subaddr(dice, type, offset), buf, len, 0);
57}
58
59static unsigned int get_clock_info(struct snd_dice *dice, __be32 *info)
60{
61 return snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
62 info, 4);
63}
64
65static int set_clock_info(struct snd_dice *dice,
66 unsigned int rate, unsigned int source)
67{
68 unsigned int retries = 3;
69 unsigned int i;
70 __be32 info;
71 u32 mask;
72 u32 clock;
73 int err;
74retry:
75 err = get_clock_info(dice, &info);
76 if (err < 0)
77 goto end;
78
79 clock = be32_to_cpu(info);
80 if (source != UINT_MAX) {
81 mask = CLOCK_SOURCE_MASK;
82 clock &= ~mask;
83 clock |= source;
84 }
85 if (rate != UINT_MAX) {
86 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
87 if (snd_dice_rates[i] == rate)
88 break;
89 }
90 if (i == ARRAY_SIZE(snd_dice_rates)) {
91 err = -EINVAL;
92 goto end;
93 }
94
95 mask = CLOCK_RATE_MASK;
96 clock &= ~mask;
97 clock |= i << CLOCK_RATE_SHIFT;
98 }
99 info = cpu_to_be32(clock);
100
101 if (completion_done(&dice->clock_accepted))
102 reinit_completion(&dice->clock_accepted);
103
104 err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
105 &info, 4);
106 if (err < 0)
107 goto end;
108
109 /* Timeout means it's invalid request, probably bus reset occurred. */
110 if (wait_for_completion_timeout(&dice->clock_accepted,
111 msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) {
112 if (retries-- == 0) {
113 err = -ETIMEDOUT;
114 goto end;
115 }
116
117 err = snd_dice_transaction_reinit(dice);
118 if (err < 0)
119 goto end;
120
121 msleep(500); /* arbitrary */
122 goto retry;
123 }
124end:
125 return err;
126}
127
128int snd_dice_transaction_get_clock_source(struct snd_dice *dice,
129 unsigned int *source)
130{
131 __be32 info;
132 int err;
133
134 err = get_clock_info(dice, &info);
135 if (err >= 0)
136 *source = be32_to_cpu(info) & CLOCK_SOURCE_MASK;
137
138 return err;
139}
140int snd_dice_transaction_set_clock_source(struct snd_dice *dice,
141 unsigned int source)
142{
143 return set_clock_info(dice, UINT_MAX, source);
144}
145
146int snd_dice_transaction_get_rate(struct snd_dice *dice, unsigned int *rate)
147{
148 __be32 info;
149 unsigned int index;
150 int err;
151
152 err = get_clock_info(dice, &info);
153 if (err < 0)
154 goto end;
155
156 index = (be32_to_cpu(info) & CLOCK_RATE_MASK) >> CLOCK_RATE_SHIFT;
157 if (index >= SND_DICE_RATES_COUNT) {
158 err = -ENOSYS;
159 goto end;
160 }
161
162 *rate = snd_dice_rates[index];
163end:
164 return err;
165}
166int snd_dice_transaction_set_rate(struct snd_dice *dice, unsigned int rate)
167{
168 return set_clock_info(dice, rate, UINT_MAX);
169}
170
171int snd_dice_transaction_set_enable(struct snd_dice *dice)
172{
173 __be32 value;
174 int err = 0;
175
176 if (dice->global_enabled)
177 goto end;
178
179 value = cpu_to_be32(1);
180 err = snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
181 get_subaddr(dice, SND_DICE_ADDR_TYPE_GLOBAL,
182 GLOBAL_ENABLE),
183 &value, 4,
184 FW_FIXED_GENERATION | dice->owner_generation);
185 if (err < 0)
186 goto end;
187
188 dice->global_enabled = true;
189end:
190 return err;
191}
192
193void snd_dice_transaction_clear_enable(struct snd_dice *dice)
194{
195 __be32 value;
196
197 value = 0;
198 snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
199 get_subaddr(dice, SND_DICE_ADDR_TYPE_GLOBAL,
200 GLOBAL_ENABLE),
201 &value, 4, FW_QUIET |
202 FW_FIXED_GENERATION | dice->owner_generation);
203
204 dice->global_enabled = false;
205}
206
207static void dice_notification(struct fw_card *card, struct fw_request *request,
208 int tcode, int destination, int source,
209 int generation, unsigned long long offset,
210 void *data, size_t length, void *callback_data)
211{
212 struct snd_dice *dice = callback_data;
213 u32 bits;
214 unsigned long flags;
215
216 if (tcode != TCODE_WRITE_QUADLET_REQUEST) {
217 fw_send_response(card, request, RCODE_TYPE_ERROR);
218 return;
219 }
220 if ((offset & 3) != 0) {
221 fw_send_response(card, request, RCODE_ADDRESS_ERROR);
222 return;
223 }
224
225 bits = be32_to_cpup(data);
226
227 spin_lock_irqsave(&dice->lock, flags);
228 dice->notification_bits |= bits;
229 spin_unlock_irqrestore(&dice->lock, flags);
230
231 fw_send_response(card, request, RCODE_COMPLETE);
232
233 if (bits & NOTIFY_CLOCK_ACCEPTED)
234 complete(&dice->clock_accepted);
235 wake_up(&dice->hwdep_wait);
236}
237
238static int register_notification_address(struct snd_dice *dice, bool retry)
239{
240 struct fw_device *device = fw_parent_device(dice->unit);
241 __be64 *buffer;
242 unsigned int retries;
243 int err;
244
245 retries = (retry) ? 3 : 0;
246
247 buffer = kmalloc(2 * 8, GFP_KERNEL);
248 if (!buffer)
249 return -ENOMEM;
250
251 for (;;) {
252 buffer[0] = cpu_to_be64(OWNER_NO_OWNER);
253 buffer[1] = cpu_to_be64(
254 ((u64)device->card->node_id << OWNER_NODE_SHIFT) |
255 dice->notification_handler.offset);
256
257 dice->owner_generation = device->generation;
258 smp_rmb(); /* node_id vs. generation */
259 err = snd_fw_transaction(dice->unit, TCODE_LOCK_COMPARE_SWAP,
260 get_subaddr(dice,
261 SND_DICE_ADDR_TYPE_GLOBAL,
262 GLOBAL_OWNER),
263 buffer, 2 * 8,
264 FW_FIXED_GENERATION |
265 dice->owner_generation);
266 if (err == 0) {
267 /* success */
268 if (buffer[0] == cpu_to_be64(OWNER_NO_OWNER))
269 break;
270 /* The address seems to be already registered. */
271 if (buffer[0] == buffer[1])
272 break;
273
274 dev_err(&dice->unit->device,
275 "device is already in use\n");
276 err = -EBUSY;
277 }
278 if (err != -EAGAIN || retries-- > 0)
279 break;
280
281 msleep(20);
282 }
283
284 kfree(buffer);
285
286 if (err < 0)
287 dice->owner_generation = -1;
288
289 return err;
290}
291
292static void unregister_notification_address(struct snd_dice *dice)
293{
294 struct fw_device *device = fw_parent_device(dice->unit);
295 __be64 *buffer;
296
297 buffer = kmalloc(2 * 8, GFP_KERNEL);
298 if (buffer == NULL)
299 return;
300
301 buffer[0] = cpu_to_be64(
302 ((u64)device->card->node_id << OWNER_NODE_SHIFT) |
303 dice->notification_handler.offset);
304 buffer[1] = cpu_to_be64(OWNER_NO_OWNER);
305 snd_fw_transaction(dice->unit, TCODE_LOCK_COMPARE_SWAP,
306 get_subaddr(dice, SND_DICE_ADDR_TYPE_GLOBAL,
307 GLOBAL_OWNER),
308 buffer, 2 * 8, FW_QUIET |
309 FW_FIXED_GENERATION | dice->owner_generation);
310
311 kfree(buffer);
312
313 dice->owner_generation = -1;
314}
315
316void snd_dice_transaction_destroy(struct snd_dice *dice)
317{
318 struct fw_address_handler *handler = &dice->notification_handler;
319
320 if (handler->callback_data == NULL)
321 return;
322
323 unregister_notification_address(dice);
324
325 fw_core_remove_address_handler(handler);
326 handler->callback_data = NULL;
327}
328
329int snd_dice_transaction_reinit(struct snd_dice *dice)
330{
331 struct fw_address_handler *handler = &dice->notification_handler;
332
333 if (handler->callback_data == NULL)
334 return -EINVAL;
335
336 return register_notification_address(dice, false);
337}
338
339int snd_dice_transaction_init(struct snd_dice *dice)
340{
341 struct fw_address_handler *handler = &dice->notification_handler;
342 __be32 *pointers;
343 int err;
344
345 /* Use the same way which dice_interface_check() does. */
346 pointers = kmalloc(sizeof(__be32) * 10, GFP_KERNEL);
347 if (pointers == NULL)
348 return -ENOMEM;
349
350 /* Get offsets for sub-addresses */
351 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
352 DICE_PRIVATE_SPACE,
353 pointers, sizeof(__be32) * 10, 0);
354 if (err < 0)
355 goto end;
356
357 /* Allocation callback in address space over host controller */
358 handler->length = 4;
359 handler->address_callback = dice_notification;
360 handler->callback_data = dice;
361 err = fw_core_add_address_handler(handler, &fw_high_memory_region);
362 if (err < 0) {
363 handler->callback_data = NULL;
364 goto end;
365 }
366
367 /* Register the address space */
368 err = register_notification_address(dice, true);
369 if (err < 0) {
370 fw_core_remove_address_handler(handler);
371 handler->callback_data = NULL;
372 goto end;
373 }
374
375 dice->global_offset = be32_to_cpu(pointers[0]) * 4;
376 dice->tx_offset = be32_to_cpu(pointers[2]) * 4;
377 dice->rx_offset = be32_to_cpu(pointers[4]) * 4;
378 dice->sync_offset = be32_to_cpu(pointers[6]) * 4;
379 dice->rsrv_offset = be32_to_cpu(pointers[8]) * 4;
380
381 /* Set up later. */
382 if (be32_to_cpu(pointers[1]) * 4 >= GLOBAL_CLOCK_CAPABILITIES + 4)
383 dice->clock_caps = 1;
384end:
385 kfree(pointers);
386 return err;
387}
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c
index d3ec778878af..dd62316ea8b3 100644
--- a/sound/firewire/dice/dice.c
+++ b/sound/firewire/dice/dice.c
@@ -5,60 +5,13 @@
5 * Licensed under the terms of the GNU General Public License, version 2. 5 * Licensed under the terms of the GNU General Public License, version 2.
6 */ 6 */
7 7
8#include <linux/compat.h> 8#include "dice.h"
9#include <linux/completion.h>
10#include <linux/delay.h>
11#include <linux/device.h>
12#include <linux/firewire.h>
13#include <linux/firewire-constants.h>
14#include <linux/jiffies.h>
15#include <linux/module.h>
16#include <linux/mod_devicetable.h>
17#include <linux/mutex.h>
18#include <linux/slab.h>
19#include <linux/spinlock.h>
20#include <linux/wait.h>
21#include <sound/control.h>
22#include <sound/core.h>
23#include <sound/firewire.h>
24#include <sound/hwdep.h>
25#include <sound/info.h>
26#include <sound/initval.h>
27#include <sound/pcm.h>
28#include <sound/pcm_params.h>
29#include "../amdtp.h"
30#include "../iso-resources.h"
31#include "../lib.h"
32#include "dice-interface.h"
33
34
35struct snd_dice {
36 struct snd_card *card;
37 struct fw_unit *unit;
38 spinlock_t lock;
39 struct mutex mutex;
40 unsigned int global_offset;
41 unsigned int rx_offset;
42 unsigned int clock_caps;
43 unsigned int rx_channels[3];
44 unsigned int rx_midi_ports[3];
45 struct fw_address_handler notification_handler;
46 int owner_generation;
47 int dev_lock_count; /* > 0 driver, < 0 userspace */
48 bool dev_lock_changed;
49 bool global_enabled;
50 struct completion clock_accepted;
51 wait_queue_head_t hwdep_wait;
52 u32 notification_bits;
53 struct fw_iso_resources rx_resources;
54 struct amdtp_stream rx_stream;
55};
56 9
57MODULE_DESCRIPTION("DICE driver"); 10MODULE_DESCRIPTION("DICE driver");
58MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 11MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
59MODULE_LICENSE("GPL v2"); 12MODULE_LICENSE("GPL v2");
60 13
61static const unsigned int dice_rates[] = { 14const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
62 /* mode 0 */ 15 /* mode 0 */
63 [0] = 32000, 16 [0] = 32000,
64 [1] = 44100, 17 [1] = 44100,
@@ -75,8 +28,8 @@ static unsigned int rate_to_index(unsigned int rate)
75{ 28{
76 unsigned int i; 29 unsigned int i;
77 30
78 for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) 31 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i)
79 if (dice_rates[i] == rate) 32 if (snd_dice_rates[i] == rate)
80 return i; 33 return i;
81 34
82 return 0; 35 return 0;
@@ -128,192 +81,6 @@ out:
128 spin_unlock_irq(&dice->lock); 81 spin_unlock_irq(&dice->lock);
129} 82}
130 83
131static inline u64 global_address(struct snd_dice *dice, unsigned int offset)
132{
133 return DICE_PRIVATE_SPACE + dice->global_offset + offset;
134}
135
136/* TODO: rx index */
137static inline u64 rx_address(struct snd_dice *dice, unsigned int offset)
138{
139 return DICE_PRIVATE_SPACE + dice->rx_offset + offset;
140}
141
142static int dice_owner_set(struct snd_dice *dice)
143{
144 struct fw_device *device = fw_parent_device(dice->unit);
145 __be64 *buffer;
146 int err, errors = 0;
147
148 buffer = kmalloc(2 * 8, GFP_KERNEL);
149 if (!buffer)
150 return -ENOMEM;
151
152 for (;;) {
153 buffer[0] = cpu_to_be64(OWNER_NO_OWNER);
154 buffer[1] = cpu_to_be64(
155 ((u64)device->card->node_id << OWNER_NODE_SHIFT) |
156 dice->notification_handler.offset);
157
158 dice->owner_generation = device->generation;
159 smp_rmb(); /* node_id vs. generation */
160 err = snd_fw_transaction(dice->unit,
161 TCODE_LOCK_COMPARE_SWAP,
162 global_address(dice, GLOBAL_OWNER),
163 buffer, 2 * 8,
164 FW_FIXED_GENERATION |
165 dice->owner_generation);
166
167 if (err == 0) {
168 if (buffer[0] != cpu_to_be64(OWNER_NO_OWNER)) {
169 dev_err(&dice->unit->device,
170 "device is already in use\n");
171 err = -EBUSY;
172 }
173 break;
174 }
175 if (err != -EAGAIN || ++errors >= 3)
176 break;
177
178 msleep(20);
179 }
180
181 kfree(buffer);
182
183 return err;
184}
185
186static int dice_owner_update(struct snd_dice *dice)
187{
188 struct fw_device *device = fw_parent_device(dice->unit);
189 __be64 *buffer;
190 int err;
191
192 if (dice->owner_generation == -1)
193 return 0;
194
195 buffer = kmalloc(2 * 8, GFP_KERNEL);
196 if (!buffer)
197 return -ENOMEM;
198
199 buffer[0] = cpu_to_be64(OWNER_NO_OWNER);
200 buffer[1] = cpu_to_be64(
201 ((u64)device->card->node_id << OWNER_NODE_SHIFT) |
202 dice->notification_handler.offset);
203
204 dice->owner_generation = device->generation;
205 smp_rmb(); /* node_id vs. generation */
206 err = snd_fw_transaction(dice->unit, TCODE_LOCK_COMPARE_SWAP,
207 global_address(dice, GLOBAL_OWNER),
208 buffer, 2 * 8,
209 FW_FIXED_GENERATION | dice->owner_generation);
210
211 if (err == 0) {
212 if (buffer[0] != cpu_to_be64(OWNER_NO_OWNER)) {
213 dev_err(&dice->unit->device,
214 "device is already in use\n");
215 err = -EBUSY;
216 }
217 } else if (err == -EAGAIN) {
218 err = 0; /* try again later */
219 }
220
221 kfree(buffer);
222
223 if (err < 0)
224 dice->owner_generation = -1;
225
226 return err;
227}
228
229static void dice_owner_clear(struct snd_dice *dice)
230{
231 struct fw_device *device = fw_parent_device(dice->unit);
232 __be64 *buffer;
233
234 buffer = kmalloc(2 * 8, GFP_KERNEL);
235 if (!buffer)
236 return;
237
238 buffer[0] = cpu_to_be64(
239 ((u64)device->card->node_id << OWNER_NODE_SHIFT) |
240 dice->notification_handler.offset);
241 buffer[1] = cpu_to_be64(OWNER_NO_OWNER);
242 snd_fw_transaction(dice->unit, TCODE_LOCK_COMPARE_SWAP,
243 global_address(dice, GLOBAL_OWNER),
244 buffer, 2 * 8, FW_QUIET |
245 FW_FIXED_GENERATION | dice->owner_generation);
246
247 kfree(buffer);
248
249 dice->owner_generation = -1;
250}
251
252static int dice_enable_set(struct snd_dice *dice)
253{
254 __be32 value;
255 int err;
256
257 value = cpu_to_be32(1);
258 err = snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
259 global_address(dice, GLOBAL_ENABLE),
260 &value, 4,
261 FW_FIXED_GENERATION | dice->owner_generation);
262 if (err < 0)
263 return err;
264
265 dice->global_enabled = true;
266
267 return 0;
268}
269
270static void dice_enable_clear(struct snd_dice *dice)
271{
272 __be32 value;
273
274 if (!dice->global_enabled)
275 return;
276
277 value = 0;
278 snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
279 global_address(dice, GLOBAL_ENABLE),
280 &value, 4, FW_QUIET |
281 FW_FIXED_GENERATION | dice->owner_generation);
282
283 dice->global_enabled = false;
284}
285
286static void dice_notification(struct fw_card *card, struct fw_request *request,
287 int tcode, int destination, int source,
288 int generation, unsigned long long offset,
289 void *data, size_t length, void *callback_data)
290{
291 struct snd_dice *dice = callback_data;
292 u32 bits;
293 unsigned long flags;
294
295 if (tcode != TCODE_WRITE_QUADLET_REQUEST) {
296 fw_send_response(card, request, RCODE_TYPE_ERROR);
297 return;
298 }
299 if ((offset & 3) != 0) {
300 fw_send_response(card, request, RCODE_ADDRESS_ERROR);
301 return;
302 }
303
304 bits = be32_to_cpup(data);
305
306 spin_lock_irqsave(&dice->lock, flags);
307 dice->notification_bits |= bits;
308 spin_unlock_irqrestore(&dice->lock, flags);
309
310 fw_send_response(card, request, RCODE_COMPLETE);
311
312 if (bits & NOTIFY_CLOCK_ACCEPTED)
313 complete(&dice->clock_accepted);
314 wake_up(&dice->hwdep_wait);
315}
316
317static int dice_rate_constraint(struct snd_pcm_hw_params *params, 84static int dice_rate_constraint(struct snd_pcm_hw_params *params,
318 struct snd_pcm_hw_rule *rule) 85 struct snd_pcm_hw_rule *rule)
319{ 86{
@@ -327,14 +94,14 @@ static int dice_rate_constraint(struct snd_pcm_hw_params *params,
327 }; 94 };
328 unsigned int i, mode; 95 unsigned int i, mode;
329 96
330 for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) { 97 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
331 mode = rate_index_to_mode(i); 98 mode = rate_index_to_mode(i);
332 if ((dice->clock_caps & (1 << i)) && 99 if ((dice->clock_caps & (1 << i)) &&
333 snd_interval_test(channels, dice->rx_channels[mode])) { 100 snd_interval_test(channels, dice->rx_channels[mode])) {
334 allowed_rates.min = min(allowed_rates.min, 101 allowed_rates.min = min(allowed_rates.min,
335 dice_rates[i]); 102 snd_dice_rates[i]);
336 allowed_rates.max = max(allowed_rates.max, 103 allowed_rates.max = max(allowed_rates.max,
337 dice_rates[i]); 104 snd_dice_rates[i]);
338 } 105 }
339 } 106 }
340 107
@@ -354,9 +121,9 @@ static int dice_channels_constraint(struct snd_pcm_hw_params *params,
354 }; 121 };
355 unsigned int i, mode; 122 unsigned int i, mode;
356 123
357 for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) 124 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i)
358 if ((dice->clock_caps & (1 << i)) && 125 if ((dice->clock_caps & (1 << i)) &&
359 snd_interval_test(rate, dice_rates[i])) { 126 snd_interval_test(rate, snd_dice_rates[i])) {
360 mode = rate_index_to_mode(i); 127 mode = rate_index_to_mode(i);
361 allowed_channels.min = min(allowed_channels.min, 128 allowed_channels.min = min(allowed_channels.min,
362 dice->rx_channels[mode]); 129 dice->rx_channels[mode]);
@@ -395,10 +162,10 @@ static int dice_open(struct snd_pcm_substream *substream)
395 162
396 runtime->hw = hardware; 163 runtime->hw = hardware;
397 164
398 for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) 165 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i)
399 if (dice->clock_caps & (1 << i)) 166 if (dice->clock_caps & (1 << i))
400 runtime->hw.rates |= 167 runtime->hw.rates |=
401 snd_pcm_rate_to_rate_bit(dice_rates[i]); 168 snd_pcm_rate_to_rate_bit(snd_dice_rates[i]);
402 snd_pcm_limit_hw_rates(runtime); 169 snd_pcm_limit_hw_rates(runtime);
403 170
404 for (i = 0; i < 3; ++i) 171 for (i = 0; i < 3; ++i)
@@ -453,7 +220,7 @@ static int dice_stream_start_packets(struct snd_dice *dice)
453 if (err < 0) 220 if (err < 0)
454 return err; 221 return err;
455 222
456 err = dice_enable_set(dice); 223 err = snd_dice_transaction_set_enable(dice);
457 if (err < 0) { 224 if (err < 0) {
458 amdtp_stream_stop(&dice->rx_stream); 225 amdtp_stream_stop(&dice->rx_stream);
459 return err; 226 return err;
@@ -475,10 +242,8 @@ static int dice_stream_start(struct snd_dice *dice)
475 goto error; 242 goto error;
476 243
477 channel = cpu_to_be32(dice->rx_resources.channel); 244 channel = cpu_to_be32(dice->rx_resources.channel);
478 err = snd_fw_transaction(dice->unit, 245 err = snd_dice_transaction_write_tx(dice, TX_ISOCHRONOUS,
479 TCODE_WRITE_QUADLET_REQUEST, 246 &channel, 4);
480 rx_address(dice, RX_ISOCHRONOUS),
481 &channel, 4, 0);
482 if (err < 0) 247 if (err < 0)
483 goto err_resources; 248 goto err_resources;
484 } 249 }
@@ -491,8 +256,7 @@ static int dice_stream_start(struct snd_dice *dice)
491 256
492err_rx_channel: 257err_rx_channel:
493 channel = cpu_to_be32((u32)-1); 258 channel = cpu_to_be32((u32)-1);
494 snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST, 259 snd_dice_transaction_write_rx(dice, RX_ISOCHRONOUS, &channel, 4);
495 rx_address(dice, RX_ISOCHRONOUS), &channel, 4, 0);
496err_resources: 260err_resources:
497 fw_iso_resources_free(&dice->rx_resources); 261 fw_iso_resources_free(&dice->rx_resources);
498error: 262error:
@@ -502,7 +266,7 @@ error:
502static void dice_stream_stop_packets(struct snd_dice *dice) 266static void dice_stream_stop_packets(struct snd_dice *dice)
503{ 267{
504 if (amdtp_stream_running(&dice->rx_stream)) { 268 if (amdtp_stream_running(&dice->rx_stream)) {
505 dice_enable_clear(dice); 269 snd_dice_transaction_clear_enable(dice);
506 amdtp_stream_stop(&dice->rx_stream); 270 amdtp_stream_stop(&dice->rx_stream);
507 } 271 }
508} 272}
@@ -517,33 +281,11 @@ static void dice_stream_stop(struct snd_dice *dice)
517 return; 281 return;
518 282
519 channel = cpu_to_be32((u32)-1); 283 channel = cpu_to_be32((u32)-1);
520 snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST, 284 snd_dice_transaction_write_rx(dice, RX_ISOCHRONOUS, &channel, 4);
521 rx_address(dice, RX_ISOCHRONOUS), &channel, 4, 0);
522 285
523 fw_iso_resources_free(&dice->rx_resources); 286 fw_iso_resources_free(&dice->rx_resources);
524} 287}
525 288
526static int dice_change_rate(struct snd_dice *dice, unsigned int clock_rate)
527{
528 __be32 value;
529 int err;
530
531 reinit_completion(&dice->clock_accepted);
532
533 value = cpu_to_be32(clock_rate | CLOCK_SOURCE_ARX1);
534 err = snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
535 global_address(dice, GLOBAL_CLOCK_SELECT),
536 &value, 4, 0);
537 if (err < 0)
538 return err;
539
540 if (!wait_for_completion_timeout(&dice->clock_accepted,
541 msecs_to_jiffies(100)))
542 dev_warn(&dice->unit->device, "clock change timed out\n");
543
544 return 0;
545}
546
547static int dice_hw_params(struct snd_pcm_substream *substream, 289static int dice_hw_params(struct snd_pcm_substream *substream,
548 struct snd_pcm_hw_params *hw_params) 290 struct snd_pcm_hw_params *hw_params)
549{ 291{
@@ -561,8 +303,7 @@ static int dice_hw_params(struct snd_pcm_substream *substream,
561 return err; 303 return err;
562 304
563 rate = params_rate(hw_params); 305 rate = params_rate(hw_params);
564 rate_index = rate_to_index(rate); 306 err = snd_dice_transaction_set_rate(dice, rate);
565 err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT);
566 if (err < 0) 307 if (err < 0)
567 return err; 308 return err;
568 309
@@ -577,6 +318,7 @@ static int dice_hw_params(struct snd_pcm_substream *substream,
577 * be aligned to SYT_INTERVAL. 318 * be aligned to SYT_INTERVAL.
578 */ 319 */
579 channels = params_channels(hw_params); 320 channels = params_channels(hw_params);
321 rate_index = rate_to_index(rate);
580 if (rate_index > 4) { 322 if (rate_index > 4) {
581 if (channels > AMDTP_MAX_CHANNELS_FOR_PCM / 2) { 323 if (channels > AMDTP_MAX_CHANNELS_FOR_PCM / 2) {
582 err = -ENOSYS; 324 err = -ENOSYS;
@@ -1118,15 +860,6 @@ static void dice_create_proc(struct snd_dice *dice)
1118 snd_info_set_text_ops(entry, dice, dice_proc_read); 860 snd_info_set_text_ops(entry, dice, dice_proc_read);
1119} 861}
1120 862
1121static void dice_card_free(struct snd_card *card)
1122{
1123 struct snd_dice *dice = card->private_data;
1124
1125 amdtp_stream_destroy(&dice->rx_stream);
1126 fw_core_remove_address_handler(&dice->notification_handler);
1127 mutex_destroy(&dice->mutex);
1128}
1129
1130#define OUI_WEISS 0x001c6a 863#define OUI_WEISS 0x001c6a
1131 864
1132#define DICE_CATEGORY_ID 0x04 865#define DICE_CATEGORY_ID 0x04
@@ -1143,12 +876,17 @@ static int dice_interface_check(struct fw_unit *unit)
1143 }; 876 };
1144 struct fw_device *device = fw_parent_device(unit); 877 struct fw_device *device = fw_parent_device(unit);
1145 struct fw_csr_iterator it; 878 struct fw_csr_iterator it;
1146 int key, value, vendor = -1, model = -1, err; 879 int key, val, vendor = -1, model = -1, err;
1147 unsigned int category, i; 880 unsigned int category, i;
1148 __be32 pointers[ARRAY_SIZE(min_values)]; 881 __be32 *pointers, value;
1149 __be32 tx_data[4]; 882 __be32 tx_data[4];
1150 __be32 version; 883 __be32 version;
1151 884
885 pointers = kmalloc_array(ARRAY_SIZE(min_values), sizeof(__be32),
886 GFP_KERNEL);
887 if (pointers == NULL)
888 return -ENOMEM;
889
1152 /* 890 /*
1153 * Check that GUID and unit directory are constructed according to DICE 891 * Check that GUID and unit directory are constructed according to DICE
1154 * rules, i.e., that the specifier ID is the GUID's OUI, and that the 892 * rules, i.e., that the specifier ID is the GUID's OUI, and that the
@@ -1156,13 +894,13 @@ static int dice_interface_check(struct fw_unit *unit)
1156 * ID, and a 22-bit serial number. 894 * ID, and a 22-bit serial number.
1157 */ 895 */
1158 fw_csr_iterator_init(&it, unit->directory); 896 fw_csr_iterator_init(&it, unit->directory);
1159 while (fw_csr_iterator_next(&it, &key, &value)) { 897 while (fw_csr_iterator_next(&it, &key, &val)) {
1160 switch (key) { 898 switch (key) {
1161 case CSR_SPECIFIER_ID: 899 case CSR_SPECIFIER_ID:
1162 vendor = value; 900 vendor = val;
1163 break; 901 break;
1164 case CSR_MODEL: 902 case CSR_MODEL:
1165 model = value; 903 model = val;
1166 break; 904 break;
1167 } 905 }
1168 } 906 }
@@ -1171,8 +909,10 @@ static int dice_interface_check(struct fw_unit *unit)
1171 else 909 else
1172 category = DICE_CATEGORY_ID; 910 category = DICE_CATEGORY_ID;
1173 if (device->config_rom[3] != ((vendor << 8) | category) || 911 if (device->config_rom[3] != ((vendor << 8) | category) ||
1174 device->config_rom[4] >> 22 != model) 912 device->config_rom[4] >> 22 != model) {
1175 return -ENODEV; 913 err = -ENODEV;
914 goto end;
915 }
1176 916
1177 /* 917 /*
1178 * Check that the sub address spaces exist and are located inside the 918 * Check that the sub address spaces exist and are located inside the
@@ -1180,14 +920,18 @@ static int dice_interface_check(struct fw_unit *unit)
1180 * minimally required registers are included. 920 * minimally required registers are included.
1181 */ 921 */
1182 err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST, 922 err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST,
1183 DICE_PRIVATE_SPACE, 923 DICE_PRIVATE_SPACE, pointers,
1184 pointers, sizeof(pointers), 0); 924 sizeof(__be32) * ARRAY_SIZE(min_values), 0);
1185 if (err < 0) 925 if (err < 0) {
1186 return -ENODEV; 926 err = -ENODEV;
1187 for (i = 0; i < ARRAY_SIZE(pointers); ++i) { 927 goto end;
928 }
929 for (i = 0; i < ARRAY_SIZE(min_values); ++i) {
1188 value = be32_to_cpu(pointers[i]); 930 value = be32_to_cpu(pointers[i]);
1189 if (value < min_values[i] || value >= 0x40000) 931 if (value < min_values[i] || value >= 0x40000) {
1190 return -ENODEV; 932 err = -ENODEV;
933 goto end;
934 }
1191 } 935 }
1192 936
1193 /* We support playback only. Let capture devices be handled by FFADO. */ 937 /* We support playback only. Let capture devices be handled by FFADO. */
@@ -1195,8 +939,10 @@ static int dice_interface_check(struct fw_unit *unit)
1195 DICE_PRIVATE_SPACE + 939 DICE_PRIVATE_SPACE +
1196 be32_to_cpu(pointers[2]) * 4, 940 be32_to_cpu(pointers[2]) * 4,
1197 tx_data, sizeof(tx_data), 0); 941 tx_data, sizeof(tx_data), 0);
1198 if (err < 0 || (tx_data[0] && tx_data[3])) 942 if (err < 0 || (tx_data[0] && tx_data[3])) {
1199 return -ENODEV; 943 err = -ENODEV;
944 goto end;
945 }
1200 946
1201 /* 947 /*
1202 * Check that the implemented DICE driver specification major version 948 * Check that the implemented DICE driver specification major version
@@ -1206,22 +952,25 @@ static int dice_interface_check(struct fw_unit *unit)
1206 DICE_PRIVATE_SPACE + 952 DICE_PRIVATE_SPACE +
1207 be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION, 953 be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
1208 &version, 4, 0); 954 &version, 4, 0);
1209 if (err < 0) 955 if (err < 0) {
1210 return -ENODEV; 956 err = -ENODEV;
957 goto end;
958 }
1211 if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) { 959 if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) {
1212 dev_err(&unit->device, 960 dev_err(&unit->device,
1213 "unknown DICE version: 0x%08x\n", be32_to_cpu(version)); 961 "unknown DICE version: 0x%08x\n", be32_to_cpu(version));
1214 return -ENODEV; 962 err = -ENODEV;
963 goto end;
1215 } 964 }
1216 965end:
1217 return 0; 966 return err;
1218} 967}
1219 968
1220static int highest_supported_mode_rate(struct snd_dice *dice, unsigned int mode) 969static int highest_supported_mode_rate(struct snd_dice *dice, unsigned int mode)
1221{ 970{
1222 int i; 971 int i;
1223 972
1224 for (i = ARRAY_SIZE(dice_rates) - 1; i >= 0; --i) 973 for (i = ARRAY_SIZE(snd_dice_rates) - 1; i >= 0; --i)
1225 if ((dice->clock_caps & (1 << i)) && 974 if ((dice->clock_caps & (1 << i)) &&
1226 rate_index_to_mode(i) == mode) 975 rate_index_to_mode(i) == mode)
1227 return i; 976 return i;
@@ -1241,13 +990,12 @@ static int dice_read_mode_params(struct snd_dice *dice, unsigned int mode)
1241 return 0; 990 return 0;
1242 } 991 }
1243 992
1244 err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT); 993 err = snd_dice_transaction_set_rate(dice, snd_dice_rates[rate_index]);
1245 if (err < 0) 994 if (err < 0)
1246 return err; 995 return err;
1247 996
1248 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, 997 err = snd_dice_transaction_read_rx(dice, RX_NUMBER_AUDIO,
1249 rx_address(dice, RX_NUMBER_AUDIO), 998 values, sizeof(values));
1250 values, 2 * 4, 0);
1251 if (err < 0) 999 if (err < 0)
1252 return err; 1000 return err;
1253 1001
@@ -1259,25 +1007,14 @@ static int dice_read_mode_params(struct snd_dice *dice, unsigned int mode)
1259 1007
1260static int dice_read_params(struct snd_dice *dice) 1008static int dice_read_params(struct snd_dice *dice)
1261{ 1009{
1262 __be32 pointers[6];
1263 __be32 value; 1010 __be32 value;
1264 int mode, err; 1011 int mode, err;
1265 1012
1266 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
1267 DICE_PRIVATE_SPACE,
1268 pointers, sizeof(pointers), 0);
1269 if (err < 0)
1270 return err;
1271
1272 dice->global_offset = be32_to_cpu(pointers[0]) * 4;
1273 dice->rx_offset = be32_to_cpu(pointers[4]) * 4;
1274
1275 /* some very old firmwares don't tell about their clock support */ 1013 /* some very old firmwares don't tell about their clock support */
1276 if (be32_to_cpu(pointers[1]) * 4 >= GLOBAL_CLOCK_CAPABILITIES + 4) { 1014 if (dice->clock_caps > 0) {
1277 err = snd_fw_transaction( 1015 err = snd_dice_transaction_read_global(dice,
1278 dice->unit, TCODE_READ_QUADLET_REQUEST, 1016 GLOBAL_CLOCK_CAPABILITIES,
1279 global_address(dice, GLOBAL_CLOCK_CAPABILITIES), 1017 &value, 4);
1280 &value, 4, 0);
1281 if (err < 0) 1018 if (err < 0)
1282 return err; 1019 return err;
1283 dice->clock_caps = be32_to_cpu(value); 1020 dice->clock_caps = be32_to_cpu(value);
@@ -1310,9 +1047,9 @@ static void dice_card_strings(struct snd_dice *dice)
1310 1047
1311 strcpy(card->shortname, "DICE"); 1048 strcpy(card->shortname, "DICE");
1312 BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname)); 1049 BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname));
1313 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, 1050 err = snd_dice_transaction_read_global(dice, GLOBAL_NICK_NAME,
1314 global_address(dice, GLOBAL_NICK_NAME), 1051 card->shortname,
1315 card->shortname, sizeof(card->shortname), 0); 1052 sizeof(card->shortname));
1316 if (err >= 0) { 1053 if (err >= 0) {
1317 /* DICE strings are returned in "always-wrong" endianness */ 1054 /* DICE strings are returned in "always-wrong" endianness */
1318 BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0); 1055 BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0);
@@ -1333,70 +1070,50 @@ static void dice_card_strings(struct snd_dice *dice)
1333 strcpy(card->mixername, "DICE"); 1070 strcpy(card->mixername, "DICE");
1334} 1071}
1335 1072
1073static void dice_card_free(struct snd_card *card)
1074{
1075 struct snd_dice *dice = card->private_data;
1076
1077 snd_dice_transaction_destroy(dice);
1078 mutex_destroy(&dice->mutex);
1079}
1080
1336static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) 1081static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
1337{ 1082{
1338 struct snd_card *card; 1083 struct snd_card *card;
1339 struct snd_dice *dice; 1084 struct snd_dice *dice;
1340 __be32 clock_sel;
1341 int err; 1085 int err;
1342 1086
1343 err = dice_interface_check(unit); 1087 err = dice_interface_check(unit);
1344 if (err < 0) 1088 if (err < 0)
1345 return err; 1089 goto end;
1346 1090
1347 err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, 1091 err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE,
1348 sizeof(*dice), &card); 1092 sizeof(*dice), &card);
1349 if (err < 0) 1093 if (err < 0)
1350 return err; 1094 goto end;
1351 1095
1352 dice = card->private_data; 1096 dice = card->private_data;
1353 dice->card = card; 1097 dice->card = card;
1098 dice->unit = unit;
1099 card->private_free = dice_card_free;
1100
1354 spin_lock_init(&dice->lock); 1101 spin_lock_init(&dice->lock);
1355 mutex_init(&dice->mutex); 1102 mutex_init(&dice->mutex);
1356 dice->unit = unit;
1357 init_completion(&dice->clock_accepted); 1103 init_completion(&dice->clock_accepted);
1358 init_waitqueue_head(&dice->hwdep_wait); 1104 init_waitqueue_head(&dice->hwdep_wait);
1359 1105
1360 dice->notification_handler.length = 4; 1106 err = snd_dice_transaction_init(dice);
1361 dice->notification_handler.address_callback = dice_notification;
1362 dice->notification_handler.callback_data = dice;
1363 err = fw_core_add_address_handler(&dice->notification_handler,
1364 &fw_high_memory_region);
1365 if (err < 0)
1366 goto err_mutex;
1367
1368 err = dice_owner_set(dice);
1369 if (err < 0) 1107 if (err < 0)
1370 goto err_notification_handler; 1108 goto error;
1371 1109
1372 err = dice_read_params(dice); 1110 err = dice_read_params(dice);
1373 if (err < 0) 1111 if (err < 0)
1374 goto err_owner; 1112 goto error;
1375
1376 err = fw_iso_resources_init(&dice->rx_resources, unit);
1377 if (err < 0)
1378 goto err_owner;
1379 dice->rx_resources.channels_mask = 0x00000000ffffffffuLL;
1380
1381 err = amdtp_stream_init(&dice->rx_stream, unit, AMDTP_OUT_STREAM,
1382 CIP_BLOCKING);
1383 if (err < 0)
1384 goto err_resources;
1385
1386 card->private_free = dice_card_free;
1387 1113
1388 dice_card_strings(dice); 1114 dice_card_strings(dice);
1389 1115
1390 err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, 1116 err = snd_dice_transaction_set_clock_source(dice, CLOCK_SOURCE_ARX1);
1391 global_address(dice, GLOBAL_CLOCK_SELECT),
1392 &clock_sel, 4, 0);
1393 if (err < 0)
1394 goto error;
1395 clock_sel &= cpu_to_be32(~CLOCK_SOURCE_MASK);
1396 clock_sel |= cpu_to_be32(CLOCK_SOURCE_ARX1);
1397 err = snd_fw_transaction(unit, TCODE_WRITE_QUADLET_REQUEST,
1398 global_address(dice, GLOBAL_CLOCK_SELECT),
1399 &clock_sel, 4, 0);
1400 if (err < 0) 1117 if (err < 0)
1401 goto error; 1118 goto error;
1402 1119
@@ -1410,22 +1127,28 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
1410 1127
1411 dice_create_proc(dice); 1128 dice_create_proc(dice);
1412 1129
1413 err = snd_card_register(card); 1130 err = fw_iso_resources_init(&dice->rx_resources, unit);
1414 if (err < 0) 1131 if (err < 0)
1415 goto error; 1132 goto error;
1133 dice->rx_resources.channels_mask = 0x00000000ffffffffuLL;
1416 1134
1417 dev_set_drvdata(&unit->device, dice); 1135 err = amdtp_stream_init(&dice->rx_stream, unit, AMDTP_OUT_STREAM,
1136 CIP_BLOCKING);
1137 if (err < 0) {
1138 fw_iso_resources_destroy(&dice->rx_resources);
1139 goto error;
1140 }
1418 1141
1419 return 0; 1142 err = snd_card_register(card);
1143 if (err < 0) {
1144 amdtp_stream_destroy(&dice->rx_stream);
1145 fw_iso_resources_destroy(&dice->rx_resources);
1146 goto error;
1147 }
1420 1148
1421err_resources: 1149 dev_set_drvdata(&unit->device, dice);
1422 fw_iso_resources_destroy(&dice->rx_resources); 1150end:
1423err_owner: 1151 return err;
1424 dice_owner_clear(dice);
1425err_notification_handler:
1426 fw_core_remove_address_handler(&dice->notification_handler);
1427err_mutex:
1428 mutex_destroy(&dice->mutex);
1429error: 1152error:
1430 snd_card_free(card); 1153 snd_card_free(card);
1431 return err; 1154 return err;
@@ -1442,7 +1165,6 @@ static void dice_remove(struct fw_unit *unit)
1442 mutex_lock(&dice->mutex); 1165 mutex_lock(&dice->mutex);
1443 1166
1444 dice_stream_stop(dice); 1167 dice_stream_stop(dice);
1445 dice_owner_clear(dice);
1446 1168
1447 mutex_unlock(&dice->mutex); 1169 mutex_unlock(&dice->mutex);
1448 1170
@@ -1453,6 +1175,9 @@ static void dice_bus_reset(struct fw_unit *unit)
1453{ 1175{
1454 struct snd_dice *dice = dev_get_drvdata(&unit->device); 1176 struct snd_dice *dice = dev_get_drvdata(&unit->device);
1455 1177
1178 /* The handler address register becomes initialized. */
1179 snd_dice_transaction_reinit(dice);
1180
1456 /* 1181 /*
1457 * On a bus reset, the DICE firmware disables streaming and then goes 1182 * On a bus reset, the DICE firmware disables streaming and then goes
1458 * off contemplating its own navel for hundreds of milliseconds before 1183 * off contemplating its own navel for hundreds of milliseconds before
@@ -1466,10 +1191,8 @@ static void dice_bus_reset(struct fw_unit *unit)
1466 mutex_lock(&dice->mutex); 1191 mutex_lock(&dice->mutex);
1467 1192
1468 dice->global_enabled = false; 1193 dice->global_enabled = false;
1469 dice_stream_stop_packets(dice);
1470
1471 dice_owner_update(dice);
1472 1194
1195 dice_stream_stop_packets(dice);
1473 fw_iso_resources_update(&dice->rx_resources); 1196 fw_iso_resources_update(&dice->rx_resources);
1474 1197
1475 mutex_unlock(&dice->mutex); 1198 mutex_unlock(&dice->mutex);
diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h
new file mode 100644
index 000000000000..c756e62ea4ec
--- /dev/null
+++ b/sound/firewire/dice/dice.h
@@ -0,0 +1,160 @@
1/*
2 * dice.h - a part of driver for Dice based devices
3 *
4 * Copyright (c) Clemens Ladisch
5 * Copyright (c) 2014 Takashi Sakamoto
6 *
7 * Licensed under the terms of the GNU General Public License, version 2.
8 */
9
10#ifndef SOUND_DICE_H_INCLUDED
11#define SOUND_DICE_H_INCLUDED
12
13#include <linux/compat.h>
14#include <linux/completion.h>
15#include <linux/delay.h>
16#include <linux/device.h>
17#include <linux/firewire.h>
18#include <linux/firewire-constants.h>
19#include <linux/jiffies.h>
20#include <linux/module.h>
21#include <linux/mod_devicetable.h>
22#include <linux/mutex.h>
23#include <linux/slab.h>
24#include <linux/spinlock.h>
25#include <linux/wait.h>
26
27#include <sound/control.h>
28#include <sound/core.h>
29#include <sound/firewire.h>
30#include <sound/hwdep.h>
31#include <sound/info.h>
32#include <sound/initval.h>
33#include <sound/pcm.h>
34#include <sound/pcm_params.h>
35
36#include "../amdtp.h"
37#include "../iso-resources.h"
38#include "../lib.h"
39#include "dice-interface.h"
40
41struct snd_dice {
42 struct snd_card *card;
43 struct fw_unit *unit;
44 spinlock_t lock;
45 struct mutex mutex;
46
47 /* Offsets for sub-addresses */
48 unsigned int global_offset;
49 unsigned int rx_offset;
50 unsigned int tx_offset;
51 unsigned int sync_offset;
52 unsigned int rsrv_offset;
53
54 unsigned int clock_caps;
55 unsigned int rx_channels[3];
56 unsigned int rx_midi_ports[3];
57 struct fw_address_handler notification_handler;
58 int owner_generation;
59 int dev_lock_count; /* > 0 driver, < 0 userspace */
60 bool dev_lock_changed;
61 bool global_enabled;
62 struct completion clock_accepted;
63 wait_queue_head_t hwdep_wait;
64 u32 notification_bits;
65 struct fw_iso_resources rx_resources;
66 struct amdtp_stream rx_stream;
67};
68
69enum snd_dice_addr_type {
70 SND_DICE_ADDR_TYPE_PRIVATE,
71 SND_DICE_ADDR_TYPE_GLOBAL,
72 SND_DICE_ADDR_TYPE_TX,
73 SND_DICE_ADDR_TYPE_RX,
74 SND_DICE_ADDR_TYPE_SYNC,
75 SND_DICE_ADDR_TYPE_RSRV,
76};
77
78int snd_dice_transaction_write(struct snd_dice *dice,
79 enum snd_dice_addr_type type,
80 unsigned int offset,
81 void *buf, unsigned int len);
82int snd_dice_transaction_read(struct snd_dice *dice,
83 enum snd_dice_addr_type type, unsigned int offset,
84 void *buf, unsigned int len);
85
86static inline int snd_dice_transaction_write_global(struct snd_dice *dice,
87 unsigned int offset,
88 void *buf, unsigned int len)
89{
90 return snd_dice_transaction_write(dice,
91 SND_DICE_ADDR_TYPE_GLOBAL, offset,
92 buf, len);
93}
94static inline int snd_dice_transaction_read_global(struct snd_dice *dice,
95 unsigned int offset,
96 void *buf, unsigned int len)
97{
98 return snd_dice_transaction_read(dice,
99 SND_DICE_ADDR_TYPE_GLOBAL, offset,
100 buf, len);
101}
102static inline int snd_dice_transaction_write_tx(struct snd_dice *dice,
103 unsigned int offset,
104 void *buf, unsigned int len)
105{
106 return snd_dice_transaction_write(dice, SND_DICE_ADDR_TYPE_TX, offset,
107 buf, len);
108}
109static inline int snd_dice_transaction_read_tx(struct snd_dice *dice,
110 unsigned int offset,
111 void *buf, unsigned int len)
112{
113 return snd_dice_transaction_read(dice, SND_DICE_ADDR_TYPE_TX, offset,
114 buf, len);
115}
116static inline int snd_dice_transaction_write_rx(struct snd_dice *dice,
117 unsigned int offset,
118 void *buf, unsigned int len)
119{
120 return snd_dice_transaction_write(dice, SND_DICE_ADDR_TYPE_RX, offset,
121 buf, len);
122}
123static inline int snd_dice_transaction_read_rx(struct snd_dice *dice,
124 unsigned int offset,
125 void *buf, unsigned int len)
126{
127 return snd_dice_transaction_read(dice, SND_DICE_ADDR_TYPE_RX, offset,
128 buf, len);
129}
130static inline int snd_dice_transaction_write_sync(struct snd_dice *dice,
131 unsigned int offset,
132 void *buf, unsigned int len)
133{
134 return snd_dice_transaction_write(dice, SND_DICE_ADDR_TYPE_SYNC, offset,
135 buf, len);
136}
137static inline int snd_dice_transaction_read_sync(struct snd_dice *dice,
138 unsigned int offset,
139 void *buf, unsigned int len)
140{
141 return snd_dice_transaction_read(dice, SND_DICE_ADDR_TYPE_SYNC, offset,
142 buf, len);
143}
144
145int snd_dice_transaction_set_clock_source(struct snd_dice *dice,
146 unsigned int source);
147int snd_dice_transaction_get_clock_source(struct snd_dice *dice,
148 unsigned int *source);
149int snd_dice_transaction_set_rate(struct snd_dice *dice, unsigned int rate);
150int snd_dice_transaction_get_rate(struct snd_dice *dice, unsigned int *rate);
151int snd_dice_transaction_set_enable(struct snd_dice *dice);
152void snd_dice_transaction_clear_enable(struct snd_dice *dice);
153int snd_dice_transaction_init(struct snd_dice *dice);
154int snd_dice_transaction_reinit(struct snd_dice *dice);
155void snd_dice_transaction_destroy(struct snd_dice *dice);
156
157#define SND_DICE_RATES_COUNT 7
158extern const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT];
159
160#endif