brintos

brintos / linux-shallow public Read only

0
0
Text · 6.4 KiB · 6e84e47 Raw
267 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ff.c - a part of driver for RME Fireface series4 *5 * Copyright (c) 2015-2017 Takashi Sakamoto6 */7 8#include "ff.h"9 10#define OUI_RME	0x000a3511 12MODULE_DESCRIPTION("RME Fireface series Driver");13MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>");14MODULE_LICENSE("GPL");15 16static 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 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	kfree(ff->msg_parser);47 48	mutex_destroy(&ff->mutex);49	fw_unit_put(ff->unit);50}51 52static 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;112error:113	snd_card_free(card);114	return err;115}116 117static 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 126static 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 134static 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 145static 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 156static 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 167static 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 178static 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};241MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table);242 243static 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 255static int __init snd_ff_init(void)256{257	return driver_register(&ff_driver.driver);258}259 260static void __exit snd_ff_exit(void)261{262	driver_unregister(&ff_driver.driver);263}264 265module_init(snd_ff_init);266module_exit(snd_ff_exit);267