diff options
Diffstat (limited to 'sound/firewire/tascam')
-rw-r--r-- | sound/firewire/tascam/Makefile | 2 | ||||
-rw-r--r-- | sound/firewire/tascam/tascam.c | 155 | ||||
-rw-r--r-- | sound/firewire/tascam/tascam.h | 33 |
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 |