cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ff.c (6304B)


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