xref: /OK3568_Linux_fs/kernel/sound/firewire/motu/motu.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * motu.c - a part of driver for MOTU FireWire series
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include "motu.h"
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #define OUI_MOTU	0x0001f2
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun MODULE_DESCRIPTION("MOTU FireWire driver");
13*4882a593Smuzhiyun MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>");
14*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun const unsigned int snd_motu_clock_rates[SND_MOTU_CLOCK_RATE_COUNT] = {
17*4882a593Smuzhiyun 	/* mode 0 */
18*4882a593Smuzhiyun 	[0] =  44100,
19*4882a593Smuzhiyun 	[1] =  48000,
20*4882a593Smuzhiyun 	/* mode 1 */
21*4882a593Smuzhiyun 	[2] =  88200,
22*4882a593Smuzhiyun 	[3] =  96000,
23*4882a593Smuzhiyun 	/* mode 2 */
24*4882a593Smuzhiyun 	[4] = 176400,
25*4882a593Smuzhiyun 	[5] = 192000,
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun 
name_card(struct snd_motu * motu)28*4882a593Smuzhiyun static void name_card(struct snd_motu *motu)
29*4882a593Smuzhiyun {
30*4882a593Smuzhiyun 	struct fw_device *fw_dev = fw_parent_device(motu->unit);
31*4882a593Smuzhiyun 	struct fw_csr_iterator it;
32*4882a593Smuzhiyun 	int key, val;
33*4882a593Smuzhiyun 	u32 version = 0;
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	fw_csr_iterator_init(&it, motu->unit->directory);
36*4882a593Smuzhiyun 	while (fw_csr_iterator_next(&it, &key, &val)) {
37*4882a593Smuzhiyun 		switch (key) {
38*4882a593Smuzhiyun 		case CSR_MODEL:
39*4882a593Smuzhiyun 			version = val;
40*4882a593Smuzhiyun 			break;
41*4882a593Smuzhiyun 		}
42*4882a593Smuzhiyun 	}
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	strcpy(motu->card->driver, "FW-MOTU");
45*4882a593Smuzhiyun 	strcpy(motu->card->shortname, motu->spec->name);
46*4882a593Smuzhiyun 	strcpy(motu->card->mixername, motu->spec->name);
47*4882a593Smuzhiyun 	snprintf(motu->card->longname, sizeof(motu->card->longname),
48*4882a593Smuzhiyun 		 "MOTU %s (version:%06x), GUID %08x%08x at %s, S%d",
49*4882a593Smuzhiyun 		 motu->spec->name, version,
50*4882a593Smuzhiyun 		 fw_dev->config_rom[3], fw_dev->config_rom[4],
51*4882a593Smuzhiyun 		 dev_name(&motu->unit->device), 100 << fw_dev->max_speed);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
motu_card_free(struct snd_card * card)54*4882a593Smuzhiyun static void motu_card_free(struct snd_card *card)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	struct snd_motu *motu = card->private_data;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	snd_motu_transaction_unregister(motu);
59*4882a593Smuzhiyun 	snd_motu_stream_destroy_duplex(motu);
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun 
do_registration(struct work_struct * work)62*4882a593Smuzhiyun static void do_registration(struct work_struct *work)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun 	struct snd_motu *motu = container_of(work, struct snd_motu, dwork.work);
65*4882a593Smuzhiyun 	int err;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	if (motu->registered)
68*4882a593Smuzhiyun 		return;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	err = snd_card_new(&motu->unit->device, -1, NULL, THIS_MODULE, 0,
71*4882a593Smuzhiyun 			   &motu->card);
72*4882a593Smuzhiyun 	if (err < 0)
73*4882a593Smuzhiyun 		return;
74*4882a593Smuzhiyun 	motu->card->private_free = motu_card_free;
75*4882a593Smuzhiyun 	motu->card->private_data = motu;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	name_card(motu);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	err = snd_motu_transaction_register(motu);
80*4882a593Smuzhiyun 	if (err < 0)
81*4882a593Smuzhiyun 		goto error;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	err = snd_motu_stream_init_duplex(motu);
84*4882a593Smuzhiyun 	if (err < 0)
85*4882a593Smuzhiyun 		goto error;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	snd_motu_proc_init(motu);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	err = snd_motu_create_pcm_devices(motu);
90*4882a593Smuzhiyun 	if (err < 0)
91*4882a593Smuzhiyun 		goto error;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) ||
94*4882a593Smuzhiyun 	    (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q) ||
95*4882a593Smuzhiyun 	    (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) ||
96*4882a593Smuzhiyun 	    (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q)) {
97*4882a593Smuzhiyun 		err = snd_motu_create_midi_devices(motu);
98*4882a593Smuzhiyun 		if (err < 0)
99*4882a593Smuzhiyun 			goto error;
100*4882a593Smuzhiyun 	}
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	err = snd_motu_create_hwdep_device(motu);
103*4882a593Smuzhiyun 	if (err < 0)
104*4882a593Smuzhiyun 		goto error;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	err = snd_card_register(motu->card);
107*4882a593Smuzhiyun 	if (err < 0)
108*4882a593Smuzhiyun 		goto error;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	motu->registered = true;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	return;
113*4882a593Smuzhiyun error:
114*4882a593Smuzhiyun 	snd_card_free(motu->card);
115*4882a593Smuzhiyun 	dev_info(&motu->unit->device,
116*4882a593Smuzhiyun 		 "Sound card registration failed: %d\n", err);
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
motu_probe(struct fw_unit * unit,const struct ieee1394_device_id * entry)119*4882a593Smuzhiyun static int motu_probe(struct fw_unit *unit,
120*4882a593Smuzhiyun 		      const struct ieee1394_device_id *entry)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun 	struct snd_motu *motu;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	/* Allocate this independently of sound card instance. */
125*4882a593Smuzhiyun 	motu = devm_kzalloc(&unit->device, sizeof(struct snd_motu), GFP_KERNEL);
126*4882a593Smuzhiyun 	if (!motu)
127*4882a593Smuzhiyun 		return -ENOMEM;
128*4882a593Smuzhiyun 	motu->unit = fw_unit_get(unit);
129*4882a593Smuzhiyun 	dev_set_drvdata(&unit->device, motu);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	motu->spec = (const struct snd_motu_spec *)entry->driver_data;
132*4882a593Smuzhiyun 	mutex_init(&motu->mutex);
133*4882a593Smuzhiyun 	spin_lock_init(&motu->lock);
134*4882a593Smuzhiyun 	init_waitqueue_head(&motu->hwdep_wait);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	/* Allocate and register this sound card later. */
137*4882a593Smuzhiyun 	INIT_DEFERRABLE_WORK(&motu->dwork, do_registration);
138*4882a593Smuzhiyun 	snd_fw_schedule_registration(unit, &motu->dwork);
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	return 0;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
motu_remove(struct fw_unit * unit)143*4882a593Smuzhiyun static void motu_remove(struct fw_unit *unit)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	struct snd_motu *motu = dev_get_drvdata(&unit->device);
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	/*
148*4882a593Smuzhiyun 	 * Confirm to stop the work for registration before the sound card is
149*4882a593Smuzhiyun 	 * going to be released. The work is not scheduled again because bus
150*4882a593Smuzhiyun 	 * reset handler is not called anymore.
151*4882a593Smuzhiyun 	 */
152*4882a593Smuzhiyun 	cancel_delayed_work_sync(&motu->dwork);
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	if (motu->registered) {
155*4882a593Smuzhiyun 		// Block till all of ALSA character devices are released.
156*4882a593Smuzhiyun 		snd_card_free(motu->card);
157*4882a593Smuzhiyun 	}
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	mutex_destroy(&motu->mutex);
160*4882a593Smuzhiyun 	fw_unit_put(motu->unit);
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
motu_bus_update(struct fw_unit * unit)163*4882a593Smuzhiyun static void motu_bus_update(struct fw_unit *unit)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun 	struct snd_motu *motu = dev_get_drvdata(&unit->device);
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	/* Postpone a workqueue for deferred registration. */
168*4882a593Smuzhiyun 	if (!motu->registered)
169*4882a593Smuzhiyun 		snd_fw_schedule_registration(unit, &motu->dwork);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	/* The handler address register becomes initialized. */
172*4882a593Smuzhiyun 	snd_motu_transaction_reregister(motu);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun #define SND_MOTU_DEV_ENTRY(model, data)			\
176*4882a593Smuzhiyun {							\
177*4882a593Smuzhiyun 	.match_flags	= IEEE1394_MATCH_VENDOR_ID |	\
178*4882a593Smuzhiyun 			  IEEE1394_MATCH_SPECIFIER_ID |	\
179*4882a593Smuzhiyun 			  IEEE1394_MATCH_VERSION,	\
180*4882a593Smuzhiyun 	.vendor_id	= OUI_MOTU,			\
181*4882a593Smuzhiyun 	.specifier_id	= OUI_MOTU,			\
182*4882a593Smuzhiyun 	.version	= model,			\
183*4882a593Smuzhiyun 	.driver_data	= (kernel_ulong_t)data,		\
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun static const struct ieee1394_device_id motu_id_table[] = {
187*4882a593Smuzhiyun 	SND_MOTU_DEV_ENTRY(0x000003, &snd_motu_spec_828mk2),
188*4882a593Smuzhiyun 	SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler),
189*4882a593Smuzhiyun 	SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite),
190*4882a593Smuzhiyun 	SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre),
191*4882a593Smuzhiyun 	SND_MOTU_DEV_ENTRY(0x000015, &snd_motu_spec_828mk3), // FireWire only.
192*4882a593Smuzhiyun 	SND_MOTU_DEV_ENTRY(0x000019, &snd_motu_spec_ultralite_mk3), // FireWire only.
193*4882a593Smuzhiyun 	SND_MOTU_DEV_ENTRY(0x000035, &snd_motu_spec_828mk3), // Hybrid.
194*4882a593Smuzhiyun 	SND_MOTU_DEV_ENTRY(0x000033, &snd_motu_spec_audio_express),
195*4882a593Smuzhiyun 	SND_MOTU_DEV_ENTRY(0x000045, &snd_motu_spec_4pre),
196*4882a593Smuzhiyun 	{ }
197*4882a593Smuzhiyun };
198*4882a593Smuzhiyun MODULE_DEVICE_TABLE(ieee1394, motu_id_table);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun static struct fw_driver motu_driver = {
201*4882a593Smuzhiyun 	.driver   = {
202*4882a593Smuzhiyun 		.owner	= THIS_MODULE,
203*4882a593Smuzhiyun 		.name	= KBUILD_MODNAME,
204*4882a593Smuzhiyun 		.bus	= &fw_bus_type,
205*4882a593Smuzhiyun 	},
206*4882a593Smuzhiyun 	.probe    = motu_probe,
207*4882a593Smuzhiyun 	.update   = motu_bus_update,
208*4882a593Smuzhiyun 	.remove   = motu_remove,
209*4882a593Smuzhiyun 	.id_table = motu_id_table,
210*4882a593Smuzhiyun };
211*4882a593Smuzhiyun 
alsa_motu_init(void)212*4882a593Smuzhiyun static int __init alsa_motu_init(void)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	return driver_register(&motu_driver.driver);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun 
alsa_motu_exit(void)217*4882a593Smuzhiyun static void __exit alsa_motu_exit(void)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	driver_unregister(&motu_driver.driver);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun module_init(alsa_motu_init);
223*4882a593Smuzhiyun module_exit(alsa_motu_exit);
224