~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/firewire/fireface/ff.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * ff.c - a part of driver for RME Fireface series
  4  *
  5  * Copyright (c) 2015-2017 Takashi Sakamoto
  6  */
  7 
  8 #include "ff.h"
  9 
 10 #define OUI_RME 0x000a35
 11 
 12 MODULE_DESCRIPTION("RME Fireface series Driver");
 13 MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>");
 14 MODULE_LICENSE("GPL");
 15 
 16 static void name_card(struct snd_ff *ff)
 17 {
 18         struct fw_device *fw_dev = fw_parent_device(ff->unit);
 19         static const char *const names[] = {
 20                 [SND_FF_UNIT_VERSION_FF800]     = "Fireface800",
 21                 [SND_FF_UNIT_VERSION_FF400]     = "Fireface400",
 22                 [SND_FF_UNIT_VERSION_UFX]       = "FirefaceUFX",
 23                 [SND_FF_UNIT_VERSION_UCX]       = "FirefaceUCX",
 24                 [SND_FF_UNIT_VERSION_802]       = "Fireface802",
 25         };
 26         const char *name;
 27 
 28         name = names[ff->unit_version];
 29 
 30         strcpy(ff->card->driver, "Fireface");
 31         strcpy(ff->card->shortname, name);
 32         strcpy(ff->card->mixername, name);
 33         snprintf(ff->card->longname, sizeof(ff->card->longname),
 34                  "RME %s, GUID %08x%08x at %s, S%d", name,
 35                  fw_dev->config_rom[3], fw_dev->config_rom[4],
 36                  dev_name(&ff->unit->device), 100 << fw_dev->max_speed);
 37 }
 38 
 39 static void ff_card_free(struct snd_card *card)
 40 {
 41         struct snd_ff *ff = card->private_data;
 42 
 43         snd_ff_stream_destroy_duplex(ff);
 44         snd_ff_transaction_unregister(ff);
 45 
 46         kfree(ff->msg_parser);
 47 
 48         mutex_destroy(&ff->mutex);
 49         fw_unit_put(ff->unit);
 50 }
 51 
 52 static int snd_ff_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry)
 53 {
 54         struct snd_card *card;
 55         struct snd_ff *ff;
 56         int err;
 57 
 58         err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*ff), &card);
 59         if (err < 0)
 60                 return err;
 61         card->private_free = ff_card_free;
 62 
 63         ff = card->private_data;
 64         ff->unit = fw_unit_get(unit);
 65         dev_set_drvdata(&unit->device, ff);
 66         ff->card = card;
 67 
 68         mutex_init(&ff->mutex);
 69         spin_lock_init(&ff->lock);
 70         init_waitqueue_head(&ff->hwdep_wait);
 71 
 72         ff->unit_version = entry->version;
 73         ff->spec = (const struct snd_ff_spec *)entry->driver_data;
 74 
 75         err = snd_ff_transaction_register(ff);
 76         if (err < 0)
 77                 goto error;
 78 
 79         name_card(ff);
 80 
 81         err = snd_ff_stream_init_duplex(ff);
 82         if (err < 0)
 83                 goto error;
 84 
 85         snd_ff_proc_init(ff);
 86 
 87         err = snd_ff_create_midi_devices(ff);
 88         if (err < 0)
 89                 goto error;
 90 
 91         err = snd_ff_create_pcm_devices(ff);
 92         if (err < 0)
 93                 goto error;
 94 
 95         err = snd_ff_create_hwdep_devices(ff);
 96         if (err < 0)
 97                 goto error;
 98 
 99         if (ff->spec->protocol->msg_parser_size > 0) {
100                 ff->msg_parser = kzalloc(ff->spec->protocol->msg_parser_size, GFP_KERNEL);
101                 if (!ff->msg_parser) {
102                         err = -ENOMEM;
103                         goto error;
104                 }
105         }
106 
107         err = snd_card_register(card);
108         if (err < 0)
109                 goto error;
110 
111         return 0;
112 error:
113         snd_card_free(card);
114         return err;
115 }
116 
117 static void snd_ff_update(struct fw_unit *unit)
118 {
119         struct snd_ff *ff = dev_get_drvdata(&unit->device);
120 
121         snd_ff_transaction_reregister(ff);
122 
123         snd_ff_stream_update_duplex(ff);
124 }
125 
126 static void snd_ff_remove(struct fw_unit *unit)
127 {
128         struct snd_ff *ff = dev_get_drvdata(&unit->device);
129 
130         // Block till all of ALSA character devices are released.
131         snd_card_free(ff->card);
132 }
133 
134 static const struct snd_ff_spec spec_ff800 = {
135         .pcm_capture_channels = {28, 20, 12},
136         .pcm_playback_channels = {28, 20, 12},
137         .midi_in_ports = 1,
138         .midi_out_ports = 1,
139         .protocol = &snd_ff_protocol_ff800,
140         .midi_high_addr = 0x000200000320ull,
141         .midi_addr_range = 12,
142         .midi_rx_addrs = {0x000080180000ull, 0},
143 };
144 
145 static const struct snd_ff_spec spec_ff400 = {
146         .pcm_capture_channels = {18, 14, 10},
147         .pcm_playback_channels = {18, 14, 10},
148         .midi_in_ports = 2,
149         .midi_out_ports = 2,
150         .protocol = &snd_ff_protocol_ff400,
151         .midi_high_addr = 0x0000801003f4ull,
152         .midi_addr_range = SND_FF_MAXIMIM_MIDI_QUADS * 4,
153         .midi_rx_addrs = {0x000080180000ull, 0x000080190000ull},
154 };
155 
156 static const struct snd_ff_spec spec_ucx = {
157         .pcm_capture_channels = {18, 14, 12},
158         .pcm_playback_channels = {18, 14, 12},
159         .midi_in_ports = 2,
160         .midi_out_ports = 2,
161         .protocol = &snd_ff_protocol_latter,
162         .midi_high_addr = 0xffff00000034ull,
163         .midi_addr_range = 0x80,
164         .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull},
165 };
166 
167 static const struct snd_ff_spec spec_ufx_802 = {
168         .pcm_capture_channels = {30, 22, 14},
169         .pcm_playback_channels = {30, 22, 14},
170         .midi_in_ports = 1,
171         .midi_out_ports = 1,
172         .protocol = &snd_ff_protocol_latter,
173         .midi_high_addr = 0xffff00000034ull,
174         .midi_addr_range = 0x80,
175         .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull},
176 };
177 
178 static const struct ieee1394_device_id snd_ff_id_table[] = {
179         /* Fireface 800 */
180         {
181                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
182                                   IEEE1394_MATCH_SPECIFIER_ID |
183                                   IEEE1394_MATCH_VERSION |
184                                   IEEE1394_MATCH_MODEL_ID,
185                 .vendor_id      = OUI_RME,
186                 .specifier_id   = OUI_RME,
187                 .version        = SND_FF_UNIT_VERSION_FF800,
188                 .model_id       = 0x101800,
189                 .driver_data    = (kernel_ulong_t)&spec_ff800,
190         },
191         /* Fireface 400 */
192         {
193                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
194                                   IEEE1394_MATCH_SPECIFIER_ID |
195                                   IEEE1394_MATCH_VERSION |
196                                   IEEE1394_MATCH_MODEL_ID,
197                 .vendor_id      = OUI_RME,
198                 .specifier_id   = OUI_RME,
199                 .version        = SND_FF_UNIT_VERSION_FF400,
200                 .model_id       = 0x101800,
201                 .driver_data    = (kernel_ulong_t)&spec_ff400,
202         },
203         // Fireface UFX.
204         {
205                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
206                                   IEEE1394_MATCH_SPECIFIER_ID |
207                                   IEEE1394_MATCH_VERSION |
208                                   IEEE1394_MATCH_MODEL_ID,
209                 .vendor_id      = OUI_RME,
210                 .specifier_id   = OUI_RME,
211                 .version        = SND_FF_UNIT_VERSION_UFX,
212                 .model_id       = 0x101800,
213                 .driver_data    = (kernel_ulong_t)&spec_ufx_802,
214         },
215         // Fireface UCX.
216         {
217                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
218                                   IEEE1394_MATCH_SPECIFIER_ID |
219                                   IEEE1394_MATCH_VERSION |
220                                   IEEE1394_MATCH_MODEL_ID,
221                 .vendor_id      = OUI_RME,
222                 .specifier_id   = OUI_RME,
223                 .version        = SND_FF_UNIT_VERSION_UCX,
224                 .model_id       = 0x101800,
225                 .driver_data    = (kernel_ulong_t)&spec_ucx,
226         },
227         // Fireface 802.
228         {
229                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
230                                   IEEE1394_MATCH_SPECIFIER_ID |
231                                   IEEE1394_MATCH_VERSION |
232                                   IEEE1394_MATCH_MODEL_ID,
233                 .vendor_id      = OUI_RME,
234                 .specifier_id   = OUI_RME,
235                 .version        = SND_FF_UNIT_VERSION_802,
236                 .model_id       = 0x101800,
237                 .driver_data    = (kernel_ulong_t)&spec_ufx_802,
238         },
239         {}
240 };
241 MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table);
242 
243 static struct fw_driver ff_driver = {
244         .driver = {
245                 .owner  = THIS_MODULE,
246                 .name   = KBUILD_MODNAME,
247                 .bus    = &fw_bus_type,
248         },
249         .probe    = snd_ff_probe,
250         .update   = snd_ff_update,
251         .remove   = snd_ff_remove,
252         .id_table = snd_ff_id_table,
253 };
254 
255 static int __init snd_ff_init(void)
256 {
257         return driver_register(&ff_driver.driver);
258 }
259 
260 static void __exit snd_ff_exit(void)
261 {
262         driver_unregister(&ff_driver.driver);
263 }
264 
265 module_init(snd_ff_init);
266 module_exit(snd_ff_exit);
267 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php