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