1 // SPDX-License-Identifier: GPL-2.0-only
3 * ff.c - a part of driver for RME Fireface series
5 * Copyright (c) 2015-2017 Takashi Sakamoto
10 #define OUI_RME 0x000a35
12 MODULE_DESCRIPTION("RME Fireface series Driver");
13 MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>");
14 MODULE_LICENSE("GPL v2");
16 static void name_card(struct snd_ff
*ff
)
18 struct fw_device
*fw_dev
= fw_parent_device(ff
->unit
);
20 strcpy(ff
->card
->driver
, "Fireface");
21 strcpy(ff
->card
->shortname
, ff
->spec
->name
);
22 strcpy(ff
->card
->mixername
, ff
->spec
->name
);
23 snprintf(ff
->card
->longname
, sizeof(ff
->card
->longname
),
24 "RME %s, GUID %08x%08x at %s, S%d", ff
->spec
->name
,
25 fw_dev
->config_rom
[3], fw_dev
->config_rom
[4],
26 dev_name(&ff
->unit
->device
), 100 << fw_dev
->max_speed
);
29 static void ff_card_free(struct snd_card
*card
)
31 struct snd_ff
*ff
= card
->private_data
;
33 snd_ff_stream_destroy_duplex(ff
);
34 snd_ff_transaction_unregister(ff
);
37 static void do_registration(struct work_struct
*work
)
39 struct snd_ff
*ff
= container_of(work
, struct snd_ff
, dwork
.work
);
45 err
= snd_card_new(&ff
->unit
->device
, -1, NULL
, THIS_MODULE
, 0,
49 ff
->card
->private_free
= ff_card_free
;
50 ff
->card
->private_data
= ff
;
52 err
= snd_ff_transaction_register(ff
);
58 err
= snd_ff_stream_init_duplex(ff
);
64 err
= snd_ff_create_midi_devices(ff
);
68 err
= snd_ff_create_pcm_devices(ff
);
72 err
= snd_ff_create_hwdep_devices(ff
);
76 err
= snd_card_register(ff
->card
);
80 ff
->registered
= true;
84 snd_card_free(ff
->card
);
85 dev_info(&ff
->unit
->device
,
86 "Sound card registration failed: %d\n", err
);
89 static int snd_ff_probe(struct fw_unit
*unit
,
90 const struct ieee1394_device_id
*entry
)
94 ff
= devm_kzalloc(&unit
->device
, sizeof(struct snd_ff
), GFP_KERNEL
);
97 ff
->unit
= fw_unit_get(unit
);
98 dev_set_drvdata(&unit
->device
, ff
);
100 mutex_init(&ff
->mutex
);
101 spin_lock_init(&ff
->lock
);
102 init_waitqueue_head(&ff
->hwdep_wait
);
104 ff
->spec
= (const struct snd_ff_spec
*)entry
->driver_data
;
106 /* Register this sound card later. */
107 INIT_DEFERRABLE_WORK(&ff
->dwork
, do_registration
);
108 snd_fw_schedule_registration(unit
, &ff
->dwork
);
113 static void snd_ff_update(struct fw_unit
*unit
)
115 struct snd_ff
*ff
= dev_get_drvdata(&unit
->device
);
117 /* Postpone a workqueue for deferred registration. */
119 snd_fw_schedule_registration(unit
, &ff
->dwork
);
121 snd_ff_transaction_reregister(ff
);
124 snd_ff_stream_update_duplex(ff
);
127 static void snd_ff_remove(struct fw_unit
*unit
)
129 struct snd_ff
*ff
= dev_get_drvdata(&unit
->device
);
132 * Confirm to stop the work for registration before the sound card is
133 * going to be released. The work is not scheduled again because bus
134 * reset handler is not called anymore.
136 cancel_work_sync(&ff
->dwork
.work
);
138 if (ff
->registered
) {
139 // Block till all of ALSA character devices are released.
140 snd_card_free(ff
->card
);
143 mutex_destroy(&ff
->mutex
);
144 fw_unit_put(ff
->unit
);
147 static const struct snd_ff_spec spec_ff800
= {
148 .name
= "Fireface800",
149 .pcm_capture_channels
= {28, 20, 12},
150 .pcm_playback_channels
= {28, 20, 12},
153 .protocol
= &snd_ff_protocol_ff800
,
154 .midi_high_addr
= 0x000200000320ull
,
155 .midi_addr_range
= 12,
156 .midi_rx_addrs
= {0x000080180000ull
, 0},
159 static const struct snd_ff_spec spec_ff400
= {
160 .name
= "Fireface400",
161 .pcm_capture_channels
= {18, 14, 10},
162 .pcm_playback_channels
= {18, 14, 10},
165 .protocol
= &snd_ff_protocol_ff400
,
166 .midi_high_addr
= 0x0000801003f4ull
,
167 .midi_addr_range
= SND_FF_MAXIMIM_MIDI_QUADS
* 4,
168 .midi_rx_addrs
= {0x000080180000ull
, 0x000080190000ull
},
171 static const struct snd_ff_spec spec_ucx
= {
172 .name
= "FirefaceUCX",
173 .pcm_capture_channels
= {18, 14, 12},
174 .pcm_playback_channels
= {18, 14, 12},
177 .protocol
= &snd_ff_protocol_latter
,
178 .midi_high_addr
= 0xffff00000034ull
,
179 .midi_addr_range
= 0x80,
180 .midi_rx_addrs
= {0xffff00000030ull
, 0xffff00000030ull
},
183 static const struct ieee1394_device_id snd_ff_id_table
[] = {
186 .match_flags
= IEEE1394_MATCH_VENDOR_ID
|
187 IEEE1394_MATCH_SPECIFIER_ID
|
188 IEEE1394_MATCH_VERSION
|
189 IEEE1394_MATCH_MODEL_ID
,
190 .vendor_id
= OUI_RME
,
191 .specifier_id
= OUI_RME
,
193 .model_id
= 0x101800,
194 .driver_data
= (kernel_ulong_t
)&spec_ff800
,
198 .match_flags
= IEEE1394_MATCH_VENDOR_ID
|
199 IEEE1394_MATCH_SPECIFIER_ID
|
200 IEEE1394_MATCH_VERSION
|
201 IEEE1394_MATCH_MODEL_ID
,
202 .vendor_id
= OUI_RME
,
203 .specifier_id
= OUI_RME
,
205 .model_id
= 0x101800,
206 .driver_data
= (kernel_ulong_t
)&spec_ff400
,
210 .match_flags
= IEEE1394_MATCH_VENDOR_ID
|
211 IEEE1394_MATCH_SPECIFIER_ID
|
212 IEEE1394_MATCH_VERSION
|
213 IEEE1394_MATCH_MODEL_ID
,
214 .vendor_id
= OUI_RME
,
215 .specifier_id
= OUI_RME
,
217 .model_id
= 0x101800,
218 .driver_data
= (kernel_ulong_t
)&spec_ucx
,
222 MODULE_DEVICE_TABLE(ieee1394
, snd_ff_id_table
);
224 static struct fw_driver ff_driver
= {
226 .owner
= THIS_MODULE
,
227 .name
= "snd-fireface",
230 .probe
= snd_ff_probe
,
231 .update
= snd_ff_update
,
232 .remove
= snd_ff_remove
,
233 .id_table
= snd_ff_id_table
,
236 static int __init
snd_ff_init(void)
238 return driver_register(&ff_driver
.driver
);
241 static void __exit
snd_ff_exit(void)
243 driver_unregister(&ff_driver
.driver
);
246 module_init(snd_ff_init
);
247 module_exit(snd_ff_exit
);