summaryrefslogtreecommitdiff
path: root/sound/firewire/tascam
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire/tascam')
-rw-r--r--sound/firewire/tascam/Makefile2
-rw-r--r--sound/firewire/tascam/tascam.c155
-rw-r--r--sound/firewire/tascam/tascam.h33
3 files changed, 190 insertions, 0 deletions
diff --git a/sound/firewire/tascam/Makefile b/sound/firewire/tascam/Makefile
new file mode 100644
index 000000000000..627129b98a5c
--- /dev/null
+++ b/sound/firewire/tascam/Makefile
@@ -0,0 +1,2 @@
+snd-firewire-tascam-objs := tascam.o
+obj-$(CONFIG_SND_FIREWIRE_TASCAM) += snd-firewire-tascam.o
diff --git a/sound/firewire/tascam/tascam.c b/sound/firewire/tascam/tascam.c
new file mode 100644
index 000000000000..9f2d2a33f58a
--- /dev/null
+++ b/sound/firewire/tascam/tascam.c
@@ -0,0 +1,155 @@
+/*
+ * tascam.c - a part of driver for TASCAM FireWire series
+ *
+ * Copyright (c) 2015 Takashi Sakamoto
+ *
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include "tascam.h"
+
+MODULE_DESCRIPTION("TASCAM FireWire series Driver");
+MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>");
+MODULE_LICENSE("GPL v2");
+
+static int check_name(struct snd_tscm *tscm)
+{
+ struct fw_device *fw_dev = fw_parent_device(tscm->unit);
+ char vendor[8];
+ char model[8];
+ __u32 data;
+
+ /* Retrieve model name. */
+ data = be32_to_cpu(fw_dev->config_rom[28]);
+ memcpy(model, &data, 4);
+ data = be32_to_cpu(fw_dev->config_rom[29]);
+ memcpy(model + 4, &data, 4);
+ model[7] = '\0';
+
+ /* Retrieve vendor name. */
+ data = be32_to_cpu(fw_dev->config_rom[23]);
+ memcpy(vendor, &data, 4);
+ data = be32_to_cpu(fw_dev->config_rom[24]);
+ memcpy(vendor + 4, &data, 4);
+ vendor[7] = '\0';
+
+ strcpy(tscm->card->driver, "FW-TASCAM");
+ strcpy(tscm->card->shortname, model);
+ strcpy(tscm->card->mixername, model);
+ snprintf(tscm->card->longname, sizeof(tscm->card->longname),
+ "%s %s, GUID %08x%08x at %s, S%d", vendor, model,
+ cpu_to_be32(fw_dev->config_rom[3]),
+ cpu_to_be32(fw_dev->config_rom[4]),
+ dev_name(&tscm->unit->device), 100 << fw_dev->max_speed);
+
+ return 0;
+}
+
+static void tscm_card_free(struct snd_card *card)
+{
+ struct snd_tscm *tscm = card->private_data;
+
+ fw_unit_put(tscm->unit);
+
+ mutex_destroy(&tscm->mutex);
+}
+
+static int snd_tscm_probe(struct fw_unit *unit,
+ const struct ieee1394_device_id *entry)
+{
+ struct snd_card *card;
+ struct snd_tscm *tscm;
+ int err;
+
+ /* create card */
+ err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE,
+ sizeof(struct snd_tscm), &card);
+ if (err < 0)
+ return err;
+ card->private_free = tscm_card_free;
+
+ /* initialize myself */
+ tscm = card->private_data;
+ tscm->card = card;
+ tscm->unit = fw_unit_get(unit);
+
+ mutex_init(&tscm->mutex);
+
+ err = check_name(tscm);
+ if (err < 0)
+ goto error;
+
+ err = snd_card_register(card);
+ if (err < 0)
+ goto error;
+
+ dev_set_drvdata(&unit->device, tscm);
+
+ return err;
+error:
+ snd_card_free(card);
+ return err;
+}
+
+static void snd_tscm_update(struct fw_unit *unit)
+{
+ return;
+}
+
+static void snd_tscm_remove(struct fw_unit *unit)
+{
+ struct snd_tscm *tscm = dev_get_drvdata(&unit->device);
+
+ /* No need to wait for releasing card object in this context. */
+ snd_card_free_when_closed(tscm->card);
+}
+
+static const struct ieee1394_device_id snd_tscm_id_table[] = {
+ /* FW-1082 */
+ {
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
+ IEEE1394_MATCH_SPECIFIER_ID |
+ IEEE1394_MATCH_VERSION,
+ .vendor_id = 0x00022e,
+ .specifier_id = 0x00022e,
+ .version = 0x800003,
+ },
+ /* FW-1884 */
+ {
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
+ IEEE1394_MATCH_SPECIFIER_ID |
+ IEEE1394_MATCH_VERSION,
+ .vendor_id = 0x00022e,
+ .specifier_id = 0x00022e,
+ .version = 0x800000,
+ },
+ /* FW-1804 mey be supported if IDs are clear. */
+ /* FE-08 requires reverse-engineering because it just has faders. */
+ {}
+};
+MODULE_DEVICE_TABLE(ieee1394, snd_tscm_id_table);
+
+static struct fw_driver tscm_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "snd-firewire-tascam",
+ .bus = &fw_bus_type,
+ },
+ .probe = snd_tscm_probe,
+ .update = snd_tscm_update,
+ .remove = snd_tscm_remove,
+ .id_table = snd_tscm_id_table,
+};
+
+static int __init snd_tscm_init(void)
+{
+ return driver_register(&tscm_driver.driver);
+}
+
+static void __exit snd_tscm_exit(void)
+{
+ driver_unregister(&tscm_driver.driver);
+}
+
+module_init(snd_tscm_init);
+module_exit(snd_tscm_exit);
diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h
new file mode 100644
index 000000000000..d2f4f67cf636
--- /dev/null
+++ b/sound/firewire/tascam/tascam.h
@@ -0,0 +1,33 @@
+/*
+ * tascam.h - a part of driver for TASCAM FireWire series
+ *
+ * Copyright (c) 2015 Takashi Sakamoto
+ *
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#ifndef SOUND_TASCAM_H_INCLUDED
+#define SOUND_TASCAM_H_INCLUDED
+
+#include <linux/device.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/compat.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+
+#include "../lib.h"
+
+struct snd_tscm {
+ struct snd_card *card;
+ struct fw_unit *unit;
+
+ struct mutex mutex;
+};
+
+#endif