xref: /linux/sound/firewire/digi00x/digi00x.c (revision 13e005f9f933a35b5e55c9d36f151efe2a8383ec)
19edf723fSTakashi Sakamoto /*
29edf723fSTakashi Sakamoto  * digi00x.c - a part of driver for Digidesign Digi 002/003 family
39edf723fSTakashi Sakamoto  *
49edf723fSTakashi Sakamoto  * Copyright (c) 2014-2015 Takashi Sakamoto
59edf723fSTakashi Sakamoto  *
69edf723fSTakashi Sakamoto  * Licensed under the terms of the GNU General Public License, version 2.
79edf723fSTakashi Sakamoto  */
89edf723fSTakashi Sakamoto 
99edf723fSTakashi Sakamoto #include "digi00x.h"
109edf723fSTakashi Sakamoto 
119edf723fSTakashi Sakamoto MODULE_DESCRIPTION("Digidesign Digi 002/003 family Driver");
129edf723fSTakashi Sakamoto MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>");
139edf723fSTakashi Sakamoto MODULE_LICENSE("GPL v2");
149edf723fSTakashi Sakamoto 
159edf723fSTakashi Sakamoto #define VENDOR_DIGIDESIGN	0x00a07e
16*13e005f9STakashi Sakamoto #define MODEL_CONSOLE		0x000001
17*13e005f9STakashi Sakamoto #define MODEL_RACK		0x000002
189edf723fSTakashi Sakamoto 
199edf723fSTakashi Sakamoto static int name_card(struct snd_dg00x *dg00x)
209edf723fSTakashi Sakamoto {
219edf723fSTakashi Sakamoto 	struct fw_device *fw_dev = fw_parent_device(dg00x->unit);
229edf723fSTakashi Sakamoto 	char name[32] = {0};
239edf723fSTakashi Sakamoto 	char *model;
249edf723fSTakashi Sakamoto 	int err;
259edf723fSTakashi Sakamoto 
269edf723fSTakashi Sakamoto 	err = fw_csr_string(dg00x->unit->directory, CSR_MODEL, name,
279edf723fSTakashi Sakamoto 			    sizeof(name));
289edf723fSTakashi Sakamoto 	if (err < 0)
299edf723fSTakashi Sakamoto 		return err;
309edf723fSTakashi Sakamoto 
319edf723fSTakashi Sakamoto 	model = skip_spaces(name);
329edf723fSTakashi Sakamoto 
339edf723fSTakashi Sakamoto 	strcpy(dg00x->card->driver, "Digi00x");
349edf723fSTakashi Sakamoto 	strcpy(dg00x->card->shortname, model);
359edf723fSTakashi Sakamoto 	strcpy(dg00x->card->mixername, model);
369edf723fSTakashi Sakamoto 	snprintf(dg00x->card->longname, sizeof(dg00x->card->longname),
379edf723fSTakashi Sakamoto 		 "Digidesign %s, GUID %08x%08x at %s, S%d", model,
38bd04809bSTakashi Sakamoto 		 fw_dev->config_rom[3], fw_dev->config_rom[4],
399edf723fSTakashi Sakamoto 		 dev_name(&dg00x->unit->device), 100 << fw_dev->max_speed);
409edf723fSTakashi Sakamoto 
419edf723fSTakashi Sakamoto 	return 0;
429edf723fSTakashi Sakamoto }
439edf723fSTakashi Sakamoto 
4486c8dd7fSTakashi Sakamoto static void dg00x_free(struct snd_dg00x *dg00x)
459edf723fSTakashi Sakamoto {
463a2a1797STakashi Sakamoto 	snd_dg00x_stream_destroy_duplex(dg00x);
4744b73088STakashi Sakamoto 	snd_dg00x_transaction_unregister(dg00x);
483a2a1797STakashi Sakamoto 
499edf723fSTakashi Sakamoto 	fw_unit_put(dg00x->unit);
509edf723fSTakashi Sakamoto 
519edf723fSTakashi Sakamoto 	mutex_destroy(&dg00x->mutex);
529edf723fSTakashi Sakamoto }
539edf723fSTakashi Sakamoto 
5486c8dd7fSTakashi Sakamoto static void dg00x_card_free(struct snd_card *card)
559edf723fSTakashi Sakamoto {
5686c8dd7fSTakashi Sakamoto 	dg00x_free(card->private_data);
5786c8dd7fSTakashi Sakamoto }
5886c8dd7fSTakashi Sakamoto 
5986c8dd7fSTakashi Sakamoto static void do_registration(struct work_struct *work)
6086c8dd7fSTakashi Sakamoto {
6186c8dd7fSTakashi Sakamoto 	struct snd_dg00x *dg00x =
6286c8dd7fSTakashi Sakamoto 			container_of(work, struct snd_dg00x, dwork.work);
639edf723fSTakashi Sakamoto 	int err;
649edf723fSTakashi Sakamoto 
6586c8dd7fSTakashi Sakamoto 	if (dg00x->registered)
6686c8dd7fSTakashi Sakamoto 		return;
6786c8dd7fSTakashi Sakamoto 
6886c8dd7fSTakashi Sakamoto 	err = snd_card_new(&dg00x->unit->device, -1, NULL, THIS_MODULE, 0,
6986c8dd7fSTakashi Sakamoto 			   &dg00x->card);
709edf723fSTakashi Sakamoto 	if (err < 0)
7186c8dd7fSTakashi Sakamoto 		return;
729edf723fSTakashi Sakamoto 
739edf723fSTakashi Sakamoto 	err = name_card(dg00x);
749edf723fSTakashi Sakamoto 	if (err < 0)
759edf723fSTakashi Sakamoto 		goto error;
769edf723fSTakashi Sakamoto 
773a2a1797STakashi Sakamoto 	err = snd_dg00x_stream_init_duplex(dg00x);
783a2a1797STakashi Sakamoto 	if (err < 0)
793a2a1797STakashi Sakamoto 		goto error;
803a2a1797STakashi Sakamoto 
81927f17dcSTakashi Sakamoto 	snd_dg00x_proc_init(dg00x);
82927f17dcSTakashi Sakamoto 
830120d0f1STakashi Sakamoto 	err = snd_dg00x_create_pcm_devices(dg00x);
840120d0f1STakashi Sakamoto 	if (err < 0)
850120d0f1STakashi Sakamoto 		goto error;
860120d0f1STakashi Sakamoto 
879fbfd38bSTakashi Sakamoto 	err = snd_dg00x_create_midi_devices(dg00x);
889fbfd38bSTakashi Sakamoto 	if (err < 0)
899fbfd38bSTakashi Sakamoto 		goto error;
909fbfd38bSTakashi Sakamoto 
91660dd3d5STakashi Sakamoto 	err = snd_dg00x_create_hwdep_device(dg00x);
92660dd3d5STakashi Sakamoto 	if (err < 0)
93660dd3d5STakashi Sakamoto 		goto error;
94660dd3d5STakashi Sakamoto 
9544b73088STakashi Sakamoto 	err = snd_dg00x_transaction_register(dg00x);
9644b73088STakashi Sakamoto 	if (err < 0)
9744b73088STakashi Sakamoto 		goto error;
9844b73088STakashi Sakamoto 
9986c8dd7fSTakashi Sakamoto 	err = snd_card_register(dg00x->card);
1009edf723fSTakashi Sakamoto 	if (err < 0)
1019edf723fSTakashi Sakamoto 		goto error;
1029edf723fSTakashi Sakamoto 
10386c8dd7fSTakashi Sakamoto 	dg00x->card->private_free = dg00x_card_free;
10486c8dd7fSTakashi Sakamoto 	dg00x->card->private_data = dg00x;
10586c8dd7fSTakashi Sakamoto 	dg00x->registered = true;
10686c8dd7fSTakashi Sakamoto 
10786c8dd7fSTakashi Sakamoto 	return;
10886c8dd7fSTakashi Sakamoto error:
10986c8dd7fSTakashi Sakamoto 	snd_dg00x_transaction_unregister(dg00x);
11086c8dd7fSTakashi Sakamoto 	snd_dg00x_stream_destroy_duplex(dg00x);
11186c8dd7fSTakashi Sakamoto 	snd_card_free(dg00x->card);
11286c8dd7fSTakashi Sakamoto 	dev_info(&dg00x->unit->device,
11386c8dd7fSTakashi Sakamoto 		 "Sound card registration failed: %d\n", err);
11486c8dd7fSTakashi Sakamoto }
11586c8dd7fSTakashi Sakamoto 
11686c8dd7fSTakashi Sakamoto static int snd_dg00x_probe(struct fw_unit *unit,
11786c8dd7fSTakashi Sakamoto 			   const struct ieee1394_device_id *entry)
11886c8dd7fSTakashi Sakamoto {
11986c8dd7fSTakashi Sakamoto 	struct snd_dg00x *dg00x;
12086c8dd7fSTakashi Sakamoto 
12186c8dd7fSTakashi Sakamoto 	/* Allocate this independent of sound card instance. */
12286c8dd7fSTakashi Sakamoto 	dg00x = kzalloc(sizeof(struct snd_dg00x), GFP_KERNEL);
12386c8dd7fSTakashi Sakamoto 	if (dg00x == NULL)
12486c8dd7fSTakashi Sakamoto 		return -ENOMEM;
12586c8dd7fSTakashi Sakamoto 
12686c8dd7fSTakashi Sakamoto 	dg00x->unit = fw_unit_get(unit);
1279edf723fSTakashi Sakamoto 	dev_set_drvdata(&unit->device, dg00x);
1289edf723fSTakashi Sakamoto 
12986c8dd7fSTakashi Sakamoto 	mutex_init(&dg00x->mutex);
13086c8dd7fSTakashi Sakamoto 	spin_lock_init(&dg00x->lock);
13186c8dd7fSTakashi Sakamoto 	init_waitqueue_head(&dg00x->hwdep_wait);
13286c8dd7fSTakashi Sakamoto 
133*13e005f9STakashi Sakamoto 	dg00x->is_console = entry->model_id == MODEL_CONSOLE;
134*13e005f9STakashi Sakamoto 
13586c8dd7fSTakashi Sakamoto 	/* Allocate and register this sound card later. */
13686c8dd7fSTakashi Sakamoto 	INIT_DEFERRABLE_WORK(&dg00x->dwork, do_registration);
13786c8dd7fSTakashi Sakamoto 	snd_fw_schedule_registration(unit, &dg00x->dwork);
13886c8dd7fSTakashi Sakamoto 
13986c8dd7fSTakashi Sakamoto 	return 0;
1409edf723fSTakashi Sakamoto }
1419edf723fSTakashi Sakamoto 
1429edf723fSTakashi Sakamoto static void snd_dg00x_update(struct fw_unit *unit)
1439edf723fSTakashi Sakamoto {
1443a2a1797STakashi Sakamoto 	struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device);
1453a2a1797STakashi Sakamoto 
14686c8dd7fSTakashi Sakamoto 	/* Postpone a workqueue for deferred registration. */
14786c8dd7fSTakashi Sakamoto 	if (!dg00x->registered)
14886c8dd7fSTakashi Sakamoto 		snd_fw_schedule_registration(unit, &dg00x->dwork);
14986c8dd7fSTakashi Sakamoto 
15044b73088STakashi Sakamoto 	snd_dg00x_transaction_reregister(dg00x);
15144b73088STakashi Sakamoto 
15286c8dd7fSTakashi Sakamoto 	/*
15386c8dd7fSTakashi Sakamoto 	 * After registration, userspace can start packet streaming, then this
15486c8dd7fSTakashi Sakamoto 	 * code block works fine.
15586c8dd7fSTakashi Sakamoto 	 */
15686c8dd7fSTakashi Sakamoto 	if (dg00x->registered) {
1573a2a1797STakashi Sakamoto 		mutex_lock(&dg00x->mutex);
1583a2a1797STakashi Sakamoto 		snd_dg00x_stream_update_duplex(dg00x);
1593a2a1797STakashi Sakamoto 		mutex_unlock(&dg00x->mutex);
1609edf723fSTakashi Sakamoto 	}
16186c8dd7fSTakashi Sakamoto }
1629edf723fSTakashi Sakamoto 
1639edf723fSTakashi Sakamoto static void snd_dg00x_remove(struct fw_unit *unit)
1649edf723fSTakashi Sakamoto {
1659edf723fSTakashi Sakamoto 	struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device);
1669edf723fSTakashi Sakamoto 
16786c8dd7fSTakashi Sakamoto 	/*
16886c8dd7fSTakashi Sakamoto 	 * Confirm to stop the work for registration before the sound card is
16986c8dd7fSTakashi Sakamoto 	 * going to be released. The work is not scheduled again because bus
17086c8dd7fSTakashi Sakamoto 	 * reset handler is not called anymore.
17186c8dd7fSTakashi Sakamoto 	 */
17286c8dd7fSTakashi Sakamoto 	cancel_delayed_work_sync(&dg00x->dwork);
17386c8dd7fSTakashi Sakamoto 
17486c8dd7fSTakashi Sakamoto 	if (dg00x->registered) {
1759edf723fSTakashi Sakamoto 		/* No need to wait for releasing card object in this context. */
1769edf723fSTakashi Sakamoto 		snd_card_free_when_closed(dg00x->card);
17786c8dd7fSTakashi Sakamoto 	} else {
17886c8dd7fSTakashi Sakamoto 		/* Don't forget this case. */
17986c8dd7fSTakashi Sakamoto 		dg00x_free(dg00x);
18086c8dd7fSTakashi Sakamoto 	}
1819edf723fSTakashi Sakamoto }
1829edf723fSTakashi Sakamoto 
1839edf723fSTakashi Sakamoto static const struct ieee1394_device_id snd_dg00x_id_table[] = {
1849edf723fSTakashi Sakamoto 	/* Both of 002/003 use the same ID. */
1859edf723fSTakashi Sakamoto 	{
1869edf723fSTakashi Sakamoto 		.match_flags = IEEE1394_MATCH_VENDOR_ID |
1879edf723fSTakashi Sakamoto 			       IEEE1394_MATCH_MODEL_ID,
1889edf723fSTakashi Sakamoto 		.vendor_id = VENDOR_DIGIDESIGN,
189*13e005f9STakashi Sakamoto 		.model_id = MODEL_CONSOLE,
190*13e005f9STakashi Sakamoto 	},
191*13e005f9STakashi Sakamoto 	{
192*13e005f9STakashi Sakamoto 		.match_flags = IEEE1394_MATCH_VENDOR_ID |
193*13e005f9STakashi Sakamoto 			       IEEE1394_MATCH_MODEL_ID,
194*13e005f9STakashi Sakamoto 		.vendor_id = VENDOR_DIGIDESIGN,
195*13e005f9STakashi Sakamoto 		.model_id = MODEL_RACK,
1969edf723fSTakashi Sakamoto 	},
1979edf723fSTakashi Sakamoto 	{}
1989edf723fSTakashi Sakamoto };
1999edf723fSTakashi Sakamoto MODULE_DEVICE_TABLE(ieee1394, snd_dg00x_id_table);
2009edf723fSTakashi Sakamoto 
2019edf723fSTakashi Sakamoto static struct fw_driver dg00x_driver = {
2029edf723fSTakashi Sakamoto 	.driver = {
2039edf723fSTakashi Sakamoto 		.owner = THIS_MODULE,
2049edf723fSTakashi Sakamoto 		.name = "snd-firewire-digi00x",
2059edf723fSTakashi Sakamoto 		.bus = &fw_bus_type,
2069edf723fSTakashi Sakamoto 	},
2079edf723fSTakashi Sakamoto 	.probe    = snd_dg00x_probe,
2089edf723fSTakashi Sakamoto 	.update   = snd_dg00x_update,
2099edf723fSTakashi Sakamoto 	.remove   = snd_dg00x_remove,
2109edf723fSTakashi Sakamoto 	.id_table = snd_dg00x_id_table,
2119edf723fSTakashi Sakamoto };
2129edf723fSTakashi Sakamoto 
2139edf723fSTakashi Sakamoto static int __init snd_dg00x_init(void)
2149edf723fSTakashi Sakamoto {
2159edf723fSTakashi Sakamoto 	return driver_register(&dg00x_driver.driver);
2169edf723fSTakashi Sakamoto }
2179edf723fSTakashi Sakamoto 
2189edf723fSTakashi Sakamoto static void __exit snd_dg00x_exit(void)
2199edf723fSTakashi Sakamoto {
2209edf723fSTakashi Sakamoto 	driver_unregister(&dg00x_driver.driver);
2219edf723fSTakashi Sakamoto }
2229edf723fSTakashi Sakamoto 
2239edf723fSTakashi Sakamoto module_init(snd_dg00x_init);
2249edf723fSTakashi Sakamoto module_exit(snd_dg00x_exit);
225