xref: /openbmc/linux/sound/firewire/motu/motu.c (revision 6c3cef4890d072afa2d77371f358abaea54ec134)
1*6c3cef48STakashi Sakamoto /*
2*6c3cef48STakashi Sakamoto  * motu.c - a part of driver for MOTU FireWire series
3*6c3cef48STakashi Sakamoto  *
4*6c3cef48STakashi Sakamoto  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
5*6c3cef48STakashi Sakamoto  *
6*6c3cef48STakashi Sakamoto  * Licensed under the terms of the GNU General Public License, version 2.
7*6c3cef48STakashi Sakamoto  */
8*6c3cef48STakashi Sakamoto 
9*6c3cef48STakashi Sakamoto #include "motu.h"
10*6c3cef48STakashi Sakamoto 
11*6c3cef48STakashi Sakamoto #define OUI_MOTU	0x0001f2
12*6c3cef48STakashi Sakamoto 
13*6c3cef48STakashi Sakamoto MODULE_DESCRIPTION("MOTU FireWire driver");
14*6c3cef48STakashi Sakamoto MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>");
15*6c3cef48STakashi Sakamoto MODULE_LICENSE("GPL v2");
16*6c3cef48STakashi Sakamoto 
17*6c3cef48STakashi Sakamoto static void name_card(struct snd_motu *motu)
18*6c3cef48STakashi Sakamoto {
19*6c3cef48STakashi Sakamoto 	struct fw_device *fw_dev = fw_parent_device(motu->unit);
20*6c3cef48STakashi Sakamoto 	struct fw_csr_iterator it;
21*6c3cef48STakashi Sakamoto 	int key, val;
22*6c3cef48STakashi Sakamoto 	u32 version = 0;
23*6c3cef48STakashi Sakamoto 
24*6c3cef48STakashi Sakamoto 	fw_csr_iterator_init(&it, motu->unit->directory);
25*6c3cef48STakashi Sakamoto 	while (fw_csr_iterator_next(&it, &key, &val)) {
26*6c3cef48STakashi Sakamoto 		switch (key) {
27*6c3cef48STakashi Sakamoto 		case CSR_VERSION:
28*6c3cef48STakashi Sakamoto 			version = val;
29*6c3cef48STakashi Sakamoto 			break;
30*6c3cef48STakashi Sakamoto 		}
31*6c3cef48STakashi Sakamoto 	}
32*6c3cef48STakashi Sakamoto 
33*6c3cef48STakashi Sakamoto 	strcpy(motu->card->driver, "FW-MOTU");
34*6c3cef48STakashi Sakamoto 	snprintf(motu->card->longname, sizeof(motu->card->longname),
35*6c3cef48STakashi Sakamoto 		 "MOTU (version:%d), GUID %08x%08x at %s, S%d",
36*6c3cef48STakashi Sakamoto 		 version,
37*6c3cef48STakashi Sakamoto 		 fw_dev->config_rom[3], fw_dev->config_rom[4],
38*6c3cef48STakashi Sakamoto 		 dev_name(&motu->unit->device), 100 << fw_dev->max_speed);
39*6c3cef48STakashi Sakamoto }
40*6c3cef48STakashi Sakamoto 
41*6c3cef48STakashi Sakamoto static void motu_card_free(struct snd_card *card)
42*6c3cef48STakashi Sakamoto {
43*6c3cef48STakashi Sakamoto 	struct snd_motu *motu = card->private_data;
44*6c3cef48STakashi Sakamoto 
45*6c3cef48STakashi Sakamoto 	fw_unit_put(motu->unit);
46*6c3cef48STakashi Sakamoto 
47*6c3cef48STakashi Sakamoto 	mutex_destroy(&motu->mutex);
48*6c3cef48STakashi Sakamoto }
49*6c3cef48STakashi Sakamoto 
50*6c3cef48STakashi Sakamoto static int motu_probe(struct fw_unit *unit,
51*6c3cef48STakashi Sakamoto 		      const struct ieee1394_device_id *entry)
52*6c3cef48STakashi Sakamoto {
53*6c3cef48STakashi Sakamoto 	struct snd_card *card;
54*6c3cef48STakashi Sakamoto 	struct snd_motu *motu;
55*6c3cef48STakashi Sakamoto 	int err;
56*6c3cef48STakashi Sakamoto 
57*6c3cef48STakashi Sakamoto 	err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE,
58*6c3cef48STakashi Sakamoto 			   sizeof(*motu), &card);
59*6c3cef48STakashi Sakamoto 	if (err < 0)
60*6c3cef48STakashi Sakamoto 		return err;
61*6c3cef48STakashi Sakamoto 
62*6c3cef48STakashi Sakamoto 	motu = card->private_data;
63*6c3cef48STakashi Sakamoto 	motu->card = card;
64*6c3cef48STakashi Sakamoto 	motu->unit = fw_unit_get(unit);
65*6c3cef48STakashi Sakamoto 	card->private_free = motu_card_free;
66*6c3cef48STakashi Sakamoto 
67*6c3cef48STakashi Sakamoto 	mutex_init(&motu->mutex);
68*6c3cef48STakashi Sakamoto 
69*6c3cef48STakashi Sakamoto 	name_card(motu);
70*6c3cef48STakashi Sakamoto 
71*6c3cef48STakashi Sakamoto 	err = snd_card_register(card);
72*6c3cef48STakashi Sakamoto 	if (err < 0)
73*6c3cef48STakashi Sakamoto 		goto error;
74*6c3cef48STakashi Sakamoto 
75*6c3cef48STakashi Sakamoto 	dev_set_drvdata(&unit->device, motu);
76*6c3cef48STakashi Sakamoto 
77*6c3cef48STakashi Sakamoto 	return 0;
78*6c3cef48STakashi Sakamoto error:
79*6c3cef48STakashi Sakamoto 	snd_card_free(card);
80*6c3cef48STakashi Sakamoto 	return err;
81*6c3cef48STakashi Sakamoto }
82*6c3cef48STakashi Sakamoto 
83*6c3cef48STakashi Sakamoto static void motu_remove(struct fw_unit *unit)
84*6c3cef48STakashi Sakamoto {
85*6c3cef48STakashi Sakamoto 	struct snd_motu *motu = dev_get_drvdata(&unit->device);
86*6c3cef48STakashi Sakamoto 
87*6c3cef48STakashi Sakamoto 	/* No need to wait for releasing card object in this context. */
88*6c3cef48STakashi Sakamoto 	snd_card_free_when_closed(motu->card);
89*6c3cef48STakashi Sakamoto }
90*6c3cef48STakashi Sakamoto 
91*6c3cef48STakashi Sakamoto static void motu_bus_update(struct fw_unit *unit)
92*6c3cef48STakashi Sakamoto {
93*6c3cef48STakashi Sakamoto 	return;
94*6c3cef48STakashi Sakamoto }
95*6c3cef48STakashi Sakamoto 
96*6c3cef48STakashi Sakamoto #define SND_MOTU_DEV_ENTRY(model)			\
97*6c3cef48STakashi Sakamoto {							\
98*6c3cef48STakashi Sakamoto 	.match_flags	= IEEE1394_MATCH_VENDOR_ID |	\
99*6c3cef48STakashi Sakamoto 			  IEEE1394_MATCH_MODEL_ID |	\
100*6c3cef48STakashi Sakamoto 			  IEEE1394_MATCH_SPECIFIER_ID,	\
101*6c3cef48STakashi Sakamoto 	.vendor_id	= OUI_MOTU,			\
102*6c3cef48STakashi Sakamoto 	.model_id	= model,			\
103*6c3cef48STakashi Sakamoto 	.specifier_id	= OUI_MOTU,			\
104*6c3cef48STakashi Sakamoto }
105*6c3cef48STakashi Sakamoto 
106*6c3cef48STakashi Sakamoto static const struct ieee1394_device_id motu_id_table[] = {
107*6c3cef48STakashi Sakamoto 	{ }
108*6c3cef48STakashi Sakamoto };
109*6c3cef48STakashi Sakamoto MODULE_DEVICE_TABLE(ieee1394, motu_id_table);
110*6c3cef48STakashi Sakamoto 
111*6c3cef48STakashi Sakamoto static struct fw_driver motu_driver = {
112*6c3cef48STakashi Sakamoto 	.driver   = {
113*6c3cef48STakashi Sakamoto 		.owner	= THIS_MODULE,
114*6c3cef48STakashi Sakamoto 		.name	= KBUILD_MODNAME,
115*6c3cef48STakashi Sakamoto 		.bus	= &fw_bus_type,
116*6c3cef48STakashi Sakamoto 	},
117*6c3cef48STakashi Sakamoto 	.probe    = motu_probe,
118*6c3cef48STakashi Sakamoto 	.update   = motu_bus_update,
119*6c3cef48STakashi Sakamoto 	.remove   = motu_remove,
120*6c3cef48STakashi Sakamoto 	.id_table = motu_id_table,
121*6c3cef48STakashi Sakamoto };
122*6c3cef48STakashi Sakamoto 
123*6c3cef48STakashi Sakamoto static int __init alsa_motu_init(void)
124*6c3cef48STakashi Sakamoto {
125*6c3cef48STakashi Sakamoto 	return driver_register(&motu_driver.driver);
126*6c3cef48STakashi Sakamoto }
127*6c3cef48STakashi Sakamoto 
128*6c3cef48STakashi Sakamoto static void __exit alsa_motu_exit(void)
129*6c3cef48STakashi Sakamoto {
130*6c3cef48STakashi Sakamoto 	driver_unregister(&motu_driver.driver);
131*6c3cef48STakashi Sakamoto }
132*6c3cef48STakashi Sakamoto 
133*6c3cef48STakashi Sakamoto module_init(alsa_motu_init);
134*6c3cef48STakashi Sakamoto module_exit(alsa_motu_exit);
135