blob: 8804e42a96c691062c363570a2f2901bedbb53ab [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 Ladisch341682c2011-09-04 22:12:06 +0200377 __be32 clock_sel, number_audio, number_midi;
Clemens Ladischa7304e32011-09-04 22:16:10 +0200378 unsigned int rate_index, rate;
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 Ladischa7304e32011-09-04 22:16:10 +0200396 rate = dice_rates[rate_index];
Clemens Ladisch341682c2011-09-04 22:12:06 +0200397
398 err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200399 rx_address(dice, RX_NUMBER_AUDIO),
400 &number_audio, 4);
401 if (err < 0)
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200402 goto err_lock;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200403 err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
404 rx_address(dice, RX_NUMBER_MIDI),
405 &number_midi, 4);
406 if (err < 0)
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200407 goto err_lock;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200408
409 runtime->hw = hardware;
Clemens Ladisch341682c2011-09-04 22:12:06 +0200410
411 runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
412 snd_pcm_limit_hw_rates(runtime);
413
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200414 runtime->hw.channels_min = be32_to_cpu(number_audio);
415 runtime->hw.channels_max = be32_to_cpu(number_audio);
416
Clemens Ladischa7304e32011-09-04 22:16:10 +0200417 amdtp_out_stream_set_parameters(&dice->stream, rate,
418 be32_to_cpu(number_audio),
419 be32_to_cpu(number_midi));
420
421 err = snd_pcm_hw_constraint_step(runtime, 0,
422 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
423 amdtp_syt_intervals[rate_index]);
424 if (err < 0)
425 goto err_lock;
426 err = snd_pcm_hw_constraint_step(runtime, 0,
427 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
428 amdtp_syt_intervals[rate_index]);
429 if (err < 0)
430 goto err_lock;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200431
432 err = snd_pcm_hw_constraint_minmax(runtime,
433 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
434 5000, 8192000);
435 if (err < 0)
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200436 goto err_lock;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200437
438 err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
439 if (err < 0)
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200440 goto err_lock;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200441
442 return 0;
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200443
444err_lock:
445 dice_unlock(dice);
446error:
447 return err;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200448}
449
450static int dice_close(struct snd_pcm_substream *substream)
451{
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200452 struct dice *dice = substream->private_data;
453
454 dice_unlock(dice);
455
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200456 return 0;
457}
458
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200459static int dice_stream_start_packets(struct dice *dice)
460{
461 int err;
462
Clemens Ladisch20b65dd2011-09-04 22:15:44 +0200463 if (amdtp_out_stream_running(&dice->stream))
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200464 return 0;
465
466 err = amdtp_out_stream_start(&dice->stream, dice->resources.channel,
467 fw_parent_device(dice->unit)->max_speed);
468 if (err < 0)
469 return err;
470
471 err = dice_enable_set(dice);
472 if (err < 0) {
473 amdtp_out_stream_stop(&dice->stream);
474 return err;
475 }
476
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200477 return 0;
478}
479
480static int dice_stream_start(struct dice *dice)
481{
482 __be32 channel;
483 int err;
484
485 if (!dice->resources.allocated) {
486 err = fw_iso_resources_allocate(&dice->resources,
487 amdtp_out_stream_get_max_payload(&dice->stream),
488 fw_parent_device(dice->unit)->max_speed);
489 if (err < 0)
490 goto error;
491
492 channel = cpu_to_be32(dice->resources.channel);
493 err = snd_fw_transaction(dice->unit,
494 TCODE_WRITE_QUADLET_REQUEST,
495 rx_address(dice, RX_ISOCHRONOUS),
496 &channel, 4);
497 if (err < 0)
498 goto err_resources;
499 }
500
501 err = dice_stream_start_packets(dice);
502 if (err < 0)
503 goto err_rx_channel;
504
505 return 0;
506
507err_rx_channel:
508 channel = cpu_to_be32((u32)-1);
509 snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
510 rx_address(dice, RX_ISOCHRONOUS), &channel, 4);
511err_resources:
512 fw_iso_resources_free(&dice->resources);
513error:
514 return err;
515}
516
517static void dice_stream_stop_packets(struct dice *dice)
518{
Clemens Ladisch20b65dd2011-09-04 22:15:44 +0200519 if (amdtp_out_stream_running(&dice->stream)) {
520 dice_enable_clear(dice);
521 amdtp_out_stream_stop(&dice->stream);
522 }
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200523}
524
525static void dice_stream_stop(struct dice *dice)
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200526{
527 __be32 channel;
528
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200529 dice_stream_stop_packets(dice);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200530
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200531 if (!dice->resources.allocated)
532 return;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200533
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200534 channel = cpu_to_be32((u32)-1);
535 snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
536 rx_address(dice, RX_ISOCHRONOUS), &channel, 4);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200537
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200538 fw_iso_resources_free(&dice->resources);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200539}
540
541static int dice_hw_params(struct snd_pcm_substream *substream,
542 struct snd_pcm_hw_params *hw_params)
543{
544 struct dice *dice = substream->private_data;
545 int err;
546
547 mutex_lock(&dice->mutex);
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200548 dice_stream_stop(dice);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200549 mutex_unlock(&dice->mutex);
550
551 err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
552 params_buffer_bytes(hw_params));
553 if (err < 0)
554 goto error;
555
556 amdtp_out_stream_set_pcm_format(&dice->stream,
557 params_format(hw_params));
558
559 return 0;
560
561error:
562 return err;
563}
564
565static int dice_hw_free(struct snd_pcm_substream *substream)
566{
567 struct dice *dice = substream->private_data;
568
569 mutex_lock(&dice->mutex);
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200570 dice_stream_stop(dice);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200571 mutex_unlock(&dice->mutex);
572
573 return snd_pcm_lib_free_vmalloc_buffer(substream);
574}
575
576static int dice_prepare(struct snd_pcm_substream *substream)
577{
578 struct dice *dice = substream->private_data;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200579 int err;
580
581 mutex_lock(&dice->mutex);
582
583 if (amdtp_out_streaming_error(&dice->stream))
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200584 dice_stream_stop_packets(dice);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200585
Clemens Ladisch6abce9e2011-09-04 22:11:14 +0200586 err = dice_stream_start(dice);
587 if (err < 0) {
588 mutex_unlock(&dice->mutex);
589 return err;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200590 }
591
592 mutex_unlock(&dice->mutex);
593
594 amdtp_out_stream_pcm_prepare(&dice->stream);
595
596 return 0;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200597}
598
599static int dice_trigger(struct snd_pcm_substream *substream, int cmd)
600{
601 struct dice *dice = substream->private_data;
602 struct snd_pcm_substream *pcm;
603
604 switch (cmd) {
605 case SNDRV_PCM_TRIGGER_START:
606 pcm = substream;
607 break;
608 case SNDRV_PCM_TRIGGER_STOP:
609 pcm = NULL;
610 break;
611 default:
612 return -EINVAL;
613 }
614 amdtp_out_stream_pcm_trigger(&dice->stream, pcm);
615
616 return 0;
617}
618
619static snd_pcm_uframes_t dice_pointer(struct snd_pcm_substream *substream)
620{
621 struct dice *dice = substream->private_data;
622
623 return amdtp_out_stream_pcm_pointer(&dice->stream);
624}
625
626static int dice_create_pcm(struct dice *dice)
627{
628 static struct snd_pcm_ops ops = {
629 .open = dice_open,
630 .close = dice_close,
631 .ioctl = snd_pcm_lib_ioctl,
632 .hw_params = dice_hw_params,
633 .hw_free = dice_hw_free,
634 .prepare = dice_prepare,
635 .trigger = dice_trigger,
636 .pointer = dice_pointer,
637 .page = snd_pcm_lib_get_vmalloc_page,
638 .mmap = snd_pcm_lib_mmap_vmalloc,
639 };
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200640 struct snd_pcm *pcm;
641 int err;
642
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200643 err = snd_pcm_new(dice->card, "DICE", 0, 1, 0, &pcm);
644 if (err < 0)
645 return err;
646 pcm->private_data = dice;
647 strcpy(pcm->name, dice->card->shortname);
648 dice->pcm = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
649 dice->pcm->ops = &ops;
650
651 return 0;
652}
653
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200654static long dice_hwdep_read(struct snd_hwdep *hwdep, char __user *buf,
655 long count, loff_t *offset)
656{
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200657 struct dice *dice = hwdep->private_data;
658 DEFINE_WAIT(wait);
659 union snd_firewire_event event;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200660
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200661 spin_lock_irq(&dice->lock);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200662
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200663 while (!dice->dev_lock_changed && dice->notification_bits == 0) {
664 prepare_to_wait(&dice->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
665 spin_unlock_irq(&dice->lock);
666 schedule();
667 finish_wait(&dice->hwdep_wait, &wait);
668 if (signal_pending(current))
669 return -ERESTARTSYS;
670 spin_lock_irq(&dice->lock);
671 }
672
673 memset(&event, 0, sizeof(event));
674 if (dice->dev_lock_changed) {
675 event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
676 event.lock_status.status = dice->dev_lock_count > 0;
677 dice->dev_lock_changed = false;
678
679 count = min(count, (long)sizeof(event.lock_status));
680 } else {
681 event.dice_notification.type = SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION;
682 event.dice_notification.notification = dice->notification_bits;
683 dice->notification_bits = 0;
684
685 count = min(count, (long)sizeof(event.dice_notification));
686 }
687
688 spin_unlock_irq(&dice->lock);
689
690 if (copy_to_user(buf, &event, count))
691 return -EFAULT;
692
693 return count;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200694}
695
696static unsigned int dice_hwdep_poll(struct snd_hwdep *hwdep, struct file *file,
697 poll_table *wait)
698{
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200699 struct dice *dice = hwdep->private_data;
700 unsigned int events;
701
702 poll_wait(file, &dice->hwdep_wait, wait);
703
704 spin_lock_irq(&dice->lock);
705 if (dice->dev_lock_changed || dice->notification_bits != 0)
706 events = POLLIN | POLLRDNORM;
707 else
708 events = 0;
709 spin_unlock_irq(&dice->lock);
710
711 return events;
712}
713
714static int dice_hwdep_get_info(struct dice *dice, void __user *arg)
715{
716 struct fw_device *dev = fw_parent_device(dice->unit);
717 struct snd_firewire_get_info info;
718
719 memset(&info, 0, sizeof(info));
720 info.type = SNDRV_FIREWIRE_TYPE_DICE;
721 info.card = dev->card->index;
722 *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
723 *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
724 strlcpy(info.device_name, dev_name(&dev->device),
725 sizeof(info.device_name));
726
727 if (copy_to_user(arg, &info, sizeof(info)))
728 return -EFAULT;
729
730 return 0;
731}
732
733static int dice_hwdep_lock(struct dice *dice)
734{
735 int err;
736
737 spin_lock_irq(&dice->lock);
738
739 if (dice->dev_lock_count == 0) {
740 dice->dev_lock_count = -1;
741 err = 0;
742 } else {
743 err = -EBUSY;
744 }
745
746 spin_unlock_irq(&dice->lock);
747
748 return err;
749}
750
751static int dice_hwdep_unlock(struct dice *dice)
752{
753 int err;
754
755 spin_lock_irq(&dice->lock);
756
757 if (dice->dev_lock_count == -1) {
758 dice->dev_lock_count = 0;
759 err = 0;
760 } else {
761 err = -EBADFD;
762 }
763
764 spin_unlock_irq(&dice->lock);
765
766 return err;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200767}
768
Clemens Ladisch9dd81e32011-09-04 22:14:54 +0200769static int dice_hwdep_release(struct snd_hwdep *hwdep, struct file *file)
770{
771 struct dice *dice = hwdep->private_data;
772
773 spin_lock_irq(&dice->lock);
774 if (dice->dev_lock_count == -1)
775 dice->dev_lock_count = 0;
776 spin_unlock_irq(&dice->lock);
777
778 return 0;
779}
780
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200781static int dice_hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file,
782 unsigned int cmd, unsigned long arg)
783{
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200784 struct dice *dice = hwdep->private_data;
785
786 switch (cmd) {
787 case SNDRV_FIREWIRE_IOCTL_GET_INFO:
788 return dice_hwdep_get_info(dice, (void __user *)arg);
789 case SNDRV_FIREWIRE_IOCTL_LOCK:
790 return dice_hwdep_lock(dice);
791 case SNDRV_FIREWIRE_IOCTL_UNLOCK:
792 return dice_hwdep_unlock(dice);
793 default:
794 return -ENOIOCTLCMD;
795 }
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200796}
797
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200798#ifdef CONFIG_COMPAT
799static int dice_hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
800 unsigned int cmd, unsigned long arg)
801{
802 return dice_hwdep_ioctl(hwdep, file, cmd,
803 (unsigned long)compat_ptr(arg));
804}
805#else
806#define dice_hwdep_compat_ioctl NULL
807#endif
808
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200809static int dice_create_hwdep(struct dice *dice)
810{
811 static const struct snd_hwdep_ops ops = {
812 .read = dice_hwdep_read,
Clemens Ladisch9dd81e32011-09-04 22:14:54 +0200813 .release = dice_hwdep_release,
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200814 .poll = dice_hwdep_poll,
815 .ioctl = dice_hwdep_ioctl,
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200816 .ioctl_compat = dice_hwdep_compat_ioctl,
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200817 };
818 struct snd_hwdep *hwdep;
819 int err;
820
821 err = snd_hwdep_new(dice->card, "DICE", 0, &hwdep);
822 if (err < 0)
823 return err;
824 strcpy(hwdep->name, "DICE");
825 hwdep->iface = SNDRV_HWDEP_IFACE_FW_DICE;
826 hwdep->ops = ops;
827 hwdep->private_data = dice;
828 hwdep->exclusive = true;
829
830 return 0;
831}
832
833static void dice_card_free(struct snd_card *card)
834{
835 struct dice *dice = card->private_data;
836
837 amdtp_out_stream_destroy(&dice->stream);
838 fw_core_remove_address_handler(&dice->notification_handler);
839 mutex_destroy(&dice->mutex);
840}
841
Clemens Ladischcbab3282011-09-04 22:16:02 +0200842#define DICE_CATEGORY_ID 0x04
843
844static int dice_interface_check(struct fw_unit *unit)
845{
846 static const int min_values[10] = {
847 10, 0x64 / 4,
848 10, 0x18 / 4,
849 10, 0x18 / 4,
850 0, 0,
851 0, 0,
852 };
853 struct fw_device *device = fw_parent_device(unit);
854 struct fw_csr_iterator it;
855 int key, value, vendor = -1, model = -1, err;
856 unsigned int i;
857 __be32 pointers[ARRAY_SIZE(min_values)];
858 __be32 version;
859
860 /*
861 * Check that GUID and unit directory are constructed according to DICE
862 * rules, i.e., that the specifier ID is the GUID's OUI, and that the
863 * GUID chip ID consists of the 8-bit DICE category ID, the 10-bit
864 * product ID, and a 22-bit serial number.
865 */
866 fw_csr_iterator_init(&it, unit->directory);
867 while (fw_csr_iterator_next(&it, &key, &value)) {
868 switch (key) {
869 case CSR_SPECIFIER_ID:
870 vendor = value;
871 break;
872 case CSR_MODEL:
873 model = value;
874 break;
875 }
876 }
877 if (device->config_rom[3] != ((vendor << 8) | DICE_CATEGORY_ID) ||
878 device->config_rom[4] >> 22 != model)
879 return -ENODEV;
880
881 /*
882 * Check that the sub address spaces exist and are located inside the
883 * private address space. The minimum values are chosen so that all
884 * minimally required registers are included.
885 */
886 err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST,
887 DICE_PRIVATE_SPACE,
888 pointers, sizeof(pointers));
889 if (err < 0)
890 return -ENODEV;
891 for (i = 0; i < ARRAY_SIZE(pointers); ++i) {
892 value = be32_to_cpu(pointers[i]);
893 if (value < min_values[i] || value >= 0x40000)
894 return -ENODEV;
895 }
896
897 /*
898 * Check that the implemented DICE driver specification major version
899 * number matches.
900 */
901 err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
902 DICE_PRIVATE_SPACE +
903 be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
904 &version, 4);
905 if (err < 0)
906 return -ENODEV;
907 if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) {
908 dev_err(&unit->device,
909 "unknown DICE version: 0x%08x\n", be32_to_cpu(version));
910 return -ENODEV;
911 }
912
913 return 0;
914}
915
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200916static int dice_init_offsets(struct dice *dice)
917{
918 __be32 pointers[6];
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200919 int err;
920
921 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
Clemens Ladischcbab3282011-09-04 22:16:02 +0200922 DICE_PRIVATE_SPACE,
923 pointers, sizeof(pointers));
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200924 if (err < 0)
925 return err;
926
927 dice->global_offset = be32_to_cpu(pointers[0]) * 4;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200928 dice->rx_offset = be32_to_cpu(pointers[4]) * 4;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200929
930 return 0;
931}
932
933static void dice_card_strings(struct dice *dice)
934{
935 struct snd_card *card = dice->card;
936 struct fw_device *dev = fw_parent_device(dice->unit);
937 char vendor[32], model[32];
938 unsigned int i;
939 int err;
940
941 strcpy(card->driver, "DICE");
942
943 strcpy(card->shortname, "DICE");
944 BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname));
945 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
946 global_address(dice, GLOBAL_NICK_NAME),
947 card->shortname, sizeof(card->shortname));
948 if (err >= 0) {
949 /* DICE strings are returned in "always-wrong" endianness */
950 BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0);
951 for (i = 0; i < sizeof(card->shortname); i += 4)
952 swab32s((u32 *)&card->shortname[i]);
953 card->shortname[sizeof(card->shortname) - 1] = '\0';
954 }
955
956 strcpy(vendor, "?");
957 fw_csr_string(dev->config_rom + 5, CSR_VENDOR, vendor, sizeof(vendor));
958 strcpy(model, "?");
959 fw_csr_string(dice->unit->directory, CSR_MODEL, model, sizeof(model));
960 snprintf(card->longname, sizeof(card->longname),
Clemens Ladischcbab3282011-09-04 22:16:02 +0200961 "%s %s (serial %u) at %s, S%d",
962 vendor, model, dev->config_rom[4] & 0x3fffff,
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200963 dev_name(&dice->unit->device), 100 << dev->max_speed);
964
965 strcpy(card->mixername, "DICE");
966}
967
968static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
969{
970 struct snd_card *card;
971 struct dice *dice;
Clemens Ladisch341682c2011-09-04 22:12:06 +0200972 __be32 clock_sel;
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200973 int err;
974
Clemens Ladischcbab3282011-09-04 22:16:02 +0200975 err = dice_interface_check(unit);
976 if (err < 0)
977 return err;
978
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200979 err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*dice), &card);
980 if (err < 0)
981 return err;
982 snd_card_set_dev(card, &unit->device);
983
984 dice = card->private_data;
985 dice->card = card;
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200986 spin_lock_init(&dice->lock);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200987 mutex_init(&dice->mutex);
988 dice->unit = unit;
Clemens Ladisch0c29c912011-09-04 22:14:15 +0200989 init_waitqueue_head(&dice->hwdep_wait);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +0200990
991 err = dice_init_offsets(dice);
992 if (err < 0)
993 goto err_mutex;
994
995 dice->notification_handler.length = 4;
996 dice->notification_handler.address_callback = dice_notification;
997 dice->notification_handler.callback_data = dice;
998 err = fw_core_add_address_handler(&dice->notification_handler,
999 &fw_high_memory_region);
1000 if (err < 0)
1001 goto err_mutex;
1002
1003 err = fw_iso_resources_init(&dice->resources, unit);
1004 if (err < 0)
1005 goto err_notification_handler;
1006 dice->resources.channels_mask = 0x00000000ffffffffuLL;
1007
Clemens Ladischa7304e32011-09-04 22:16:10 +02001008 err = amdtp_out_stream_init(&dice->stream, unit,
1009 CIP_BLOCKING | CIP_HI_DUALWIRE);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001010 if (err < 0)
1011 goto err_resources;
1012
1013 err = dice_owner_set(dice);
1014 if (err < 0)
1015 goto err_stream;
1016
1017 card->private_free = dice_card_free;
1018
1019 dice_card_strings(dice);
1020
Clemens Ladisch341682c2011-09-04 22:12:06 +02001021 err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
1022 global_address(dice, GLOBAL_CLOCK_SELECT),
1023 &clock_sel, 4);
1024 if (err < 0)
1025 goto error;
1026 clock_sel &= cpu_to_be32(~CLOCK_SOURCE_MASK);
1027 clock_sel |= cpu_to_be32(CLOCK_SOURCE_ARX1);
1028 err = snd_fw_transaction(unit, TCODE_WRITE_QUADLET_REQUEST,
1029 global_address(dice, GLOBAL_CLOCK_SELECT),
1030 &clock_sel, 4);
1031 if (err < 0)
1032 goto error;
1033
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001034 err = dice_create_pcm(dice);
1035 if (err < 0)
1036 goto error;
1037
1038 err = dice_create_hwdep(dice);
1039 if (err < 0)
1040 goto error;
1041
1042 err = snd_card_register(card);
1043 if (err < 0)
1044 goto error;
1045
1046 dev_set_drvdata(&unit->device, dice);
1047
1048 return 0;
1049
1050err_stream:
1051 amdtp_out_stream_destroy(&dice->stream);
1052err_resources:
1053 fw_iso_resources_destroy(&dice->resources);
1054err_notification_handler:
1055 fw_core_remove_address_handler(&dice->notification_handler);
1056err_mutex:
1057 mutex_destroy(&dice->mutex);
1058error:
1059 snd_card_free(card);
1060 return err;
1061}
1062
1063static void dice_remove(struct fw_unit *unit)
1064{
1065 struct dice *dice = dev_get_drvdata(&unit->device);
1066
Clemens Ladisch4ed31f202011-09-04 22:13:09 +02001067 mutex_lock(&dice->mutex);
1068
1069 amdtp_out_stream_pcm_abort(&dice->stream);
1070
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001071 snd_card_disconnect(dice->card);
1072
Clemens Ladisch6abce9e2011-09-04 22:11:14 +02001073 dice_stream_stop(dice);
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001074 dice_owner_clear(dice);
Clemens Ladisch4ed31f202011-09-04 22:13:09 +02001075
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001076 mutex_unlock(&dice->mutex);
1077
1078 snd_card_free_when_closed(dice->card);
1079}
1080
1081static void dice_bus_reset(struct fw_unit *unit)
1082{
1083 struct dice *dice = dev_get_drvdata(&unit->device);
1084
1085 mutex_lock(&dice->mutex);
Clemens Ladisch6abce9e2011-09-04 22:11:14 +02001086
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001087 /*
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001088 * On a bus reset, the DICE firmware disables streaming and then goes
1089 * off contemplating its own navel for hundreds of milliseconds before
1090 * it can react to any of our attempts to reenable streaming. This
1091 * means that we lose synchronization anyway, so we force our streams
1092 * to stop so that the application can restart them in an orderly
1093 * manner.
1094 */
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001095 amdtp_out_stream_pcm_abort(&dice->stream);
Clemens Ladisch6abce9e2011-09-04 22:11:14 +02001096 dice_stream_stop_packets(dice);
1097
1098 dice_owner_update(dice);
1099
1100 fw_iso_resources_update(&dice->resources);
1101
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001102 mutex_unlock(&dice->mutex);
1103}
1104
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001105#define DICE_INTERFACE 0x000001
1106
1107static const struct ieee1394_device_id dice_id_table[] = {
1108 {
Clemens Ladischcbab3282011-09-04 22:16:02 +02001109 .match_flags = IEEE1394_MATCH_VERSION,
1110 .version = DICE_INTERFACE,
Clemens Ladisch82fbb4f2011-09-04 22:04:49 +02001111 },
1112 { }
1113};
1114MODULE_DEVICE_TABLE(ieee1394, dice_id_table);
1115
1116static struct fw_driver dice_driver = {
1117 .driver = {
1118 .owner = THIS_MODULE,
1119 .name = KBUILD_MODNAME,
1120 .bus = &fw_bus_type,
1121 },
1122 .probe = dice_probe,
1123 .update = dice_bus_reset,
1124 .remove = dice_remove,
1125 .id_table = dice_id_table,
1126};
1127
1128static int __init alsa_dice_init(void)
1129{
1130 return driver_register(&dice_driver.driver);
1131}
1132
1133static void __exit alsa_dice_exit(void)
1134{
1135 driver_unregister(&dice_driver.driver);
1136}
1137
1138module_init(alsa_dice_init);
1139module_exit(alsa_dice_exit);