2 * TC Applied Technologies Digital Interface Communications Engine driver
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 * Licensed under the terms of the GNU General Public License, version 2.
8 #include <linux/delay.h>
9 #include <linux/device.h>
10 #include <linux/firewire.h>
11 #include <linux/firewire-constants.h>
12 #include <linux/module.h>
13 #include <linux/mod_devicetable.h>
14 #include <linux/mutex.h>
15 #include <linux/slab.h>
16 #include <sound/control.h>
17 #include <sound/core.h>
18 #include <sound/hwdep.h>
19 #include <sound/initval.h>
20 #include <sound/pcm.h>
21 #include <sound/pcm_params.h>
23 #include "iso-resources.h"
26 #define DICE_PRIVATE_SPACE 0xffffe0000000uLL
28 /* offset from DICE_PRIVATE_SPACE; offsets and sizes in quadlets */
29 #define DICE_GLOBAL_OFFSET 0x00
30 #define DICE_GLOBAL_SIZE 0x04
31 #define DICE_TX_OFFSET 0x08
32 #define DICE_TX_SIZE 0x0c
33 #define DICE_RX_OFFSET 0x10
34 #define DICE_RX_SIZE 0x14
36 /* pointed to by DICE_GLOBAL_OFFSET */
37 #define GLOBAL_OWNER 0x000
38 #define OWNER_NO_OWNER 0xffff000000000000uLL
39 #define OWNER_NODE_SHIFT 48
40 #define GLOBAL_NOTIFICATION 0x008
41 #define NOTIFY_RX_CFG_CHG 0x00000001
42 #define NOTIFY_TX_CFG_CHG 0x00000002
43 #define NOTIFY_DUP_ISOC 0x00000004
44 #define NOTIFY_BW_ERR 0x00000008
45 #define NOTIFY_LOCK_CHG 0x00000010
46 #define NOTIFY_CLOCK_ACCEPTED 0x00000020
47 #define NOTIFY_INTERFACE_CHG 0x00000040
48 #define NOTIFY_MESSAGE 0x00100000
49 #define GLOBAL_NICK_NAME 0x00c
50 #define NICK_NAME_SIZE 64
51 #define GLOBAL_CLOCK_SELECT 0x04c
52 #define CLOCK_SOURCE_MASK 0x000000ff
53 #define CLOCK_SOURCE_AES1 0x00000000
54 #define CLOCK_SOURCE_AES2 0x00000001
55 #define CLOCK_SOURCE_AES3 0x00000002
56 #define CLOCK_SOURCE_AES4 0x00000003
57 #define CLOCK_SOURCE_AES_ANY 0x00000004
58 #define CLOCK_SOURCE_ADAT 0x00000005
59 #define CLOCK_SOURCE_TDIF 0x00000006
60 #define CLOCK_SOURCE_WC 0x00000007
61 #define CLOCK_SOURCE_ARX1 0x00000008
62 #define CLOCK_SOURCE_ARX2 0x00000009
63 #define CLOCK_SOURCE_ARX3 0x0000000a
64 #define CLOCK_SOURCE_ARX4 0x0000000b
65 #define CLOCK_SOURCE_INTERNAL 0x0000000c
66 #define CLOCK_RATE_MASK 0x0000ff00
67 #define CLOCK_RATE_32000 0x00000000
68 #define CLOCK_RATE_44100 0x00000100
69 #define CLOCK_RATE_48000 0x00000200
70 #define CLOCK_RATE_88200 0x00000300
71 #define CLOCK_RATE_96000 0x00000400
72 #define CLOCK_RATE_176400 0x00000500
73 #define CLOCK_RATE_192000 0x00000600
74 #define CLOCK_RATE_ANY_LOW 0x00000700
75 #define CLOCK_RATE_ANY_MID 0x00000800
76 #define CLOCK_RATE_ANY_HIGH 0x00000900
77 #define CLOCK_RATE_NONE 0x00000a00
78 #define GLOBAL_ENABLE 0x050
79 #define ENABLE 0x00000001
80 #define GLOBAL_STATUS 0x054
81 #define STATUS_SOURCE_LOCKED 0x00000001
82 #define STATUS_RATE_CONFLICT 0x00000002
83 #define STATUS_NOMINAL_RATE_MASK 0x0000ff00
84 #define GLOBAL_EXTENDED_STATUS 0x058
85 #define EXT_STATUS_AES1_LOCKED 0x00000001
86 #define EXT_STATUS_AES2_LOCKED 0x00000002
87 #define EXT_STATUS_AES3_LOCKED 0x00000004
88 #define EXT_STATUS_AES4_LOCKED 0x00000008
89 #define EXT_STATUS_ADAT_LOCKED 0x00000010
90 #define EXT_STATUS_TDIF_LOCKED 0x00000020
91 #define EXT_STATUS_ARX1_LOCKED 0x00000040
92 #define EXT_STATUS_ARX2_LOCKED 0x00000080
93 #define EXT_STATUS_ARX3_LOCKED 0x00000100
94 #define EXT_STATUS_ARX4_LOCKED 0x00000200
95 #define EXT_STATUS_WC_LOCKED 0x00000400
96 #define EXT_STATUS_AES1_SLIP 0x00010000
97 #define EXT_STATUS_AES2_SLIP 0x00020000
98 #define EXT_STATUS_AES3_SLIP 0x00040000
99 #define EXT_STATUS_AES4_SLIP 0x00080000
100 #define EXT_STATUS_ADAT_SLIP 0x00100000
101 #define EXT_STATUS_TDIF_SLIP 0x00200000
102 #define EXT_STATUS_ARX1_SLIP 0x00400000
103 #define EXT_STATUS_ARX2_SLIP 0x00800000
104 #define EXT_STATUS_ARX3_SLIP 0x01000000
105 #define EXT_STATUS_ARX4_SLIP 0x02000000
106 #define EXT_STATUS_WC_SLIP 0x04000000
107 #define GLOBAL_SAMPLE_RATE 0x05c
108 #define GLOBAL_VERSION 0x060
109 #define GLOBAL_CLOCK_CAPABILITIES 0x064
110 #define CLOCK_CAP_RATE_32000 0x00000001
111 #define CLOCK_CAP_RATE_44100 0x00000002
112 #define CLOCK_CAP_RATE_48000 0x00000004
113 #define CLOCK_CAP_RATE_88200 0x00000008
114 #define CLOCK_CAP_RATE_96000 0x00000010
115 #define CLOCK_CAP_RATE_176400 0x00000020
116 #define CLOCK_CAP_RATE_192000 0x00000040
117 #define CLOCK_CAP_SOURCE_AES1 0x00010000
118 #define CLOCK_CAP_SOURCE_AES2 0x00020000
119 #define CLOCK_CAP_SOURCE_AES3 0x00040000
120 #define CLOCK_CAP_SOURCE_AES4 0x00080000
121 #define CLOCK_CAP_SOURCE_AES_ANY 0x00100000
122 #define CLOCK_CAP_SOURCE_ADAT 0x00200000
123 #define CLOCK_CAP_SOURCE_TDIF 0x00400000
124 #define CLOCK_CAP_SOURCE_WC 0x00800000
125 #define CLOCK_CAP_SOURCE_ARX1 0x01000000
126 #define CLOCK_CAP_SOURCE_ARX2 0x02000000
127 #define CLOCK_CAP_SOURCE_ARX3 0x04000000
128 #define CLOCK_CAP_SOURCE_ARX4 0x08000000
129 #define CLOCK_CAP_SOURCE_INTERNAL 0x10000000
130 #define GLOBAL_CLOCK_SOURCE_NAMES 0x068
131 #define CLOCK_SOURCE_NAMES_SIZE 256
133 /* pointed to by DICE_TX_OFFSET */
134 #define TX_NUMBER 0x000
135 #define TX_SIZE 0x004
136 /* repeated TX_NUMBER times, offset by TX_SIZE quadlets */
137 #define TX_ISOCHRONOUS 0x008
138 #define TX_NUMBER_AUDIO 0x00c
139 #define TX_NUMBER_MIDI 0x010
140 #define TX_SPEED 0x014
141 #define TX_NAMES 0x018
142 #define TX_NAMES_SIZE 256
143 #define TX_AC3_CAPABILITIES 0x118
144 #define TX_AC3_ENABLE 0x11c
146 /* pointed to by DICE_RX_OFFSET */
147 #define RX_NUMBER 0x000
148 #define RX_SIZE 0x004
149 /* repeated RX_NUMBER times, offset by RX_SIZE quadlets */
150 #define RX_ISOCHRONOUS 0x008
151 #define RX_SEQ_START 0x00c
152 #define RX_NUMBER_AUDIO 0x010
153 #define RX_NUMBER_MIDI 0x014
154 #define RX_NAMES 0x018
155 #define RX_NAMES_SIZE 256
156 #define RX_AC3_CAPABILITIES 0x118
157 #define RX_AC3_ENABLE 0x11c
160 #define FIRMWARE_LOAD_SPACE 0xffffe0100000uLL
162 /* offset from FIRMWARE_LOAD_SPACE */
163 #define FIRMWARE_VERSION 0x000
164 #define FIRMWARE_OPCODE 0x004
165 #define OPCODE_MASK 0x00000fff
166 #define OPCODE_GET_IMAGE_DESC 0x00000000
167 #define OPCODE_DELETE_IMAGE 0x00000001
168 #define OPCODE_CREATE_IMAGE 0x00000002
169 #define OPCODE_UPLOAD 0x00000003
170 #define OPCODE_UPLOAD_STAT 0x00000004
171 #define OPCODE_RESET_IMAGE 0x00000005
172 #define OPCODE_TEST_ACTION 0x00000006
173 #define OPCODE_GET_RUNNING_IMAGE_VINFO 0x0000000a
174 #define OPCODE_EXECUTE 0x80000000
175 #define FIRMWARE_RETURN_STATUS 0x008
176 #define FIRMWARE_PROGRESS 0x00c
177 #define PROGRESS_CURR_MASK 0x00000fff
178 #define PROGRESS_MAX_MASK 0x00fff000
179 #define PROGRESS_TOUT_MASK 0x0f000000
180 #define PROGRESS_FLAG 0x80000000
181 #define FIRMWARE_CAPABILITIES 0x010
182 #define FL_CAP_AUTOERASE 0x00000001
183 #define FL_CAP_PROGRESS 0x00000002
184 #define FIRMWARE_DATA 0x02c
185 #define TEST_CMD_POKE 0x00000001
186 #define TEST_CMD_PEEK 0x00000002
187 #define CMD_GET_AVS_CNT 0x00000003
188 #define CMD_CLR_AVS_CNT 0x00000004
189 #define CMD_SET_MODE 0x00000005
190 #define CMD_SET_MIDIBP 0x00000006
191 #define CMD_GET_AVSPHASE 0x00000007
192 #define CMD_ENABLE_BNC_SYNC 0x00000008
193 #define CMD_PULSE_BNC_SYNC 0x00000009
194 #define CMD_EMUL_SLOW_CMD 0x0000000a
195 #define FIRMWARE_TEST_DELAY 0xfd8
196 #define FIRMWARE_TEST_BUF 0xfdc
200 #define EAP_PRIVATE_SPACE 0xffffe0200000uLL
202 #define EAP_CAPABILITY_OFFSET 0x000
203 #define EAP_CAPABILITY_SIZE 0x004
206 #define EAP_ROUTER_CAPS 0x000
207 #define ROUTER_EXPOSED 0x00000001
208 #define ROUTER_READ_ONLY 0x00000002
209 #define ROUTER_FLASH 0x00000004
210 #define MAX_ROUTES_MASK 0xffff0000
211 #define EAP_MIXER_CAPS 0x004
212 #define MIXER_EXPOSED 0x00000001
213 #define MIXER_READ_ONLY 0x00000002
214 #define MIXER_FLASH 0x00000004
215 #define MIXER_IN_DEV_MASK 0x000000f0
216 #define MIXER_OUT_DEV_MASK 0x00000f00
217 #define MIXER_INPUTS_MASK 0x00ff0000
218 #define MIXER_OUTPUTS_MASK 0xff000000
219 #define EAP_GENERAL_CAPS 0x008
220 #define GENERAL_STREAM_CONFIG 0x00000001
221 #define GENERAL_FLASH 0x00000002
222 #define GENERAL_PEAK 0x00000004
223 #define GENERAL_MAX_TX_STREAMS_MASK 0x000000f0
224 #define GENERAL_MAX_RX_STREAMS_MASK 0x00000f00
225 #define GENERAL_STREAM_CONFIG_FLASH 0x00001000
226 #define GENERAL_CHIP_MASK 0x00ff0000
227 #define GENERAL_CHIP_DICE_II 0x00000000
228 #define GENERAL_CHIP_DICE_MINI 0x00010000
229 #define GENERAL_CHIP_DICE_JR 0x00020000
233 struct snd_card
*card
;
234 struct fw_unit
*unit
;
236 unsigned int global_offset
;
237 unsigned int rx_offset
;
238 struct fw_address_handler notification_handler
;
239 int owner_generation
;
242 struct snd_pcm_substream
*pcm
;
243 struct fw_iso_resources resources
;
244 struct amdtp_out_stream stream
;
247 MODULE_DESCRIPTION("DICE driver");
248 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
249 MODULE_LICENSE("GPL v2");
251 static inline u64
global_address(struct dice
*dice
, unsigned int offset
)
253 return DICE_PRIVATE_SPACE
+ dice
->global_offset
+ offset
;
257 static inline u64
rx_address(struct dice
*dice
, unsigned int offset
)
259 return DICE_PRIVATE_SPACE
+ dice
->rx_offset
+ offset
;
262 static int dice_owner_set(struct dice
*dice
)
264 struct fw_device
*device
= fw_parent_device(dice
->unit
);
266 int rcode
, err
, errors
= 0;
268 buffer
= kmalloc(2 * 8, GFP_KERNEL
);
273 buffer
[0] = cpu_to_be64(OWNER_NO_OWNER
);
274 buffer
[1] = cpu_to_be64(
275 ((u64
)device
->card
->node_id
<< OWNER_NODE_SHIFT
) |
276 dice
->notification_handler
.offset
);
278 dice
->owner_generation
= device
->generation
;
279 smp_rmb(); /* node_id vs. generation */
280 rcode
= fw_run_transaction(device
->card
,
281 TCODE_LOCK_COMPARE_SWAP
,
283 dice
->owner_generation
,
285 global_address(dice
, GLOBAL_OWNER
),
288 if (rcode
== RCODE_COMPLETE
) {
289 if (buffer
[0] == cpu_to_be64(OWNER_NO_OWNER
)) {
292 dev_err(&dice
->unit
->device
,
293 "device is already in use\n");
298 if (rcode_is_permanent_error(rcode
) || ++errors
>= 3) {
299 dev_err(&dice
->unit
->device
,
300 "setting device owner failed: %s\n",
301 fw_rcode_string(rcode
));
313 static int dice_owner_update(struct dice
*dice
)
315 struct fw_device
*device
= fw_parent_device(dice
->unit
);
317 int rcode
, err
, errors
= 0;
319 if (dice
->owner_generation
== -1)
322 buffer
= kmalloc(2 * 8, GFP_KERNEL
);
327 buffer
[0] = cpu_to_be64(OWNER_NO_OWNER
);
328 buffer
[1] = cpu_to_be64(
329 ((u64
)device
->card
->node_id
<< OWNER_NODE_SHIFT
) |
330 dice
->notification_handler
.offset
);
332 dice
->owner_generation
= device
->generation
;
333 smp_rmb(); /* node_id vs. generation */
334 rcode
= fw_run_transaction(device
->card
,
335 TCODE_LOCK_COMPARE_SWAP
,
337 dice
->owner_generation
,
339 global_address(dice
, GLOBAL_OWNER
),
342 if (rcode
== RCODE_COMPLETE
) {
343 if (buffer
[0] == cpu_to_be64(OWNER_NO_OWNER
)) {
346 dev_err(&dice
->unit
->device
,
347 "device is already in use\n");
352 if (rcode
== RCODE_GENERATION
) {
353 err
= 0; /* try again later */
356 if (rcode_is_permanent_error(rcode
) || ++errors
>= 3) {
357 dev_err(&dice
->unit
->device
,
358 "setting device owner failed: %s\n",
359 fw_rcode_string(rcode
));
369 dice
->owner_generation
= -1;
374 static void dice_owner_clear(struct dice
*dice
)
376 struct fw_device
*device
= fw_parent_device(dice
->unit
);
378 int rcode
, errors
= 0;
380 buffer
= kmalloc(2 * 8, GFP_KERNEL
);
385 buffer
[0] = cpu_to_be64(
386 ((u64
)device
->card
->node_id
<< OWNER_NODE_SHIFT
) |
387 dice
->notification_handler
.offset
);
388 buffer
[1] = cpu_to_be64(OWNER_NO_OWNER
);
390 rcode
= fw_run_transaction(device
->card
,
391 TCODE_LOCK_COMPARE_SWAP
,
393 dice
->owner_generation
,
395 global_address(dice
, GLOBAL_OWNER
),
398 if (rcode
== RCODE_COMPLETE
)
400 if (rcode
== RCODE_GENERATION
)
402 if (rcode_is_permanent_error(rcode
) || ++errors
>= 3) {
403 dev_err(&dice
->unit
->device
,
404 "clearing device owner failed: %s\n",
405 fw_rcode_string(rcode
));
413 dice
->owner_generation
= -1;
416 static int dice_enable_set(struct dice
*dice
)
418 struct fw_device
*device
= fw_parent_device(dice
->unit
);
420 int rcode
, err
, errors
= 0;
422 value
= cpu_to_be32(ENABLE
);
424 rcode
= fw_run_transaction(device
->card
,
425 TCODE_WRITE_QUADLET_REQUEST
,
427 dice
->owner_generation
,
429 global_address(dice
, GLOBAL_ENABLE
),
431 if (rcode
== RCODE_COMPLETE
) {
432 dice
->global_enabled
= true;
436 if (rcode
== RCODE_GENERATION
) {
440 if (rcode_is_permanent_error(rcode
) || ++errors
>= 3) {
441 dev_err(&dice
->unit
->device
,
442 "device enabling failed: %s\n",
443 fw_rcode_string(rcode
));
453 static void dice_enable_clear(struct dice
*dice
)
455 struct fw_device
*device
= fw_parent_device(dice
->unit
);
457 int rcode
, errors
= 0;
461 rcode
= fw_run_transaction(device
->card
,
462 TCODE_WRITE_QUADLET_REQUEST
,
464 dice
->owner_generation
,
466 global_address(dice
, GLOBAL_ENABLE
),
468 if (rcode
== RCODE_COMPLETE
||
469 rcode
== RCODE_GENERATION
)
471 if (rcode_is_permanent_error(rcode
) || ++errors
>= 3) {
472 dev_err(&dice
->unit
->device
,
473 "device disabling failed: %s\n",
474 fw_rcode_string(rcode
));
479 dice
->global_enabled
= false;
482 static void dice_notification(struct fw_card
*card
, struct fw_request
*request
,
483 int tcode
, int destination
, int source
,
484 int generation
, unsigned long long offset
,
485 void *data
, size_t length
, void *callback_data
)
487 struct dice
*dice
= callback_data
;
489 if (tcode
!= TCODE_WRITE_QUADLET_REQUEST
) {
490 fw_send_response(card
, request
, RCODE_TYPE_ERROR
);
493 if ((offset
& 3) != 0) {
494 fw_send_response(card
, request
, RCODE_ADDRESS_ERROR
);
497 dev_info(&dice
->unit
->device
,
498 "notification: %08x\n", be32_to_cpup(data
));
499 fw_send_response(card
, request
, RCODE_COMPLETE
);
502 static int dice_open(struct snd_pcm_substream
*substream
)
504 static const struct snd_pcm_hardware hardware
= {
505 .info
= SNDRV_PCM_INFO_MMAP
|
506 SNDRV_PCM_INFO_MMAP_VALID
|
507 SNDRV_PCM_INFO_BATCH
|
508 SNDRV_PCM_INFO_INTERLEAVED
|
509 SNDRV_PCM_INFO_BLOCK_TRANSFER
,
510 .formats
= AMDTP_OUT_PCM_FORMAT_BITS
,
511 .rates
= SNDRV_PCM_RATE_44100
,
514 .buffer_bytes_max
= 16 * 1024 * 1024,
515 .period_bytes_min
= 1,
516 .period_bytes_max
= UINT_MAX
,
518 .periods_max
= UINT_MAX
,
520 struct dice
*dice
= substream
->private_data
;
521 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
522 __be32 number_audio
, number_midi
;
525 err
= snd_fw_transaction(dice
->unit
, TCODE_READ_QUADLET_REQUEST
,
526 rx_address(dice
, RX_NUMBER_AUDIO
),
530 err
= snd_fw_transaction(dice
->unit
, TCODE_READ_QUADLET_REQUEST
,
531 rx_address(dice
, RX_NUMBER_MIDI
),
536 runtime
->hw
= hardware
;
537 runtime
->hw
.channels_min
= be32_to_cpu(number_audio
);
538 runtime
->hw
.channels_max
= be32_to_cpu(number_audio
);
540 amdtp_out_stream_set_rate(&dice
->stream
, 44100);
541 amdtp_out_stream_set_pcm(&dice
->stream
, be32_to_cpu(number_audio
));
542 amdtp_out_stream_set_midi(&dice
->stream
, be32_to_cpu(number_midi
));
544 err
= snd_pcm_hw_constraint_minmax(runtime
,
545 SNDRV_PCM_HW_PARAM_PERIOD_TIME
,
550 err
= snd_pcm_hw_constraint_msbits(runtime
, 0, 32, 24);
557 static int dice_close(struct snd_pcm_substream
*substream
)
562 static void dice_stop_stream(struct dice
*dice
)
566 if (dice
->stream_running
) {
567 dice_enable_clear(dice
);
569 amdtp_out_stream_stop(&dice
->stream
);
571 channel
= cpu_to_be32((u32
)-1);
572 snd_fw_transaction(dice
->unit
, TCODE_WRITE_QUADLET_REQUEST
,
573 rx_address(dice
, RX_ISOCHRONOUS
),
576 fw_iso_resources_free(&dice
->resources
);
578 dice
->stream_running
= false;
582 static int dice_hw_params(struct snd_pcm_substream
*substream
,
583 struct snd_pcm_hw_params
*hw_params
)
585 struct dice
*dice
= substream
->private_data
;
588 mutex_lock(&dice
->mutex
);
589 dice_stop_stream(dice
);
590 mutex_unlock(&dice
->mutex
);
592 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
593 params_buffer_bytes(hw_params
));
597 amdtp_out_stream_set_pcm_format(&dice
->stream
,
598 params_format(hw_params
));
606 static int dice_hw_free(struct snd_pcm_substream
*substream
)
608 struct dice
*dice
= substream
->private_data
;
610 mutex_lock(&dice
->mutex
);
611 dice_stop_stream(dice
);
612 mutex_unlock(&dice
->mutex
);
614 return snd_pcm_lib_free_vmalloc_buffer(substream
);
617 static int dice_prepare(struct snd_pcm_substream
*substream
)
619 struct dice
*dice
= substream
->private_data
;
620 struct fw_device
*device
= fw_parent_device(dice
->unit
);
624 mutex_lock(&dice
->mutex
);
626 if (amdtp_out_streaming_error(&dice
->stream
))
627 dice_stop_stream(dice
);
629 if (!dice
->stream_running
) {
630 err
= fw_iso_resources_allocate(&dice
->resources
,
631 amdtp_out_stream_get_max_payload(&dice
->stream
),
637 channel
= cpu_to_be32(dice
->resources
.channel
);
638 err
= snd_fw_transaction(dice
->unit
,
639 TCODE_WRITE_QUADLET_REQUEST
,
640 rx_address(dice
, RX_ISOCHRONOUS
),
645 err
= amdtp_out_stream_start(&dice
->stream
,
646 dice
->resources
.channel
,
651 err
= dice_enable_set(dice
);
655 dice
->stream_running
= true;
658 mutex_unlock(&dice
->mutex
);
660 amdtp_out_stream_pcm_prepare(&dice
->stream
);
665 amdtp_out_stream_stop(&dice
->stream
);
667 fw_iso_resources_free(&dice
->resources
);
669 mutex_unlock(&dice
->mutex
);
674 static int dice_trigger(struct snd_pcm_substream
*substream
, int cmd
)
676 struct dice
*dice
= substream
->private_data
;
677 struct snd_pcm_substream
*pcm
;
680 case SNDRV_PCM_TRIGGER_START
:
683 case SNDRV_PCM_TRIGGER_STOP
:
689 amdtp_out_stream_pcm_trigger(&dice
->stream
, pcm
);
694 static snd_pcm_uframes_t
dice_pointer(struct snd_pcm_substream
*substream
)
696 struct dice
*dice
= substream
->private_data
;
698 return amdtp_out_stream_pcm_pointer(&dice
->stream
);
701 static int dice_create_pcm(struct dice
*dice
)
703 static struct snd_pcm_ops ops
= {
706 .ioctl
= snd_pcm_lib_ioctl
,
707 .hw_params
= dice_hw_params
,
708 .hw_free
= dice_hw_free
,
709 .prepare
= dice_prepare
,
710 .trigger
= dice_trigger
,
711 .pointer
= dice_pointer
,
712 .page
= snd_pcm_lib_get_vmalloc_page
,
713 .mmap
= snd_pcm_lib_mmap_vmalloc
,
719 clock
= cpu_to_be32(CLOCK_SOURCE_ARX1
| CLOCK_RATE_44100
);
720 err
= snd_fw_transaction(dice
->unit
, TCODE_WRITE_QUADLET_REQUEST
,
721 global_address(dice
, GLOBAL_CLOCK_SELECT
),
726 err
= snd_pcm_new(dice
->card
, "DICE", 0, 1, 0, &pcm
);
729 pcm
->private_data
= dice
;
730 strcpy(pcm
->name
, dice
->card
->shortname
);
731 dice
->pcm
= pcm
->streams
[SNDRV_PCM_STREAM_PLAYBACK
].substream
;
732 dice
->pcm
->ops
= &ops
;
737 // TODO: implement these
739 static long dice_hwdep_read(struct snd_hwdep
*hwdep
, char __user
*buf
,
740 long count
, loff_t
*offset
)
745 static int dice_hwdep_open(struct snd_hwdep
*hwdep
, struct file
*file
)
750 static int dice_hwdep_release(struct snd_hwdep
*hwdep
, struct file
*file
)
755 static unsigned int dice_hwdep_poll(struct snd_hwdep
*hwdep
, struct file
*file
,
758 return POLLERR
| POLLHUP
;
761 static int dice_hwdep_ioctl(struct snd_hwdep
*hwdep
, struct file
*file
,
762 unsigned int cmd
, unsigned long arg
)
767 static int dice_create_hwdep(struct dice
*dice
)
769 static const struct snd_hwdep_ops ops
= {
770 .read
= dice_hwdep_read
,
771 .open
= dice_hwdep_open
,
772 .release
= dice_hwdep_release
,
773 .poll
= dice_hwdep_poll
,
774 .ioctl
= dice_hwdep_ioctl
,
775 .ioctl_compat
= dice_hwdep_ioctl
,
777 struct snd_hwdep
*hwdep
;
780 err
= snd_hwdep_new(dice
->card
, "DICE", 0, &hwdep
);
783 strcpy(hwdep
->name
, "DICE");
784 hwdep
->iface
= SNDRV_HWDEP_IFACE_FW_DICE
;
786 hwdep
->private_data
= dice
;
787 hwdep
->exclusive
= true;
792 static void dice_card_free(struct snd_card
*card
)
794 struct dice
*dice
= card
->private_data
;
796 amdtp_out_stream_destroy(&dice
->stream
);
797 fw_core_remove_address_handler(&dice
->notification_handler
);
798 mutex_destroy(&dice
->mutex
);
801 static int dice_init_offsets(struct dice
*dice
)
804 unsigned int global_size
, rx_size
;
807 err
= snd_fw_transaction(dice
->unit
, TCODE_READ_BLOCK_REQUEST
,
808 DICE_PRIVATE_SPACE
, &pointers
, 6 * 4);
812 dice
->global_offset
= be32_to_cpu(pointers
[0]) * 4;
813 global_size
= be32_to_cpu(pointers
[1]);
814 dice
->rx_offset
= be32_to_cpu(pointers
[4]) * 4;
815 rx_size
= be32_to_cpu(pointers
[5]);
817 /* some sanity checks to ensure that we actually have a DICE */
818 if (dice
->global_offset
< 10 * 4 || global_size
< 0x168 / 4 ||
819 dice
->rx_offset
< 10 * 4 || rx_size
< 0x120 / 4) {
820 dev_err(&dice
->unit
->device
, "invalid register pointers\n");
827 static void dice_card_strings(struct dice
*dice
)
829 struct snd_card
*card
= dice
->card
;
830 struct fw_device
*dev
= fw_parent_device(dice
->unit
);
831 char vendor
[32], model
[32];
835 strcpy(card
->driver
, "DICE");
837 strcpy(card
->shortname
, "DICE");
838 BUILD_BUG_ON(NICK_NAME_SIZE
< sizeof(card
->shortname
));
839 err
= snd_fw_transaction(dice
->unit
, TCODE_READ_BLOCK_REQUEST
,
840 global_address(dice
, GLOBAL_NICK_NAME
),
841 card
->shortname
, sizeof(card
->shortname
));
843 /* DICE strings are returned in "always-wrong" endianness */
844 BUILD_BUG_ON(sizeof(card
->shortname
) % 4 != 0);
845 for (i
= 0; i
< sizeof(card
->shortname
); i
+= 4)
846 swab32s((u32
*)&card
->shortname
[i
]);
847 card
->shortname
[sizeof(card
->shortname
) - 1] = '\0';
851 fw_csr_string(dev
->config_rom
+ 5, CSR_VENDOR
, vendor
, sizeof(vendor
));
853 fw_csr_string(dice
->unit
->directory
, CSR_MODEL
, model
, sizeof(model
));
854 snprintf(card
->longname
, sizeof(card
->longname
),
855 "%s %s, GUID %08x%08x at %s, S%d",
856 vendor
, model
, dev
->config_rom
[3], dev
->config_rom
[4],
857 dev_name(&dice
->unit
->device
), 100 << dev
->max_speed
);
859 strcpy(card
->mixername
, "DICE");
862 static int dice_probe(struct fw_unit
*unit
, const struct ieee1394_device_id
*id
)
864 struct snd_card
*card
;
868 err
= snd_card_create(-1, NULL
, THIS_MODULE
, sizeof(*dice
), &card
);
871 snd_card_set_dev(card
, &unit
->device
);
873 dice
= card
->private_data
;
875 mutex_init(&dice
->mutex
);
878 err
= dice_init_offsets(dice
);
882 dice
->notification_handler
.length
= 4;
883 dice
->notification_handler
.address_callback
= dice_notification
;
884 dice
->notification_handler
.callback_data
= dice
;
885 err
= fw_core_add_address_handler(&dice
->notification_handler
,
886 &fw_high_memory_region
);
890 err
= fw_iso_resources_init(&dice
->resources
, unit
);
892 goto err_notification_handler
;
893 dice
->resources
.channels_mask
= 0x00000000ffffffffuLL
;
895 err
= amdtp_out_stream_init(&dice
->stream
, unit
, CIP_NONBLOCKING
);
899 err
= dice_owner_set(dice
);
903 card
->private_free
= dice_card_free
;
905 dice_card_strings(dice
);
907 err
= dice_create_pcm(dice
);
911 err
= dice_create_hwdep(dice
);
915 err
= snd_card_register(card
);
919 dev_set_drvdata(&unit
->device
, dice
);
924 amdtp_out_stream_destroy(&dice
->stream
);
926 fw_iso_resources_destroy(&dice
->resources
);
927 err_notification_handler
:
928 fw_core_remove_address_handler(&dice
->notification_handler
);
930 mutex_destroy(&dice
->mutex
);
936 static void dice_remove(struct fw_unit
*unit
)
938 struct dice
*dice
= dev_get_drvdata(&unit
->device
);
940 snd_card_disconnect(dice
->card
);
942 mutex_lock(&dice
->mutex
);
943 amdtp_out_stream_pcm_abort(&dice
->stream
);
944 dice_stop_stream(dice
);
945 dice_owner_clear(dice
);
946 mutex_unlock(&dice
->mutex
);
948 snd_card_free_when_closed(dice
->card
);
951 static void dice_bus_reset(struct fw_unit
*unit
)
953 struct dice
*dice
= dev_get_drvdata(&unit
->device
);
955 mutex_lock(&dice
->mutex
);
957 * XXX is the following true?
958 * On a bus reset, the DICE firmware disables streaming and then goes
959 * off contemplating its own navel for hundreds of milliseconds before
960 * it can react to any of our attempts to reenable streaming. This
961 * means that we lose synchronization anyway, so we force our streams
962 * to stop so that the application can restart them in an orderly
965 dice_owner_update(dice
);
966 amdtp_out_stream_pcm_abort(&dice
->stream
);
967 dice_stop_stream(dice
);
968 mutex_unlock(&dice
->mutex
);
971 #define TC_OUI 0x000166
972 #define DICE_INTERFACE 0x000001
974 static const struct ieee1394_device_id dice_id_table
[] = {
976 .match_flags
= IEEE1394_MATCH_SPECIFIER_ID
|
977 IEEE1394_MATCH_VERSION
,
978 .specifier_id
= TC_OUI
,
979 .version
= DICE_INTERFACE
,
983 MODULE_DEVICE_TABLE(ieee1394
, dice_id_table
);
985 static struct fw_driver dice_driver
= {
987 .owner
= THIS_MODULE
,
988 .name
= KBUILD_MODNAME
,
992 .update
= dice_bus_reset
,
993 .remove
= dice_remove
,
994 .id_table
= dice_id_table
,
997 static int __init
alsa_dice_init(void)
999 return driver_register(&dice_driver
.driver
);
1002 static void __exit
alsa_dice_exit(void)
1004 driver_unregister(&dice_driver
.driver
);
1007 module_init(alsa_dice_init
);
1008 module_exit(alsa_dice_exit
);