blob: e1d8dff2339711d0cbb41eaa5880b8dc237f1b9c [file] [log] [blame]
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001/*
2 * TC Applied Technologies Digital Interface Communications Engine driver
3 *
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 * Licensed under the terms of the GNU General Public License, version 2.
6 */
7
Clemens Ladisch0c29c912011-09-04 22:14:15 +02008#include <linux/compat.h>
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02009#include <linux/delay.h>
10#include <linux/device.h>
11#include <linux/firewire.h>
12#include <linux/firewire-constants.h>
13#include <linux/module.h>
14#include <linux/mod_devicetable.h>
15#include <linux/mutex.h>
16#include <linux/slab.h>
Clemens Ladisch0c29c912011-09-04 22:14:15 +020017#include <linux/spinlock.h>
18#include <linux/wait.h>
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +020019#include <sound/control.h>
20#include <sound/core.h>
Clemens Ladisch0c29c912011-09-04 22:14:15 +020021#include <sound/firewire.h>
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +020022#include <sound/hwdep.h>
23#include <sound/initval.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include "amdtp.h"
27#include "iso-resources.h"
28#include "lib.h"
Clemens Ladisch54e72f02011-09-04 22:15:54 +020029#include "dice-interface.h"
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +020030
31
32struct dice {
33 struct snd_card *card;
34 struct fw_unit *unit;
Clemens Ladisch0c29c912011-09-04 22:14:15 +020035 spinlock_t lock;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +020036 struct mutex mutex;
37 unsigned int global_offset;
38 unsigned int rx_offset;
39 struct fw_address_handler notification_handler;
40 int owner_generation;
Clemens Ladisch0c29c912011-09-04 22:14:15 +020041 int dev_lock_count; /* > 0 driver, < 0 userspace */
42 bool dev_lock_changed;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +020043 bool global_enabled;
Clemens Ladisch0c29c912011-09-04 22:14:15 +020044 wait_queue_head_t hwdep_wait;
45 u32 notification_bits;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +020046 struct snd_pcm_substream *pcm;
47 struct fw_iso_resources resources;
48 struct amdtp_out_stream stream;
49};
50
51MODULE_DESCRIPTION("DICE driver");
52MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
53MODULE_LICENSE("GPL v2");
54
Clemens Ladisch341682c2011-09-04 22:12:06 +020055static const unsigned int dice_rates[] = {
56 [0] = 32000,
57 [1] = 44100,
58 [2] = 48000,
59 [3] = 88200,
60 [4] = 96000,
61 [5] = 176400,
62 [6] = 192000,
63};
64
Clemens Ladisch0c29c912011-09-04 22:14:15 +020065static void dice_lock_changed(struct dice *dice)
66{
67 dice->dev_lock_changed = true;
68 wake_up(&dice->hwdep_wait);
69}
70
71static int dice_try_lock(struct dice *dice)
72{
73 int err;
74
75 spin_lock_irq(&dice->lock);
76
77 if (dice->dev_lock_count < 0) {
78 err = -EBUSY;
79 goto out;
80 }
81
82 if (dice->dev_lock_count++ == 0)
83 dice_lock_changed(dice);
84 err = 0;
85
86out:
87 spin_unlock_irq(&dice->lock);
88
89 return err;
90}
91
92static void dice_unlock(struct dice *dice)
93{
94 spin_lock_irq(&dice->lock);
95
96 if (WARN_ON(dice->dev_lock_count <= 0))
97 goto out;
98
99 if (--dice->dev_lock_count == 0)
100 dice_lock_changed(dice);
101
102out:
103 spin_unlock_irq(&dice->lock);
104}
105
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200106static inline u64 global_address(struct dice *dice, unsigned int offset)
107{
108 return DICE_PRIVATE_SPACE + dice->global_offset + offset;
109}
110
111// TODO: rx index
112static inline u64 rx_address(struct dice *dice, unsigned int offset)
113{
114 return DICE_PRIVATE_SPACE + dice->rx_offset + offset;
115}
116
117static int dice_owner_set(struct dice *dice)
118{
119 struct fw_device *device = fw_parent_device(dice->unit);
120 __be64 *buffer;
121 int rcode, err, errors = 0;
122
123 buffer = kmalloc(2 * 8, GFP_KERNEL);
124 if (!buffer)
125 return -ENOMEM;
126
127 for (;;) {
128 buffer[0] = cpu_to_be64(OWNER_NO_OWNER);
129 buffer[1] = cpu_to_be64(
130 ((u64)device->card->node_id << OWNER_NODE_SHIFT) |
131 dice->notification_handler.offset);
132
133 dice->owner_generation = device->generation;
134 smp_rmb(); /* node_id vs. generation */
135 rcode = fw_run_transaction(device->card,
136 TCODE_LOCK_COMPARE_SWAP,
137 device->node_id,
138 dice->owner_generation,
139 device->max_speed,
140 global_address(dice, GLOBAL_OWNER),
141 buffer, 2 * 8);
142
143 if (rcode == RCODE_COMPLETE) {
144 if (buffer[0] == cpu_to_be64(OWNER_NO_OWNER)) {
145 err = 0;
146 } else {
147 dev_err(&dice->unit->device,
148 "device is already in use\n");
149 err = -EBUSY;
150 }
151 break;
152 }
153 if (rcode_is_permanent_error(rcode) || ++errors >= 3) {
154 dev_err(&dice->unit->device,
155 "setting device owner failed: %s\n",
156 fw_rcode_string(rcode));
157 err = -EIO;
158 break;
159 }
160 msleep(20);
161 }
162
163 kfree(buffer);
164
165 return err;
166}
167
168static int dice_owner_update(struct dice *dice)
169{
170 struct fw_device *device = fw_parent_device(dice->unit);
171 __be64 *buffer;
172 int rcode, err, errors = 0;
173
174 if (dice->owner_generation == -1)
175 return 0;
176
177 buffer = kmalloc(2 * 8, GFP_KERNEL);
178 if (!buffer)
179 return -ENOMEM;
180
181 for (;;) {
182 buffer[0] = cpu_to_be64(OWNER_NO_OWNER);
183 buffer[1] = cpu_to_be64(
184 ((u64)device->card->node_id << OWNER_NODE_SHIFT) |
185 dice->notification_handler.offset);
186
187 dice->owner_generation = device->generation;
188 smp_rmb(); /* node_id vs. generation */
189 rcode = fw_run_transaction(device->card,
190 TCODE_LOCK_COMPARE_SWAP,
191 device->node_id,
192 dice->owner_generation,
193 device->max_speed,
194 global_address(dice, GLOBAL_OWNER),
195 buffer, 2 * 8);
196
197 if (rcode == RCODE_COMPLETE) {
198 if (buffer[0] == cpu_to_be64(OWNER_NO_OWNER)) {
199 err = 0;
200 } else {
201 dev_err(&dice->unit->device,
202 "device is already in use\n");
203 err = -EBUSY;
204 }
205 break;
206 }
207 if (rcode == RCODE_GENERATION) {
208 err = 0; /* try again later */
209 break;
210 }
211 if (rcode_is_permanent_error(rcode) || ++errors >= 3) {
212 dev_err(&dice->unit->device,
213 "setting device owner failed: %s\n",
214 fw_rcode_string(rcode));
215 err = -EIO;
216 break;
217 }
218 msleep(20);
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 dice *dice)
230{
231 struct fw_device *device = fw_parent_device(dice->unit);
232 __be64 *buffer;
233 int rcode, errors = 0;
234
235 buffer = kmalloc(2 * 8, GFP_KERNEL);
236 if (!buffer)
237 return;
238
239 for (;;) {
240 buffer[0] = cpu_to_be64(
241 ((u64)device->card->node_id << OWNER_NODE_SHIFT) |
242 dice->notification_handler.offset);
243 buffer[1] = cpu_to_be64(OWNER_NO_OWNER);
244
245 rcode = fw_run_transaction(device->card,
246 TCODE_LOCK_COMPARE_SWAP,
247 device->node_id,
248 dice->owner_generation,
249 device->max_speed,
250 global_address(dice, GLOBAL_OWNER),
251 buffer, 2 * 8);
252
253 if (rcode == RCODE_COMPLETE)
254 break;
255 if (rcode == RCODE_GENERATION)
256 break;
257 if (rcode_is_permanent_error(rcode) || ++errors >= 3) {
258 dev_err(&dice->unit->device,
259 "clearing device owner failed: %s\n",
260 fw_rcode_string(rcode));
261 break;
262 }
263 msleep(20);
264 }
265
266 kfree(buffer);
267
268 dice->owner_generation = -1;
269}
270
271static int dice_enable_set(struct dice *dice)
272{
273 struct fw_device *device = fw_parent_device(dice->unit);
274 __be32 value;
275 int rcode, err, errors = 0;
276
Clemens Ladisch54e72f02011-09-04 22:15:54 +0200277 value = cpu_to_be32(1);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200278 for (;;) {
279 rcode = fw_run_transaction(device->card,
280 TCODE_WRITE_QUADLET_REQUEST,
281 device->node_id,
282 dice->owner_generation,
283 device->max_speed,
284 global_address(dice, GLOBAL_ENABLE),
285 &value, 4);
286 if (rcode == RCODE_COMPLETE) {
287 dice->global_enabled = true;
288 err = 0;
289 break;
290 }
291 if (rcode == RCODE_GENERATION) {
292 err = -EAGAIN;
293 break;
294 }
295 if (rcode_is_permanent_error(rcode) || ++errors >= 3) {
296 dev_err(&dice->unit->device,
297 "device enabling failed: %s\n",
298 fw_rcode_string(rcode));
299 err = -EIO;
300 break;
301 }
302 msleep(20);
303 }
304
305 return err;
306}
307
308static void dice_enable_clear(struct dice *dice)
309{
310 struct fw_device *device = fw_parent_device(dice->unit);
311 __be32 value;
312 int rcode, errors = 0;
313
314 value = 0;
315 for (;;) {
316 rcode = fw_run_transaction(device->card,
317 TCODE_WRITE_QUADLET_REQUEST,
318 device->node_id,
319 dice->owner_generation,
320 device->max_speed,
321 global_address(dice, GLOBAL_ENABLE),
322 &value, 4);
323 if (rcode == RCODE_COMPLETE ||
324 rcode == RCODE_GENERATION)
325 break;
326 if (rcode_is_permanent_error(rcode) || ++errors >= 3) {
327 dev_err(&dice->unit->device,
328 "device disabling failed: %s\n",
329 fw_rcode_string(rcode));
330 break;
331 }
332 msleep(20);
333 }
334 dice->global_enabled = false;
335}
336
337static void dice_notification(struct fw_card *card, struct fw_request *request,
338 int tcode, int destination, int source,
339 int generation, unsigned long long offset,
340 void *data, size_t length, void *callback_data)
341{
342 struct dice *dice = callback_data;
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200343 unsigned long flags;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200344
345 if (tcode != TCODE_WRITE_QUADLET_REQUEST) {
346 fw_send_response(card, request, RCODE_TYPE_ERROR);
347 return;
348 }
349 if ((offset & 3) != 0) {
350 fw_send_response(card, request, RCODE_ADDRESS_ERROR);
351 return;
352 }
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200353 spin_lock_irqsave(&dice->lock, flags);
354 dice->notification_bits |= be32_to_cpup(data);
355 spin_unlock_irqrestore(&dice->lock, flags);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200356 fw_send_response(card, request, RCODE_COMPLETE);
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200357 wake_up(&dice->hwdep_wait);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200358}
359
360static int dice_open(struct snd_pcm_substream *substream)
361{
362 static const struct snd_pcm_hardware hardware = {
363 .info = SNDRV_PCM_INFO_MMAP |
364 SNDRV_PCM_INFO_MMAP_VALID |
365 SNDRV_PCM_INFO_BATCH |
366 SNDRV_PCM_INFO_INTERLEAVED |
367 SNDRV_PCM_INFO_BLOCK_TRANSFER,
368 .formats = AMDTP_OUT_PCM_FORMAT_BITS,
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200369 .buffer_bytes_max = 16 * 1024 * 1024,
370 .period_bytes_min = 1,
371 .period_bytes_max = UINT_MAX,
372 .periods_min = 1,
373 .periods_max = UINT_MAX,
374 };
375 struct dice *dice = substream->private_data;
376 struct snd_pcm_runtime *runtime = substream->runtime;
Clemens Ladischa644a942011-09-04 22:17:31 +0200377 __be32 clock_sel, data[2];
378 unsigned int rate_index, number_audio, number_midi;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200379 int err;
380
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200381 err = dice_try_lock(dice);
382 if (err < 0)
383 goto error;
384
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200385 err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
Clemens Ladisch341682c2011-09-04 22:12:06 +0200386 global_address(dice, GLOBAL_CLOCK_SELECT),
387 &clock_sel, 4);
388 if (err < 0)
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200389 goto err_lock;
Clemens Ladischa7304e32011-09-04 22:16:10 +0200390 rate_index = (be32_to_cpu(clock_sel) & CLOCK_RATE_MASK)
391 >> CLOCK_RATE_SHIFT;
392 if (rate_index >= ARRAY_SIZE(dice_rates)) {
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200393 err = -ENXIO;
394 goto err_lock;
395 }
Clemens Ladisch341682c2011-09-04 22:12:06 +0200396
Clemens Ladischa644a942011-09-04 22:17:31 +0200397 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200398 rx_address(dice, RX_NUMBER_AUDIO),
Clemens Ladischa644a942011-09-04 22:17:31 +0200399 data, 2 * 4);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200400 if (err < 0)
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200401 goto err_lock;
Clemens Ladischa644a942011-09-04 22:17:31 +0200402 number_audio = be32_to_cpu(data[0]);
403 number_midi = be32_to_cpu(data[1]);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200404
405 runtime->hw = hardware;
Clemens Ladisch341682c2011-09-04 22:12:06 +0200406
Clemens Ladischa644a942011-09-04 22:17:31 +0200407 runtime->hw.rates = snd_pcm_rate_to_rate_bit(dice_rates[rate_index]);
Clemens Ladisch341682c2011-09-04 22:12:06 +0200408 snd_pcm_limit_hw_rates(runtime);
409
Clemens Ladischa644a942011-09-04 22:17:31 +0200410 runtime->hw.channels_min = number_audio;
411 runtime->hw.channels_max = number_audio;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200412
Clemens Ladischa644a942011-09-04 22:17:31 +0200413 amdtp_out_stream_set_parameters(&dice->stream, dice_rates[rate_index],
414 number_audio, number_midi);
Clemens Ladischa7304e32011-09-04 22:16:10 +0200415
416 err = snd_pcm_hw_constraint_step(runtime, 0,
417 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
418 amdtp_syt_intervals[rate_index]);
419 if (err < 0)
420 goto err_lock;
421 err = snd_pcm_hw_constraint_step(runtime, 0,
422 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
423 amdtp_syt_intervals[rate_index]);
424 if (err < 0)
425 goto err_lock;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200426
427 err = snd_pcm_hw_constraint_minmax(runtime,
428 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
429 5000, 8192000);
430 if (err < 0)
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200431 goto err_lock;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200432
433 err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
434 if (err < 0)
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200435 goto err_lock;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200436
437 return 0;
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200438
439err_lock:
440 dice_unlock(dice);
441error:
442 return err;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200443}
444
445static int dice_close(struct snd_pcm_substream *substream)
446{
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200447 struct dice *dice = substream->private_data;
448
449 dice_unlock(dice);
450
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200451 return 0;
452}
453
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200454static int dice_stream_start_packets(struct dice *dice)
455{
456 int err;
457
Clemens Ladisch20b65dd2011-09-04 22:15:44 +0200458 if (amdtp_out_stream_running(&dice->stream))
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200459 return 0;
460
461 err = amdtp_out_stream_start(&dice->stream, dice->resources.channel,
462 fw_parent_device(dice->unit)->max_speed);
463 if (err < 0)
464 return err;
465
466 err = dice_enable_set(dice);
467 if (err < 0) {
468 amdtp_out_stream_stop(&dice->stream);
469 return err;
470 }
471
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200472 return 0;
473}
474
475static int dice_stream_start(struct dice *dice)
476{
477 __be32 channel;
478 int err;
479
480 if (!dice->resources.allocated) {
481 err = fw_iso_resources_allocate(&dice->resources,
482 amdtp_out_stream_get_max_payload(&dice->stream),
483 fw_parent_device(dice->unit)->max_speed);
484 if (err < 0)
485 goto error;
486
487 channel = cpu_to_be32(dice->resources.channel);
488 err = snd_fw_transaction(dice->unit,
489 TCODE_WRITE_QUADLET_REQUEST,
490 rx_address(dice, RX_ISOCHRONOUS),
491 &channel, 4);
492 if (err < 0)
493 goto err_resources;
494 }
495
496 err = dice_stream_start_packets(dice);
497 if (err < 0)
498 goto err_rx_channel;
499
500 return 0;
501
502err_rx_channel:
503 channel = cpu_to_be32((u32)-1);
504 snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
505 rx_address(dice, RX_ISOCHRONOUS), &channel, 4);
506err_resources:
507 fw_iso_resources_free(&dice->resources);
508error:
509 return err;
510}
511
512static void dice_stream_stop_packets(struct dice *dice)
513{
Clemens Ladisch20b65dd2011-09-04 22:15:44 +0200514 if (amdtp_out_stream_running(&dice->stream)) {
515 dice_enable_clear(dice);
516 amdtp_out_stream_stop(&dice->stream);
517 }
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200518}
519
520static void dice_stream_stop(struct dice *dice)
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200521{
522 __be32 channel;
523
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200524 dice_stream_stop_packets(dice);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200525
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200526 if (!dice->resources.allocated)
527 return;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200528
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200529 channel = cpu_to_be32((u32)-1);
530 snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
531 rx_address(dice, RX_ISOCHRONOUS), &channel, 4);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200532
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200533 fw_iso_resources_free(&dice->resources);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200534}
535
536static int dice_hw_params(struct snd_pcm_substream *substream,
537 struct snd_pcm_hw_params *hw_params)
538{
539 struct dice *dice = substream->private_data;
540 int err;
541
542 mutex_lock(&dice->mutex);
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200543 dice_stream_stop(dice);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200544 mutex_unlock(&dice->mutex);
545
546 err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
547 params_buffer_bytes(hw_params));
548 if (err < 0)
549 goto error;
550
551 amdtp_out_stream_set_pcm_format(&dice->stream,
552 params_format(hw_params));
553
554 return 0;
555
556error:
557 return err;
558}
559
560static int dice_hw_free(struct snd_pcm_substream *substream)
561{
562 struct dice *dice = substream->private_data;
563
564 mutex_lock(&dice->mutex);
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200565 dice_stream_stop(dice);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200566 mutex_unlock(&dice->mutex);
567
568 return snd_pcm_lib_free_vmalloc_buffer(substream);
569}
570
571static int dice_prepare(struct snd_pcm_substream *substream)
572{
573 struct dice *dice = substream->private_data;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200574 int err;
575
576 mutex_lock(&dice->mutex);
577
578 if (amdtp_out_streaming_error(&dice->stream))
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200579 dice_stream_stop_packets(dice);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200580
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200581 err = dice_stream_start(dice);
582 if (err < 0) {
583 mutex_unlock(&dice->mutex);
584 return err;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200585 }
586
587 mutex_unlock(&dice->mutex);
588
589 amdtp_out_stream_pcm_prepare(&dice->stream);
590
591 return 0;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200592}
593
594static int dice_trigger(struct snd_pcm_substream *substream, int cmd)
595{
596 struct dice *dice = substream->private_data;
597 struct snd_pcm_substream *pcm;
598
599 switch (cmd) {
600 case SNDRV_PCM_TRIGGER_START:
601 pcm = substream;
602 break;
603 case SNDRV_PCM_TRIGGER_STOP:
604 pcm = NULL;
605 break;
606 default:
607 return -EINVAL;
608 }
609 amdtp_out_stream_pcm_trigger(&dice->stream, pcm);
610
611 return 0;
612}
613
614static snd_pcm_uframes_t dice_pointer(struct snd_pcm_substream *substream)
615{
616 struct dice *dice = substream->private_data;
617
618 return amdtp_out_stream_pcm_pointer(&dice->stream);
619}
620
621static int dice_create_pcm(struct dice *dice)
622{
623 static struct snd_pcm_ops ops = {
624 .open = dice_open,
625 .close = dice_close,
626 .ioctl = snd_pcm_lib_ioctl,
627 .hw_params = dice_hw_params,
628 .hw_free = dice_hw_free,
629 .prepare = dice_prepare,
630 .trigger = dice_trigger,
631 .pointer = dice_pointer,
632 .page = snd_pcm_lib_get_vmalloc_page,
633 .mmap = snd_pcm_lib_mmap_vmalloc,
634 };
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200635 struct snd_pcm *pcm;
636 int err;
637
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200638 err = snd_pcm_new(dice->card, "DICE", 0, 1, 0, &pcm);
639 if (err < 0)
640 return err;
641 pcm->private_data = dice;
642 strcpy(pcm->name, dice->card->shortname);
643 dice->pcm = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
644 dice->pcm->ops = &ops;
645
646 return 0;
647}
648
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200649static long dice_hwdep_read(struct snd_hwdep *hwdep, char __user *buf,
650 long count, loff_t *offset)
651{
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200652 struct dice *dice = hwdep->private_data;
653 DEFINE_WAIT(wait);
654 union snd_firewire_event event;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200655
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200656 spin_lock_irq(&dice->lock);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200657
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200658 while (!dice->dev_lock_changed && dice->notification_bits == 0) {
659 prepare_to_wait(&dice->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
660 spin_unlock_irq(&dice->lock);
661 schedule();
662 finish_wait(&dice->hwdep_wait, &wait);
663 if (signal_pending(current))
664 return -ERESTARTSYS;
665 spin_lock_irq(&dice->lock);
666 }
667
668 memset(&event, 0, sizeof(event));
669 if (dice->dev_lock_changed) {
670 event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
671 event.lock_status.status = dice->dev_lock_count > 0;
672 dice->dev_lock_changed = false;
673
674 count = min(count, (long)sizeof(event.lock_status));
675 } else {
676 event.dice_notification.type = SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION;
677 event.dice_notification.notification = dice->notification_bits;
678 dice->notification_bits = 0;
679
680 count = min(count, (long)sizeof(event.dice_notification));
681 }
682
683 spin_unlock_irq(&dice->lock);
684
685 if (copy_to_user(buf, &event, count))
686 return -EFAULT;
687
688 return count;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200689}
690
691static unsigned int dice_hwdep_poll(struct snd_hwdep *hwdep, struct file *file,
692 poll_table *wait)
693{
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200694 struct dice *dice = hwdep->private_data;
695 unsigned int events;
696
697 poll_wait(file, &dice->hwdep_wait, wait);
698
699 spin_lock_irq(&dice->lock);
700 if (dice->dev_lock_changed || dice->notification_bits != 0)
701 events = POLLIN | POLLRDNORM;
702 else
703 events = 0;
704 spin_unlock_irq(&dice->lock);
705
706 return events;
707}
708
709static int dice_hwdep_get_info(struct dice *dice, void __user *arg)
710{
711 struct fw_device *dev = fw_parent_device(dice->unit);
712 struct snd_firewire_get_info info;
713
714 memset(&info, 0, sizeof(info));
715 info.type = SNDRV_FIREWIRE_TYPE_DICE;
716 info.card = dev->card->index;
717 *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
718 *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
719 strlcpy(info.device_name, dev_name(&dev->device),
720 sizeof(info.device_name));
721
722 if (copy_to_user(arg, &info, sizeof(info)))
723 return -EFAULT;
724
725 return 0;
726}
727
728static int dice_hwdep_lock(struct dice *dice)
729{
730 int err;
731
732 spin_lock_irq(&dice->lock);
733
734 if (dice->dev_lock_count == 0) {
735 dice->dev_lock_count = -1;
736 err = 0;
737 } else {
738 err = -EBUSY;
739 }
740
741 spin_unlock_irq(&dice->lock);
742
743 return err;
744}
745
746static int dice_hwdep_unlock(struct dice *dice)
747{
748 int err;
749
750 spin_lock_irq(&dice->lock);
751
752 if (dice->dev_lock_count == -1) {
753 dice->dev_lock_count = 0;
754 err = 0;
755 } else {
756 err = -EBADFD;
757 }
758
759 spin_unlock_irq(&dice->lock);
760
761 return err;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200762}
763
Clemens Ladisch9dd81e32011-09-04 22:14:54 +0200764static int dice_hwdep_release(struct snd_hwdep *hwdep, struct file *file)
765{
766 struct dice *dice = hwdep->private_data;
767
768 spin_lock_irq(&dice->lock);
769 if (dice->dev_lock_count == -1)
770 dice->dev_lock_count = 0;
771 spin_unlock_irq(&dice->lock);
772
773 return 0;
774}
775
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200776static int dice_hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file,
777 unsigned int cmd, unsigned long arg)
778{
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200779 struct dice *dice = hwdep->private_data;
780
781 switch (cmd) {
782 case SNDRV_FIREWIRE_IOCTL_GET_INFO:
783 return dice_hwdep_get_info(dice, (void __user *)arg);
784 case SNDRV_FIREWIRE_IOCTL_LOCK:
785 return dice_hwdep_lock(dice);
786 case SNDRV_FIREWIRE_IOCTL_UNLOCK:
787 return dice_hwdep_unlock(dice);
788 default:
789 return -ENOIOCTLCMD;
790 }
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200791}
792
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200793#ifdef CONFIG_COMPAT
794static int dice_hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
795 unsigned int cmd, unsigned long arg)
796{
797 return dice_hwdep_ioctl(hwdep, file, cmd,
798 (unsigned long)compat_ptr(arg));
799}
800#else
801#define dice_hwdep_compat_ioctl NULL
802#endif
803
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200804static int dice_create_hwdep(struct dice *dice)
805{
806 static const struct snd_hwdep_ops ops = {
807 .read = dice_hwdep_read,
Clemens Ladisch9dd81e32011-09-04 22:14:54 +0200808 .release = dice_hwdep_release,
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200809 .poll = dice_hwdep_poll,
810 .ioctl = dice_hwdep_ioctl,
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200811 .ioctl_compat = dice_hwdep_compat_ioctl,
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200812 };
813 struct snd_hwdep *hwdep;
814 int err;
815
816 err = snd_hwdep_new(dice->card, "DICE", 0, &hwdep);
817 if (err < 0)
818 return err;
819 strcpy(hwdep->name, "DICE");
820 hwdep->iface = SNDRV_HWDEP_IFACE_FW_DICE;
821 hwdep->ops = ops;
822 hwdep->private_data = dice;
823 hwdep->exclusive = true;
824
825 return 0;
826}
827
828static void dice_card_free(struct snd_card *card)
829{
830 struct dice *dice = card->private_data;
831
832 amdtp_out_stream_destroy(&dice->stream);
833 fw_core_remove_address_handler(&dice->notification_handler);
834 mutex_destroy(&dice->mutex);
835}
836
Clemens Ladischcbab3282011-09-04 22:16:02 +0200837#define DICE_CATEGORY_ID 0x04
838
839static int dice_interface_check(struct fw_unit *unit)
840{
841 static const int min_values[10] = {
842 10, 0x64 / 4,
843 10, 0x18 / 4,
844 10, 0x18 / 4,
845 0, 0,
846 0, 0,
847 };
848 struct fw_device *device = fw_parent_device(unit);
849 struct fw_csr_iterator it;
850 int key, value, vendor = -1, model = -1, err;
851 unsigned int i;
852 __be32 pointers[ARRAY_SIZE(min_values)];
853 __be32 version;
854
855 /*
856 * Check that GUID and unit directory are constructed according to DICE
857 * rules, i.e., that the specifier ID is the GUID's OUI, and that the
858 * GUID chip ID consists of the 8-bit DICE category ID, the 10-bit
859 * product ID, and a 22-bit serial number.
860 */
861 fw_csr_iterator_init(&it, unit->directory);
862 while (fw_csr_iterator_next(&it, &key, &value)) {
863 switch (key) {
864 case CSR_SPECIFIER_ID:
865 vendor = value;
866 break;
867 case CSR_MODEL:
868 model = value;
869 break;
870 }
871 }
872 if (device->config_rom[3] != ((vendor << 8) | DICE_CATEGORY_ID) ||
873 device->config_rom[4] >> 22 != model)
874 return -ENODEV;
875
876 /*
877 * Check that the sub address spaces exist and are located inside the
878 * private address space. The minimum values are chosen so that all
879 * minimally required registers are included.
880 */
881 err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST,
882 DICE_PRIVATE_SPACE,
883 pointers, sizeof(pointers));
884 if (err < 0)
885 return -ENODEV;
886 for (i = 0; i < ARRAY_SIZE(pointers); ++i) {
887 value = be32_to_cpu(pointers[i]);
888 if (value < min_values[i] || value >= 0x40000)
889 return -ENODEV;
890 }
891
892 /*
893 * Check that the implemented DICE driver specification major version
894 * number matches.
895 */
896 err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
897 DICE_PRIVATE_SPACE +
898 be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
899 &version, 4);
900 if (err < 0)
901 return -ENODEV;
902 if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) {
903 dev_err(&unit->device,
904 "unknown DICE version: 0x%08x\n", be32_to_cpu(version));
905 return -ENODEV;
906 }
907
908 return 0;
909}
910
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200911static int dice_init_offsets(struct dice *dice)
912{
913 __be32 pointers[6];
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200914 int err;
915
916 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
Clemens Ladischcbab3282011-09-04 22:16:02 +0200917 DICE_PRIVATE_SPACE,
918 pointers, sizeof(pointers));
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200919 if (err < 0)
920 return err;
921
922 dice->global_offset = be32_to_cpu(pointers[0]) * 4;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200923 dice->rx_offset = be32_to_cpu(pointers[4]) * 4;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200924
925 return 0;
926}
927
928static void dice_card_strings(struct dice *dice)
929{
930 struct snd_card *card = dice->card;
931 struct fw_device *dev = fw_parent_device(dice->unit);
932 char vendor[32], model[32];
933 unsigned int i;
934 int err;
935
936 strcpy(card->driver, "DICE");
937
938 strcpy(card->shortname, "DICE");
939 BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname));
940 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
941 global_address(dice, GLOBAL_NICK_NAME),
942 card->shortname, sizeof(card->shortname));
943 if (err >= 0) {
944 /* DICE strings are returned in "always-wrong" endianness */
945 BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0);
946 for (i = 0; i < sizeof(card->shortname); i += 4)
947 swab32s((u32 *)&card->shortname[i]);
948 card->shortname[sizeof(card->shortname) - 1] = '\0';
949 }
950
951 strcpy(vendor, "?");
952 fw_csr_string(dev->config_rom + 5, CSR_VENDOR, vendor, sizeof(vendor));
953 strcpy(model, "?");
954 fw_csr_string(dice->unit->directory, CSR_MODEL, model, sizeof(model));
955 snprintf(card->longname, sizeof(card->longname),
Clemens Ladischcbab3282011-09-04 22:16:02 +0200956 "%s %s (serial %u) at %s, S%d",
957 vendor, model, dev->config_rom[4] & 0x3fffff,
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200958 dev_name(&dice->unit->device), 100 << dev->max_speed);
959
960 strcpy(card->mixername, "DICE");
961}
962
963static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
964{
965 struct snd_card *card;
966 struct dice *dice;
Clemens Ladisch341682c2011-09-04 22:12:06 +0200967 __be32 clock_sel;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200968 int err;
969
Clemens Ladischcbab3282011-09-04 22:16:02 +0200970 err = dice_interface_check(unit);
971 if (err < 0)
972 return err;
973
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200974 err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*dice), &card);
975 if (err < 0)
976 return err;
977 snd_card_set_dev(card, &unit->device);
978
979 dice = card->private_data;
980 dice->card = card;
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200981 spin_lock_init(&dice->lock);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200982 mutex_init(&dice->mutex);
983 dice->unit = unit;
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200984 init_waitqueue_head(&dice->hwdep_wait);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200985
986 err = dice_init_offsets(dice);
987 if (err < 0)
988 goto err_mutex;
989
990 dice->notification_handler.length = 4;
991 dice->notification_handler.address_callback = dice_notification;
992 dice->notification_handler.callback_data = dice;
993 err = fw_core_add_address_handler(&dice->notification_handler,
994 &fw_high_memory_region);
995 if (err < 0)
996 goto err_mutex;
997
998 err = fw_iso_resources_init(&dice->resources, unit);
999 if (err < 0)
1000 goto err_notification_handler;
1001 dice->resources.channels_mask = 0x00000000ffffffffuLL;
1002
Clemens Ladischa7304e32011-09-04 22:16:10 +02001003 err = amdtp_out_stream_init(&dice->stream, unit,
1004 CIP_BLOCKING | CIP_HI_DUALWIRE);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001005 if (err < 0)
1006 goto err_resources;
1007
1008 err = dice_owner_set(dice);
1009 if (err < 0)
1010 goto err_stream;
1011
1012 card->private_free = dice_card_free;
1013
1014 dice_card_strings(dice);
1015
Clemens Ladisch341682c2011-09-04 22:12:06 +02001016 err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
1017 global_address(dice, GLOBAL_CLOCK_SELECT),
1018 &clock_sel, 4);
1019 if (err < 0)
1020 goto error;
1021 clock_sel &= cpu_to_be32(~CLOCK_SOURCE_MASK);
1022 clock_sel |= cpu_to_be32(CLOCK_SOURCE_ARX1);
1023 err = snd_fw_transaction(unit, TCODE_WRITE_QUADLET_REQUEST,
1024 global_address(dice, GLOBAL_CLOCK_SELECT),
1025 &clock_sel, 4);
1026 if (err < 0)
1027 goto error;
1028
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001029 err = dice_create_pcm(dice);
1030 if (err < 0)
1031 goto error;
1032
1033 err = dice_create_hwdep(dice);
1034 if (err < 0)
1035 goto error;
1036
1037 err = snd_card_register(card);
1038 if (err < 0)
1039 goto error;
1040
1041 dev_set_drvdata(&unit->device, dice);
1042
1043 return 0;
1044
1045err_stream:
1046 amdtp_out_stream_destroy(&dice->stream);
1047err_resources:
1048 fw_iso_resources_destroy(&dice->resources);
1049err_notification_handler:
1050 fw_core_remove_address_handler(&dice->notification_handler);
1051err_mutex:
1052 mutex_destroy(&dice->mutex);
1053error:
1054 snd_card_free(card);
1055 return err;
1056}
1057
1058static void dice_remove(struct fw_unit *unit)
1059{
1060 struct dice *dice = dev_get_drvdata(&unit->device);
1061
Clemens Ladisch4ed31f202011-09-04 22:13:09 +02001062 mutex_lock(&dice->mutex);
1063
1064 amdtp_out_stream_pcm_abort(&dice->stream);
1065
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001066 snd_card_disconnect(dice->card);
1067
Clemens Ladisch6abce9e2011-09-04 22:11:14 +02001068 dice_stream_stop(dice);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001069 dice_owner_clear(dice);
Clemens Ladisch4ed31f202011-09-04 22:13:09 +02001070
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001071 mutex_unlock(&dice->mutex);
1072
1073 snd_card_free_when_closed(dice->card);
1074}
1075
1076static void dice_bus_reset(struct fw_unit *unit)
1077{
1078 struct dice *dice = dev_get_drvdata(&unit->device);
1079
1080 mutex_lock(&dice->mutex);
Clemens Ladisch6abce9e2011-09-04 22:11:14 +02001081
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001082 /*
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001083 * On a bus reset, the DICE firmware disables streaming and then goes
1084 * off contemplating its own navel for hundreds of milliseconds before
1085 * it can react to any of our attempts to reenable streaming. This
1086 * means that we lose synchronization anyway, so we force our streams
1087 * to stop so that the application can restart them in an orderly
1088 * manner.
1089 */
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001090 amdtp_out_stream_pcm_abort(&dice->stream);
Clemens Ladisch6abce9e2011-09-04 22:11:14 +02001091 dice_stream_stop_packets(dice);
1092
1093 dice_owner_update(dice);
1094
1095 fw_iso_resources_update(&dice->resources);
1096
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001097 mutex_unlock(&dice->mutex);
1098}
1099
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001100#define DICE_INTERFACE 0x000001
1101
1102static const struct ieee1394_device_id dice_id_table[] = {
1103 {
Clemens Ladischcbab3282011-09-04 22:16:02 +02001104 .match_flags = IEEE1394_MATCH_VERSION,
1105 .version = DICE_INTERFACE,
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001106 },
1107 { }
1108};
1109MODULE_DEVICE_TABLE(ieee1394, dice_id_table);
1110
1111static struct fw_driver dice_driver = {
1112 .driver = {
1113 .owner = THIS_MODULE,
1114 .name = KBUILD_MODNAME,
1115 .bus = &fw_bus_type,
1116 },
1117 .probe = dice_probe,
1118 .update = dice_bus_reset,
1119 .remove = dice_remove,
1120 .id_table = dice_id_table,
1121};
1122
1123static int __init alsa_dice_init(void)
1124{
1125 return driver_register(&dice_driver.driver);
1126}
1127
1128static void __exit alsa_dice_exit(void)
1129{
1130 driver_unregister(&dice_driver.driver);
1131}
1132
1133module_init(alsa_dice_init);
1134module_exit(alsa_dice_exit);